FFmpeg
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
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_WL32 unsigned int_TMPL AV_WL24 unsigned int_TMPL AV_WL16 uint64_t_TMPL AV_WB64 unsigned int_TMPL AV_WB32 unsigned int_TMPL AV_WB24 unsigned int_TMPL AV_RB16
Definition: bytestream.h:87
void * priv_data
Opaque filter-specific private data.
Definition: avcodec.h:5784
static void truehd_core_flush(AVBSFContext *ctx)
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
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce then the filter should push the output frames on the output link immediately As an exception to the previous rule if the input frame is enough to produce several output frames then the filter needs output only at least one per link The additional frames can be left buffered in the filter
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:238