Originally committed as revision 26104 to svn://svn.ffmpeg.org/ffmpeg/trunktags/n0.8
@@ -13,6 +13,9 @@ libavutil: 2009-03-08 | |||||
API changes, most recent first: | API changes, most recent first: | ||||
2010-12-XX - r26104 - lavformat 52.91.0 - av_find_best_stream() | |||||
Add av_find_best_stream to libavformat/avformat.h. | |||||
2010-12-27 - r26103 - lavf 52.90.0 | 2010-12-27 - r26103 - lavf 52.90.0 | ||||
Add AVFMT_NOSTREAMS flag for formats with no streams, | Add AVFMT_NOSTREAMS flag for formats with no streams, | ||||
like e.g. text metadata. | like e.g. text metadata. | ||||
@@ -22,7 +22,7 @@ | |||||
#define AVFORMAT_AVFORMAT_H | #define AVFORMAT_AVFORMAT_H | ||||
#define LIBAVFORMAT_VERSION_MAJOR 52 | #define LIBAVFORMAT_VERSION_MAJOR 52 | ||||
#define LIBAVFORMAT_VERSION_MINOR 90 | |||||
#define LIBAVFORMAT_VERSION_MINOR 91 | |||||
#define LIBAVFORMAT_VERSION_MICRO 0 | #define LIBAVFORMAT_VERSION_MICRO 0 | ||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ | ||||
@@ -1140,6 +1140,37 @@ AVFormatContext *avformat_alloc_context(void); | |||||
*/ | */ | ||||
int av_find_stream_info(AVFormatContext *ic); | int av_find_stream_info(AVFormatContext *ic); | ||||
/** | |||||
* Find the "best" stream in the file. | |||||
* The best stream is determined according to various heuristics as the most | |||||
* likely to be what the user expects. | |||||
* If the decoder parameter is non-NULL, av_find_best_stream will find the | |||||
* default decoder for the stream's codec; streams for which no decoder can | |||||
* be found are ignored. | |||||
* | |||||
* @param ic media file handle | |||||
* @param type stream type: video, audio, subtitles, etc. | |||||
* @param wanted_stream_nb user-requested stream number, | |||||
* or -1 for automatic selection | |||||
* @param related_stream try to find a stream related (eg. in the same | |||||
* program) to this one, or -1 if none | |||||
* @param decoder_ret if non-NULL, returns the decoder for the | |||||
* selected stream | |||||
* @param flags flags; none are currently defined | |||||
* @return the non-negative stream number in case of success, | |||||
* AVERROR_STREAM_NOT_FOUND if no stream with the requested type | |||||
* could be found, | |||||
* AVERROR_DECODER_NOT_FOUND if streams were found but no decoder | |||||
* @note If av_find_best_stream returns successfully and decoder_ret is not | |||||
* NULL, then *decoder_ret is guaranteed to be set to a valid AVCodec. | |||||
*/ | |||||
int av_find_best_stream(AVFormatContext *ic, | |||||
enum AVMediaType type, | |||||
int wanted_stream_nb, | |||||
int related_stream, | |||||
AVCodec **decoder_ret, | |||||
int flags); | |||||
/** | /** | ||||
* Read a transport packet from a media file. | * Read a transport packet from a media file. | ||||
* | * | ||||
@@ -2458,6 +2458,67 @@ int av_find_stream_info(AVFormatContext *ic) | |||||
return ret; | return ret; | ||||
} | } | ||||
static AVProgram *find_program_from_stream(AVFormatContext *ic, int s) | |||||
{ | |||||
int i, j; | |||||
for (i = 0; i < ic->nb_programs; i++) | |||||
for (j = 0; j < ic->programs[i]->nb_stream_indexes; j++) | |||||
if (ic->programs[i]->stream_index[j] == s) | |||||
return ic->programs[i]; | |||||
return NULL; | |||||
} | |||||
int av_find_best_stream(AVFormatContext *ic, | |||||
enum AVMediaType type, | |||||
int wanted_stream_nb, | |||||
int related_stream, | |||||
AVCodec **decoder_ret, | |||||
int flags) | |||||
{ | |||||
int i, nb_streams = ic->nb_streams, stream_number = 0; | |||||
int ret = AVERROR_STREAM_NOT_FOUND, best_count = -1; | |||||
unsigned *program = NULL; | |||||
AVCodec *decoder = NULL, *best_decoder = NULL; | |||||
if (related_stream >= 0 && wanted_stream_nb < 0) { | |||||
AVProgram *p = find_program_from_stream(ic, related_stream); | |||||
if (p) { | |||||
program = p->stream_index; | |||||
nb_streams = p->nb_stream_indexes; | |||||
} | |||||
} | |||||
for (i = 0; i < nb_streams; i++) { | |||||
AVStream *st = ic->streams[program ? program[i] : i]; | |||||
AVCodecContext *avctx = st->codec; | |||||
if (avctx->codec_type != type) | |||||
continue; | |||||
if (wanted_stream_nb >= 0 && stream_number++ != wanted_stream_nb) | |||||
continue; | |||||
if (decoder_ret) { | |||||
decoder = avcodec_find_decoder(ic->streams[i]->codec->codec_id); | |||||
if (!decoder) { | |||||
if (ret < 0) | |||||
ret = AVERROR_DECODER_NOT_FOUND; | |||||
continue; | |||||
} | |||||
} | |||||
if (best_count >= st->codec_info_nb_frames) | |||||
continue; | |||||
best_count = st->codec_info_nb_frames; | |||||
ret = i; | |||||
best_decoder = decoder; | |||||
if (program && i == nb_streams - 1 && ret < 0) { | |||||
program = NULL; | |||||
nb_streams = ic->nb_streams; | |||||
i = 0; /* no related stream found, try again with everything */ | |||||
} | |||||
} | |||||
if (decoder_ret) | |||||
*decoder_ret = best_decoder; | |||||
return ret; | |||||
} | |||||
/*******************************************************/ | /*******************************************************/ | ||||
int av_read_play(AVFormatContext *s) | int av_read_play(AVFormatContext *s) | ||||