summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-12-12 01:00:58 +0100
committerwm4 <wm4@nowhere>2014-12-12 01:00:58 +0100
commitd17c3b63c3f00e7c624be4b8f6b11096435ffb3d (patch)
tree850f251dc028ae92cb0e83ea4b15cf8baf941ae5
parent47452443c50f34219ed0744eae9492f56b32b878 (diff)
downloadmpv-d17c3b63c3f00e7c624be4b8f6b11096435ffb3d.tar.bz2
mpv-d17c3b63c3f00e7c624be4b8f6b11096435ffb3d.tar.xz
command: add properties for current bitrate
Fixes #1192.
-rw-r--r--DOCS/man/input.rst11
-rw-r--r--demux/demux.c33
-rw-r--r--demux/demux.h1
-rw-r--r--player/command.c23
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),