FFmpeg  4.2.2
truehd_core_bsf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Paul B Mahol
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "avcodec.h"
22 #include "bsf.h"
23 #include "get_bits.h"
24 #include "mlp_parse.h"
25 #include "mlp.h"
26 
27 typedef struct AccessUnit {
29  uint16_t offset;
30  uint16_t optional;
31 } AccessUnit;
32 
33 typedef struct TrueHDCoreContext {
34  const AVClass *class;
35 
38 
40 {
42  GetBitContext gbc;
44  int ret, i, last_offset = 0;
45  int in_size, out_size;
46  int have_header = 0;
47  int substream_bytes = 0;
48  int end;
49 
50  ret = ff_bsf_get_packet_ref(ctx, pkt);
51  if (ret < 0)
52  return ret;
53 
54  if (pkt->size < 4) {
55  ret = AVERROR_INVALIDDATA;
56  goto fail;
57  }
58 
59  in_size = (AV_RB16(pkt->data) & 0xFFF) * 2;
60  if (in_size < 4 || in_size > pkt->size) {
61  ret = AVERROR_INVALIDDATA;
62  goto fail;
63  }
64 
65  ret = init_get_bits8(&gbc, pkt->data + 4, pkt->size - 4);
66  if (ret < 0)
67  goto fail;
68 
69  if (show_bits_long(&gbc, 32) == 0xf8726fba) {
70  if ((ret = ff_mlp_read_major_sync(ctx, &s->hdr, &gbc)) < 0)
71  goto fail;
72  have_header = 1;
73  }
74 
76  ret = AVERROR_INVALIDDATA;
77  goto fail;
78  }
79 
80  for (i = 0; i < s->hdr.num_substreams; i++) {
81  for (int j = 0; j < 4; j++)
82  units[i].bits[j] = get_bits1(&gbc);
83 
84  units[i].offset = get_bits(&gbc, 12);
85  if (i < 3) {
86  last_offset = units[i].offset * 2;
87  substream_bytes += 2;
88  }
89 
90  if (units[i].bits[0]) {
91  units[i].optional = get_bits(&gbc, 16);
92  if (i < 3)
93  substream_bytes += 2;
94  }
95  }
96  end = get_bits_count(&gbc) >> 3;
97 
98  out_size = end + 4 + last_offset;
99  if (out_size < in_size) {
100  int bpos = 0, reduce = end - have_header * 28 - substream_bytes;
101  uint16_t parity_nibble, dts = AV_RB16(pkt->data + 2);
102  uint16_t auheader;
103  uint8_t header[28];
104 
105  av_assert1(reduce >= 0 && reduce % 2 == 0);
106 
107  if (have_header) {
108  memcpy(header, pkt->data + 4, 28);
109  header[16] = (header[16] & 0x0c) | (FFMIN(s->hdr.num_substreams, 3) << 4);
110  header[17] &= 0x7f;
111  header[25] &= 0xfe;
112  AV_WL16(header + 26, ff_mlp_checksum16(header, 26));
113  }
114 
115  pkt->data += reduce;
116  out_size -= reduce;
117  pkt->size = out_size;
118 
119  ret = av_packet_make_writable(pkt);
120  if (ret < 0)
121  goto fail;
122 
123  AV_WB16(pkt->data + 2, dts);
124  parity_nibble = dts;
125  parity_nibble ^= out_size / 2;
126 
127  for (i = 0; i < FFMIN(s->hdr.num_substreams, 3); i++) {
128  uint16_t substr_hdr = 0;
129 
130  substr_hdr |= (units[i].bits[0] << 15);
131  substr_hdr |= (units[i].bits[1] << 14);
132  substr_hdr |= (units[i].bits[2] << 13);
133  substr_hdr |= (units[i].bits[3] << 12);
134  substr_hdr |= units[i].offset;
135 
136  AV_WB16(pkt->data + have_header * 28 + 4 + bpos, substr_hdr);
137 
138  parity_nibble ^= substr_hdr;
139  bpos += 2;
140 
141  if (units[i].bits[0]) {
142  AV_WB16(pkt->data + have_header * 28 + 4 + bpos, units[i].optional);
143 
144  parity_nibble ^= units[i].optional;
145  bpos += 2;
146  }
147  }
148 
149  parity_nibble ^= parity_nibble >> 8;
150  parity_nibble ^= parity_nibble >> 4;
151  parity_nibble &= 0xF;
152 
153  auheader = (parity_nibble ^ 0xF) << 12;
154  auheader |= (out_size / 2) & 0x0fff;
155  AV_WB16(pkt->data, auheader);
156 
157  if (have_header)
158  memcpy(pkt->data + 4, header, 28);
159  }
160 
161 fail:
162  if (ret < 0)
163  av_packet_unref(pkt);
164 
165  return ret;
166 }
167 
169 {
170  TrueHDCoreContext *s = ctx->priv_data;
171  memset(&s->hdr, 0, sizeof(s->hdr));
172 }
173 
174 static const enum AVCodecID codec_ids[] = {
176 };
177 
179  .name = "truehd_core",
180  .priv_data_size = sizeof(TrueHDCoreContext),
183  .codec_ids = codec_ids,
184 };
static unsigned int show_bits_long(GetBitContext *s, int n)
Show 0-32 bits.
Definition: get_bits.h:602
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
static void flush(AVCodecContext *avctx)
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:379
const AVBitStreamFilter ff_truehd_core_bsf
uint16_t ff_mlp_checksum16(const uint8_t *buf, unsigned int buf_size)
Definition: mlp.c:85
int num_substreams
Number of substreams within stream.
Definition: mlp_parse.h:56
The bitstream filter state.
Definition: avcodec.h:5763
int size
Definition: avcodec.h:1478
int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb)
Read a major sync info header - contains high level information about the stream - sample rate...
Definition: mlp_parse.c:136
int out_size
Definition: movenc.c:55
static AVPacket pkt
void * priv_data
Opaque filter-specific private data.
Definition: avcodec.h:5784
static void truehd_core_flush(AVBSFContext *ctx)
static void filter(int16_t *output, ptrdiff_t out_stride, int16_t *low, ptrdiff_t low_stride, int16_t *high, ptrdiff_t high_stride, int len, int clip)
Definition: cfhd.c:153
uint8_t
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
const char * name
Definition: avcodec.h:5813
uint8_t * data
Definition: avcodec.h:1477
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:219
bitstream reader API header.
static const uint8_t header[24]
Definition: sdr2.c:67
#define AV_WB16(p, v)
Definition: intreadwrite.h:405
int av_packet_make_writable(AVPacket *pkt)
Create a writable reference for the data described by a given packet, avoiding data copy if possible...
Definition: avpacket.c:682
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: avcodec.h:215
#define AV_RB16
Definition: intreadwrite.h:53
static enum AVCodecID codec_ids[]
#define fail()
Definition: checkasm.h:120
uint16_t optional
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:53
#define FFMIN(a, b)
Definition: common.h:96
MLPHeaderInfo hdr
static int truehd_core_filter(AVBSFContext *ctx, AVPacket *pkt)
AVFormatContext * ctx
Definition: movenc.c:48
uint8_t bits[4]
#define s(width, name)
Definition: cbs_vp9.c:257
Libavcodec external API header.
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:677
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:599
uint16_t offset
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:498
Describe the class of an AVClass context structure.
Definition: log.h:67
#define MAX_SUBSTREAMS
Maximum number of substreams that can be decoded.
Definition: mlp.h:48
#define AV_WL16(p, v)
Definition: intreadwrite.h:412
This structure stores compressed data.
Definition: avcodec.h:1454
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:239