In ts demuxer, support aac flexmux using extradata in iods, issue #2346
Originally committed as revision 25806 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
parent
91360ce61d
commit
798c6facb7
@ -138,7 +138,7 @@ OBJS-$(CONFIG_MPEG2SVCD_MUXER) += mpegenc.o
|
|||||||
OBJS-$(CONFIG_MPEG1VIDEO_MUXER) += rawenc.o
|
OBJS-$(CONFIG_MPEG1VIDEO_MUXER) += rawenc.o
|
||||||
OBJS-$(CONFIG_MPEG2VIDEO_MUXER) += rawenc.o
|
OBJS-$(CONFIG_MPEG2VIDEO_MUXER) += rawenc.o
|
||||||
OBJS-$(CONFIG_MPEGPS_DEMUXER) += mpeg.o
|
OBJS-$(CONFIG_MPEGPS_DEMUXER) += mpeg.o
|
||||||
OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpegts.o
|
OBJS-$(CONFIG_MPEGTS_DEMUXER) += mpegts.o isom.o
|
||||||
OBJS-$(CONFIG_MPEGTS_MUXER) += mpegtsenc.o adtsenc.o
|
OBJS-$(CONFIG_MPEGTS_MUXER) += mpegtsenc.o adtsenc.o
|
||||||
OBJS-$(CONFIG_MPEGVIDEO_DEMUXER) += mpegvideodec.o rawdec.o
|
OBJS-$(CONFIG_MPEGVIDEO_DEMUXER) += mpegvideodec.o rawdec.o
|
||||||
OBJS-$(CONFIG_MPJPEG_MUXER) += mpjpeg.o
|
OBJS-$(CONFIG_MPJPEG_MUXER) += mpjpeg.o
|
||||||
|
@ -21,9 +21,14 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//#define DEBUG
|
||||||
|
|
||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "isom.h"
|
#include "isom.h"
|
||||||
|
#include "riff.h"
|
||||||
|
#include "libavcodec/mpeg4audio.h"
|
||||||
|
#include "libavcodec/mpegaudiodata.h"
|
||||||
|
|
||||||
/* http://www.mp4ra.org */
|
/* http://www.mp4ra.org */
|
||||||
/* ordered by muxing preference */
|
/* ordered by muxing preference */
|
||||||
@ -326,3 +331,79 @@ int ff_mov_lang_to_iso639(unsigned code, char to[4])
|
|||||||
memcpy(to, mov_mdhd_language_map[code], 4);
|
memcpy(to, mov_mdhd_language_map[code], 4);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ff_mp4_read_descr_len(ByteIOContext *pb)
|
||||||
|
{
|
||||||
|
int len = 0;
|
||||||
|
int count = 4;
|
||||||
|
while (count--) {
|
||||||
|
int c = get_byte(pb);
|
||||||
|
len = (len << 7) | (c & 0x7f);
|
||||||
|
if (!(c & 0x80))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_mp4_read_descr(AVFormatContext *fc, ByteIOContext *pb, int *tag)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
*tag = get_byte(pb);
|
||||||
|
len = ff_mp4_read_descr_len(pb);
|
||||||
|
dprintf(fc, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const AVCodecTag mp4_audio_types[] = {
|
||||||
|
{ CODEC_ID_MP3ON4, AOT_PS }, /* old mp3on4 draft */
|
||||||
|
{ CODEC_ID_MP3ON4, AOT_L1 }, /* layer 1 */
|
||||||
|
{ CODEC_ID_MP3ON4, AOT_L2 }, /* layer 2 */
|
||||||
|
{ CODEC_ID_MP3ON4, AOT_L3 }, /* layer 3 */
|
||||||
|
{ CODEC_ID_MP4ALS, AOT_ALS }, /* MPEG-4 ALS */
|
||||||
|
{ CODEC_ID_NONE, AOT_NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, ByteIOContext *pb)
|
||||||
|
{
|
||||||
|
int len, tag;
|
||||||
|
int object_type_id = get_byte(pb);
|
||||||
|
get_byte(pb); /* stream type */
|
||||||
|
get_be24(pb); /* buffer size db */
|
||||||
|
get_be32(pb); /* max bitrate */
|
||||||
|
get_be32(pb); /* avg bitrate */
|
||||||
|
|
||||||
|
st->codec->codec_id= ff_codec_get_id(ff_mp4_obj_type, object_type_id);
|
||||||
|
dprintf(fc, "esds object type id 0x%02x\n", object_type_id);
|
||||||
|
len = ff_mp4_read_descr(fc, pb, &tag);
|
||||||
|
if (tag == MP4DecSpecificDescrTag) {
|
||||||
|
dprintf(fc, "Specific MPEG4 header len=%d\n", len);
|
||||||
|
if((uint64_t)len > (1<<30))
|
||||||
|
return -1;
|
||||||
|
av_free(st->codec->extradata);
|
||||||
|
st->codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
if (!st->codec->extradata)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
get_buffer(pb, st->codec->extradata, len);
|
||||||
|
st->codec->extradata_size = len;
|
||||||
|
if (st->codec->codec_id == CODEC_ID_AAC) {
|
||||||
|
MPEG4AudioConfig cfg;
|
||||||
|
ff_mpeg4audio_get_config(&cfg, st->codec->extradata,
|
||||||
|
st->codec->extradata_size);
|
||||||
|
st->codec->channels = cfg.channels;
|
||||||
|
if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4
|
||||||
|
st->codec->sample_rate = ff_mpa_freq_tab[cfg.sampling_index];
|
||||||
|
else if (cfg.ext_sample_rate)
|
||||||
|
st->codec->sample_rate = cfg.ext_sample_rate;
|
||||||
|
else
|
||||||
|
st->codec->sample_rate = cfg.sample_rate;
|
||||||
|
dprintf(fc, "mp4a config channels %d obj %d ext obj %d "
|
||||||
|
"sample rate %d ext sample rate %d\n", st->codec->channels,
|
||||||
|
cfg.object_type, cfg.ext_object_type,
|
||||||
|
cfg.sample_rate, cfg.ext_sample_rate);
|
||||||
|
if (!(st->codec->codec_id = ff_codec_get_id(mp4_audio_types,
|
||||||
|
cfg.object_type)))
|
||||||
|
st->codec->codec_id = CODEC_ID_AAC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -142,6 +142,14 @@ typedef struct MOVContext {
|
|||||||
} MOVContext;
|
} MOVContext;
|
||||||
|
|
||||||
int ff_mp4_read_descr_len(ByteIOContext *pb);
|
int ff_mp4_read_descr_len(ByteIOContext *pb);
|
||||||
|
int ff_mp4_read_descr(AVFormatContext *fc, ByteIOContext *pb, int *tag);
|
||||||
|
int ff_mp4_read_dec_config_descr(AVFormatContext *fc, AVStream *st, ByteIOContext *pb);
|
||||||
|
|
||||||
|
#define MP4IODescrTag 0x02
|
||||||
|
#define MP4ESDescrTag 0x03
|
||||||
|
#define MP4DecConfigDescrTag 0x04
|
||||||
|
#define MP4DecSpecificDescrTag 0x05
|
||||||
|
|
||||||
int ff_mov_read_esds(AVFormatContext *fc, ByteIOContext *pb, MOVAtom atom);
|
int ff_mov_read_esds(AVFormatContext *fc, ByteIOContext *pb, MOVAtom atom);
|
||||||
enum CodecID ff_mov_get_lpcm_codec_id(int bps, int flags);
|
enum CodecID ff_mov_get_lpcm_codec_id(int bps, int flags);
|
||||||
|
|
||||||
|
@ -31,8 +31,6 @@
|
|||||||
#include "avformat.h"
|
#include "avformat.h"
|
||||||
#include "riff.h"
|
#include "riff.h"
|
||||||
#include "isom.h"
|
#include "isom.h"
|
||||||
#include "libavcodec/mpeg4audio.h"
|
|
||||||
#include "libavcodec/mpegaudiodata.h"
|
|
||||||
#include "libavcodec/get_bits.h"
|
#include "libavcodec/get_bits.h"
|
||||||
|
|
||||||
#if CONFIG_ZLIB
|
#if CONFIG_ZLIB
|
||||||
@ -462,41 +460,6 @@ static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ff_mp4_read_descr_len(ByteIOContext *pb)
|
|
||||||
{
|
|
||||||
int len = 0;
|
|
||||||
int count = 4;
|
|
||||||
while (count--) {
|
|
||||||
int c = get_byte(pb);
|
|
||||||
len = (len << 7) | (c & 0x7f);
|
|
||||||
if (!(c & 0x80))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mp4_read_descr(AVFormatContext *fc, ByteIOContext *pb, int *tag)
|
|
||||||
{
|
|
||||||
int len;
|
|
||||||
*tag = get_byte(pb);
|
|
||||||
len = ff_mp4_read_descr_len(pb);
|
|
||||||
dprintf(fc, "MPEG4 description: tag=0x%02x len=%d\n", *tag, len);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MP4ESDescrTag 0x03
|
|
||||||
#define MP4DecConfigDescrTag 0x04
|
|
||||||
#define MP4DecSpecificDescrTag 0x05
|
|
||||||
|
|
||||||
static const AVCodecTag mp4_audio_types[] = {
|
|
||||||
{ CODEC_ID_MP3ON4, AOT_PS }, /* old mp3on4 draft */
|
|
||||||
{ CODEC_ID_MP3ON4, AOT_L1 }, /* layer 1 */
|
|
||||||
{ CODEC_ID_MP3ON4, AOT_L2 }, /* layer 2 */
|
|
||||||
{ CODEC_ID_MP3ON4, AOT_L3 }, /* layer 3 */
|
|
||||||
{ CODEC_ID_MP4ALS, AOT_ALS }, /* MPEG-4 ALS */
|
|
||||||
{ CODEC_ID_NONE, AOT_NULL },
|
|
||||||
};
|
|
||||||
|
|
||||||
int ff_mov_read_esds(AVFormatContext *fc, ByteIOContext *pb, MOVAtom atom)
|
int ff_mov_read_esds(AVFormatContext *fc, ByteIOContext *pb, MOVAtom atom)
|
||||||
{
|
{
|
||||||
AVStream *st;
|
AVStream *st;
|
||||||
@ -507,55 +470,16 @@ int ff_mov_read_esds(AVFormatContext *fc, ByteIOContext *pb, MOVAtom atom)
|
|||||||
st = fc->streams[fc->nb_streams-1];
|
st = fc->streams[fc->nb_streams-1];
|
||||||
|
|
||||||
get_be32(pb); /* version + flags */
|
get_be32(pb); /* version + flags */
|
||||||
len = mp4_read_descr(fc, pb, &tag);
|
len = ff_mp4_read_descr(fc, pb, &tag);
|
||||||
if (tag == MP4ESDescrTag) {
|
if (tag == MP4ESDescrTag) {
|
||||||
get_be16(pb); /* ID */
|
get_be16(pb); /* ID */
|
||||||
get_byte(pb); /* priority */
|
get_byte(pb); /* priority */
|
||||||
} else
|
} else
|
||||||
get_be16(pb); /* ID */
|
get_be16(pb); /* ID */
|
||||||
|
|
||||||
len = mp4_read_descr(fc, pb, &tag);
|
len = ff_mp4_read_descr(fc, pb, &tag);
|
||||||
if (tag == MP4DecConfigDescrTag) {
|
if (tag == MP4DecConfigDescrTag)
|
||||||
int object_type_id = get_byte(pb);
|
ff_mp4_read_dec_config_descr(fc, st, pb);
|
||||||
get_byte(pb); /* stream type */
|
|
||||||
get_be24(pb); /* buffer size db */
|
|
||||||
get_be32(pb); /* max bitrate */
|
|
||||||
get_be32(pb); /* avg bitrate */
|
|
||||||
|
|
||||||
st->codec->codec_id= ff_codec_get_id(ff_mp4_obj_type, object_type_id);
|
|
||||||
dprintf(fc, "esds object type id 0x%02x\n", object_type_id);
|
|
||||||
len = mp4_read_descr(fc, pb, &tag);
|
|
||||||
if (tag == MP4DecSpecificDescrTag) {
|
|
||||||
dprintf(fc, "Specific MPEG4 header len=%d\n", len);
|
|
||||||
if((uint64_t)len > (1<<30))
|
|
||||||
return -1;
|
|
||||||
av_free(st->codec->extradata);
|
|
||||||
st->codec->extradata = av_mallocz(len + FF_INPUT_BUFFER_PADDING_SIZE);
|
|
||||||
if (!st->codec->extradata)
|
|
||||||
return AVERROR(ENOMEM);
|
|
||||||
get_buffer(pb, st->codec->extradata, len);
|
|
||||||
st->codec->extradata_size = len;
|
|
||||||
if (st->codec->codec_id == CODEC_ID_AAC) {
|
|
||||||
MPEG4AudioConfig cfg;
|
|
||||||
ff_mpeg4audio_get_config(&cfg, st->codec->extradata,
|
|
||||||
st->codec->extradata_size);
|
|
||||||
st->codec->channels = cfg.channels;
|
|
||||||
if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4
|
|
||||||
st->codec->sample_rate = ff_mpa_freq_tab[cfg.sampling_index];
|
|
||||||
else if (cfg.ext_sample_rate)
|
|
||||||
st->codec->sample_rate = cfg.ext_sample_rate;
|
|
||||||
else
|
|
||||||
st->codec->sample_rate = cfg.sample_rate;
|
|
||||||
dprintf(fc, "mp4a config channels %d obj %d ext obj %d "
|
|
||||||
"sample rate %d ext sample rate %d\n", st->codec->channels,
|
|
||||||
cfg.object_type, cfg.ext_object_type,
|
|
||||||
cfg.sample_rate, cfg.ext_sample_rate);
|
|
||||||
if (!(st->codec->codec_id = ff_codec_get_id(mp4_audio_types,
|
|
||||||
cfg.object_type)))
|
|
||||||
st->codec->codec_id = CODEC_ID_AAC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "mpegts.h"
|
#include "mpegts.h"
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "seek.h"
|
#include "seek.h"
|
||||||
|
#include "isom.h"
|
||||||
|
|
||||||
/* 1.0 second at 24Mbit/s */
|
/* 1.0 second at 24Mbit/s */
|
||||||
#define MAX_SCAN_PACKETS 32000
|
#define MAX_SCAN_PACKETS 32000
|
||||||
@ -852,6 +853,42 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid)
|
|||||||
return pes;
|
return pes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mp4_read_iods(AVFormatContext *s, uint8_t *buf, unsigned size,
|
||||||
|
uint16_t *es_id, uint8_t **dec_config_descr,
|
||||||
|
int *dec_config_descr_size)
|
||||||
|
{
|
||||||
|
ByteIOContext pb;
|
||||||
|
int tag;
|
||||||
|
unsigned len;
|
||||||
|
|
||||||
|
init_put_byte(&pb, buf, size, 0, NULL, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
len = ff_mp4_read_descr(s, &pb, &tag);
|
||||||
|
if (tag == MP4IODescrTag) {
|
||||||
|
get_be16(&pb); // ID
|
||||||
|
get_byte(&pb);
|
||||||
|
get_byte(&pb);
|
||||||
|
get_byte(&pb);
|
||||||
|
get_byte(&pb);
|
||||||
|
get_byte(&pb);
|
||||||
|
len = ff_mp4_read_descr(s, &pb, &tag);
|
||||||
|
if (tag == MP4ESDescrTag) {
|
||||||
|
*es_id = get_be16(&pb); /* ES_ID */
|
||||||
|
dprintf(s, "ES_ID %#x\n", *es_id);
|
||||||
|
get_byte(&pb); /* priority */
|
||||||
|
len = ff_mp4_read_descr(s, &pb, &tag);
|
||||||
|
if (tag == MP4DecConfigDescrTag) {
|
||||||
|
*dec_config_descr = av_malloc(len);
|
||||||
|
if (!*dec_config_descr)
|
||||||
|
return AVERROR(ENOMEM);
|
||||||
|
*dec_config_descr_size = len;
|
||||||
|
get_buffer(&pb, *dec_config_descr, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
|
static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len)
|
||||||
{
|
{
|
||||||
MpegTSContext *ts = filter->u.section_filter.opaque;
|
MpegTSContext *ts = filter->u.section_filter.opaque;
|
||||||
@ -863,6 +900,9 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
|
|||||||
int desc_list_len, desc_len, desc_tag;
|
int desc_list_len, desc_len, desc_tag;
|
||||||
char language[4];
|
char language[4];
|
||||||
uint32_t prog_reg_desc = 0; /* registration descriptor */
|
uint32_t prog_reg_desc = 0; /* registration descriptor */
|
||||||
|
uint8_t *mp4_dec_config_descr = NULL;
|
||||||
|
int mp4_dec_config_descr_len = 0;
|
||||||
|
int mp4_es_id = 0;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
dprintf(ts->stream, "PMT: len %i\n", section_len);
|
dprintf(ts->stream, "PMT: len %i\n", section_len);
|
||||||
@ -895,11 +935,20 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
|
|||||||
uint8_t tag, len;
|
uint8_t tag, len;
|
||||||
tag = get8(&p, p_end);
|
tag = get8(&p, p_end);
|
||||||
len = get8(&p, p_end);
|
len = get8(&p, p_end);
|
||||||
|
|
||||||
|
dprintf(ts->stream, "program tag: 0x%02x len=%d\n", tag, len);
|
||||||
|
|
||||||
if(len > program_info_length - 2)
|
if(len > program_info_length - 2)
|
||||||
//something else is broken, exit the program_descriptors_loop
|
//something else is broken, exit the program_descriptors_loop
|
||||||
break;
|
break;
|
||||||
program_info_length -= len + 2;
|
program_info_length -= len + 2;
|
||||||
if(tag == 0x05 && len >= 4) { // registration descriptor
|
if (tag == 0x1d) { // IOD descriptor
|
||||||
|
get8(&p, p_end); // scope
|
||||||
|
get8(&p, p_end); // label
|
||||||
|
len -= 2;
|
||||||
|
mp4_read_iods(ts->stream, p, len, &mp4_es_id,
|
||||||
|
&mp4_dec_config_descr, &mp4_dec_config_descr_len);
|
||||||
|
} else if (tag == 0x05 && len >= 4) { // registration descriptor
|
||||||
prog_reg_desc = bytestream_get_le32(&p);
|
prog_reg_desc = bytestream_get_le32(&p);
|
||||||
len -= 4;
|
len -= 4;
|
||||||
}
|
}
|
||||||
@ -968,6 +1017,19 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
|
|||||||
mpegts_find_stream_type(st, desc_tag, DESC_types);
|
mpegts_find_stream_type(st, desc_tag, DESC_types);
|
||||||
|
|
||||||
switch(desc_tag) {
|
switch(desc_tag) {
|
||||||
|
case 0x1F: /* FMC descriptor */
|
||||||
|
get16(&p, desc_end);
|
||||||
|
if (st->codec->codec_id == CODEC_ID_AAC_LATM &&
|
||||||
|
mp4_dec_config_descr_len && mp4_es_id == pid) {
|
||||||
|
ByteIOContext pb;
|
||||||
|
init_put_byte(&pb, mp4_dec_config_descr,
|
||||||
|
mp4_dec_config_descr_len, 0, NULL, NULL, NULL, NULL);
|
||||||
|
ff_mp4_read_dec_config_descr(ts->stream, st, &pb);
|
||||||
|
if (st->codec->codec_id == CODEC_ID_AAC &&
|
||||||
|
st->codec->extradata_size > 0)
|
||||||
|
st->need_parsing = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 0x56: /* DVB teletext descriptor */
|
case 0x56: /* DVB teletext descriptor */
|
||||||
language[0] = get8(&p, desc_end);
|
language[0] = get8(&p, desc_end);
|
||||||
language[1] = get8(&p, desc_end);
|
language[1] = get8(&p, desc_end);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user