1
0
mirror of https://github.com/mpv-player/mpv synced 2025-04-23 15:47:54 +00:00

player: simplistic HLS bitrate selection

--hls-bitrate=min/max lets you select the min or max bitrate. That's it.
Something more sophisticated might be possible, but is probably not even
worth the effort.
This commit is contained in:
wm4 2014-09-01 23:47:27 +02:00
parent 8d92128f6b
commit 5f14543668
6 changed files with 44 additions and 13 deletions

View File

@ -2838,11 +2838,9 @@ Network
Use ``<string>`` as user agent for HTTP streaming.
``--cookies``, ``--no-cookies``
(network only)
Support cookies when making HTTP requests. Disabled by default.
``--cookies-file=<filename>``
(network only)
Read HTTP cookies from <filename>. The file is assumed to be in Netscape
format.
@ -2882,6 +2880,17 @@ Network
network transport when playing ``rtsp://...`` URLs. The value ``lavf``
leaves the decision to libavformat.
``--hls-bitrate=<no|min|max>``
If HLS streams are played, this option controls what streams are selected
by default. The option allows the following parameters:
:no: Don't do anything special. Typically, this will simply pick the
first audio/video streams it can find. (Default.)
:min: Pick the streams with the lowest bitrate.
:max: Same, but highest bitrate.
The bitrate as used is sent by the server, and there's no guarantee it's
actually meaningful.
DVB
---

View File

@ -429,6 +429,19 @@ static void export_replaygain(demuxer_t *demuxer, sh_audio_t *sh, AVStream *st)
#endif
}
// Return a dictionary entry as (decimal) integer.
static int dict_get_decimal(AVDictionary *dict, const char *entry, int def)
{
AVDictionaryEntry *e = av_dict_get(dict, entry, NULL, 0);
if (e && e->value) {
char *end = NULL;
long int r = strtol(e->value, &end, 10);
if (end && !end[0] && r >= INT_MIN && r <= INT_MAX)
return r;
}
return def;
}
static void handle_stream(demuxer_t *demuxer, int i)
{
lavf_priv_t *priv = demuxer->priv;
@ -505,13 +518,9 @@ static void handle_stream(demuxer_t *demuxer, int i)
if (sd)
sh_video->rotate = -av_display_rotation_get((uint32_t *)sd);
#else
AVDictionaryEntry *rot = av_dict_get(st->metadata, "rotate", NULL, 0);
if (rot && rot->value) {
char *end = NULL;
long int r = strtol(rot->value, &end, 10);
if (end && !end[0])
sh_video->rotate = r;
}
int rot = dict_get_decimal(st->metadata, "rotate", -1);
if (rot >= 0)
sh_video->rotate = rot;
#endif
sh_video->rotate = ((sh_video->rotate % 360) + 360) % 360;
@ -589,6 +598,7 @@ static void handle_stream(demuxer_t *demuxer, int i)
AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
if (lang && lang->value)
sh->lang = talloc_strdup(sh, lang->value);
sh->hls_bitrate = dict_get_decimal(st->metadata, "variant_bitrate", 0);
}
select_tracks(demuxer, i);

View File

@ -55,6 +55,7 @@ struct sh_stream {
char *title;
char *lang; // language code
bool default_track; // container default track flag
int hls_bitrate;
// stream is a picture (such as album art)
struct demux_packet *attached_picture;

View File

@ -202,6 +202,9 @@ const m_option_t mp_opts[] = {
OPT_STRING("quvi-format", quvi_format, 0),
OPT_FLAG("quvi-fetch-subtitles", quvi_fetch_subtitles, 0),
OPT_CHOICE("hls-bitrate", hls_bitrate, M_OPT_FIXED,
({"no", 0}, {"min", 1}, {"max", 2})),
#if HAVE_CDDA
OPT_SUBSTRUCT("cdda", stream_cdda_opts, stream_cdda_conf, 0),
OPT_STRING("cdrom-device", cdrom_device, 0),

View File

@ -123,6 +123,7 @@ typedef struct MPOpts {
char *force_configdir;
int use_filedir_conf;
int network_rtsp_transport;
int hls_bitrate;
struct mp_cache_opts stream_cache;
int chapterrange[2];
int edition_id;

View File

@ -464,13 +464,15 @@ static int match_lang(char **langs, char *lang)
* 1b) track was passed explicitly (is not an auto-loaded subtitle)
* 2) earlier match in lang list
* 3) track is marked default
* 4) lower track number
* If select_fallback is not set, 4) is only used to determine whether a
* 4) attached picture, HLS bitrate
* 5) lower track number
* If select_fallback is not set, 5) is only used to determine whether a
* matching track is preferred over another track. Otherwise, always pick a
* track (if nothing else matches, return the track with lowest ID).
*/
// Return whether t1 is preferred over t2
static bool compare_track(struct track *t1, struct track *t2, char **langs)
static bool compare_track(struct track *t1, struct track *t2, char **langs,
struct MPOpts *opts)
{
bool ext1 = t1->is_external && !t1->no_default;
bool ext2 = t2->is_external && !t2->no_default;
@ -485,6 +487,11 @@ static bool compare_track(struct track *t1, struct track *t2, char **langs)
return t1->default_track;
if (t1->attached_picture != t2->attached_picture)
return !t1->attached_picture;
if (t1->stream && t2->stream && opts->hls_bitrate) {
int d = t1->stream->hls_bitrate - t2->stream->hls_bitrate;
if (d)
return opts->hls_bitrate == 1 ? d < 0 : d > 0;
}
return t1->user_tid <= t2->user_tid;
}
static struct track *select_track(struct MPContext *mpctx,
@ -500,7 +507,7 @@ static struct track *select_track(struct MPContext *mpctx,
continue;
if (track->user_tid == tid)
return track;
if (!pick || compare_track(track, pick, langs))
if (!pick || compare_track(track, pick, langs, mpctx->opts))
pick = track;
}
if (pick && !select_fallback && !(pick->is_external && !pick->no_default)