diff options
author | wm4 <wm4@nowhere> | 2014-12-12 01:00:58 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-12-12 01:00:58 +0100 |
commit | d17c3b63c3f00e7c624be4b8f6b11096435ffb3d (patch) | |
tree | 850f251dc028ae92cb0e83ea4b15cf8baf941ae5 | |
parent | 47452443c50f34219ed0744eae9492f56b32b878 (diff) | |
download | mpv-d17c3b63c3f00e7c624be4b8f6b11096435ffb3d.tar.bz2 mpv-d17c3b63c3f00e7c624be4b8f6b11096435ffb3d.tar.xz |
command: add properties for current bitrate
Fixes #1192.
-rw-r--r-- | DOCS/man/input.rst | 11 | ||||
-rw-r--r-- | demux/demux.c | 33 | ||||
-rw-r--r-- | demux/demux.h | 1 | ||||
-rw-r--r-- | player/command.c | 23 |
4 files changed, 67 insertions, 1 deletions
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index fc0640553b..dd2c20bee3 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -1445,6 +1445,17 @@ Property list whether the video window is visible. If the ``--force-window`` option is used, this is usually always returns ``yes``. +``packet-video-bitrate``, ``packet-audio-bitrate``, ``packet-sub-bitrate`` + Bitrate values calculated on the packet level. This works by dividing the + bit size of all packets between two keyframes by their presentation + timestamp distance. (This uses the timestamps are stored in the file, so + e.g. playback speed does not influence the returned values.) In particular, + the video bitrate will update only per keyframe, and show the "past" + bitrate. To make the property more UI friendly, updates to these properties + are throttled in a certain way. + + How exactly these values are calculated might change in the future. + ``audio-device-list`` Return the list of discovered audio devices. This is mostly for use with the client API, and reflects what ``--audio-device=help`` with the command diff --git a/demux/demux.c b/demux/demux.c index ea0464cdae..e7b0729b77 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -146,6 +146,9 @@ struct demux_stream { size_t bytes; // total bytes of packets in buffer double base_ts; // timestamp of the last packet returned to decoder double last_ts; // timestamp of the last packet added to queue + double last_br_ts; // timestamp of last packet bitrate was calculated + size_t last_br_bytes; // summed packet sizes since last bitrate calculation + double bitrate; struct demux_packet *head; struct demux_packet *tail; }; @@ -172,7 +175,9 @@ static void ds_flush(struct demux_stream *ds) ds->head = ds->tail = NULL; ds->packs = 0; ds->bytes = 0; - ds->last_ts = ds->base_ts = MP_NOPTS_VALUE; + ds->last_ts = ds->base_ts = ds->last_br_ts = MP_NOPTS_VALUE; + ds->last_br_bytes = 0; + ds->bitrate = -1; ds->eof = false; ds->active = false; } @@ -514,6 +519,22 @@ static struct demux_packet *dequeue_packet(struct demux_stream *ds) if (ts != MP_NOPTS_VALUE) ds->base_ts = ts; + if (pkt->keyframe) { + // Update bitrate - only at keyframe points, because we use the + // (possibly) reordered packet timestamps instead of realtime. + double d = ts - ds->last_br_ts; + if (ts == MP_NOPTS_VALUE || ds->last_br_ts == MP_NOPTS_VALUE || d < 0) { + ds->bitrate = -1; + ds->last_br_ts = ts; + ds->last_br_bytes = 0; + } else if (d > 0 && d >= 0.5) { // a window of least 500ms for UI purposes + ds->bitrate = ds->last_br_bytes / d; + ds->last_br_ts = ts; + ds->last_br_bytes = 0; + } + } + ds->last_br_bytes += pkt->len; + // This implies this function is actually called from "the" user thread. if (pkt->pos >= ds->in->d_user->filepos) ds->in->d_user->filepos = pkt->pos; @@ -1233,6 +1254,16 @@ static int cached_demux_control(struct demux_internal *in, int cmd, void *arg) in->tracks_switched = true; pthread_cond_signal(&in->wakeup); return DEMUXER_CTRL_OK; + case DEMUXER_CTRL_GET_BITRATE_STATS: { + double *rates = arg; + for (int n = 0; n < STREAM_TYPE_COUNT; n++) + rates[n] = 0; + for (int n = 0; n < in->d_user->num_streams; n++) { + struct demux_stream *ds = in->d_user->streams[n]->ds; + rates[ds->type] += MPMAX(0, ds->bitrate); + } + return DEMUXER_CTRL_OK; + } case DEMUXER_CTRL_GET_READER_STATE: { struct demux_ctrl_reader_state *r = arg; *r = (struct demux_ctrl_reader_state){ diff --git a/demux/demux.h b/demux/demux.h index 39bfee7fea..ca96d60732 100644 --- a/demux/demux.h +++ b/demux/demux.h @@ -56,6 +56,7 @@ enum demux_ctrl { DEMUXER_CTRL_STREAM_CTRL, DEMUXER_CTRL_GET_READER_STATE, DEMUXER_CTRL_GET_NAV_EVENT, + DEMUXER_CTRL_GET_BITRATE_STATS, // double[STREAM_TYPE_COUNT] }; struct demux_ctrl_reader_state { diff --git a/player/command.c b/player/command.c index 2387eb25d8..1b7156bb6c 100644 --- a/player/command.c +++ b/player/command.c @@ -2970,6 +2970,23 @@ static int mp_property_ab_loop(void *ctx, struct m_property *prop, return r; } +static int mp_property_packet_bitrate(void *ctx, struct m_property *prop, + int action, void *arg) +{ + MPContext *mpctx = ctx; + int type = (intptr_t)prop->priv; + + if (!mpctx->demuxer) + return M_PROPERTY_UNAVAILABLE; + + double r[STREAM_TYPE_COUNT]; + if (demux_control(mpctx->demuxer, DEMUXER_CTRL_GET_BITRATE_STATS, &r) < 1) + return M_PROPERTY_UNAVAILABLE; + + // r[type] is in bytes/second -> kilobits + return m_property_int64_ro(action, arg, r[type] * 8 / 1000.0 + 0.5); +} + static int mp_property_version(void *ctx, struct m_property *prop, int action, void *arg) { @@ -3301,6 +3318,12 @@ static const struct m_property mp_properties[] = { {"ab-loop-a", mp_property_ab_loop}, {"ab-loop-b", mp_property_ab_loop}, +#define PROPERTY_BITRATE(name, type) \ + {name, mp_property_packet_bitrate, (void *)(intptr_t)type} + PROPERTY_BITRATE("packet-video-bitrate", STREAM_VIDEO), + PROPERTY_BITRATE("packet-audio-bitrate", STREAM_AUDIO), + PROPERTY_BITRATE("packet-sub-bitrate", STREAM_SUB), + #define PROPERTY_TV_COLOR(name, type) \ {name, mp_property_tv_color, (void *)(intptr_t)type} PROPERTY_TV_COLOR("tv-brightness", TV_COLOR_BRIGHTNESS), |