xref: /third_party/ffmpeg/libavformat/adtsenc.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * ADTS muxer.
3cabdff1aSopenharmony_ci * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.com>
4cabdff1aSopenharmony_ci *                    Mans Rullgard <mans@mansr.com>
5cabdff1aSopenharmony_ci *
6cabdff1aSopenharmony_ci * This file is part of FFmpeg.
7cabdff1aSopenharmony_ci *
8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
12cabdff1aSopenharmony_ci *
13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16cabdff1aSopenharmony_ci * Lesser General Public License for more details.
17cabdff1aSopenharmony_ci *
18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21cabdff1aSopenharmony_ci */
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_ci#include "libavcodec/get_bits.h"
24cabdff1aSopenharmony_ci#include "libavcodec/put_bits.h"
25cabdff1aSopenharmony_ci#include "libavcodec/codec_id.h"
26cabdff1aSopenharmony_ci#include "libavcodec/codec_par.h"
27cabdff1aSopenharmony_ci#include "libavcodec/packet.h"
28cabdff1aSopenharmony_ci#include "libavcodec/mpeg4audio.h"
29cabdff1aSopenharmony_ci#include "libavutil/opt.h"
30cabdff1aSopenharmony_ci#include "avformat.h"
31cabdff1aSopenharmony_ci#include "apetag.h"
32cabdff1aSopenharmony_ci#include "id3v2.h"
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci#define ADTS_HEADER_SIZE 7
35cabdff1aSopenharmony_ci
36cabdff1aSopenharmony_citypedef struct ADTSContext {
37cabdff1aSopenharmony_ci    AVClass *class;
38cabdff1aSopenharmony_ci    int write_adts;
39cabdff1aSopenharmony_ci    int objecttype;
40cabdff1aSopenharmony_ci    int sample_rate_index;
41cabdff1aSopenharmony_ci    int channel_conf;
42cabdff1aSopenharmony_ci    int pce_size;
43cabdff1aSopenharmony_ci    int apetag;
44cabdff1aSopenharmony_ci    int id3v2tag;
45cabdff1aSopenharmony_ci    int mpeg_id;
46cabdff1aSopenharmony_ci    uint8_t pce_data[MAX_PCE_SIZE];
47cabdff1aSopenharmony_ci} ADTSContext;
48cabdff1aSopenharmony_ci
49cabdff1aSopenharmony_ci#define ADTS_MAX_FRAME_BYTES ((1 << 14) - 1)
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_cistatic int adts_decode_extradata(AVFormatContext *s, ADTSContext *adts, const uint8_t *buf, int size)
52cabdff1aSopenharmony_ci{
53cabdff1aSopenharmony_ci    GetBitContext gb;
54cabdff1aSopenharmony_ci    PutBitContext pb;
55cabdff1aSopenharmony_ci    MPEG4AudioConfig m4ac;
56cabdff1aSopenharmony_ci    int off, ret;
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci    ret = init_get_bits8(&gb, buf, size);
59cabdff1aSopenharmony_ci    if (ret < 0)
60cabdff1aSopenharmony_ci        return ret;
61cabdff1aSopenharmony_ci    off = avpriv_mpeg4audio_get_config2(&m4ac, buf, size, 1, s);
62cabdff1aSopenharmony_ci    if (off < 0)
63cabdff1aSopenharmony_ci        return off;
64cabdff1aSopenharmony_ci    skip_bits_long(&gb, off);
65cabdff1aSopenharmony_ci    adts->objecttype        = m4ac.object_type - 1;
66cabdff1aSopenharmony_ci    adts->sample_rate_index = m4ac.sampling_index;
67cabdff1aSopenharmony_ci    adts->channel_conf      = m4ac.chan_config;
68cabdff1aSopenharmony_ci
69cabdff1aSopenharmony_ci    if (adts->objecttype > 3U) {
70cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "MPEG-4 AOT %d is not allowed in ADTS\n", adts->objecttype+1);
71cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
72cabdff1aSopenharmony_ci    }
73cabdff1aSopenharmony_ci    if (adts->sample_rate_index == 15) {
74cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Escape sample rate index illegal in ADTS\n");
75cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
76cabdff1aSopenharmony_ci    }
77cabdff1aSopenharmony_ci    if (get_bits(&gb, 1)) {
78cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "960/120 MDCT window is not allowed in ADTS\n");
79cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
80cabdff1aSopenharmony_ci    }
81cabdff1aSopenharmony_ci    if (get_bits(&gb, 1)) {
82cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Scalable configurations are not allowed in ADTS\n");
83cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
84cabdff1aSopenharmony_ci    }
85cabdff1aSopenharmony_ci    if (get_bits(&gb, 1)) {
86cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Extension flag is not allowed in ADTS\n");
87cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
88cabdff1aSopenharmony_ci    }
89cabdff1aSopenharmony_ci    if (!adts->channel_conf) {
90cabdff1aSopenharmony_ci        init_put_bits(&pb, adts->pce_data, MAX_PCE_SIZE);
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ci        put_bits(&pb, 3, 5); //ID_PCE
93cabdff1aSopenharmony_ci        adts->pce_size = (ff_copy_pce_data(&pb, &gb) + 3) / 8;
94cabdff1aSopenharmony_ci        flush_put_bits(&pb);
95cabdff1aSopenharmony_ci    }
96cabdff1aSopenharmony_ci
97cabdff1aSopenharmony_ci    adts->write_adts = 1;
98cabdff1aSopenharmony_ci
99cabdff1aSopenharmony_ci    return 0;
100cabdff1aSopenharmony_ci}
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_cistatic int adts_init(AVFormatContext *s)
103cabdff1aSopenharmony_ci{
104cabdff1aSopenharmony_ci    ADTSContext *adts = s->priv_data;
105cabdff1aSopenharmony_ci    AVCodecParameters *par = s->streams[0]->codecpar;
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci    if (par->codec_id != AV_CODEC_ID_AAC) {
108cabdff1aSopenharmony_ci        av_log(s, AV_LOG_ERROR, "Only AAC streams can be muxed by the ADTS muxer\n");
109cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
110cabdff1aSopenharmony_ci    }
111cabdff1aSopenharmony_ci    if (par->extradata_size > 0)
112cabdff1aSopenharmony_ci        return adts_decode_extradata(s, adts, par->extradata,
113cabdff1aSopenharmony_ci                                     par->extradata_size);
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_ci    return 0;
116cabdff1aSopenharmony_ci}
117cabdff1aSopenharmony_ci
118cabdff1aSopenharmony_cistatic int adts_write_header(AVFormatContext *s)
119cabdff1aSopenharmony_ci{
120cabdff1aSopenharmony_ci    ADTSContext *adts = s->priv_data;
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci    if (adts->id3v2tag)
123cabdff1aSopenharmony_ci        ff_id3v2_write_simple(s, 4, ID3v2_DEFAULT_MAGIC);
124cabdff1aSopenharmony_ci
125cabdff1aSopenharmony_ci    return 0;
126cabdff1aSopenharmony_ci}
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_cistatic int adts_write_frame_header(ADTSContext *ctx,
129cabdff1aSopenharmony_ci                                   uint8_t *buf, int size, int pce_size)
130cabdff1aSopenharmony_ci{
131cabdff1aSopenharmony_ci    PutBitContext pb;
132cabdff1aSopenharmony_ci
133cabdff1aSopenharmony_ci    unsigned full_frame_size = (unsigned)ADTS_HEADER_SIZE + size + pce_size;
134cabdff1aSopenharmony_ci    if (full_frame_size > ADTS_MAX_FRAME_BYTES) {
135cabdff1aSopenharmony_ci        av_log(NULL, AV_LOG_ERROR, "ADTS frame size too large: %u (max %d)\n",
136cabdff1aSopenharmony_ci               full_frame_size, ADTS_MAX_FRAME_BYTES);
137cabdff1aSopenharmony_ci        return AVERROR_INVALIDDATA;
138cabdff1aSopenharmony_ci    }
139cabdff1aSopenharmony_ci
140cabdff1aSopenharmony_ci    init_put_bits(&pb, buf, ADTS_HEADER_SIZE);
141cabdff1aSopenharmony_ci
142cabdff1aSopenharmony_ci    /* adts_fixed_header */
143cabdff1aSopenharmony_ci    put_bits(&pb, 12, 0xfff);   /* syncword */
144cabdff1aSopenharmony_ci    put_bits(&pb, 1, ctx->mpeg_id); /* ID */
145cabdff1aSopenharmony_ci    put_bits(&pb, 2, 0);        /* layer */
146cabdff1aSopenharmony_ci    put_bits(&pb, 1, 1);        /* protection_absent */
147cabdff1aSopenharmony_ci    put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */
148cabdff1aSopenharmony_ci    put_bits(&pb, 4, ctx->sample_rate_index);
149cabdff1aSopenharmony_ci    put_bits(&pb, 1, 0);        /* private_bit */
150cabdff1aSopenharmony_ci    put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */
151cabdff1aSopenharmony_ci    put_bits(&pb, 1, 0);        /* original_copy */
152cabdff1aSopenharmony_ci    put_bits(&pb, 1, 0);        /* home */
153cabdff1aSopenharmony_ci
154cabdff1aSopenharmony_ci    /* adts_variable_header */
155cabdff1aSopenharmony_ci    put_bits(&pb, 1, 0);        /* copyright_identification_bit */
156cabdff1aSopenharmony_ci    put_bits(&pb, 1, 0);        /* copyright_identification_start */
157cabdff1aSopenharmony_ci    put_bits(&pb, 13, full_frame_size); /* aac_frame_length */
158cabdff1aSopenharmony_ci    put_bits(&pb, 11, 0x7ff);   /* adts_buffer_fullness */
159cabdff1aSopenharmony_ci    put_bits(&pb, 2, 0);        /* number_of_raw_data_blocks_in_frame */
160cabdff1aSopenharmony_ci
161cabdff1aSopenharmony_ci    flush_put_bits(&pb);
162cabdff1aSopenharmony_ci
163cabdff1aSopenharmony_ci    return 0;
164cabdff1aSopenharmony_ci}
165cabdff1aSopenharmony_ci
166cabdff1aSopenharmony_cistatic int adts_write_packet(AVFormatContext *s, AVPacket *pkt)
167cabdff1aSopenharmony_ci{
168cabdff1aSopenharmony_ci    ADTSContext *adts = s->priv_data;
169cabdff1aSopenharmony_ci    AVCodecParameters *par = s->streams[0]->codecpar;
170cabdff1aSopenharmony_ci    AVIOContext *pb = s->pb;
171cabdff1aSopenharmony_ci    uint8_t buf[ADTS_HEADER_SIZE];
172cabdff1aSopenharmony_ci
173cabdff1aSopenharmony_ci    if (!pkt->size)
174cabdff1aSopenharmony_ci        return 0;
175cabdff1aSopenharmony_ci    if (!par->extradata_size) {
176cabdff1aSopenharmony_ci        uint8_t *side_data;
177cabdff1aSopenharmony_ci        size_t side_data_size;
178cabdff1aSopenharmony_ci        int ret;
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_ci        side_data = av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
181cabdff1aSopenharmony_ci                                            &side_data_size);
182cabdff1aSopenharmony_ci        if (side_data_size) {
183cabdff1aSopenharmony_ci            ret = adts_decode_extradata(s, adts, side_data, side_data_size);
184cabdff1aSopenharmony_ci            if (ret < 0)
185cabdff1aSopenharmony_ci                return ret;
186cabdff1aSopenharmony_ci            ret = ff_alloc_extradata(par, side_data_size);
187cabdff1aSopenharmony_ci            if (ret < 0)
188cabdff1aSopenharmony_ci                return ret;
189cabdff1aSopenharmony_ci            memcpy(par->extradata, side_data, side_data_size);
190cabdff1aSopenharmony_ci        }
191cabdff1aSopenharmony_ci    }
192cabdff1aSopenharmony_ci    if (adts->write_adts) {
193cabdff1aSopenharmony_ci        int err = adts_write_frame_header(adts, buf, pkt->size,
194cabdff1aSopenharmony_ci                                             adts->pce_size);
195cabdff1aSopenharmony_ci        if (err < 0)
196cabdff1aSopenharmony_ci            return err;
197cabdff1aSopenharmony_ci        avio_write(pb, buf, ADTS_HEADER_SIZE);
198cabdff1aSopenharmony_ci        if (adts->pce_size) {
199cabdff1aSopenharmony_ci            avio_write(pb, adts->pce_data, adts->pce_size);
200cabdff1aSopenharmony_ci            adts->pce_size = 0;
201cabdff1aSopenharmony_ci        }
202cabdff1aSopenharmony_ci    }
203cabdff1aSopenharmony_ci    avio_write(pb, pkt->data, pkt->size);
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci    return 0;
206cabdff1aSopenharmony_ci}
207cabdff1aSopenharmony_ci
208cabdff1aSopenharmony_cistatic int adts_write_trailer(AVFormatContext *s)
209cabdff1aSopenharmony_ci{
210cabdff1aSopenharmony_ci    ADTSContext *adts = s->priv_data;
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ci    if (adts->apetag)
213cabdff1aSopenharmony_ci        ff_ape_write_tag(s);
214cabdff1aSopenharmony_ci
215cabdff1aSopenharmony_ci    return 0;
216cabdff1aSopenharmony_ci}
217cabdff1aSopenharmony_ci
218cabdff1aSopenharmony_ci#define ENC AV_OPT_FLAG_ENCODING_PARAM
219cabdff1aSopenharmony_ci#define OFFSET(obj) offsetof(ADTSContext, obj)
220cabdff1aSopenharmony_cistatic const AVOption options[] = {
221cabdff1aSopenharmony_ci    { "write_id3v2",  "Enable ID3v2 tag writing",   OFFSET(id3v2tag), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC},
222cabdff1aSopenharmony_ci    { "write_apetag", "Enable APE tag writing",     OFFSET(apetag),   AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC},
223cabdff1aSopenharmony_ci    { "write_mpeg2",  "Set MPEG version to MPEG-2", OFFSET(mpeg_id),  AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, ENC},
224cabdff1aSopenharmony_ci    { NULL },
225cabdff1aSopenharmony_ci};
226cabdff1aSopenharmony_ci
227cabdff1aSopenharmony_cistatic const AVClass adts_muxer_class = {
228cabdff1aSopenharmony_ci    .class_name     = "ADTS muxer",
229cabdff1aSopenharmony_ci    .item_name      = av_default_item_name,
230cabdff1aSopenharmony_ci    .option         = options,
231cabdff1aSopenharmony_ci    .version        = LIBAVUTIL_VERSION_INT,
232cabdff1aSopenharmony_ci};
233cabdff1aSopenharmony_ci
234cabdff1aSopenharmony_ciconst AVOutputFormat ff_adts_muxer = {
235cabdff1aSopenharmony_ci    .name              = "adts",
236cabdff1aSopenharmony_ci    .long_name         = NULL_IF_CONFIG_SMALL("ADTS AAC (Advanced Audio Coding)"),
237cabdff1aSopenharmony_ci    .mime_type         = "audio/aac",
238cabdff1aSopenharmony_ci    .extensions        = "aac,adts",
239cabdff1aSopenharmony_ci    .priv_data_size    = sizeof(ADTSContext),
240cabdff1aSopenharmony_ci    .audio_codec       = AV_CODEC_ID_AAC,
241cabdff1aSopenharmony_ci    .video_codec       = AV_CODEC_ID_NONE,
242cabdff1aSopenharmony_ci    .init              = adts_init,
243cabdff1aSopenharmony_ci    .write_header      = adts_write_header,
244cabdff1aSopenharmony_ci    .write_packet      = adts_write_packet,
245cabdff1aSopenharmony_ci    .write_trailer     = adts_write_trailer,
246cabdff1aSopenharmony_ci    .priv_class        = &adts_muxer_class,
247cabdff1aSopenharmony_ci    .flags             = AVFMT_NOTIMESTAMPS,
248cabdff1aSopenharmony_ci};
249