1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * Copyright (c) 2018 Paul B Mahol 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * This file is part of FFmpeg. 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 7cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 8cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 9cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 10cabdff1aSopenharmony_ci * 11cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 12cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 13cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14cabdff1aSopenharmony_ci * Lesser General Public License for more details. 15cabdff1aSopenharmony_ci * 16cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 17cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 18cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 19cabdff1aSopenharmony_ci */ 20cabdff1aSopenharmony_ci 21cabdff1aSopenharmony_ci#include "bsf.h" 22cabdff1aSopenharmony_ci#include "bsf_internal.h" 23cabdff1aSopenharmony_ci#include "get_bits.h" 24cabdff1aSopenharmony_ci#include "mlp_parse.h" 25cabdff1aSopenharmony_ci#include "mlp.h" 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_citypedef struct AccessUnit { 28cabdff1aSopenharmony_ci uint8_t bits[4]; 29cabdff1aSopenharmony_ci uint16_t offset; 30cabdff1aSopenharmony_ci uint16_t optional; 31cabdff1aSopenharmony_ci} AccessUnit; 32cabdff1aSopenharmony_ci 33cabdff1aSopenharmony_citypedef struct TrueHDCoreContext { 34cabdff1aSopenharmony_ci MLPHeaderInfo hdr; 35cabdff1aSopenharmony_ci} TrueHDCoreContext; 36cabdff1aSopenharmony_ci 37cabdff1aSopenharmony_cistatic int truehd_core_filter(AVBSFContext *ctx, AVPacket *pkt) 38cabdff1aSopenharmony_ci{ 39cabdff1aSopenharmony_ci TrueHDCoreContext *s = ctx->priv_data; 40cabdff1aSopenharmony_ci GetBitContext gbc; 41cabdff1aSopenharmony_ci AccessUnit units[MAX_SUBSTREAMS]; 42cabdff1aSopenharmony_ci int ret, i, last_offset = 0; 43cabdff1aSopenharmony_ci int in_size, out_size; 44cabdff1aSopenharmony_ci int have_header = 0; 45cabdff1aSopenharmony_ci int substream_bytes = 0; 46cabdff1aSopenharmony_ci int end; 47cabdff1aSopenharmony_ci 48cabdff1aSopenharmony_ci ret = ff_bsf_get_packet_ref(ctx, pkt); 49cabdff1aSopenharmony_ci if (ret < 0) 50cabdff1aSopenharmony_ci return ret; 51cabdff1aSopenharmony_ci 52cabdff1aSopenharmony_ci if (pkt->size < 4) { 53cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 54cabdff1aSopenharmony_ci goto fail; 55cabdff1aSopenharmony_ci } 56cabdff1aSopenharmony_ci 57cabdff1aSopenharmony_ci in_size = (AV_RB16(pkt->data) & 0xFFF) * 2; 58cabdff1aSopenharmony_ci if (in_size < 4 || in_size > pkt->size) { 59cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 60cabdff1aSopenharmony_ci goto fail; 61cabdff1aSopenharmony_ci } 62cabdff1aSopenharmony_ci 63cabdff1aSopenharmony_ci ret = init_get_bits8(&gbc, pkt->data + 4, pkt->size - 4); 64cabdff1aSopenharmony_ci if (ret < 0) 65cabdff1aSopenharmony_ci goto fail; 66cabdff1aSopenharmony_ci 67cabdff1aSopenharmony_ci if (show_bits_long(&gbc, 32) == 0xf8726fba) { 68cabdff1aSopenharmony_ci if ((ret = ff_mlp_read_major_sync(ctx, &s->hdr, &gbc)) < 0) 69cabdff1aSopenharmony_ci goto fail; 70cabdff1aSopenharmony_ci have_header = 1; 71cabdff1aSopenharmony_ci } 72cabdff1aSopenharmony_ci 73cabdff1aSopenharmony_ci if (s->hdr.num_substreams > MAX_SUBSTREAMS) { 74cabdff1aSopenharmony_ci ret = AVERROR_INVALIDDATA; 75cabdff1aSopenharmony_ci goto fail; 76cabdff1aSopenharmony_ci } 77cabdff1aSopenharmony_ci 78cabdff1aSopenharmony_ci for (i = 0; i < s->hdr.num_substreams; i++) { 79cabdff1aSopenharmony_ci for (int j = 0; j < 4; j++) 80cabdff1aSopenharmony_ci units[i].bits[j] = get_bits1(&gbc); 81cabdff1aSopenharmony_ci 82cabdff1aSopenharmony_ci units[i].offset = get_bits(&gbc, 12); 83cabdff1aSopenharmony_ci if (i < 3) { 84cabdff1aSopenharmony_ci last_offset = units[i].offset * 2; 85cabdff1aSopenharmony_ci substream_bytes += 2; 86cabdff1aSopenharmony_ci } 87cabdff1aSopenharmony_ci 88cabdff1aSopenharmony_ci if (units[i].bits[0]) { 89cabdff1aSopenharmony_ci units[i].optional = get_bits(&gbc, 16); 90cabdff1aSopenharmony_ci if (i < 3) 91cabdff1aSopenharmony_ci substream_bytes += 2; 92cabdff1aSopenharmony_ci } 93cabdff1aSopenharmony_ci } 94cabdff1aSopenharmony_ci end = get_bits_count(&gbc) >> 3; 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci out_size = end + 4 + last_offset; 97cabdff1aSopenharmony_ci if (out_size < in_size) { 98cabdff1aSopenharmony_ci int bpos = 0, reduce = end - have_header * 28 - substream_bytes; 99cabdff1aSopenharmony_ci uint16_t parity_nibble, dts = AV_RB16(pkt->data + 2); 100cabdff1aSopenharmony_ci uint16_t auheader; 101cabdff1aSopenharmony_ci uint8_t header[28]; 102cabdff1aSopenharmony_ci 103cabdff1aSopenharmony_ci av_assert1(reduce >= 0 && reduce % 2 == 0); 104cabdff1aSopenharmony_ci 105cabdff1aSopenharmony_ci if (have_header) { 106cabdff1aSopenharmony_ci memcpy(header, pkt->data + 4, 28); 107cabdff1aSopenharmony_ci header[16] = (header[16] & 0x0c) | (FFMIN(s->hdr.num_substreams, 3) << 4); 108cabdff1aSopenharmony_ci header[17] &= 0x7f; 109cabdff1aSopenharmony_ci header[25] &= 0xfe; 110cabdff1aSopenharmony_ci AV_WL16(header + 26, ff_mlp_checksum16(header, 26)); 111cabdff1aSopenharmony_ci } 112cabdff1aSopenharmony_ci 113cabdff1aSopenharmony_ci pkt->data += reduce; 114cabdff1aSopenharmony_ci out_size -= reduce; 115cabdff1aSopenharmony_ci pkt->size = out_size; 116cabdff1aSopenharmony_ci 117cabdff1aSopenharmony_ci ret = av_packet_make_writable(pkt); 118cabdff1aSopenharmony_ci if (ret < 0) 119cabdff1aSopenharmony_ci goto fail; 120cabdff1aSopenharmony_ci 121cabdff1aSopenharmony_ci AV_WB16(pkt->data + 2, dts); 122cabdff1aSopenharmony_ci parity_nibble = dts; 123cabdff1aSopenharmony_ci parity_nibble ^= out_size / 2; 124cabdff1aSopenharmony_ci 125cabdff1aSopenharmony_ci for (i = 0; i < FFMIN(s->hdr.num_substreams, 3); i++) { 126cabdff1aSopenharmony_ci uint16_t substr_hdr = 0; 127cabdff1aSopenharmony_ci 128cabdff1aSopenharmony_ci substr_hdr |= (units[i].bits[0] << 15); 129cabdff1aSopenharmony_ci substr_hdr |= (units[i].bits[1] << 14); 130cabdff1aSopenharmony_ci substr_hdr |= (units[i].bits[2] << 13); 131cabdff1aSopenharmony_ci substr_hdr |= (units[i].bits[3] << 12); 132cabdff1aSopenharmony_ci substr_hdr |= units[i].offset; 133cabdff1aSopenharmony_ci 134cabdff1aSopenharmony_ci AV_WB16(pkt->data + have_header * 28 + 4 + bpos, substr_hdr); 135cabdff1aSopenharmony_ci 136cabdff1aSopenharmony_ci parity_nibble ^= substr_hdr; 137cabdff1aSopenharmony_ci bpos += 2; 138cabdff1aSopenharmony_ci 139cabdff1aSopenharmony_ci if (units[i].bits[0]) { 140cabdff1aSopenharmony_ci AV_WB16(pkt->data + have_header * 28 + 4 + bpos, units[i].optional); 141cabdff1aSopenharmony_ci 142cabdff1aSopenharmony_ci parity_nibble ^= units[i].optional; 143cabdff1aSopenharmony_ci bpos += 2; 144cabdff1aSopenharmony_ci } 145cabdff1aSopenharmony_ci } 146cabdff1aSopenharmony_ci 147cabdff1aSopenharmony_ci parity_nibble ^= parity_nibble >> 8; 148cabdff1aSopenharmony_ci parity_nibble ^= parity_nibble >> 4; 149cabdff1aSopenharmony_ci parity_nibble &= 0xF; 150cabdff1aSopenharmony_ci 151cabdff1aSopenharmony_ci auheader = (parity_nibble ^ 0xF) << 12; 152cabdff1aSopenharmony_ci auheader |= (out_size / 2) & 0x0fff; 153cabdff1aSopenharmony_ci AV_WB16(pkt->data, auheader); 154cabdff1aSopenharmony_ci 155cabdff1aSopenharmony_ci if (have_header) 156cabdff1aSopenharmony_ci memcpy(pkt->data + 4, header, 28); 157cabdff1aSopenharmony_ci } 158cabdff1aSopenharmony_ci 159cabdff1aSopenharmony_cifail: 160cabdff1aSopenharmony_ci if (ret < 0) 161cabdff1aSopenharmony_ci av_packet_unref(pkt); 162cabdff1aSopenharmony_ci 163cabdff1aSopenharmony_ci return ret; 164cabdff1aSopenharmony_ci} 165cabdff1aSopenharmony_ci 166cabdff1aSopenharmony_cistatic void truehd_core_flush(AVBSFContext *ctx) 167cabdff1aSopenharmony_ci{ 168cabdff1aSopenharmony_ci TrueHDCoreContext *s = ctx->priv_data; 169cabdff1aSopenharmony_ci memset(&s->hdr, 0, sizeof(s->hdr)); 170cabdff1aSopenharmony_ci} 171cabdff1aSopenharmony_ci 172cabdff1aSopenharmony_cistatic const enum AVCodecID codec_ids[] = { 173cabdff1aSopenharmony_ci AV_CODEC_ID_TRUEHD, AV_CODEC_ID_NONE, 174cabdff1aSopenharmony_ci}; 175cabdff1aSopenharmony_ci 176cabdff1aSopenharmony_ciconst FFBitStreamFilter ff_truehd_core_bsf = { 177cabdff1aSopenharmony_ci .p.name = "truehd_core", 178cabdff1aSopenharmony_ci .p.codec_ids = codec_ids, 179cabdff1aSopenharmony_ci .priv_data_size = sizeof(TrueHDCoreContext), 180cabdff1aSopenharmony_ci .filter = truehd_core_filter, 181cabdff1aSopenharmony_ci .flush = truehd_core_flush, 182cabdff1aSopenharmony_ci}; 183