FFmpeg
truehd_core.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 {
28  uint8_t bits[4];
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 
49  if (ret < 0)
50  return ret;
51 
52  if (pkt->size < 4) {
54  goto fail;
55  }
56 
57  in_size = (AV_RB16(pkt->data) & 0xFFF) * 2;
58  if (in_size < 4 || in_size > pkt->size) {
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 
73  if (s->hdr.num_substreams > MAX_SUBSTREAMS) {
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;
111  }
112 
113  pkt->data += reduce;
114  out_size -= reduce;
115  pkt->size = out_size;
116 
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)
162 
163  return ret;
164 }
165 
167 {
169  memset(&s->hdr, 0, sizeof(s->hdr));
170 }
171 
172 static const enum AVCodecID codec_ids[] = {
174 };
175 
177  .p.name = "truehd_core",
178  .p.codec_ids = codec_ids,
179  .priv_data_size = sizeof(TrueHDCoreContext),
182 };
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:427
show_bits_long
static unsigned int show_bits_long(GetBitContext *s, int n)
Show 0-32 bits.
Definition: get_bits.h:495
bsf_internal.h
TrueHDCoreContext
Definition: truehd_core.c:33
AVBitStreamFilter::name
const char * name
Definition: bsf.h:112
get_bits_count
static int get_bits_count(const GetBitContext *s)
Definition: get_bits.h:266
out_size
int out_size
Definition: movenc.c:55
truehd_core_filter
static int truehd_core_filter(AVBSFContext *ctx, AVPacket *pkt)
Definition: truehd_core.c:37
AVPacket::data
uint8_t * data
Definition: packet.h:522
TrueHDCoreContext::hdr
MLPHeaderInfo hdr
Definition: truehd_core.c:34
codec_ids
static enum AVCodecID codec_ids[]
Definition: truehd_core.c:172
filter
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
Definition: filter_design.txt:228
AV_CODEC_ID_TRUEHD
@ AV_CODEC_ID_TRUEHD
Definition: codec_id.h:484
AVBSFContext
The bitstream filter state.
Definition: bsf.h:68
get_bits
static unsigned int get_bits(GetBitContext *s, int n)
Read 1-25 bits.
Definition: get_bits.h:335
ff_mlp_checksum16
uint16_t ff_mlp_checksum16(const uint8_t *buf, unsigned int buf_size)
Definition: mlp.c:89
bsf.h
fail
#define fail()
Definition: checkasm.h:179
GetBitContext
Definition: get_bits.h:108
pkt
AVPacket * pkt
Definition: movenc.c:59
init_get_bits8
static int init_get_bits8(GetBitContext *s, const uint8_t *buffer, int byte_size)
Initialize GetBitContext.
Definition: get_bits.h:545
s
#define s(width, name)
Definition: cbs_vp9.c:198
bits
uint8_t bits
Definition: vp3data.h:128
ctx
AVFormatContext * ctx
Definition: movenc.c:48
get_bits.h
ff_truehd_core_bsf
const FFBitStreamFilter ff_truehd_core_bsf
Definition: truehd_core.c:176
FFBitStreamFilter
Definition: bsf_internal.h:27
AV_WB16
#define AV_WB16(p, v)
Definition: intreadwrite.h:403
get_bits1
static unsigned int get_bits1(GetBitContext *s)
Definition: get_bits.h:388
flush
void(* flush)(AVBSFContext *ctx)
Definition: dts2pts.c:367
AVCodecID
AVCodecID
Identify the syntax and semantics of the bitstream.
Definition: codec_id.h:49
AccessUnit::optional
uint16_t optional
Definition: truehd_core.c:30
FFBitStreamFilter::p
AVBitStreamFilter p
The public AVBitStreamFilter.
Definition: bsf_internal.h:31
AVPacket::size
int size
Definition: packet.h:523
truehd_core_flush
static void truehd_core_flush(AVBSFContext *ctx)
Definition: truehd_core.c:166
MAX_SUBSTREAMS
#define MAX_SUBSTREAMS
Maximum number of substreams that can be decoded.
Definition: mlp.h:51
header
static const uint8_t header[24]
Definition: sdr2.c:68
AV_WL16
#define AV_WL16(p, v)
Definition: intreadwrite.h:410
ff_mlp_read_major_sync
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
AccessUnit
Definition: truehd_core.c:27
mlp_parse.h
AV_CODEC_ID_NONE
@ AV_CODEC_ID_NONE
Definition: codec_id.h:50
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
AccessUnit::offset
uint16_t offset
Definition: truehd_core.c:29
AccessUnit::bits
uint8_t bits[4]
Definition: truehd_core.c:28
av_assert1
#define av_assert1(cond)
assert() equivalent, that does not lie in speed critical code.
Definition: avassert.h:56
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
MLPHeaderInfo
Definition: mlp_parse.h:30
ret
ret
Definition: filter_design.txt:187
av_packet_make_writable
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:509
mlp.h
AVPacket
This structure stores compressed data.
Definition: packet.h:499
ff_bsf_get_packet_ref
int ff_bsf_get_packet_ref(AVBSFContext *ctx, AVPacket *pkt)
Called by bitstream filters to get packet for filtering.
Definition: bsf.c:256
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1283
AV_RB16
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:98