00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "libavcodec/get_bits.h"
00023 #include "libavcodec/put_bits.h"
00024 #include "libavcodec/avcodec.h"
00025 #include "libavcodec/mpeg4audio.h"
00026 #include "libavutil/opt.h"
00027 #include "avformat.h"
00028 #include "rawenc.h"
00029
00030 #define MAX_EXTRADATA_SIZE 1024
00031
00032 typedef struct {
00033 AVClass *av_class;
00034 int off;
00035 int channel_conf;
00036 int object_type;
00037 int counter;
00038 int mod;
00039 uint8_t buffer[0x1fff + MAX_EXTRADATA_SIZE + 1024];
00040 } LATMContext;
00041
00042 static const AVOption options[] = {
00043 {"smc-interval", "StreamMuxConfig interval.",
00044 offsetof(LATMContext, mod), AV_OPT_TYPE_INT, {.dbl = 0x0014}, 0x0001, 0xffff, AV_OPT_FLAG_ENCODING_PARAM},
00045 {NULL},
00046 };
00047
00048 static const AVClass latm_muxer_class = {
00049 .class_name = "LATM/LOAS muxer",
00050 .item_name = av_default_item_name,
00051 .option = options,
00052 .version = LIBAVUTIL_VERSION_INT,
00053 };
00054
00055 static int latm_decode_extradata(LATMContext *ctx, uint8_t *buf, int size)
00056 {
00057 MPEG4AudioConfig m4ac;
00058
00059 if (size > MAX_EXTRADATA_SIZE) {
00060 av_log(ctx, AV_LOG_ERROR, "Extradata is larger than currently supported.\n");
00061 return AVERROR_INVALIDDATA;
00062 }
00063 ctx->off = avpriv_mpeg4audio_get_config(&m4ac, buf, size * 8, 1);
00064 if (ctx->off < 0)
00065 return ctx->off;
00066
00067 if (ctx->object_type == AOT_ALS && (ctx->off & 7)) {
00068
00069 av_log(ctx, AV_LOG_ERROR, "BUG: ALS offset is not byte-aligned\n");
00070 return AVERROR_INVALIDDATA;
00071 }
00072
00073
00074 if (m4ac.object_type > AOT_SBR && m4ac.object_type != AOT_ALS) {
00075 av_log(ctx, AV_LOG_ERROR, "Muxing MPEG-4 AOT %d in LATM is not supported\n", m4ac.object_type);
00076 return AVERROR_INVALIDDATA;
00077 }
00078 ctx->channel_conf = m4ac.chan_config;
00079 ctx->object_type = m4ac.object_type;
00080
00081 return 0;
00082 }
00083
00084 static int latm_write_header(AVFormatContext *s)
00085 {
00086 LATMContext *ctx = s->priv_data;
00087 AVCodecContext *avctx = s->streams[0]->codec;
00088
00089 if (avctx->codec_id == CODEC_ID_AAC_LATM)
00090 return 0;
00091
00092 if (avctx->extradata_size > 0 &&
00093 latm_decode_extradata(ctx, avctx->extradata, avctx->extradata_size) < 0)
00094 return AVERROR_INVALIDDATA;
00095
00096 return 0;
00097 }
00098
00099 static void latm_write_frame_header(AVFormatContext *s, PutBitContext *bs)
00100 {
00101 LATMContext *ctx = s->priv_data;
00102 AVCodecContext *avctx = s->streams[0]->codec;
00103 int header_size;
00104
00105
00106 put_bits(bs, 1, !!ctx->counter);
00107
00108 if (!ctx->counter) {
00109
00110 put_bits(bs, 1, 0);
00111 put_bits(bs, 1, 1);
00112 put_bits(bs, 6, 0);
00113 put_bits(bs, 4, 0);
00114 put_bits(bs, 3, 0);
00115
00116
00117 if (ctx->object_type == AOT_ALS) {
00118 header_size = avctx->extradata_size-(ctx->off >> 3);
00119 avpriv_copy_bits(bs, &avctx->extradata[ctx->off >> 3], header_size);
00120 } else {
00121
00122
00123 avpriv_copy_bits(bs, avctx->extradata, ctx->off + 3);
00124
00125 if (!ctx->channel_conf) {
00126 GetBitContext gb;
00127 init_get_bits(&gb, avctx->extradata, avctx->extradata_size * 8);
00128 skip_bits_long(&gb, ctx->off + 3);
00129 avpriv_copy_pce_data(bs, &gb);
00130 }
00131 }
00132
00133 put_bits(bs, 3, 0);
00134 put_bits(bs, 8, 0xff);
00135
00136 put_bits(bs, 1, 0);
00137 put_bits(bs, 1, 0);
00138 }
00139
00140 ctx->counter++;
00141 ctx->counter %= ctx->mod;
00142 }
00143
00144 static int latm_write_packet(AVFormatContext *s, AVPacket *pkt)
00145 {
00146 LATMContext *ctx = s->priv_data;
00147 AVIOContext *pb = s->pb;
00148 PutBitContext bs;
00149 int i, len;
00150 uint8_t loas_header[] = "\x56\xe0\x00";
00151
00152 if (s->streams[0]->codec->codec_id == CODEC_ID_AAC_LATM)
00153 return ff_raw_write_packet(s, pkt);
00154
00155 if (pkt->size > 2 && pkt->data[0] == 0xff && (pkt->data[1] >> 4) == 0xf) {
00156 av_log(s, AV_LOG_ERROR, "ADTS header detected - ADTS will not be incorrectly muxed into LATM\n");
00157 return AVERROR_INVALIDDATA;
00158 }
00159 if (pkt->size > 0x1fff)
00160 goto too_large;
00161
00162 init_put_bits(&bs, ctx->buffer, pkt->size+1024+MAX_EXTRADATA_SIZE);
00163
00164 latm_write_frame_header(s, &bs);
00165
00166
00167 for (i = 0; i <= pkt->size-255; i+=255)
00168 put_bits(&bs, 8, 255);
00169
00170 put_bits(&bs, 8, pkt->size-i);
00171
00172
00173
00174
00175 if (pkt->size && (pkt->data[0] & 0xe1) == 0x81) {
00176
00177
00178
00179
00180
00181
00182
00183
00184 put_bits(&bs, 8, pkt->data[0] & 0xfe);
00185 avpriv_copy_bits(&bs, pkt->data + 1, 8*pkt->size - 8);
00186 } else
00187 avpriv_copy_bits(&bs, pkt->data, 8*pkt->size);
00188
00189 avpriv_align_put_bits(&bs);
00190 flush_put_bits(&bs);
00191
00192 len = put_bits_count(&bs) >> 3;
00193
00194 if (len > 0x1fff)
00195 goto too_large;
00196
00197 loas_header[1] |= (len >> 8) & 0x1f;
00198 loas_header[2] |= len & 0xff;
00199
00200 avio_write(pb, loas_header, 3);
00201 avio_write(pb, ctx->buffer, len);
00202
00203 return 0;
00204
00205 too_large:
00206 av_log(s, AV_LOG_ERROR, "LATM packet size larger than maximum size 0x1fff\n");
00207 return AVERROR_INVALIDDATA;
00208 }
00209
00210 AVOutputFormat ff_latm_muxer = {
00211 .name = "latm",
00212 .long_name = NULL_IF_CONFIG_SMALL("LOAS/LATM"),
00213 .mime_type = "audio/MP4A-LATM",
00214 .extensions = "latm,loas",
00215 .priv_data_size = sizeof(LATMContext),
00216 .audio_codec = CODEC_ID_AAC,
00217 .video_codec = CODEC_ID_NONE,
00218 .write_header = latm_write_header,
00219 .write_packet = latm_write_packet,
00220 .priv_class = &latm_muxer_class,
00221 };