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