diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index f7532f74bf..d286361066 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -313,6 +313,8 @@ enum CodecID { /* other specific kind of codecs (generally used for attachments) */ CODEC_ID_TTF= 0x18000, + CODEC_ID_PROBE= 0x19000, ///< codec_id is not known (like CODEC_ID_NONE) but lavf should attempt to identify it + CODEC_ID_MPEG2TS= 0x20000, /**< _FAKE_ codec to indicate a raw MPEG-2 TS * stream (only used by libavformat) */ }; diff --git a/libavformat/asf.c b/libavformat/asf.c index dc6557402a..f285b73903 100644 --- a/libavformat/asf.c +++ b/libavformat/asf.c @@ -264,7 +264,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap) if (is_dvr_ms_audio) { // codec_id and codec_tag are unreliable in dvr_ms // files. Set them later by probing stream. - st->codec->codec_id = CODEC_ID_NONE; + st->codec->codec_id = CODEC_ID_PROBE; st->codec->codec_tag = 0; } st->need_parsing = AVSTREAM_PARSE_FULL; diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 500c0cf377..23450af1bd 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -391,6 +391,8 @@ typedef struct AVStream { char *filename; /**< source filename of the stream */ int disposition; /**< AV_DISPOSITION_* bitfield */ + + AVProbeData probe_data; } AVStream; #define AV_PROGRAM_RUNNING 1 @@ -555,6 +557,14 @@ typedef struct AVFormatContext { */ int debug; #define FF_FDEBUG_TS 0x0001 + + /** + * raw packets from the demuxer, prior to parsing and decoding. + * This buffer is used for buffering packets until the codec can + * be identified, as parsing cannot be done without knowing the + * codec. + */ + struct AVPacketList *raw_packet_buffer; } AVFormatContext; typedef struct AVPacketList { diff --git a/libavformat/utils.c b/libavformat/utils.c index 329228db92..4faef19dee 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -540,12 +540,30 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret; AVStream *st; + + for(;;){ + AVPacketList *pktl = s->raw_packet_buffer; + + if (pktl) { + *pkt = pktl->pkt; + if(s->streams[pkt->stream_index]->codec->codec_id != CODEC_ID_PROBE){ + s->raw_packet_buffer = pktl->next; + av_free(pktl); + return 0; + } + } + av_init_packet(pkt); ret= s->iformat->read_packet(s, pkt); if (ret < 0) return ret; st= s->streams[pkt->stream_index]; + if(!pktl && st->codec->codec_id!=CODEC_ID_PROBE) + return ret; + + add_to_pktbuf(&s->raw_packet_buffer, pkt); + switch(st->codec->codec_type){ case CODEC_TYPE_VIDEO: if(s->video_codec_id) st->codec->codec_id= s->video_codec_id; @@ -558,7 +576,21 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) break; } - return ret; + if(st->codec->codec_id == CODEC_ID_PROBE){ + AVProbeData *pd = &st->probe_data; + + pd->buf = av_realloc(pd->buf, pd->buf_size+pkt->size+AVPROBE_PADDING_SIZE); + memcpy(pd->buf+pd->buf_size, pkt->data, pkt->size); + pd->buf_size += pkt->size; + memset(pd->buf+pd->buf_size, 0, AVPROBE_PADDING_SIZE); + + set_codec_from_probe_data(st, pd, 1); + if(st->codec->codec_id != CODEC_ID_PROBE){ + pd->buf_size=0; + av_freep(&pd->buf); + } + } + } } /**********************************************************/