diff options
Diffstat (limited to 'video')
-rw-r--r-- | video/decode/dec_video.c | 224 | ||||
-rw-r--r-- | video/decode/dec_video.h | 6 | ||||
-rw-r--r-- | video/decode/lavc.h | 2 | ||||
-rw-r--r-- | video/decode/vd.c | 4 | ||||
-rw-r--r-- | video/decode/vd.h | 9 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 116 | ||||
-rw-r--r-- | video/filter/vf.h | 1 | ||||
-rw-r--r-- | video/img_fourcc.h | 10 |
8 files changed, 131 insertions, 241 deletions
diff --git a/video/decode/dec_video.c b/video/decode/dec_video.c index 8730703216..191a13d3fb 100644 --- a/video/decode/dec_video.c +++ b/video/decode/dec_video.c @@ -22,7 +22,9 @@ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> -#include <unistd.h> +#include <assert.h> + +#include "demux/codec_tags.h" #include "core/mp_msg.h" @@ -32,7 +34,7 @@ #include "stream/stream.h" #include "demux/demux.h" -#include "core/codec-cfg.h" +#include "core/codecs.h" #include "video/out/vo.h" #include "video/csputils.h" @@ -180,173 +182,97 @@ void uninit_video(sh_video_t *sh_video) { if (!sh_video->initialized) return; - mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Uninit video: %s\n", sh_video->codec->drv); + mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Uninit video.\n"); sh_video->vd_driver->uninit(sh_video); vf_uninit_filter_chain(sh_video->vfilter); + talloc_free(sh_video->gsh->decoder_desc); + sh_video->gsh->decoder_desc = NULL; sh_video->initialized = 0; } -void vfm_help(void) +static int init_video_codec(sh_video_t *sh_video, const char *decoder) { - int i; - mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Available (compiled-in) video codec families/drivers:\n"); - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_DRIVERS\n"); - mp_msg(MSGT_DECVIDEO, MSGL_INFO, " vfm: info: (comment)\n"); - for (i = 0; mpcodecs_vd_drivers[i] != NULL; i++) - mp_msg(MSGT_DECVIDEO, MSGL_INFO, "%8s %s (%s)\n", - mpcodecs_vd_drivers[i]->info->short_name, - mpcodecs_vd_drivers[i]->info->name, - mpcodecs_vd_drivers[i]->info->comment); + assert(!sh_video->vf_initialized); + + if (!sh_video->vd_driver->init(sh_video, decoder)) { + mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Video decoder init failed.\n"); + //uninit_video(sh_video); + return 0; + } + + sh_video->initialized = 1; + sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE; + sh_video->prev_sorted_pts = MP_NOPTS_VALUE; + return 1; } -static int init_video(sh_video_t *sh_video, char *codecname, char *vfm, - int status, stringset_t *selected) +struct mp_decoder_list *mp_video_decoder_list(void) { - int force = 0; - unsigned int orig_fourcc = - sh_video->bih ? sh_video->bih->biCompression : 0; - sh_video->codec = NULL; - sh_video->vf_initialized = 0; - if (codecname && codecname[0] == '+') { - codecname = &codecname[1]; - force = 1; - } + struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); + for (int i = 0; mpcodecs_vd_drivers[i] != NULL; i++) + mpcodecs_vd_drivers[i]->add_decoders(list); + return list; +} - while (1) { - int i; - int orig_w, orig_h; - // restore original fourcc: - if (sh_video->bih) - sh_video->bih->biCompression = orig_fourcc; - if (! - (sh_video->codec = - find_video_codec(sh_video->format, - sh_video->bih ? ((unsigned int *) &sh_video-> - bih->biCompression) : NULL, - sh_video->codec, force))) - break; - // ok we found one codec - if (stringset_test(selected, sh_video->codec->name)) - continue; // already tried & failed - if (codecname && strcmp(sh_video->codec->name, codecname)) - continue; // -vc - if (vfm && strcmp(sh_video->codec->drv, vfm)) - continue; // vfm doesn't match - if (!force && sh_video->codec->status < status) - continue; // too unstable - stringset_add(selected, sh_video->codec->name); // tagging it - // ok, it matches all rules, let's find the driver! - for (i = 0; mpcodecs_vd_drivers[i] != NULL; i++) - if (!strcmp(mpcodecs_vd_drivers[i]->info->short_name, - sh_video->codec->drv)) - break; - sh_video->vd_driver = mpcodecs_vd_drivers[i]; - if (!sh_video->vd_driver) { // driver not available (==compiled in) - mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, - _("Requested video codec family [%s] (vfm=%s) not available.\nEnable it at compilation.\n"), - sh_video->codec->name, sh_video->codec->drv); - continue; - } - orig_w = sh_video->bih ? sh_video->bih->biWidth : sh_video->disp_w; - orig_h = sh_video->bih ? sh_video->bih->biHeight : sh_video->disp_h; - sh_video->disp_w = orig_w; - sh_video->disp_h = orig_h; - if (sh_video->bih) { - sh_video->bih->biWidth = sh_video->disp_w; - sh_video->bih->biHeight = sh_video->disp_h; - } +static struct mp_decoder_list *mp_select_video_decoders(const char *codec, + char *selection) +{ + struct mp_decoder_list *list = mp_video_decoder_list(); + struct mp_decoder_list *new = mp_select_decoders(list, codec, selection); + talloc_free(list); + return new; +} - // init() - const struct vd_functions *vd = sh_video->vd_driver; - mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Opening video decoder: [%s] %s\n", - vd->info->short_name, vd->info->name); - // clear vf init error, it is no longer relevant - if (sh_video->vf_initialized < 0) - sh_video->vf_initialized = 0; - if (!vd->init(sh_video)) { - mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Video decoder init failed for " - "codecs.conf entry \"%s\".\n", sh_video->codec->name); - sh_video->disp_w = orig_w; - sh_video->disp_h = orig_h; - if (sh_video->bih) { - sh_video->bih->biWidth = sh_video->disp_w; - sh_video->bih->biHeight = sh_video->disp_h; - } - continue; // try next... - } - // Yeah! We got it! - sh_video->initialized = 1; - sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE; - sh_video->prev_sorted_pts = MP_NOPTS_VALUE; - return 1; +static const struct vd_functions *find_driver(const char *name) +{ + for (int i = 0; mpcodecs_vd_drivers[i] != NULL; i++) { + if (strcmp(mpcodecs_vd_drivers[i]->name, name) == 0) + return mpcodecs_vd_drivers[i]; } - return 0; + return NULL; } -int init_best_video_codec(sh_video_t *sh_video, char **video_codec_list, - char **video_fm_list) +int init_best_video_codec(sh_video_t *sh_video, char* video_decoders) { - char *vc_l_default[2] = { "", (char *) NULL }; - stringset_t selected; - // hack: - if (!video_codec_list) - video_codec_list = vc_l_default; - // Go through the codec.conf and find the best codec... - sh_video->initialized = 0; - stringset_init(&selected); - while (!sh_video->initialized && *video_codec_list) { - char *video_codec = *(video_codec_list++); - if (video_codec[0]) { - if (video_codec[0] == '-') { - // disable this codec: - stringset_add(&selected, video_codec + 1); - } else { - // forced codec by name: - mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Forced video codec: %s\n", - video_codec); - init_video(sh_video, video_codec, NULL, -1, &selected); - } - } else { - int status; - // try in stability order: UNTESTED, WORKING, BUGGY. never try CRASHING. - if (video_fm_list) { - char **fmlist = video_fm_list; - // try first the preferred codec families: - while (!sh_video->initialized && *fmlist) { - char *video_fm = *(fmlist++); - mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Trying to force video codec driver family %s...\n", - video_fm); - for (status = CODECS_STATUS__MAX; - status >= CODECS_STATUS__MIN; --status) - if (init_video - (sh_video, NULL, video_fm, status, &selected)) - break; - } - } - if (!sh_video->initialized) - for (status = CODECS_STATUS__MAX; status >= CODECS_STATUS__MIN; - --status) - if (init_video(sh_video, NULL, NULL, status, &selected)) - break; + assert(!sh_video->initialized); + + struct mp_decoder_entry *decoder = NULL; + struct mp_decoder_list *list = + mp_select_video_decoders(sh_video->gsh->codec, video_decoders); + + mp_print_decoders(MSGT_DECVIDEO, MSGL_V, "Codec list:", list); + + for (int n = 0; n < list->num_entries; n++) { + struct mp_decoder_entry *sel = &list->entries[n]; + const struct vd_functions *driver = find_driver(sel->family); + if (!driver) + continue; + mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Opening video decoder %s:%s\n", + sel->family, sel->decoder); + sh_video->vd_driver = driver; + if (init_video_codec(sh_video, sel->decoder)) { + decoder = sel; + break; } + sh_video->vd_driver = NULL; + mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "Video decoder init failed for " + "%s:%s\n", sel->family, sel->decoder); } - stringset_free(&selected); - if (!sh_video->initialized) { - mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Cannot find codec matching selected -vo and video format 0x%X.\n", - sh_video->format); - return 0; // failed + if (sh_video->initialized) { + sh_video->gsh->decoder_desc = + talloc_asprintf(NULL, "%s [%s:%s]", decoder->desc, decoder->family, + decoder->decoder); + mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Selected video codec: %s\n", + sh_video->gsh->decoder_desc); + } else { + mp_msg(MSGT_DECVIDEO, MSGL_ERR, + "Failed to initialize a video decoder for codec '%s'.\n", + sh_video->gsh->codec ? sh_video->gsh->codec : "<unknown>"); } - mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Selected video codec: %s [%s]\n", - sh_video->codecname ? sh_video->codecname : sh_video->codec->info, - sh_video->vd_driver->info->print_name ? - sh_video->vd_driver->info->print_name : - sh_video->vd_driver->info->short_name); - mp_tmsg(MSGT_DECVIDEO, MSGL_V, - "Video codecs.conf entry: %s (%s) vfm: %s\n", - sh_video->codec->name, sh_video->codec->info, sh_video->codec->drv); - return 1; // success + talloc_free(list); + return sh_video->initialized; } void *decode_video(sh_video_t *sh_video, struct demux_packet *packet, diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index c7c535c68e..b6b85e86f6 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -22,11 +22,11 @@ #include "demux/stheader.h" struct osd_state; +struct mp_decoder_list; -// dec_video.c: -void vfm_help(void); +struct mp_decoder_list *mp_video_decoder_list(void); -int init_best_video_codec(sh_video_t *sh_video, char** video_codec_list, char** video_fm_list); +int init_best_video_codec(sh_video_t *sh_video, char* video_decoders); void uninit_video(sh_video_t *sh_video); struct demux_packet; diff --git a/video/decode/lavc.h b/video/decode/lavc.h index 4a9077de21..d23c3e85f6 100644 --- a/video/decode/lavc.h +++ b/video/decode/lavc.h @@ -18,7 +18,7 @@ typedef struct ffmpeg_ctx { int best_csp; AVRational last_sample_aspect_ratio; enum AVDiscard skip_frame; - AVCodec *software_fallback; + const char *software_fallback_decoder; struct FramePool *dr1_buffer_pool; struct mp_image_pool *non_dr1_pool; } vd_ffmpeg_ctx; diff --git a/video/decode/vd.c b/video/decode/vd.c index a9c0d21821..99710f43d5 100644 --- a/video/decode/vd.c +++ b/video/decode/vd.c @@ -25,8 +25,6 @@ #include "core/mp_msg.h" #include "core/options.h" -#include "core/codec-cfg.h" - #include "video/img_format.h" #include "stream/stream.h" @@ -114,7 +112,7 @@ int mpcodecs_config_vo(sh_video_t *sh, int w, int h, unsigned int out_fmt) sh->vfilter = vf; // autodetect flipping - bool flip = !!opts->flip != !!(sh->codec->flags & CODECS_FLAG_FLIP); + bool flip = opts->flip; if (flip && !(sh->output_flags & VFCAP_FLIP)) { // we need to flip, but no flipping filter avail. vf_add_before_vo(&vf, "flip", NULL); diff --git a/video/decode/vd.h b/video/decode/vd.h index b3b980fea4..c4c2b7f465 100644 --- a/video/decode/vd.h +++ b/video/decode/vd.h @@ -20,18 +20,17 @@ #define MPLAYER_VD_H #include "video/mp_image.h" -#include "core/mpc_info.h" #include "demux/stheader.h" -typedef struct mp_codec_info vd_info_t; - struct demux_packet; +struct mp_decoder_list; /* interface of video decoder drivers */ typedef struct vd_functions { - const vd_info_t *info; - int (*init)(sh_video_t *sh); + const char *name; + void (*add_decoders)(struct mp_decoder_list *list); + int (*init)(sh_video_t *sh, const char *decoder); void (*uninit)(sh_video_t *sh); int (*control)(sh_video_t *sh, int cmd, void *arg); struct mp_image *(*decode)(struct sh_video *sh, struct demux_packet *pkt, diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 1661ddd210..77fb800994 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -35,6 +35,8 @@ #include "core/mp_msg.h" #include "core/options.h" #include "core/av_opts.h" +#include "core/av_common.h" +#include "core/codecs.h" #include "compat/mpbswap.h" #include "video/fmt-conversion.h" @@ -45,19 +47,9 @@ #include "video/filter/vf.h" #include "demux/stheader.h" #include "demux/demux_packet.h" -#include "core/codec-cfg.h" #include "osdep/numcores.h" #include "video/csputils.h" -static const vd_info_t info = { - "libavcodec video codecs", - "ffmpeg", - "", - "", - "native codecs", - .print_name = "libavcodec", -}; - #include "libavcodec/avcodec.h" #include "lavc.h" @@ -67,7 +59,7 @@ static const vd_info_t info = { #include "core/m_option.h" -static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec); +static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec); static void uninit_avctx(sh_video_t *sh); static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic); static void release_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic); @@ -155,70 +147,53 @@ static enum AVDiscard str2AVDiscard(char *str) return AVDISCARD_DEFAULT; } -static int init(sh_video_t *sh) +static int init(sh_video_t *sh, const char *decoder) { vd_ffmpeg_ctx *ctx; - AVCodec *lavc_codec = NULL; - ctx = sh->context = talloc_zero(NULL, vd_ffmpeg_ctx); ctx->non_dr1_pool = talloc_steal(ctx, mp_image_pool_new(16)); - if (sh->codec->dll) { - lavc_codec = avcodec_find_decoder_by_name(sh->codec->dll); - if (!lavc_codec) { - mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, - "Cannot find codec '%s' in libavcodec...\n", - sh->codec->dll); - uninit(sh); - return 0; - } - } else if (sh->libav_codec_id) { - lavc_codec = avcodec_find_decoder(sh->libav_codec_id); - if (!lavc_codec) { - mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Libavcodec has no decoder " - "for this codec\n"); - uninit(sh); - return 0; - } - } - if (!lavc_codec) { - uninit(sh); - return 0; - } - - struct hwdec *hwdec = find_hwcodec(sh->opts->hwdec_api, lavc_codec->name); + struct hwdec *hwdec = find_hwcodec(sh->opts->hwdec_api, decoder); if (hwdec) { AVCodec *lavc_hwcodec = avcodec_find_decoder_by_name(hwdec->hw_codec); if (lavc_hwcodec) { - ctx->software_fallback = lavc_codec; - lavc_codec = lavc_hwcodec; + ctx->software_fallback_decoder = decoder; + decoder = lavc_hwcodec->name; } else { hwdec = NULL; mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "Using software decoding.\n"); } } - if (!init_avctx(sh, lavc_codec, hwdec)) { - mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error initializing hardware " - "decoding, falling back to software decoding.\n"); - lavc_codec = ctx->software_fallback; - ctx->software_fallback = NULL; - if (!init_avctx(sh, lavc_codec, NULL)) { - uninit(sh); - return 0; + if (!init_avctx(sh, decoder, hwdec)) { + if (ctx->software_fallback_decoder) { + mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error initializing hardware " + "decoding, falling back to software decoding.\n"); + decoder = ctx->software_fallback_decoder; + ctx->software_fallback_decoder = NULL; + if (!init_avctx(sh, decoder, NULL)) { + uninit(sh); + return 0; + } } } return 1; } -static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec) +static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec) { vd_ffmpeg_ctx *ctx = sh->context; struct lavc_param *lavc_param = &sh->opts->lavc_param; + bool mp_rawvideo = false; + + if (strcmp(decoder, "mp-rawvideo") == 0) { + mp_rawvideo = true; + decoder = "rawvideo"; + } - sh->codecname = lavc_codec->long_name; - if (!sh->codecname) - sh->codecname = lavc_codec->name; + AVCodec *lavc_codec = avcodec_find_decoder_by_name(decoder); + if (!lavc_codec) + return 0; ctx->do_dr1 = ctx->do_hw_dr1 = 0; ctx->pix_fmt = PIX_FMT_NONE; @@ -264,8 +239,8 @@ static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec) avctx->flags |= lavc_param->bitexact; - avctx->coded_width = sh->disp_w; - avctx->coded_height = sh->disp_h; + avctx->coded_width = sh->bih ? sh->bih->biWidth : sh->disp_w; + avctx->coded_height = sh->bih ? sh->bih->biHeight : sh->disp_h; avctx->workaround_bugs = lavc_param->workaround_bugs; if (lavc_param->gray) avctx->flags |= CODEC_FLAG_GRAY; @@ -340,14 +315,6 @@ static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec) } break; - case MKTAG('M', 'P', 'v', 'f'): - avctx->codec_tag = 0; - avctx->pix_fmt = imgfmt2pixfmt(sh->imgfmt); - break; - case MKTAG('M', 'P', 'r', 'v'): - avctx->codec_tag = sh->imgfmt; - break; - default: if (!sh->bih || sh->bih->biSize <= sizeof(*sh->bih)) break; @@ -361,6 +328,11 @@ static int init_avctx(sh_video_t *sh, AVCodec *lavc_codec, struct hwdec *hwdec) if (sh->bih) avctx->bits_per_coded_sample = sh->bih->biBitCount; + if (mp_rawvideo && sh->format >= IMGFMT_START && sh->format < IMGFMT_END) { + avctx->pix_fmt = imgfmt2pixfmt(sh->format); + avctx->codec_tag = 0; + } + /* open it */ if (avcodec_open2(avctx, lavc_codec, NULL) < 0) { mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not open codec.\n"); @@ -375,8 +347,6 @@ static void uninit_avctx(sh_video_t *sh) vd_ffmpeg_ctx *ctx = sh->context; AVCodecContext *avctx = ctx->avctx; - sh->codecname = NULL; - if (avctx) { if (avctx->codec && avcodec_close(avctx) < 0) mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not close codec.\n"); @@ -661,14 +631,14 @@ static struct mp_image *decode_with_fallback(struct sh_video *sh, return mpi; // Failed hardware decoding? Try again in software. - if (ctx->software_fallback) { + if (ctx->software_fallback_decoder) { uninit_avctx(sh); sh->vf_initialized = 0; mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error using hardware " "decoding, falling back to software decoding.\n"); - AVCodec *codec = ctx->software_fallback; - ctx->software_fallback = NULL; - if (init_avctx(sh, codec, NULL)) { + const char *decoder = ctx->software_fallback_decoder; + ctx->software_fallback_decoder = NULL; + if (init_avctx(sh, decoder, NULL)) { mpi = NULL; decode(sh, packet, data, len, flags, reordered_pts, &mpi); return mpi; @@ -700,8 +670,16 @@ static int control(sh_video_t *sh, int cmd, void *arg) return CONTROL_UNKNOWN; } +static void add_decoders(struct mp_decoder_list *list) +{ + mp_add_lavc_decoders(list, AVMEDIA_TYPE_VIDEO); + mp_add_decoder(list, "lavc", "mp-rawvideo", "mp-rawvideo", + "raw video"); +} + const struct vd_functions mpcodecs_vd_ffmpeg = { - .info = &info, + .name = "lavc", + .add_decoders = add_decoders, .init = init, .uninit = uninit, .control = control, diff --git a/video/filter/vf.h b/video/filter/vf.h index 44b820c04a..1bc0d5121c 100644 --- a/video/filter/vf.h +++ b/video/filter/vf.h @@ -24,7 +24,6 @@ #include "video/mp_image.h" #include "core/mp_common.h" -#include "core/mpc_info.h" #include "video/vfcap.h" struct MPOpts; diff --git a/video/img_fourcc.h b/video/img_fourcc.h index fecb13f297..ee30ff0c26 100644 --- a/video/img_fourcc.h +++ b/video/img_fourcc.h @@ -40,16 +40,6 @@ #define MP_FOURCC_MJPEG MP_FOURCC('M', 'J', 'P', 'G') -/* mplayer internal FourCCs - * see codecs.conf/vd_lavc.c - */ - -// lavc raw video decoder uses fourcc specified in sh_video->imgfmt -#define MP_FOURCC_RAWVIDEO MP_FOURCC('M', 'P', 'r', 'v') - -// lavc raw video decoder uses image format (IMGFMT_*) in sh_video->imgfmt -#define MP_FOURCC_IMGFMT MP_FOURCC('M', 'P', 'v', 'f') - // NOTE: no "HM12" decoder exists, as vd_hmblck has been removed // likely breaks video with some TV cards #define MP_FOURCC_HM12 0x32314D48 |