diff --git a/DOCS/interface-changes/codec-info.txt b/DOCS/interface-changes/codec-info.txt new file mode 100644 index 0000000000..3d7df21b6c --- /dev/null +++ b/DOCS/interface-changes/codec-info.txt @@ -0,0 +1 @@ +add `video-codec-info` and `audio-codec-info` properties diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index 7b7d94051f..22b53b3feb 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -2401,11 +2401,25 @@ Property list Similar to ``ao-volume``, but controls the mute state. May be unimplemented even if ``ao-volume`` works. -``audio-codec`` - Audio codec selected for decoding. +``audio-codec-info`` + Audio codec information. -``audio-codec-name`` - Audio codec. + ``audio-codec-info/name`` + The codec name used by this track, for example ``aac``. + + ``audio-codec-info/desc`` + The codec descriptive name used by this track. + + ``audio-codec-info/profile`` + The codec profile used by this track. Available only if the track has + been already decoded. + + :: + + MPV_FORMAT_NODE_MAP + "name" MPV_FORMAT_STRING + "desc" MPV_FORMAT_STRING + "profile" MPV_FORMAT_STRING ``audio-params`` Audio format as output by the audio decoder. @@ -2490,11 +2504,25 @@ Property list multiple interop drivers for the same hardware decoder, depending on platform and VO. -``video-format`` - Video format as string. +``video-codec-info`` + Video codec information. -``video-codec`` - Video codec selected for decoding. + ``video-codec-info/name`` + The codec name used by this track, for example ``h264``. + + ``video-codec-info/desc`` + The codec descriptive name used by this track. + + ``video-codec-info/profile`` + The codec profile used by this track. Available only if the track has + been already decoded. + + :: + + MPV_FORMAT_NODE_MAP + "name" MPV_FORMAT_STRING + "desc" MPV_FORMAT_STRING + "profile" MPV_FORMAT_STRING ``width``, ``height`` Video size. This uses the size of the video as decoded, or if no video @@ -3057,6 +3085,13 @@ Property list The codec name used by this track, for example ``h264``. Unavailable in some rare cases. + ``track-list/N/codec-desc`` + The codec descriptive name used by this track. + + ``track-list/N/codec-profile`` + The codec profile used by this track. Available only if the track has + been already decoded. + ``track-list/N/external`` ``yes``/true if the track is an external file, ``no``/false or unavailable otherwise. This is set for separate subtitle files. @@ -3157,6 +3192,8 @@ Property list "external" MPV_FORMAT_FLAG "external-filename" MPV_FORMAT_STRING "codec" MPV_FORMAT_STRING + "codec-desc" MPV_FORMAT_STRING + "codec-profile" MPV_FORMAT_STRING "ff-index" MPV_FORMAT_INT64 "decoder-desc" MPV_FORMAT_STRING "demux-w" MPV_FORMAT_INT64 diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 11a5f131d7..9b5f1fb467 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -44,6 +44,7 @@ #include "options/options.h" struct priv { + struct mp_codec_params *codec; AVCodecContext *avctx; AVFrame *avframe; AVPacket *avpkt; @@ -219,6 +220,8 @@ static int receive_frame(struct mp_filter *da, struct mp_frame *out) if (!priv->avframe->buf[0]) return ret; + mp_codec_info_from_av(avctx, priv->codec); + double out_pts = mp_pts_from_av(priv->avframe->pts, &priv->codec_timebase); struct mp_aframe *mpframe = mp_aframe_from_avframe(priv->avframe); @@ -305,12 +308,16 @@ static struct mp_decoder *create(struct mp_filter *parent, da->log = mp_log_new(da, parent->log, NULL); struct priv *priv = da->priv; + priv->codec = codec; priv->public.f = da; if (!init(da, codec, decoder)) { talloc_free(da); return NULL; } + + codec->codec_desc = priv->avctx->codec_descriptor->long_name; + return &priv->public; } diff --git a/common/av_common.c b/common/av_common.c index 5d07349af0..e5733c3848 100644 --- a/common/av_common.c +++ b/common/av_common.c @@ -402,3 +402,12 @@ void mp_free_av_packet(AVPacket **pkt) } av_packet_free(pkt); } + +void mp_codec_info_from_av(const AVCodecContext *avctx, struct mp_codec_params *c) +{ + c->codec_profile = av_get_profile_name(avctx->codec, avctx->profile); + if (!c->codec_profile) + c->codec_profile = avcodec_profile_name(avctx->codec_id, avctx->profile); + c->codec = avctx->codec_descriptor->name; + c->codec_desc = avctx->codec_descriptor->long_name; +} diff --git a/common/av_common.h b/common/av_common.h index 1f05e14fab..c584085890 100644 --- a/common/av_common.h +++ b/common/av_common.h @@ -50,5 +50,6 @@ void mp_avdict_print_unset(struct mp_log *log, int msgl, struct AVDictionary *d) int mp_set_avopts(struct mp_log *log, void *avobj, char **kv); int mp_set_avopts_pos(struct mp_log *log, void *avobj, void *posargs, char **kv); void mp_free_av_packet(AVPacket **pkt); +void mp_codec_info_from_av(const AVCodecContext *avctx, struct mp_codec_params *c); #endif diff --git a/demux/stheader.h b/demux/stheader.h index 438ef7db41..4f33bbc711 100644 --- a/demux/stheader.h +++ b/demux/stheader.h @@ -72,6 +72,12 @@ struct mp_codec_params { // E.g. "h264" (usually corresponds to AVCodecDescriptor.name) const char *codec; + // Usually corresponds to AVCodecDescriptor.long_name + const char *codec_desc; + + // Corresponding codec profile + const char *codec_profile; + // Usually a FourCC, exact meaning depends on codec. unsigned int codec_tag; diff --git a/player/command.c b/player/command.c index 31dcd7f0f9..aed4027586 100644 --- a/player/command.c +++ b/player/command.c @@ -1829,26 +1829,30 @@ static int mp_property_audio_delay(void *ctx, struct m_property *prop, return mp_property_generic_option(mpctx, prop, action, arg); } -/// Audio codec tag (RO) -static int mp_property_audio_codec_name(void *ctx, struct m_property *prop, - int action, void *arg) +static int property_codec_info(MPContext *mpctx, struct m_property *prop, + int action, void *arg, enum stream_type st) { - MPContext *mpctx = ctx; - struct track *track = mpctx->current_track[0][STREAM_AUDIO]; - const char *c = track && track->stream ? track->stream->codec->codec : NULL; - return m_property_strdup_ro(action, arg, c); + struct track *track = mpctx->current_track[0][st]; + if (!track || !track->stream) + return M_PROPERTY_UNAVAILABLE; + + struct m_sub_property props[] = { + {"name", SUB_PROP_STR(track->stream->codec->codec), + .unavailable = !track->stream->codec->codec}, + {"desc", SUB_PROP_STR(track->stream->codec->codec_desc), + .unavailable = !track->stream->codec->codec_desc}, + {"profile", SUB_PROP_STR(track->stream->codec->codec_profile), + .unavailable = !track->stream->codec->codec_profile}, + {0} + }; + + return m_property_read_sub(props, action, arg); } -/// Audio codec name (RO) -static int mp_property_audio_codec(void *ctx, struct m_property *prop, - int action, void *arg) +static int mp_property_audio_codec_info(void *ctx, struct m_property *prop, + int action, void *arg) { - MPContext *mpctx = ctx; - struct track *track = mpctx->current_track[0][STREAM_AUDIO]; - char desc[256] = ""; - if (track && track->dec) - mp_decoder_wrapper_get_desc(track->dec, desc, sizeof(desc)); - return m_property_strdup_ro(action, arg, desc[0] ? desc : NULL); + return property_codec_info(ctx, prop, action, arg, STREAM_AUDIO); } static int property_audiofmt(struct mp_aframe *fmt, int action, void *arg) @@ -2055,6 +2059,10 @@ static int get_track_entry(int item, int action, void *arg, void *ctx) .unavailable = !decoder_desc[0]}, {"codec", SUB_PROP_STR(p.codec), .unavailable = !p.codec}, + {"codec-desc", SUB_PROP_STR(p.codec_desc), + .unavailable = !p.codec_desc}, + {"codec-profile", SUB_PROP_STR(p.codec_profile), + .unavailable = !p.codec_profile}, {"demux-w", SUB_PROP_INT(p.disp_w), .unavailable = !p.disp_w}, {"demux-h", SUB_PROP_INT(p.disp_h), .unavailable = !p.disp_h}, {"demux-crop-x",SUB_PROP_INT(p.crop.x0), .unavailable = !has_crop}, @@ -2264,26 +2272,10 @@ static int mp_property_frame_count(void *ctx, struct m_property *prop, return m_property_int_ro(action, arg, frames); } -/// Video codec tag (RO) -static int mp_property_video_format(void *ctx, struct m_property *prop, - int action, void *arg) +static int mp_property_video_codec_info(void *ctx, struct m_property *prop, + int action, void *arg) { - MPContext *mpctx = ctx; - struct track *track = mpctx->current_track[0][STREAM_VIDEO]; - const char *c = track && track->stream ? track->stream->codec->codec : NULL; - return m_property_strdup_ro(action, arg, c); -} - -/// Video codec name (RO) -static int mp_property_video_codec(void *ctx, struct m_property *prop, - int action, void *arg) -{ - MPContext *mpctx = ctx; - struct track *track = mpctx->current_track[0][STREAM_VIDEO]; - char desc[256] = ""; - if (track && track->dec) - mp_decoder_wrapper_get_desc(track->dec, desc, sizeof(desc)); - return m_property_strdup_ro(action, arg, desc[0] ? desc : NULL); + return property_codec_info(ctx, prop, action, arg, STREAM_VIDEO); } static const char *get_aspect_ratio_name(double ratio) @@ -4027,8 +4019,9 @@ static const struct m_property mp_properties_base[] = { {"ao-volume", mp_property_ao_volume}, {"ao-mute", mp_property_ao_mute}, {"audio-delay", mp_property_audio_delay}, - {"audio-codec-name", mp_property_audio_codec_name}, - {"audio-codec", mp_property_audio_codec}, + {"audio-codec-info", mp_property_audio_codec_info}, + M_PROPERTY_ALIAS("audio-codec-name", "audio-codec-info/name"), + M_PROPERTY_ALIAS("audio-codec", "audio-codec-info/desc"), {"audio-params", mp_property_audio_params}, {"audio-out-params", mp_property_audio_out_params}, {"aid", property_switch_track, .priv = (void *)(const int[]){0, STREAM_AUDIO}}, @@ -4041,9 +4034,10 @@ static const struct m_property mp_properties_base[] = { {"video-out-params", mp_property_vo_imgparams}, {"video-dec-params", mp_property_dec_imgparams}, {"video-params", mp_property_vd_imgparams}, - {"video-format", mp_property_video_format}, {"video-frame-info", mp_property_video_frame_info}, - {"video-codec", mp_property_video_codec}, + {"video-codec-info", mp_property_video_codec_info}, + M_PROPERTY_ALIAS("video-format", "video-codec-info/name"), + M_PROPERTY_ALIAS("video-codec", "video-codec-info/desc"), M_PROPERTY_ALIAS("dwidth", "video-out-params/dw"), M_PROPERTY_ALIAS("dheight", "video-out-params/dh"), M_PROPERTY_ALIAS("width", "video-params/w"), @@ -4189,10 +4183,10 @@ static const char *const *const mp_event_property_change[] = { "video-format", "video-codec", "video-bitrate", "dwidth", "dheight", "width", "height", "container-fps", "aspect", "aspect-name", "vo-configured", "current-vo", "video-dec-params", "osd-dimensions", "hwdec", "hwdec-current", "hwdec-interop", - "window-id"), + "window-id", "video-codec-info"), E(MPV_EVENT_AUDIO_RECONFIG, "audio-format", "audio-codec", "audio-bitrate", "samplerate", "channels", "audio", "volume", "volume-gain", "mute", - "current-ao", "audio-codec-name", "audio-params", + "current-ao", "audio-codec-name", "audio-params", "audio-codec-info", "audio-out-params", "volume-max", "volume-gain-min", "volume-gain-max", "mixer-active"), E(MPV_EVENT_SEEK, "seeking", "core-idle", "eof-reached"), E(MPV_EVENT_PLAYBACK_RESTART, "seeking", "core-idle", "eof-reached"), diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 8756a59b11..05b66edbd8 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -1215,6 +1215,8 @@ static int decode_frame(struct mp_filter *vd) return ret; } + mp_codec_info_from_av(avctx, ctx->codec); + // If something was decoded successfully, it must return a frame with valid // data. assert(ctx->pic->buf[0]); @@ -1443,6 +1445,9 @@ static struct mp_decoder *create(struct mp_filter *parent, talloc_free(vd); return NULL; } + + codec->codec_desc = ctx->avctx->codec_descriptor->long_name; + return &ctx->public; }