libavformat/adtsenc.c
a283db39
 /*
  * ADTS muxer.
  * Copyright (c) 2006 Baptiste Coudurier <baptiste.coudurier@smartjog.com>
f2250162
  *                    Mans Rullgard <mans@mansr.com>
a283db39
  *
b78e7197
  * This file is part of FFmpeg.
  *
  * FFmpeg is free software; you can redistribute it and/or
a283db39
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
b78e7197
  * version 2.1 of the License, or (at your option) any later version.
a283db39
  *
b78e7197
  * FFmpeg is distributed in the hope that it will be useful,
a283db39
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
b78e7197
  * License along with FFmpeg; if not, write to the Free Software
a283db39
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
245976da
 
9106a698
 #include "libavcodec/get_bits.h"
b2755007
 #include "libavcodec/put_bits.h"
ad925587
 #include "libavcodec/avcodec.h"
5935f9d6
 #include "libavcodec/mpeg4audio.h"
c994b428
 #include "libavutil/opt.h"
a283db39
 #include "avformat.h"
c994b428
 #include "apetag.h"
485d3ea0
 
 #define ADTS_HEADER_SIZE 7
 
 typedef struct {
c994b428
     AVClass *class;
485d3ea0
     int write_adts;
     int objecttype;
     int sample_rate_index;
     int channel_conf;
     int pce_size;
c994b428
     int apetag;
485d3ea0
     uint8_t pce_data[MAX_PCE_SIZE];
 } ADTSContext;
a283db39
 
ac47e014
 #define ADTS_MAX_FRAME_BYTES ((1 << 13) - 1)
 
485d3ea0
 static int adts_decode_extradata(AVFormatContext *s, ADTSContext *adts, uint8_t *buf, int size)
a283db39
 {
     GetBitContext gb;
97d43183
     PutBitContext pb;
5935f9d6
     MPEG4AudioConfig m4ac;
     int off;
a283db39
 
     init_get_bits(&gb, buf, size * 8);
fd095539
     off = avpriv_mpeg4audio_get_config(&m4ac, buf, size * 8, 1);
5935f9d6
     if (off < 0)
         return off;
     skip_bits_long(&gb, off);
     adts->objecttype        = m4ac.object_type - 1;
     adts->sample_rate_index = m4ac.sampling_index;
     adts->channel_conf      = m4ac.chan_config;
a283db39
 
496dcbbc
     if (adts->objecttype > 3U) {
ecc3a139
         av_log(s, AV_LOG_ERROR, "MPEG-4 AOT %d is not allowed in ADTS\n", adts->objecttype+1);
dd44d9e3
         return -1;
     }
     if (adts->sample_rate_index == 15) {
         av_log(s, AV_LOG_ERROR, "Escape sample rate index illegal in ADTS\n");
         return -1;
     }
496dcbbc
     if (get_bits(&gb, 1)) {
         av_log(s, AV_LOG_ERROR, "960/120 MDCT window is not allowed in ADTS\n");
         return -1;
     }
     if (get_bits(&gb, 1)) {
         av_log(s, AV_LOG_ERROR, "Scalable configurations are not allowed in ADTS\n");
         return -1;
     }
7f01a419
     if (get_bits(&gb, 1)) {
         av_log(s, AV_LOG_ERROR, "Extension flag is not allowed in ADTS\n");
         return -1;
     }
97d43183
     if (!adts->channel_conf) {
         init_put_bits(&pb, adts->pce_data, MAX_PCE_SIZE);
 
         put_bits(&pb, 3, 5); //ID_PCE
59a9a235
         adts->pce_size = (avpriv_copy_pce_data(&pb, &gb) + 3) / 8;
97d43183
         flush_put_bits(&pb);
     }
dd44d9e3
 
a283db39
     adts->write_adts = 1;
 
     return 0;
 }
 
 static int adts_write_header(AVFormatContext *s)
 {
     ADTSContext *adts = s->priv_data;
     AVCodecContext *avc = s->streams[0]->codec;
 
cfde3a7e
     if (avc->extradata_size > 0 &&
485d3ea0
             adts_decode_extradata(s, adts, avc->extradata, avc->extradata_size) < 0)
dd44d9e3
         return -1;
a283db39
 
     return 0;
 }
 
485d3ea0
 static int adts_write_frame_header(ADTSContext *ctx,
                                    uint8_t *buf, int size, int pce_size)
a283db39
 {
     PutBitContext pb;
 
ac47e014
     unsigned full_frame_size = (unsigned)ADTS_HEADER_SIZE + size + pce_size;
     if (full_frame_size > ADTS_MAX_FRAME_BYTES) {
         av_log(NULL, AV_LOG_ERROR, "ADTS frame size too large: %u (max %d)\n",
                full_frame_size, ADTS_MAX_FRAME_BYTES);
         return AVERROR_INVALIDDATA;
     }
 
a283db39
     init_put_bits(&pb, buf, ADTS_HEADER_SIZE);
 
     /* adts_fixed_header */
     put_bits(&pb, 12, 0xfff);   /* syncword */
     put_bits(&pb, 1, 0);        /* ID */
     put_bits(&pb, 2, 0);        /* layer */
     put_bits(&pb, 1, 1);        /* protection_absent */
     put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */
     put_bits(&pb, 4, ctx->sample_rate_index);
     put_bits(&pb, 1, 0);        /* private_bit */
     put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */
     put_bits(&pb, 1, 0);        /* original_copy */
     put_bits(&pb, 1, 0);        /* home */
 
     /* adts_variable_header */
     put_bits(&pb, 1, 0);        /* copyright_identification_bit */
     put_bits(&pb, 1, 0);        /* copyright_identification_start */
