mirror of https://github.com/mpv-player/mpv
mplayer: let frontend print stream info, instead of demuxers
When playing a file, users (i.e. me) expect mplayer to print a list of video/audio/subtitle streams. Currently, this is done in each demuxer separately. This also means the output is formatted differently depending which demuxer is active. Add code to print an uniformly formatted streams list in the player front end. Extend the streams headers to export additional information about the streams. Change the lavf and mkv demuxers to follow this new scheme, and raise the log level for the "old" printing functions. The intention is to make every demuxer behave like this eventually. The stream list output attempts to provide codec information. It's a bit hacky and doesn't always provide useful output, and I'm not sure how to do it better.
This commit is contained in:
parent
3daf32adfd
commit
521a598068
|
@ -299,6 +299,9 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
if (override_tag)
|
||||
codec->codec_tag = override_tag;
|
||||
|
||||
AVCodec *avc = avcodec_find_decoder(codec->codec_id);
|
||||
const char *codec_name = avc ? avc->name : "unknown";
|
||||
|
||||
switch (codec->codec_type) {
|
||||
case AVMEDIA_TYPE_AUDIO: {
|
||||
WAVEFORMATEX *wf;
|
||||
|
@ -306,6 +309,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
sh_audio = new_sh_audio_aid(demuxer, i, priv->audio_streams);
|
||||
if (!sh_audio)
|
||||
break;
|
||||
sh_audio->demuxer_id = i;
|
||||
sh_audio->demuxer_codecname = codec_name;
|
||||
stream_type = "audio";
|
||||
priv->astreams[priv->audio_streams] = i;
|
||||
sh_audio->libav_codec_id = codec->codec_id;
|
||||
|
@ -384,6 +389,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
sh_video = new_sh_video_vid(demuxer, i, priv->video_streams);
|
||||
if (!sh_video)
|
||||
break;
|
||||
sh_video->demuxer_id = i;
|
||||
sh_video->demuxer_codecname = codec_name;
|
||||
stream_type = "video";
|
||||
priv->vstreams[priv->video_streams] = i;
|
||||
sh_video->libav_codec_id = codec->codec_id;
|
||||
|
@ -495,6 +502,8 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
sh_sub = new_sh_sub_sid(demuxer, i, priv->sub_streams);
|
||||
if (!sh_sub)
|
||||
break;
|
||||
sh_sub->demuxer_id = i;
|
||||
sh_sub->demuxer_codecname = codec_name;
|
||||
stream_type = "subtitle";
|
||||
priv->sstreams[priv->sub_streams] = i;
|
||||
sh_sub->libav_codec_id = codec->codec_id;
|
||||
|
@ -534,18 +543,16 @@ static void handle_stream(demuxer_t *demuxer, AVFormatContext *avfc, int i)
|
|||
st->discard = AVDISCARD_ALL;
|
||||
}
|
||||
if (stream_type) {
|
||||
AVCodec *avc = avcodec_find_decoder(codec->codec_id);
|
||||
const char *codec_name = avc ? avc->name : "unknown";
|
||||
if (!avc && *stream_type == 's' && demuxer->s_streams[i])
|
||||
codec_name = sh_sub_type2str((demuxer->s_streams[i])->type);
|
||||
mp_msg(MSGT_DEMUX, MSGL_INFO, "[lavf] stream %d: %s (%s), -%cid %d",
|
||||
mp_msg(MSGT_DEMUX, MSGL_V, "[lavf] stream %d: %s (%s), -%cid %d",
|
||||
i, stream_type, codec_name, *stream_type, stream_id);
|
||||
if (lang && lang->value && *stream_type != 'v')
|
||||
mp_msg(MSGT_DEMUX, MSGL_INFO, ", -%clang %s",
|
||||
mp_msg(MSGT_DEMUX, MSGL_V, ", -%clang %s",
|
||||
*stream_type, lang->value);
|
||||
if (title && title->value)
|
||||
mp_msg(MSGT_DEMUX, MSGL_INFO, ", %s", title->value);
|
||||
mp_msg(MSGT_DEMUX, MSGL_INFO, "\n");
|
||||
mp_msg(MSGT_DEMUX, MSGL_V, ", %s", title->value);
|
||||
mp_msg(MSGT_DEMUX, MSGL_V, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1121,12 +1121,12 @@ static void display_create_tracks(demuxer_t *demuxer)
|
|||
break;
|
||||
}
|
||||
if (mkv_d->tracks[i]->name)
|
||||
mp_tmsg(MSGT_DEMUX, MSGL_INFO,
|
||||
mp_tmsg(MSGT_DEMUX, MSGL_V,
|
||||
"[mkv] Track ID %u: %s (%s) \"%s\", %s\n",
|
||||
mkv_d->tracks[i]->tnum, type, mkv_d->tracks[i]->codec_id,
|
||||
mkv_d->tracks[i]->name, str);
|
||||
else
|
||||
mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[mkv] Track ID %u: %s (%s), %s\n",
|
||||
mp_tmsg(MSGT_DEMUX, MSGL_V, "[mkv] Track ID %u: %s (%s), %s\n",
|
||||
mkv_d->tracks[i]->tnum, type, mkv_d->tracks[i]->codec_id,
|
||||
str);
|
||||
}
|
||||
|
@ -1271,6 +1271,8 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track,
|
|||
}
|
||||
|
||||
sh_v = new_sh_video(demuxer, vid);
|
||||
sh_v->demuxer_id = track->tnum;
|
||||
sh_v->demuxer_codecname = track->codec_id;
|
||||
sh_v->title = talloc_strdup(sh_v, track->name);
|
||||
sh_v->bih = bih;
|
||||
sh_v->format = sh_v->bih->biCompression;
|
||||
|
@ -1342,6 +1344,8 @@ static int demux_mkv_open_audio(demuxer_t *demuxer, mkv_track_t *track,
|
|||
|
||||
if (track->language && (strcmp(track->language, "und") != 0))
|
||||
sh_a->lang = talloc_strdup(sh_a, track->language);
|
||||
sh_a->demuxer_id = track->tnum;
|
||||
sh_a->demuxer_codecname = track->codec_id;
|
||||
sh_a->title = talloc_strdup(sh_a, track->name);
|
||||
sh_a->default_track = track->default_track;
|
||||
sh_a->ds = demuxer->audio;
|
||||
|
@ -1579,6 +1583,8 @@ static int demux_mkv_open_sub(demuxer_t *demuxer, mkv_track_t *track,
|
|||
int size;
|
||||
uint8_t *buffer;
|
||||
sh_sub_t *sh = new_sh_sub(demuxer, sid);
|
||||
sh->demuxer_id = track->tnum;
|
||||
sh->demuxer_codecname = track->codec_id;
|
||||
track->sh_sub = sh;
|
||||
sh->type = track->subtitle_type;
|
||||
size = track->private_size;
|
||||
|
@ -1720,7 +1726,7 @@ static int demux_mkv_open(demuxer_t *demuxer)
|
|||
MATROSKA_TRACK_VIDEO);
|
||||
|
||||
if (track && demuxer->v_streams[track->id]) {
|
||||
mp_tmsg(MSGT_DEMUX, MSGL_INFO, "[mkv] Will play video track %u.\n",
|
||||
mp_tmsg(MSGT_DEMUX, MSGL_V, "[mkv] Will play video track %u.\n",
|
||||
track->tnum);
|
||||
demuxer->video->id = track->id;
|
||||
demuxer->video->sh = demuxer->v_streams[track->id];
|
||||
|
|
|
@ -354,6 +354,10 @@ sh_sub_t *new_sh_sub_sid(demuxer_t *demuxer, int id, int sid)
|
|||
else {
|
||||
struct sh_sub *sh = talloc_zero(demuxer, struct sh_sub);
|
||||
demuxer->s_streams[id] = sh;
|
||||
sh->stream_type = STREAM_SUBTITLE;
|
||||
sh->demuxer_id = demuxer->new_stream_id++;
|
||||
sh->id = sid;
|
||||
sh->index = id;
|
||||
sh->sid = sid;
|
||||
sh->opts = demuxer->opts;
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SUBTITLE_ID=%d\n", sid);
|
||||
|
@ -394,6 +398,10 @@ sh_audio_t *new_sh_audio_aid(demuxer_t *demuxer, int id, int aid)
|
|||
mp_tmsg(MSGT_DEMUXER, MSGL_V, "==> Found audio stream: %d\n", id);
|
||||
struct sh_audio *sh = talloc_zero(demuxer, struct sh_audio);
|
||||
demuxer->a_streams[id] = sh;
|
||||
sh->stream_type = STREAM_AUDIO;
|
||||
sh->demuxer_id = demuxer->new_stream_id++;
|
||||
sh->id = aid;
|
||||
sh->index = id;
|
||||
sh->aid = aid;
|
||||
sh->ds = demuxer->audio;
|
||||
// set some defaults
|
||||
|
@ -430,6 +438,10 @@ sh_video_t *new_sh_video_vid(demuxer_t *demuxer, int id, int vid)
|
|||
mp_tmsg(MSGT_DEMUXER, MSGL_V, "==> Found video stream: %d\n", id);
|
||||
struct sh_video *sh = talloc_zero(demuxer, struct sh_video);
|
||||
demuxer->v_streams[id] = sh;
|
||||
sh->stream_type = STREAM_VIDEO;
|
||||
sh->demuxer_id = demuxer->new_stream_id++;
|
||||
sh->id = vid;
|
||||
sh->index = id;
|
||||
sh->vid = vid;
|
||||
sh->ds = demuxer->video;
|
||||
sh->opts = demuxer->opts;
|
||||
|
|
|
@ -282,6 +282,8 @@ typedef struct demuxer {
|
|||
char **info; // metadata
|
||||
struct MPOpts *opts;
|
||||
struct demuxer_params *params;
|
||||
|
||||
int new_stream_id;
|
||||
} demuxer_t;
|
||||
|
||||
typedef struct {
|
||||
|
|
|
@ -26,9 +26,24 @@
|
|||
struct MPOpts;
|
||||
struct demuxer;
|
||||
|
||||
enum STREAM_TYPE {
|
||||
STREAM_VIDEO = 1,
|
||||
STREAM_AUDIO,
|
||||
STREAM_SUBTITLE,
|
||||
};
|
||||
|
||||
// Stream headers:
|
||||
|
||||
// id: the type specific id, e.g. aid or sid
|
||||
// index: index into stream array (currently one array per type)
|
||||
// demuxer_id: demuxer specific ID (-1 if unknown, otherwise >= 0)
|
||||
|
||||
#define SH_COMMON \
|
||||
enum STREAM_TYPE stream_type; \
|
||||
int id; \
|
||||
int index; \
|
||||
int demuxer_id; \
|
||||
const char *demuxer_codecname; \
|
||||
struct MPOpts *opts; \
|
||||
struct demux_stream *ds; \
|
||||
struct codecs *codec; \
|
||||
|
|
74
mplayer.c
74
mplayer.c
|
@ -428,6 +428,63 @@ char *get_metadata(struct MPContext *mpctx, metadata_t type)
|
|||
return talloc_strdup(NULL, "");
|
||||
}
|
||||
|
||||
static void print_stream(struct MPContext *mpctx, sh_common_t *s)
|
||||
{
|
||||
const char *tname = "?";
|
||||
const char *selopt = "?";
|
||||
const char *langopt = "?";
|
||||
switch (s->stream_type) {
|
||||
case STREAM_VIDEO:
|
||||
tname = "video"; selopt = "vid"; langopt = "vlang";
|
||||
break;
|
||||
case STREAM_AUDIO:
|
||||
tname = "audio"; selopt = "aid"; langopt = "alang";
|
||||
break;
|
||||
case STREAM_SUBTITLE:
|
||||
tname = "subtitle"; selopt = "sid"; langopt = "slang";
|
||||
break;
|
||||
}
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "[stream] ID %d: %s", s->demuxer_id, tname);
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " --%s=%d", selopt, s->id);
|
||||
if (s->lang)
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " --%s=%s", langopt, s->lang);
|
||||
if (s->default_track)
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " (*)");
|
||||
if (s->title)
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " '%s'", s->title);
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " (");
|
||||
if (s->format) {
|
||||
// not sure about endian crap
|
||||
char name[sizeof(s->format) + 1] = {0};
|
||||
memcpy(name, &s->format, sizeof(s->format));
|
||||
bool ok = true;
|
||||
for (int n = 0; name[n]; n++) {
|
||||
if ((name[n] < 32 || name[n] >= 128) && name[n] != 0)
|
||||
ok = false;
|
||||
}
|
||||
if (ok && strlen(name) > 0) {
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s", name);
|
||||
} else {
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "%#x", s->format);
|
||||
}
|
||||
} else if (s->stream_type == STREAM_SUBTITLE) {
|
||||
char t = ((sh_sub_t*)s)->type;
|
||||
const char *name = NULL;
|
||||
switch (t) {
|
||||
case 't': name = "SRT"; break;
|
||||
case 'a': name = "ASS"; break;
|
||||
case 'v': name = "VobSub"; break;
|
||||
}
|
||||
if (!name)
|
||||
name = (char[2]){t, '\0'};
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s", name);
|
||||
}
|
||||
if (s->demuxer_codecname)
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "/%s", s->demuxer_codecname);
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, ")");
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "\n");
|
||||
}
|
||||
|
||||
static void print_file_properties(struct MPContext *mpctx, const char *filename)
|
||||
{
|
||||
double start_pts = MP_NOPTS_VALUE;
|
||||
|
@ -503,6 +560,23 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename)
|
|||
}
|
||||
}
|
||||
}
|
||||
// xxx I think this might be invalid C
|
||||
// should resolve the crapmess in stheader.h
|
||||
for (int n = 0; n < MAX_V_STREAMS; n++) {
|
||||
sh_common_t *s = (sh_common_t*)mpctx->demuxer->v_streams[n];
|
||||
if (s)
|
||||
print_stream(mpctx, s);
|
||||
}
|
||||
for (int n = 0; n < MAX_A_STREAMS; n++) {
|
||||
sh_common_t *s = (sh_common_t*)mpctx->demuxer->a_streams[n];
|
||||
if (s)
|
||||
print_stream(mpctx, s);
|
||||
}
|
||||
for (int n = 0; n < MAX_S_STREAMS; n++) {
|
||||
sh_common_t *s = (sh_common_t*)mpctx->demuxer->s_streams[n];
|
||||
if (s)
|
||||
print_stream(mpctx, s);
|
||||
}
|
||||
}
|
||||
|
||||
/// step size of mixer changes
|
||||
|
|
Loading…
Reference in New Issue