avformat/utils: Move av_find_best_stream to avformat.c
It is not forbidden to call this with a muxer, so it is moved to avformat.c and not demux_utils.c. ff_find_decoder(), which is used by av_find_best_stream() is also moved as well, despite being even more geared towards demuxers. Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@outlook.com>
This commit is contained in:
parent
e00d0ef46d
commit
8e2f48ff78
@ -312,6 +312,72 @@ int av_find_default_stream_index(AVFormatContext *s)
|
|||||||
return best_stream;
|
return best_stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,
|
||||||
|
int wanted_stream_nb, int related_stream,
|
||||||
|
const AVCodec **decoder_ret, int flags)
|
||||||
|
{
|
||||||
|
int nb_streams = ic->nb_streams;
|
||||||
|
int ret = AVERROR_STREAM_NOT_FOUND;
|
||||||
|
int best_count = -1, best_multiframe = -1, best_disposition = -1;
|
||||||
|
int count, multiframe, disposition;
|
||||||
|
int64_t best_bitrate = -1;
|
||||||
|
int64_t bitrate;
|
||||||
|
unsigned *program = NULL;
|
||||||
|
const AVCodec *decoder = NULL, *best_decoder = NULL;
|
||||||
|
|
||||||
|
if (related_stream >= 0 && wanted_stream_nb < 0) {
|
||||||
|
AVProgram *p = av_find_program_from_stream(ic, NULL, related_stream);
|
||||||
|
if (p) {
|
||||||
|
program = p->stream_index;
|
||||||
|
nb_streams = p->nb_stream_indexes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < nb_streams; i++) {
|
||||||
|
int real_stream_index = program ? program[i] : i;
|
||||||
|
AVStream *st = ic->streams[real_stream_index];
|
||||||
|
AVCodecParameters *par = st->codecpar;
|
||||||
|
if (par->codec_type != type)
|
||||||
|
continue;
|
||||||
|
if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb)
|
||||||
|
continue;
|
||||||
|
if (type == AVMEDIA_TYPE_AUDIO && !(par->ch_layout.nb_channels && par->sample_rate))
|
||||||
|
continue;
|
||||||
|
if (decoder_ret) {
|
||||||
|
decoder = ff_find_decoder(ic, st, par->codec_id);
|
||||||
|
if (!decoder) {
|
||||||
|
if (ret < 0)
|
||||||
|
ret = AVERROR_DECODER_NOT_FOUND;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
disposition = !(st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED | AV_DISPOSITION_VISUAL_IMPAIRED))
|
||||||
|
+ !! (st->disposition & AV_DISPOSITION_DEFAULT);
|
||||||
|
count = ffstream(st)->codec_info_nb_frames;
|
||||||
|
bitrate = par->bit_rate;
|
||||||
|
multiframe = FFMIN(5, count);
|
||||||
|
if ((best_disposition > disposition) ||
|
||||||
|
(best_disposition == disposition && best_multiframe > multiframe) ||
|
||||||
|
(best_disposition == disposition && best_multiframe == multiframe && best_bitrate > bitrate) ||
|
||||||
|
(best_disposition == disposition && best_multiframe == multiframe && best_bitrate == bitrate && best_count >= count))
|
||||||
|
continue;
|
||||||
|
best_disposition = disposition;
|
||||||
|
best_count = count;
|
||||||
|
best_bitrate = bitrate;
|
||||||
|
best_multiframe = multiframe;
|
||||||
|
ret = real_stream_index;
|
||||||
|
best_decoder = decoder;
|
||||||
|
if (program && i == nb_streams - 1 && ret < 0) {
|
||||||
|
program = NULL;
|
||||||
|
nb_streams = ic->nb_streams;
|
||||||
|
/* no related stream found, try again with everything */
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (decoder_ret)
|
||||||
|
*decoder_ret = best_decoder;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches a stream specifier (but ignores requested index).
|
* Matches a stream specifier (but ignores requested index).
|
||||||
*
|
*
|
||||||
@ -595,3 +661,21 @@ AVRational av_stream_get_codec_timebase(const AVStream *st)
|
|||||||
// See avformat_transfer_internal_stream_timing_info() TODO.
|
// See avformat_transfer_internal_stream_timing_info() TODO.
|
||||||
return cffstream(st)->avctx->time_base;
|
return cffstream(st)->avctx->time_base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st,
|
||||||
|
enum AVCodecID codec_id)
|
||||||
|
{
|
||||||
|
switch (st->codecpar->codec_type) {
|
||||||
|
case AVMEDIA_TYPE_VIDEO:
|
||||||
|
if (s->video_codec) return s->video_codec;
|
||||||
|
break;
|
||||||
|
case AVMEDIA_TYPE_AUDIO:
|
||||||
|
if (s->audio_codec) return s->audio_codec;
|
||||||
|
break;
|
||||||
|
case AVMEDIA_TYPE_SUBTITLE:
|
||||||
|
if (s->subtitle_codec) return s->subtitle_codec;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return avcodec_find_decoder(codec_id);
|
||||||
|
}
|
||||||
|
@ -76,24 +76,6 @@ int ff_copy_whiteblacklists(AVFormatContext *dst, const AVFormatContext *src)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AVCodec *ff_find_decoder(AVFormatContext *s, const AVStream *st,
|
|
||||||
enum AVCodecID codec_id)
|
|
||||||
{
|
|
||||||
switch (st->codecpar->codec_type) {
|
|
||||||
case AVMEDIA_TYPE_VIDEO:
|
|
||||||
if (s->video_codec) return s->video_codec;
|
|
||||||
break;
|
|
||||||
case AVMEDIA_TYPE_AUDIO:
|
|
||||||
if (s->audio_codec) return s->audio_codec;
|
|
||||||
break;
|
|
||||||
case AVMEDIA_TYPE_SUBTITLE:
|
|
||||||
if (s->subtitle_codec) return s->subtitle_codec;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return avcodec_find_decoder(codec_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* an arbitrarily chosen "sane" max packet size -- 50M */
|
/* an arbitrarily chosen "sane" max packet size -- 50M */
|
||||||
#define SANE_CHUNK_SIZE (50000000)
|
#define SANE_CHUNK_SIZE (50000000)
|
||||||
|
|
||||||
@ -305,72 +287,6 @@ int ff_alloc_extradata(AVCodecParameters *par, int size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int av_find_best_stream(AVFormatContext *ic, enum AVMediaType type,
|
|
||||||
int wanted_stream_nb, int related_stream,
|
|
||||||
const AVCodec **decoder_ret, int flags)
|
|
||||||
{
|
|
||||||
int nb_streams = ic->nb_streams;
|
|
||||||
int ret = AVERROR_STREAM_NOT_FOUND;
|
|
||||||
int best_count = -1, best_multiframe = -1, best_disposition = -1;
|
|
||||||
int count, multiframe, disposition;
|
|
||||||
int64_t best_bitrate = -1;
|
|
||||||
int64_t bitrate;
|
|
||||||
unsigned *program = NULL;
|
|
||||||
const AVCodec *decoder = NULL, *best_decoder = NULL;
|
|
||||||
|
|
||||||
if (related_stream >= 0 && wanted_stream_nb < 0) {
|
|
||||||
AVProgram *p = av_find_program_from_stream(ic, NULL, related_stream);
|
|
||||||
if (p) {
|
|
||||||
program = p->stream_index;
|
|
||||||
nb_streams = p->nb_stream_indexes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (unsigned i = 0; i < nb_streams; i++) {
|
|
||||||
int real_stream_index = program ? program[i] : i;
|
|
||||||
AVStream *st = ic->streams[real_stream_index];
|
|
||||||
AVCodecParameters *par = st->codecpar;
|
|
||||||
if (par->codec_type != type)
|
|
||||||
continue;
|
|
||||||
if (wanted_stream_nb >= 0 && real_stream_index != wanted_stream_nb)
|
|
||||||
continue;
|
|
||||||
if (type == AVMEDIA_TYPE_AUDIO && !(par->ch_layout.nb_channels && par->sample_rate))
|
|
||||||
continue;
|
|
||||||
if (decoder_ret) {
|
|
||||||
decoder = ff_find_decoder(ic, st, par->codec_id);
|
|
||||||
if (!decoder) {
|
|
||||||
if (ret < 0)
|
|
||||||
ret = AVERROR_DECODER_NOT_FOUND;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
disposition = !(st->disposition & (AV_DISPOSITION_HEARING_IMPAIRED | AV_DISPOSITION_VISUAL_IMPAIRED))
|
|
||||||
+ !! (st->disposition & AV_DISPOSITION_DEFAULT);
|
|
||||||
count = ffstream(st)->codec_info_nb_frames;
|
|
||||||
bitrate = par->bit_rate;
|
|
||||||
multiframe = FFMIN(5, count);
|
|
||||||
if ((best_disposition > disposition) ||
|
|
||||||
(best_disposition == disposition && best_multiframe > multiframe) ||
|
|
||||||
(best_disposition == disposition && best_multiframe == multiframe && best_bitrate > bitrate) ||
|
|
||||||
(best_disposition == disposition && best_multiframe == multiframe && best_bitrate == bitrate && best_count >= count))
|
|
||||||
continue;
|
|
||||||
best_disposition = disposition;
|
|
||||||
best_count = count;
|
|
||||||
best_bitrate = bitrate;
|
|
||||||
best_multiframe = multiframe;
|
|
||||||
ret = real_stream_index;
|
|
||||||
best_decoder = decoder;
|
|
||||||
if (program && i == nb_streams - 1 && ret < 0) {
|
|
||||||
program = NULL;
|
|
||||||
nb_streams = ic->nb_streams;
|
|
||||||
/* no related stream found, try again with everything */
|
|
||||||
i = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (decoder_ret)
|
|
||||||
*decoder_ret = best_decoder;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************************************************/
|
/*******************************************************/
|
||||||
|
|
||||||
int ff_stream_side_data_copy(AVStream *dst, const AVStream *src)
|
int ff_stream_side_data_copy(AVStream *dst, const AVStream *src)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user