ac47e014
     put_bits(&pb, 13, full_frame_size); /* aac_frame_length */
a283db39
     put_bits(&pb, 11, 0x7ff);   /* adts_buffer_fullness */
     put_bits(&pb, 2, 0);        /* number_of_raw_data_blocks_in_frame */
 
     flush_put_bits(&pb);
 
     return 0;
 }
 
 static int adts_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     ADTSContext *adts = s->priv_data;
ae628ec1
     AVIOContext *pb = s->pb;
8fdd542c
     uint8_t buf[ADTS_HEADER_SIZE];
a283db39
 
4f6a6e1f
     if (!pkt->size)
         return 0;
cfde3a7e
     if (adts->write_adts) {
485d3ea0
         int err = adts_write_frame_header(adts, buf, pkt->size,
ac47e014
                                              adts->pce_size);
         if (err < 0)
             return err;
77eb5504
         avio_write(pb, buf, ADTS_HEADER_SIZE);
cfde3a7e
         if (adts->pce_size) {
77eb5504
             avio_write(pb, adts->pce_data, adts->pce_size);
8fdd542c
             adts->pce_size = 0;
         }
     }
77eb5504
     avio_write(pb, pkt->data, pkt->size);
a283db39
 
     return 0;
 }
 
c994b428
 static int adts_write_trailer(AVFormatContext *s)
 {
     ADTSContext *adts = s->priv_data;
 
     if (adts->apetag)
         ff_ape_write_tag(s);
 
     return 0;
 }
 
 #define ENC AV_OPT_FLAG_ENCODING_PARAM
 #define OFFSET(obj) offsetof(ADTSContext, obj)
 static const AVOption options[] = {
     { "write_apetag", "Enable APE tag writing", OFFSET(apetag), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, ENC},
     { NULL },
 };
 
 static const AVClass adts_muxer_class = {
     .class_name     = "ADTS muxer",
     .item_name      = av_default_item_name,
     .option         = options,
     .version        = LIBAVUTIL_VERSION_INT,
 };
 
c6610a21
 AVOutputFormat ff_adts_muxer = {
dfc2c4d9
     .name              = "adts",
0177b7d2
     .long_name         = NULL_IF_CONFIG_SMALL("ADTS AAC (Advanced Audio Coding)"),
dfc2c4d9
     .mime_type         = "audio/aac",
     .extensions        = "aac,adts",
     .priv_data_size    = sizeof(ADTSContext),
36ef5369
     .audio_codec       = AV_CODEC_ID_AAC,
     .video_codec       = AV_CODEC_ID_NONE,
dfc2c4d9
     .write_header      = adts_write_header,
     .write_packet      = adts_write_packet,
c994b428
     .write_trailer     = adts_write_trailer,
     .priv_class        = &adts_muxer_class,
a283db39
 };