1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * MLP parser 3cabdff1aSopenharmony_ci * Copyright (c) 2007 Ian Caulfield 4cabdff1aSopenharmony_ci * 5cabdff1aSopenharmony_ci * This file is part of FFmpeg. 6cabdff1aSopenharmony_ci * 7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 11cabdff1aSopenharmony_ci * 12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15cabdff1aSopenharmony_ci * Lesser General Public License for more details. 16cabdff1aSopenharmony_ci * 17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20cabdff1aSopenharmony_ci */ 21cabdff1aSopenharmony_ci 22cabdff1aSopenharmony_ci/** 23cabdff1aSopenharmony_ci * @file 24cabdff1aSopenharmony_ci * MLP parser 25cabdff1aSopenharmony_ci */ 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include <stdint.h> 28cabdff1aSopenharmony_ci 29cabdff1aSopenharmony_ci#include "libavutil/internal.h" 30cabdff1aSopenharmony_ci#include "get_bits.h" 31cabdff1aSopenharmony_ci#include "parser.h" 32cabdff1aSopenharmony_ci#include "mlp_parse.h" 33cabdff1aSopenharmony_ci#include "mlp.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_citypedef struct MLPParseContext 36cabdff1aSopenharmony_ci{ 37cabdff1aSopenharmony_ci ParseContext pc; 38cabdff1aSopenharmony_ci 39cabdff1aSopenharmony_ci int bytes_left; 40cabdff1aSopenharmony_ci 41cabdff1aSopenharmony_ci int in_sync; 42cabdff1aSopenharmony_ci 43cabdff1aSopenharmony_ci int num_substreams; 44cabdff1aSopenharmony_ci} MLPParseContext; 45cabdff1aSopenharmony_ci 46cabdff1aSopenharmony_cistatic av_cold int mlp_init(AVCodecParserContext *s) 47cabdff1aSopenharmony_ci{ 48cabdff1aSopenharmony_ci ff_mlp_init_crc(); 49cabdff1aSopenharmony_ci return 0; 50cabdff1aSopenharmony_ci} 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_cistatic int mlp_parse(AVCodecParserContext *s, 53cabdff1aSopenharmony_ci AVCodecContext *avctx, 54cabdff1aSopenharmony_ci const uint8_t **poutbuf, int *poutbuf_size, 55cabdff1aSopenharmony_ci const uint8_t *buf, int buf_size) 56cabdff1aSopenharmony_ci{ 57cabdff1aSopenharmony_ci MLPParseContext *mp = s->priv_data; 58cabdff1aSopenharmony_ci int sync_present; 59cabdff1aSopenharmony_ci uint8_t parity_bits; 60cabdff1aSopenharmony_ci int next; 61cabdff1aSopenharmony_ci int ret; 62cabdff1aSopenharmony_ci int i, p = 0; 63cabdff1aSopenharmony_ci 64cabdff1aSopenharmony_ci s->key_frame = 0; 65cabdff1aSopenharmony_ci 66cabdff1aSopenharmony_ci *poutbuf_size = 0; 67cabdff1aSopenharmony_ci *poutbuf = NULL; 68cabdff1aSopenharmony_ci if (buf_size == 0) 69cabdff1aSopenharmony_ci return 0; 70cabdff1aSopenharmony_ci 71cabdff1aSopenharmony_ci if (s->flags & PARSER_FLAG_COMPLETE_FRAMES) { 72cabdff1aSopenharmony_ci next = buf_size; 73cabdff1aSopenharmony_ci } else { 74cabdff1aSopenharmony_ci if (!mp->in_sync) { 75cabdff1aSopenharmony_ci // Not in sync - find a major sync header 76cabdff1aSopenharmony_ci 77cabdff1aSopenharmony_ci for (i = 0; i < buf_size; i++) { 78cabdff1aSopenharmony_ci mp->pc.state = (mp->pc.state << 8) | buf[i]; 79cabdff1aSopenharmony_ci if ((mp->pc.state & 0xfffffffe) == 0xf8726fba && 80cabdff1aSopenharmony_ci // ignore if we do not have the data for the start of header 81cabdff1aSopenharmony_ci mp->pc.index + i >= 7) { 82cabdff1aSopenharmony_ci mp->in_sync = 1; 83cabdff1aSopenharmony_ci mp->bytes_left = 0; 84cabdff1aSopenharmony_ci break; 85cabdff1aSopenharmony_ci } 86cabdff1aSopenharmony_ci } 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci if (!mp->in_sync) { 89cabdff1aSopenharmony_ci if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1) 90cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); 91cabdff1aSopenharmony_ci return buf_size; 92cabdff1aSopenharmony_ci } 93cabdff1aSopenharmony_ci 94cabdff1aSopenharmony_ci if ((ret = ff_combine_frame(&mp->pc, i - 7, &buf, &buf_size)) < 0) { 95cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); 96cabdff1aSopenharmony_ci return ret; 97cabdff1aSopenharmony_ci } 98cabdff1aSopenharmony_ci 99cabdff1aSopenharmony_ci return i - 7; 100cabdff1aSopenharmony_ci } 101cabdff1aSopenharmony_ci 102cabdff1aSopenharmony_ci if (mp->bytes_left == 0) { 103cabdff1aSopenharmony_ci // Find length of this packet 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci /* Copy overread bytes from last frame into buffer. */ 106cabdff1aSopenharmony_ci for(; mp->pc.overread>0; mp->pc.overread--) { 107cabdff1aSopenharmony_ci mp->pc.buffer[mp->pc.index++]= mp->pc.buffer[mp->pc.overread_index++]; 108cabdff1aSopenharmony_ci } 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_ci if (mp->pc.index + buf_size < 2) { 111cabdff1aSopenharmony_ci if (ff_combine_frame(&mp->pc, END_NOT_FOUND, &buf, &buf_size) != -1) 112cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_WARNING, "ff_combine_frame failed\n"); 113cabdff1aSopenharmony_ci return buf_size; 114cabdff1aSopenharmony_ci } 115cabdff1aSopenharmony_ci 116cabdff1aSopenharmony_ci mp->bytes_left = ((mp->pc.index > 0 ? mp->pc.buffer[0] : buf[0]) << 8) 117cabdff1aSopenharmony_ci | (mp->pc.index > 1 ? mp->pc.buffer[1] : buf[1-mp->pc.index]); 118cabdff1aSopenharmony_ci mp->bytes_left = (mp->bytes_left & 0xfff) * 2; 119cabdff1aSopenharmony_ci if (mp->bytes_left <= 0) { // prevent infinite loop 120cabdff1aSopenharmony_ci goto lost_sync; 121cabdff1aSopenharmony_ci } 122cabdff1aSopenharmony_ci mp->bytes_left -= mp->pc.index; 123cabdff1aSopenharmony_ci } 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci next = (mp->bytes_left > buf_size) ? END_NOT_FOUND : mp->bytes_left; 126cabdff1aSopenharmony_ci 127cabdff1aSopenharmony_ci if (ff_combine_frame(&mp->pc, next, &buf, &buf_size) < 0) { 128cabdff1aSopenharmony_ci mp->bytes_left -= buf_size; 129cabdff1aSopenharmony_ci return buf_size; 130cabdff1aSopenharmony_ci } 131cabdff1aSopenharmony_ci 132cabdff1aSopenharmony_ci mp->bytes_left = 0; 133cabdff1aSopenharmony_ci } 134cabdff1aSopenharmony_ci 135cabdff1aSopenharmony_ci sync_present = buf_size >= 8 && (AV_RB32(buf + 4) & 0xfffffffe) == 0xf8726fba; 136cabdff1aSopenharmony_ci 137cabdff1aSopenharmony_ci if (!sync_present) { 138cabdff1aSopenharmony_ci /* The first nibble of a frame is a parity check of the 4-byte 139cabdff1aSopenharmony_ci * access unit header and all the 2- or 4-byte substream headers. */ 140cabdff1aSopenharmony_ci // Only check when this isn't a sync frame - syncs have a checksum. 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci s->key_frame = 0; 143cabdff1aSopenharmony_ci 144cabdff1aSopenharmony_ci parity_bits = 0; 145cabdff1aSopenharmony_ci for (i = -1; i < mp->num_substreams; i++) { 146cabdff1aSopenharmony_ci parity_bits ^= buf[p++]; 147cabdff1aSopenharmony_ci parity_bits ^= buf[p++]; 148cabdff1aSopenharmony_ci 149cabdff1aSopenharmony_ci if (i < 0 || buf[p-2] & 0x80) { 150cabdff1aSopenharmony_ci parity_bits ^= buf[p++]; 151cabdff1aSopenharmony_ci parity_bits ^= buf[p++]; 152cabdff1aSopenharmony_ci } 153cabdff1aSopenharmony_ci } 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci if ((((parity_bits >> 4) ^ parity_bits) & 0xF) != 0xF) { 156cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_INFO, "mlpparse: Parity check failed.\n"); 157cabdff1aSopenharmony_ci goto lost_sync; 158cabdff1aSopenharmony_ci } 159cabdff1aSopenharmony_ci } else { 160cabdff1aSopenharmony_ci GetBitContext gb; 161cabdff1aSopenharmony_ci MLPHeaderInfo mh; 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci init_get_bits(&gb, buf + 4, (buf_size - 4) << 3); 164cabdff1aSopenharmony_ci if (ff_mlp_read_major_sync(avctx, &mh, &gb) < 0) 165cabdff1aSopenharmony_ci goto lost_sync; 166cabdff1aSopenharmony_ci 167cabdff1aSopenharmony_ci s->key_frame = 1; 168cabdff1aSopenharmony_ci 169cabdff1aSopenharmony_ci avctx->bits_per_raw_sample = mh.group1_bits; 170cabdff1aSopenharmony_ci if (avctx->bits_per_raw_sample > 16) 171cabdff1aSopenharmony_ci avctx->sample_fmt = AV_SAMPLE_FMT_S32; 172cabdff1aSopenharmony_ci else 173cabdff1aSopenharmony_ci avctx->sample_fmt = AV_SAMPLE_FMT_S16; 174cabdff1aSopenharmony_ci avctx->sample_rate = mh.group1_samplerate; 175cabdff1aSopenharmony_ci avctx->frame_size = 176cabdff1aSopenharmony_ci s->duration = mh.access_unit_size; 177cabdff1aSopenharmony_ci 178cabdff1aSopenharmony_ci av_channel_layout_uninit(&avctx->ch_layout); 179cabdff1aSopenharmony_ci if (mh.stream_type == 0xbb) { 180cabdff1aSopenharmony_ci /* MLP stream */ 181cabdff1aSopenharmony_ci av_channel_layout_from_mask(&avctx->ch_layout, mh.channel_layout_mlp); 182cabdff1aSopenharmony_ci } else { /* mh.stream_type == 0xba */ 183cabdff1aSopenharmony_ci /* TrueHD stream */ 184cabdff1aSopenharmony_ci if (!mh.channels_thd_stream2) { 185cabdff1aSopenharmony_ci av_channel_layout_from_mask(&avctx->ch_layout, mh.channel_layout_thd_stream1); 186cabdff1aSopenharmony_ci } else { 187cabdff1aSopenharmony_ci av_channel_layout_from_mask(&avctx->ch_layout, mh.channel_layout_thd_stream2); 188cabdff1aSopenharmony_ci } 189cabdff1aSopenharmony_ci } 190cabdff1aSopenharmony_ci 191cabdff1aSopenharmony_ci if (!mh.is_vbr) /* Stream is CBR */ 192cabdff1aSopenharmony_ci avctx->bit_rate = mh.peak_bitrate; 193cabdff1aSopenharmony_ci 194cabdff1aSopenharmony_ci mp->num_substreams = mh.num_substreams; 195cabdff1aSopenharmony_ci } 196cabdff1aSopenharmony_ci 197cabdff1aSopenharmony_ci *poutbuf = buf; 198cabdff1aSopenharmony_ci *poutbuf_size = buf_size; 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci return next; 201cabdff1aSopenharmony_ci 202cabdff1aSopenharmony_cilost_sync: 203cabdff1aSopenharmony_ci mp->in_sync = 0; 204cabdff1aSopenharmony_ci return 1; 205cabdff1aSopenharmony_ci} 206cabdff1aSopenharmony_ci 207cabdff1aSopenharmony_ciconst AVCodecParser ff_mlp_parser = { 208cabdff1aSopenharmony_ci .codec_ids = { AV_CODEC_ID_MLP, AV_CODEC_ID_TRUEHD }, 209cabdff1aSopenharmony_ci .priv_data_size = sizeof(MLPParseContext), 210cabdff1aSopenharmony_ci .parser_init = mlp_init, 211cabdff1aSopenharmony_ci .parser_parse = mlp_parse, 212cabdff1aSopenharmony_ci .parser_close = ff_parse_close, 213cabdff1aSopenharmony_ci}; 214