From patchwork Tue Nov 20 18:17:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 11095 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 4BD3044C73E for ; Tue, 20 Nov 2018 20:17:18 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id BF5F6689EE3; Tue, 20 Nov 2018 20:17:18 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f67.google.com (mail-wm1-f67.google.com [209.85.128.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id A6613680885 for ; Tue, 20 Nov 2018 20:17:12 +0200 (EET) Received: by mail-wm1-f67.google.com with SMTP id w7-v6so3055120wmc.1 for ; Tue, 20 Nov 2018 10:17:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=q/pYPP4wP3YmcAN6j4gnTKj3/BBMgKeIbH+9sfxBTsA=; b=W/VIcuap/ItCr/LRnztf2W2UtChY4VtsizH0iR/atCbNifUAr62YRtrPXJ8T0LUsGW a1hqt1YdBwf2lUiBW39BhDaBJXo8bpCn9Nj/dNRsf9U69zfZ0rGVMWoRi0xuqSIF97Ug 1hptnyhK6GlwRXqoDlEN4qZ57oIw6DU56+IZc6YyWrtV/gBXn2XZxWtjA/OvDXwT4YKL r/Z+wQumcyhPX30ssR8NnNE31fpnIcnwSEUutRhZhldfRP9gnIAE5JlJcSZ4lNVyCPJP cgPGg3O9RmHkBrWYw6IzsbTniv+YdPuaqhGmrmCT6sULPgG2Ftr8EOMmclpInIYaufJw +W+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id; bh=q/pYPP4wP3YmcAN6j4gnTKj3/BBMgKeIbH+9sfxBTsA=; b=H2k7xnbyw0dvdC7ElueJdGOqnSwlTBqWdtw/47hF3FahfmOI99VT7BUnK7KMj1FSJ3 R8qh+QBJcC82alNirGi7EmD7VEY+hF7lvsDyGG97Esls+6SVrsMY/nih9WNKbmd+OM97 ACvz7QoveffWEuZE1AIFoE8FYOEmSNHkuuhOOwoNiS1jCXGphbbkQlWqyYVU9nuqGUsB kmujCgkyDEpYRGd0xULHme4Ozbflbb+bB52l51wzFm1XIj5vsEURxTbGwiB2JYXVg8PS KO0uBjj78jHs/XFV3rr5ONv8EEm2dt0GWW1py9bdZ080Z+CSxjg3S8E9xU9VlF11uaya dJSw== X-Gm-Message-State: AGRZ1gIqtVaAZaZKYxcoy5WcT57Wjz9DppQ+aWKuiqeSRw7I7ErdDydN OEYVD1+h4Lp/x6OzRBA4b8ivgwBv X-Google-Smtp-Source: AJdET5cdzFtTcY53Wd3QdEQZUWqyBHg5Cn3zOk75ZHFNPFh4YWM5KE1L0Zf033vVXn/unEVBtN7ABw== X-Received: by 2002:a1c:e910:: with SMTP id q16-v6mr3100999wmc.148.1542737834045; Tue, 20 Nov 2018 10:17:14 -0800 (PST) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id a12sm10734458wrm.45.2018.11.20.10.17.13 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 20 Nov 2018 10:17:13 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Tue, 20 Nov 2018 19:17:02 +0100 Message-Id: <20181120181702.17988-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 Subject: [FFmpeg-devel] [PATCH] avcodec: add truehd_core bitstream filter X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- doc/bitstream_filters.texi | 4 + libavcodec/Makefile | 1 + libavcodec/bitstream_filters.c | 1 + libavcodec/truehd_core_bsf.c | 182 +++++++++++++++++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 libavcodec/truehd_core_bsf.c diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 655a2c1e63..15c578aa8a 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -634,6 +634,10 @@ This can be useful for debugging low-level stream issues. Supports H.264, H.265, MPEG-2 and VP9. +@section truehd_core + +Extract the core from a TrueHD stream, dropping ATMOS data. + @section vp9_metadata Modify metadata embedded in a VP9 stream. diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 716f26d191..bcced2e371 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -1085,6 +1085,7 @@ OBJS-$(CONFIG_PRORES_METADATA_BSF) += prores_metadata_bsf.o OBJS-$(CONFIG_REMOVE_EXTRADATA_BSF) += remove_extradata_bsf.o OBJS-$(CONFIG_TEXT2MOVSUB_BSF) += movsub_bsf.o OBJS-$(CONFIG_TRACE_HEADERS_BSF) += trace_headers_bsf.o +OBJS-$(CONFIG_TRUEHD_CORE_BSF) += truehd_core_bsf.o OBJS-$(CONFIG_VP9_METADATA_BSF) += vp9_metadata_bsf.o OBJS-$(CONFIG_VP9_RAW_REORDER_BSF) += vp9_raw_reorder_bsf.o OBJS-$(CONFIG_VP9_SUPERFRAME_BSF) += vp9_superframe_bsf.o diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c index 2a8598bac2..2c999d3c1d 100644 --- a/libavcodec/bitstream_filters.c +++ b/libavcodec/bitstream_filters.c @@ -51,6 +51,7 @@ extern const AVBitStreamFilter ff_prores_metadata_bsf; extern const AVBitStreamFilter ff_remove_extradata_bsf; extern const AVBitStreamFilter ff_text2movsub_bsf; extern const AVBitStreamFilter ff_trace_headers_bsf; +extern const AVBitStreamFilter ff_truehd_core_bsf; extern const AVBitStreamFilter ff_vp9_metadata_bsf; extern const AVBitStreamFilter ff_vp9_raw_reorder_bsf; extern const AVBitStreamFilter ff_vp9_superframe_bsf; diff --git a/libavcodec/truehd_core_bsf.c b/libavcodec/truehd_core_bsf.c new file mode 100644 index 0000000000..0449719185 --- /dev/null +++ b/libavcodec/truehd_core_bsf.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2018 Paul B Mahol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avcodec.h" +#include "bsf.h" +#include "get_bits.h" +#include "mlp_parser.h" +#include "mlp.h" + +typedef struct AccessUnit { + uint8_t bits[4]; + uint16_t offset; + uint16_t optional; +} AccessUnit; + +typedef struct TrueHDCoreContext { + const AVClass *class; + + AccessUnit units[4]; + + MLPHeaderInfo hdr; +} TrueHDCoreContext; + +static int truehd_core_filter(AVBSFContext *ctx, AVPacket *out) +{ + TrueHDCoreContext *s = ctx->priv_data; + GetBitContext gbc; + AVPacket *in; + int ret, i, size, last_offset = 0; + int in_size, out_size; + int have_header = 0; + int substream_bits = 0; + int start, end; + uint16_t dts; + + ret = ff_bsf_get_packet(ctx, &in); + if (ret < 0) + return ret; + + ret = init_get_bits8(&gbc, in->data, 4); + if (ret < 0) + goto fail; + + skip_bits(&gbc, 4); + in_size = get_bits(&gbc, 12) * 2; + if (in_size < 4 || in_size > in->size) + goto fail; + + out_size = in_size; + dts = get_bits(&gbc, 16); + + ret = init_get_bits8(&gbc, in->data + 4, in->size - 4); + if (ret < 0) + goto fail; + + if (show_bits_long(&gbc, 32) == 0xf8726fba) { + if ((ret = ff_mlp_read_major_sync(ctx, &s->hdr, &gbc)) != 0) + goto fail; + have_header = 1; + } + + start = get_bits_count(&gbc); + for (i = 0; i < s->hdr.num_substreams; i++) { + for (int j = 0; j < 4; j++) + s->units[i].bits[j] = get_bits1(&gbc); + + s->units[i].offset = get_bits(&gbc, 12) * 2; + if (i < FFMIN(s->hdr.num_substreams, 3)) { + last_offset = s->units[i].offset; + substream_bits += 16; + } + + if (s->units[i].bits[0]) { + s->units[i].optional = get_bits(&gbc, 16); + if (i < FFMIN(s->hdr.num_substreams, 3)) + substream_bits += 16; + } + } + end = get_bits_count(&gbc); + + ret = av_packet_copy_props(out, in); + if (ret < 0) + goto fail; + + size = ((end + 7) >> 3) + 4 + last_offset; + if (size >= 0 && size <= in->size) + out_size = size; + ret = av_grow_packet(out, out_size); + if (ret < 0) + goto fail; + + if (out_size < in_size) { + int bpos = 0, reduce = (end - start - substream_bits) >> 4; + uint16_t parity_nibble = 0; + uint16_t auheader; + + AV_WB16(out->data + 2, dts); + parity_nibble = dts; + out->size -= reduce * 2; + parity_nibble ^= out->size / 2; + + if (have_header) { + memcpy(out->data + 4, in->data + 4, 28); + out->data[16 + 4] = (out->data[16 + 4] & 0x0f) | (FFMIN(s->hdr.num_substreams, 3) << 4); + out->data[25 + 4] = out->data[25 + 4] & 0xfe; + out->data[26 + 4] = 0xff; + out->data[27 + 4] = 0xff; + AV_WL16(out->data + 4 + 26, ff_mlp_checksum16(out->data + 4, 26)); + } + + for (i = 0; i < FFMIN(s->hdr.num_substreams, 3); i++) { + uint16_t substr_hdr = 0; + + substr_hdr |= (s->units[i].bits[0] << 15); + substr_hdr |= (s->units[i].bits[1] << 14); + substr_hdr |= (s->units[i].bits[2] << 13); + substr_hdr |= (s->units[i].bits[3] << 12); + substr_hdr |= (s->units[i].offset / 2) & 0x0FFF; + + AV_WB16(out->data + have_header * 28 + 4 + bpos, substr_hdr); + + parity_nibble ^= out->data[have_header * 28 + 4 + bpos++]; + parity_nibble ^= out->data[have_header * 28 + 4 + bpos++]; + + if (s->units[i].bits[0]) { + AV_WB16(out->data + have_header * 28 + 4 + bpos, s->units[i].optional); + + parity_nibble ^= out->data[have_header * 28 + 4 + bpos++]; + parity_nibble ^= out->data[have_header * 28 + 4 + bpos++]; + } + } + + parity_nibble ^= parity_nibble >> 8; + parity_nibble ^= parity_nibble >> 4; + parity_nibble &= 0xF; + + memcpy(out->data + have_header * 28 + 4 + bpos, + in->data + 4 + (end >> 3), + out_size - (4 + (end >> 3))); + auheader = (parity_nibble ^ 0xF) << 12; + auheader |= (out->size / 2) & 0x0fff; + AV_WB16(out->data, auheader); + } else { + memcpy(out->data, in->data, out_size); + } + + av_packet_free(&in); + + return 0; +fail: + av_packet_unref(out); + av_packet_free(&in); + return ret; +} + +static const enum AVCodecID codec_ids[] = { + AV_CODEC_ID_TRUEHD, AV_CODEC_ID_NONE, +}; + +const AVBitStreamFilter ff_truehd_core_bsf = { + .name = "truehd_core", + .priv_data_size = sizeof(TrueHDCoreContext), + .filter = truehd_core_filter, + .codec_ids = codec_ids, +};