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 "bsf.h"
22 #include "bsf_internal.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 {
36 
38 {
40  GetBitContext gbc;
42  int ret, i, last_offset = 0;
43  int in_size, out_size;
44  int have_header = 0;
45  int substream_bytes = 0;
46  int end;
47 
48  ret = ff_bsf_get_packet_ref(ctx, pkt);
49  if (ret < 0)
50  return ret;
51 
52  if (pkt->size < 4) {
53  ret = AVERROR_INVALIDDATA;
54  goto fail;
55  }
56 
57  in_size = (AV_RB16(pkt->data) & 0xFFF) * 2;
58  if (in_size < 4 || in_size > pkt->size) {
59  ret = AVERROR_INVALIDDATA;
60  goto fail;
61  }
62 
63  ret = init_get_bits8(&gbc, pkt->data + 4, pkt->size - 4);
64  if (ret < 0)
65  goto fail;
66 
67  if (show_bits_long(&gbc, 32) == 0xf8726fba) {
68  if ((ret = ff_mlp_read_major_sync(ctx, &s->hdr, &gbc)) < 0)
69  goto fail;
70  have_header = 1;
71  }
72 
74  ret = AVERROR_INVALIDDATA;
75  goto fail;
76  }
77 
78  for (i = 0; i < s->hdr.num_substreams; i++) {
79  for (int j = 0; j < 4; j++)
80  units[i].bits[j] = get_bits1(&gbc);
81 
82  units[i].offset = get_bits(&gbc, 12);
83  if (i < 3) {
84  last_offset = units[i].offset * 2;
85  substream_bytes += 2;
86  }
87 
88  if (units[i].bits[0]) {
89  units[i].optional = get_bits(&gbc, 16);
90  if (i < 3)
91  substream_bytes += 2;
92  }
93  }
94  end = get_bits_count(&gbc) >> 3;
95 
96  out_size = end + 4 + last_offset;
97  if (out_size < in_size) {
98  int bpos = 0, reduce = end - have_header * 28 - substream_bytes;
99  uint16_t parity_nibble, dts = AV_RB16(pkt->data + 2);
100  uint16_t auheader;
101  uint8_t header[28];
102 
103  av_assert1(reduce >= 0 && reduce % 2 == 0);
104 
105  if (have_header) {
106  memcpy(header, pkt->data + 4, 28);
107  header[16] = (header[16] & 0x0c) | (FFMIN(s->hdr.num_substreams, 3) << 4);
108  header[17] &= 0x7f;
109  header[25] &= 0xfe;
110  AV_WL16(header + 26, ff_mlp_checksum16(header, 26));
111  }
112 
113  pkt->data += reduce;
114  out_size -= reduce;
115  pkt->size = out_size;
116 
117  ret = av_packet_make_writable(pkt);
118  if (ret < 0)
119  goto fail;
120 
121  AV_WB16(pkt->data + 2, dts);
122  parity_nibble = dts;
123  parity_nibble ^= out_size / 2;
124 
125  for (i = 0; i < FFMIN(s->hdr.num_substreams, 3); i++) {
126  uint16_t substr_hdr = 0;
127 
128  substr_hdr |= (units[i].bits[0] << 15);
129  substr_hdr |= (units[i].bits[1] << 14);
130  substr_hdr |= (units[i].bits[2] << 13);
131  substr_hdr |= (units[i].bits[3] << 12);
132  substr_hdr |= units[i].offset;
133 
134  AV_WB16(pkt->data + have_header * 28 + 4 + bpos, substr_hdr);
135 
136  parity_nibble ^= substr_hdr;
137  bpos += 2;
138 
139  if (units[i].bits[0]) {
140  AV_WB16(pkt->data + have_header * 28 + 4 + bpos, units[i].optional);
141 
142  parity_nibble ^= units[i].optional;
143  bpos += 2;
144  }
145  }
146 
147  parity_nibble ^= parity_nibble >> 8;
148  parity_nibble ^= parity_nibble >> 4;
149  parity_nibble &= 0xF;
150 
151  auheader = (parity_nibble ^ 0xF) << 12;
152  auheader |= (out_size / 2) & 0x0fff;
153  AV_WB16(pkt->data, auheader);
154 
155  if (have_header)
156  memcpy(pkt->data + 4, header, 28);
157  }
158 
159 fail:
160  if (ret < 0)
161  av_packet_unref(pkt);
162 
163  return ret;
164 }
165 
167 {
168  TrueHDCoreContext *s = ctx->priv_data;
169  memset(&s->hdr, 0, sizeof(s->hdr));
170 }
171 
172 static const enum AVCodecID codec_ids[] = {
174 };
175 
177  .name = "truehd_core",
178  .priv_data_size = sizeof(TrueHDCoreContext),
181  .codec_ids = codec_ids,
182 };
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: bsf.h:49
int size
Definition: packet.h:364
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:86
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: bsf.h:70
static void truehd_core_flush(AVBSFContext *ctx)
uint8_t
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:92
const char * name
Definition: bsf.h:99
uint8_t * data
Definition: packet.h:363
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:691
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:46
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:123
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
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:606
uint16_t offset
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:498
#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: packet.h:340
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:252
int i
Definition: input.c:407