Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * LATM/LOAS muxer | ||
3 | * Copyright (c) 2011 Kieran Kunhya <kieran@kunhya.com> | ||
4 | * | ||
5 | * This file is part of FFmpeg. | ||
6 | * | ||
7 | * FFmpeg is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2.1 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * FFmpeg is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with FFmpeg; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | */ | ||
21 | |||
22 | #include "libavcodec/get_bits.h" | ||
23 | #include "libavcodec/put_bits.h" | ||
24 | #include "libavcodec/codec_id.h" | ||
25 | #include "libavcodec/codec_par.h" | ||
26 | #include "libavcodec/packet.h" | ||
27 | #include "libavcodec/mpeg4audio.h" | ||
28 | #include "libavcodec/mpeg4audio_copy_pce.h" | ||
29 | #include "libavutil/opt.h" | ||
30 | #include "avformat.h" | ||
31 | #include "internal.h" | ||
32 | #include "mux.h" | ||
33 | #include "rawenc.h" | ||
34 | |||
35 | #define MAX_EXTRADATA_SIZE 1024 | ||
36 | |||
37 | typedef struct LATMContext { | ||
38 | AVClass *av_class; | ||
39 | int off; | ||
40 | int channel_conf; | ||
41 | int object_type; | ||
42 | int counter; | ||
43 | int mod; | ||
44 | uint8_t buffer[0x1fff + MAX_EXTRADATA_SIZE + 1024]; | ||
45 | } LATMContext; | ||
46 | |||
47 | static const AVOption options[] = { | ||
48 | {"smc-interval", "StreamMuxConfig interval.", | ||
49 | offsetof(LATMContext, mod), AV_OPT_TYPE_INT, {.i64 = 0x0014}, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM}, | ||
50 | {NULL}, | ||
51 | }; | ||
52 | |||
53 | static const AVClass latm_muxer_class = { | ||
54 | .class_name = "LATM/LOAS muxer", | ||
55 | .item_name = av_default_item_name, | ||
56 | .option = options, | ||
57 | .version = LIBAVUTIL_VERSION_INT, | ||
58 | }; | ||
59 | |||
60 | 1 | static int latm_decode_extradata(AVFormatContext *s, uint8_t *buf, int size) | |
61 | { | ||
62 | 1 | LATMContext *ctx = s->priv_data; | |
63 | MPEG4AudioConfig m4ac; | ||
64 | |||
65 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (size > MAX_EXTRADATA_SIZE) { |
66 | ✗ | av_log(s, AV_LOG_ERROR, "Extradata is larger than currently supported.\n"); | |
67 | ✗ | return AVERROR_INVALIDDATA; | |
68 | } | ||
69 | 1 | ctx->off = avpriv_mpeg4audio_get_config2(&m4ac, buf, size, 1, s); | |
70 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ctx->off < 0) |
71 | ✗ | return ctx->off; | |
72 | |||
73 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | if (ctx->object_type == AOT_ALS && (ctx->off & 7)) { |
74 | // as long as avpriv_mpeg4audio_get_config works correctly this is impossible | ||
75 | ✗ | av_log(s, AV_LOG_ERROR, "BUG: ALS offset is not byte-aligned\n"); | |
76 | ✗ | return AVERROR_INVALIDDATA; | |
77 | } | ||
78 | /* FIXME: are any formats not allowed in LATM? */ | ||
79 | |||
80 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | if (m4ac.object_type > AOT_SBR && m4ac.object_type != AOT_ALS) { |
81 | ✗ | av_log(s, AV_LOG_ERROR, "Muxing MPEG-4 AOT %d in LATM is not supported\n", m4ac.object_type); | |
82 | ✗ | return AVERROR_INVALIDDATA; | |
83 | } | ||
84 | 1 | ctx->channel_conf = m4ac.chan_config; | |
85 | 1 | ctx->object_type = m4ac.object_type; | |
86 | |||
87 | 1 | return 0; | |
88 | } | ||
89 | |||
90 | 1 | static int latm_write_header(AVFormatContext *s) | |
91 | { | ||
92 | 1 | AVCodecParameters *par = s->streams[0]->codecpar; | |
93 | |||
94 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (par->codec_id == AV_CODEC_ID_AAC_LATM) |
95 | ✗ | return 0; | |
96 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | if (par->codec_id != AV_CODEC_ID_AAC && par->codec_id != AV_CODEC_ID_MP4ALS) { |
97 | ✗ | av_log(s, AV_LOG_ERROR, "Only AAC, LATM and ALS are supported\n"); | |
98 | ✗ | return AVERROR(EINVAL); | |
99 | } | ||
100 | |||
101 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
2 | if (par->extradata_size > 0 && |
102 | 1 | latm_decode_extradata(s, par->extradata, par->extradata_size) < 0) | |
103 | ✗ | return AVERROR_INVALIDDATA; | |
104 | |||
105 | 1 | return 0; | |
106 | } | ||
107 | |||
108 | 373 | static void copy_bits(PutBitContext *pb, const uint8_t *src, int length) | |
109 | { | ||
110 | 373 | int words = length >> 4; | |
111 | 373 | int bits = length & 15; | |
112 | int i; | ||
113 |
2/2✓ Branch 0 taken 32698 times.
✓ Branch 1 taken 373 times.
|
33071 | for (i = 0; i < words; i++) |
114 | 32698 | put_bits(pb, 16, AV_RB16(src + 2 * i)); | |
115 |
2/2✓ Branch 0 taken 164 times.
✓ Branch 1 taken 209 times.
|
373 | if (bits) |
116 | 164 | put_bits(pb, bits, AV_RB16(src + 2 * words) >> (16 - bits)); | |
117 | 373 | } | |
118 | |||
119 | 355 | static void latm_write_frame_header(AVFormatContext *s, PutBitContext *bs) | |
120 | { | ||
121 | 355 | LATMContext *ctx = s->priv_data; | |
122 | 355 | AVCodecParameters *par = s->streams[0]->codecpar; | |
123 | int header_size; | ||
124 | |||
125 | /* AudioMuxElement */ | ||
126 | 355 | put_bits(bs, 1, !!ctx->counter); | |
127 | |||
128 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 337 times.
|
355 | if (!ctx->counter) { |
129 | /* StreamMuxConfig */ | ||
130 | 18 | put_bits(bs, 1, 0); /* audioMuxVersion */ | |
131 | 18 | put_bits(bs, 1, 1); /* allStreamsSameTimeFraming */ | |
132 | 18 | put_bits(bs, 6, 0); /* numSubFrames */ | |
133 | 18 | put_bits(bs, 4, 0); /* numProgram */ | |
134 | 18 | put_bits(bs, 3, 0); /* numLayer */ | |
135 | |||
136 | /* AudioSpecificConfig */ | ||
137 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (ctx->object_type == AOT_ALS) { |
138 | ✗ | header_size = (par->extradata_size - (ctx->off >> 3)) * 8; | |
139 | ✗ | copy_bits(bs, &par->extradata[ctx->off >> 3], header_size); | |
140 | } else { | ||
141 | // + 3 assumes not scalable and dependsOnCoreCoder == 0, | ||
142 | // see decode_ga_specific_config in libavcodec/aacdec.c | ||
143 | 18 | copy_bits(bs, par->extradata, ctx->off + 3); | |
144 | |||
145 |
1/2✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
|
18 | if (!ctx->channel_conf) { |
146 | GetBitContext gb; | ||
147 | 18 | int ret = init_get_bits8(&gb, par->extradata, par->extradata_size); | |
148 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | av_assert0(ret >= 0); // extradata size has been checked already, so this should not fail |
149 | 18 | skip_bits_long(&gb, ctx->off + 3); | |
150 | 18 | ff_copy_pce_data(bs, &gb); | |
151 | } | ||
152 | } | ||
153 | |||
154 | 18 | put_bits(bs, 3, 0); /* frameLengthType */ | |
155 | 18 | put_bits(bs, 8, 0xff); /* latmBufferFullness */ | |
156 | |||
157 | 18 | put_bits(bs, 1, 0); /* otherDataPresent */ | |
158 | 18 | put_bits(bs, 1, 0); /* crcCheckPresent */ | |
159 | } | ||
160 | |||
161 | 355 | ctx->counter++; | |
162 | 355 | ctx->counter %= ctx->mod; | |
163 | 355 | } | |
164 | |||
165 | 355 | static int latm_write_packet(AVFormatContext *s, AVPacket *pkt) | |
166 | { | ||
167 | 355 | LATMContext *ctx = s->priv_data; | |
168 | 355 | AVCodecParameters *par = s->streams[0]->codecpar; | |
169 | 355 | AVIOContext *pb = s->pb; | |
170 | PutBitContext bs; | ||
171 | int i, len; | ||
172 | 355 | uint8_t loas_header[] = "\x56\xe0\x00"; | |
173 | |||
174 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 355 times.
|
355 | if (par->codec_id == AV_CODEC_ID_AAC_LATM) |
175 | ✗ | return ff_raw_write_packet(s, pkt); | |
176 | |||
177 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 355 times.
|
355 | if (!par->extradata) { |
178 | ✗ | if(pkt->size > 2 && pkt->data[0] == 0x56 && (pkt->data[1] >> 4) == 0xe && | |
179 | ✗ | (AV_RB16(pkt->data + 1) & 0x1FFF) + 3 == pkt->size) | |
180 | ✗ | return ff_raw_write_packet(s, pkt); | |
181 | else { | ||
182 | uint8_t *side_data; | ||
183 | size_t side_data_size; | ||
184 | int ret; | ||
185 | |||
186 | ✗ | side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, | |
187 | &side_data_size); | ||
188 | ✗ | if (side_data_size) { | |
189 | ✗ | if (latm_decode_extradata(s, side_data, side_data_size) < 0) | |
190 | ✗ | return AVERROR_INVALIDDATA; | |
191 | ✗ | ret = ff_alloc_extradata(par, side_data_size); | |
192 | ✗ | if (ret < 0) | |
193 | ✗ | return ret; | |
194 | ✗ | memcpy(par->extradata, side_data, side_data_size); | |
195 | } else | ||
196 | ✗ | return AVERROR_INVALIDDATA; | |
197 | } | ||
198 | } | ||
199 | |||
200 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 355 times.
|
355 | if (pkt->size > 0x1fff) |
201 | ✗ | goto too_large; | |
202 | |||
203 | 355 | init_put_bits(&bs, ctx->buffer, pkt->size+1024+MAX_EXTRADATA_SIZE); | |
204 | |||
205 | 355 | latm_write_frame_header(s, &bs); | |
206 | |||
207 | /* PayloadLengthInfo() */ | ||
208 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 355 times.
|
361 | for (i = 0; i <= pkt->size-255; i+=255) |
209 | 6 | put_bits(&bs, 8, 255); | |
210 | |||
211 | 355 | put_bits(&bs, 8, pkt->size-i); | |
212 | |||
213 | /* The LATM payload is written unaligned */ | ||
214 | |||
215 | /* PayloadMux() */ | ||
216 |
2/4✓ Branch 0 taken 355 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 355 times.
✗ Branch 3 not taken.
|
355 | if (pkt->size && (pkt->data[0] & 0xe1) == 0x81) { |
217 | // Convert byte-aligned DSE to non-aligned. | ||
218 | // Due to the input format encoding we know that | ||
219 | // it is naturally byte-aligned in the input stream, | ||
220 | // so there are no padding bits to account for. | ||
221 | // To avoid having to add padding bits and rearrange | ||
222 | // the whole stream we just remove the byte-align flag. | ||
223 | // This allows us to remux our FATE AAC samples into latm | ||
224 | // files that are still playable with minimal effort. | ||
225 | 355 | put_bits(&bs, 8, pkt->data[0] & 0xfe); | |
226 | 355 | copy_bits(&bs, pkt->data + 1, 8*pkt->size - 8); | |
227 | } else | ||
228 | ✗ | copy_bits(&bs, pkt->data, 8*pkt->size); | |
229 | |||
230 | 355 | flush_put_bits(&bs); | |
231 | |||
232 | 355 | len = put_bytes_output(&bs); | |
233 | |||
234 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 355 times.
|
355 | if (len > 0x1fff) |
235 | ✗ | goto too_large; | |
236 | |||
237 | 355 | loas_header[1] |= (len >> 8) & 0x1f; | |
238 | 355 | loas_header[2] |= len & 0xff; | |
239 | |||
240 | 355 | avio_write(pb, loas_header, 3); | |
241 | 355 | avio_write(pb, ctx->buffer, len); | |
242 | |||
243 | 355 | return 0; | |
244 | |||
245 | ✗ | too_large: | |
246 | ✗ | av_log(s, AV_LOG_ERROR, "LATM packet size larger than maximum size 0x1fff\n"); | |
247 | ✗ | return AVERROR_INVALIDDATA; | |
248 | } | ||
249 | |||
250 | 1 | static int latm_check_bitstream(AVFormatContext *s, AVStream *st, | |
251 | const AVPacket *pkt) | ||
252 | { | ||
253 | 1 | int ret = 1; | |
254 | |||
255 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (st->codecpar->codec_id == AV_CODEC_ID_AAC) { |
256 |
2/4✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
1 | if (pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) |
257 | ✗ | ret = ff_stream_add_bitstream_filter(st, "aac_adtstoasc", NULL); | |
258 | } | ||
259 | |||
260 | 1 | return ret; | |
261 | } | ||
262 | |||
263 | const FFOutputFormat ff_latm_muxer = { | ||
264 | .p.name = "latm", | ||
265 | .p.long_name = NULL_IF_CONFIG_SMALL("LOAS/LATM"), | ||
266 | .p.mime_type = "audio/MP4A-LATM", | ||
267 | .p.extensions = "latm,loas", | ||
268 | .priv_data_size = sizeof(LATMContext), | ||
269 | .p.audio_codec = AV_CODEC_ID_AAC, | ||
270 | .p.video_codec = AV_CODEC_ID_NONE, | ||
271 | .p.subtitle_codec = AV_CODEC_ID_NONE, | ||
272 | .flags_internal = FF_OFMT_FLAG_MAX_ONE_OF_EACH, | ||
273 | .write_header = latm_write_header, | ||
274 | .write_packet = latm_write_packet, | ||
275 | .p.priv_class = &latm_muxer_class, | ||
276 | .check_bitstream= latm_check_bitstream, | ||
277 | .p.flags = AVFMT_NOTIMESTAMPS, | ||
278 | }; | ||
279 |