PageRenderTime 30ms CodeModel.GetById 16ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/libavformat/adtsenc.c

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