1
0
mirror of https://github.com/mpv-player/mpv synced 2025-04-07 01:53:06 +00:00

video: move decoder context from sh_video into new struct

This is similar to the sh_audio commit.

This is mostly cosmetic in nature, except that it also adds automatical
freeing of the decoder driver's state struct (which was in
sh_video->context, now in dec_video->priv).

Also remove all the stheader.h fields that are not needed anymore.
This commit is contained in:
wm4 2013-11-23 21:36:20 +01:00
parent 057af4697c
commit 3486302514
18 changed files with 410 additions and 411 deletions

View File

@ -241,7 +241,6 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type)
.demuxer = demuxer, .demuxer = demuxer,
.index = demuxer->num_streams, .index = demuxer->num_streams,
.demuxer_id = demuxer_id, // may be overwritten by demuxer .demuxer_id = demuxer_id, // may be overwritten by demuxer
.opts = demuxer->opts,
.ds = talloc_zero(sh, struct demux_stream), .ds = talloc_zero(sh, struct demux_stream),
}; };
MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh); MP_TARRAY_APPEND(demuxer, demuxer->streams, demuxer->num_streams, sh);
@ -249,21 +248,18 @@ struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type)
case STREAM_VIDEO: { case STREAM_VIDEO: {
struct sh_video *sht = talloc_zero(demuxer, struct sh_video); struct sh_video *sht = talloc_zero(demuxer, struct sh_video);
sht->gsh = sh; sht->gsh = sh;
sht->opts = sh->opts;
sh->video = sht; sh->video = sht;
break; break;
} }
case STREAM_AUDIO: { case STREAM_AUDIO: {
struct sh_audio *sht = talloc_zero(demuxer, struct sh_audio); struct sh_audio *sht = talloc_zero(demuxer, struct sh_audio);
sht->gsh = sh; sht->gsh = sh;
sht->opts = sh->opts;
sh->audio = sht; sh->audio = sht;
break; break;
} }
case STREAM_SUB: { case STREAM_SUB: {
struct sh_sub *sht = talloc_zero(demuxer, struct sh_sub); struct sh_sub *sht = talloc_zero(demuxer, struct sh_sub);
sht->gsh = sh; sht->gsh = sh;
sht->opts = sh->opts;
sh->sub = sht; sh->sub = sht;
break; break;
} }

View File

@ -63,30 +63,14 @@ struct sh_stream {
// stream is a picture (such as album art) // stream is a picture (such as album art)
struct demux_packet *attached_picture; struct demux_packet *attached_picture;
// Human readable description of the running decoder, or NULL
char *decoder_desc;
// shouldn't exist type of stuff
struct MPOpts *opts;
// Internal to demux.c // Internal to demux.c
struct demux_stream *ds; struct demux_stream *ds;
}; };
#define SH_COMMON \
struct sh_stream *gsh; \
struct MPOpts *opts; \
/* usually a FourCC, exact meaning depends on gsh->format */ \
unsigned int format; \
int initialized; \
/* audio: last known pts value in output from decoder \
* video: predicted/interpolated PTS of the current frame */ \
double pts; \
/* decoder context */ \
void *context; \
typedef struct sh_audio { typedef struct sh_audio {
SH_COMMON struct sh_stream *gsh;
/* usually a FourCC, exact meaning depends on gsh->codec */
unsigned int format;
int samplerate; int samplerate;
struct mp_chmap channels; struct mp_chmap channels;
int i_bps; // == bitrate (compressed bytes/sec) int i_bps; // == bitrate (compressed bytes/sec)
@ -98,37 +82,18 @@ typedef struct sh_audio {
} sh_audio_t; } sh_audio_t;
typedef struct sh_video { typedef struct sh_video {
SH_COMMON struct sh_stream *gsh;
float next_frame_time; /* usually a FourCC, exact meaning depends on gsh->codec */
double last_pts; unsigned int format;
double buffered_pts[32];
int num_buffered_pts;
double codec_reordered_pts;
double prev_codec_reordered_pts;
int num_reordered_pts_problems;
double sorted_pts;
double prev_sorted_pts;
int num_sorted_pts_problems;
int pts_assoc_mode;
// output format: (set by demuxer)
float fps; // frames per second (set only if constant fps) float fps; // frames per second (set only if constant fps)
float aspect; // aspect ratio stored in the file (for prescaling) float aspect; // aspect ratio stored in the file (for prescaling)
float stream_aspect; // aspect ratio in media headers (DVD IFO files)
int i_bps; // == bitrate (compressed bytes/sec) int i_bps; // == bitrate (compressed bytes/sec)
int disp_w, disp_h; // display size (filled by demuxer or decoder) int disp_w, disp_h; // display size
// output driver/filters: (set by libmpcodecs core)
struct vf_instance *vfilter; // video filter chain
const struct vd_functions *vd_driver;
int vf_initialized; // -1 failed, 0 not done, 1 done
long vf_reconfig_count; // incremented each mpcodecs_reconfig_vo() call
struct mp_image_params *vf_input; // video filter input params
struct mp_hwdec_info *hwdec_info; // video output hwdec handles
// win32-compatible codec parameters:
MP_BITMAPINFOHEADER *bih; MP_BITMAPINFOHEADER *bih;
} sh_video_t; } sh_video_t;
typedef struct sh_sub { typedef struct sh_sub {
SH_COMMON struct sh_stream *gsh;
unsigned char *extradata; // extra header data passed from demuxer unsigned char *extradata; // extra header data passed from demuxer
int extradata_len; int extradata_len;
int frame_based; // timestamps are frame-based int frame_based; // timestamps are frame-based

View File

@ -36,6 +36,7 @@
#include "audio/filter/af.h" #include "audio/filter/af.h"
#include "audio/out/ao.h" #include "audio/out/ao.h"
#include "demux/demux.h" #include "demux/demux.h"
#include "video/decode/dec_video.h"
#include "mp_core.h" #include "mp_core.h"
@ -302,7 +303,7 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize)
if (hrseek) if (hrseek)
ptsdiff = written_pts - mpctx->hrseek_pts; ptsdiff = written_pts - mpctx->hrseek_pts;
else else
ptsdiff = written_pts - mpctx->sh_video->pts - mpctx->delay ptsdiff = written_pts - mpctx->d_video->pts - mpctx->delay
- mpctx->audio_delay; - mpctx->audio_delay;
samples = ptsdiff * real_samplerate; samples = ptsdiff * real_samplerate;
@ -376,7 +377,7 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts)
playsize = ao_get_space(ao); playsize = ao_get_space(ao);
// Coming here with hrseek_active still set means audio-only // Coming here with hrseek_active still set means audio-only
if (!mpctx->sh_video || !mpctx->sync_audio_to_video) if (!mpctx->d_video || !mpctx->sync_audio_to_video)
mpctx->syncing_audio = false; mpctx->syncing_audio = false;
if (!opts->initial_audio_sync || !modifiable_audio_format) { if (!opts->initial_audio_sync || !modifiable_audio_format) {
mpctx->syncing_audio = false; mpctx->syncing_audio = false;

View File

@ -316,7 +316,7 @@ static int mp_property_length(m_option_t *prop, int action, void *arg,
static int mp_property_avsync(m_option_t *prop, int action, void *arg, static int mp_property_avsync(m_option_t *prop, int action, void *arg,
MPContext *mpctx) MPContext *mpctx)
{ {
if (!mpctx->d_audio || !mpctx->sh_video) if (!mpctx->d_audio || !mpctx->d_video)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
if (mpctx->last_av_difference == MP_NOPTS_VALUE) if (mpctx->last_av_difference == MP_NOPTS_VALUE)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
@ -623,8 +623,8 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg,
case M_PROPERTY_SET: case M_PROPERTY_SET:
angle = demuxer_set_angle(demuxer, *(int *)arg); angle = demuxer_set_angle(demuxer, *(int *)arg);
if (angle >= 0) { if (angle >= 0) {
if (mpctx->sh_video) if (mpctx->d_video)
resync_video_stream(mpctx->sh_video); video_resync_stream(mpctx->d_video);
if (mpctx->d_audio) if (mpctx->d_audio)
audio_resync_stream(mpctx->d_audio); audio_resync_stream(mpctx->d_audio);
@ -817,7 +817,7 @@ static int mp_property_volrestore(m_option_t *prop, int action,
static int mp_property_audio_delay(m_option_t *prop, int action, static int mp_property_audio_delay(m_option_t *prop, int action,
void *arg, MPContext *mpctx) void *arg, MPContext *mpctx)
{ {
if (!(mpctx->d_audio && mpctx->sh_video)) if (!(mpctx->d_audio && mpctx->d_video))
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
float delay = mpctx->opts->audio_delay; float delay = mpctx->opts->audio_delay;
switch (action) { switch (action) {
@ -1168,7 +1168,7 @@ static int probe_deint_filters(struct MPContext *mpctx, const char *cmd)
static int get_deinterlacing(struct MPContext *mpctx) static int get_deinterlacing(struct MPContext *mpctx)
{ {
vf_instance_t *vf = mpctx->sh_video->vfilter; vf_instance_t *vf = mpctx->d_video->vfilter;
int enabled = 0; int enabled = 0;
if (vf->control(vf, VFCTRL_GET_DEINTERLACE, &enabled) != CONTROL_OK) if (vf->control(vf, VFCTRL_GET_DEINTERLACE, &enabled) != CONTROL_OK)
enabled = -1; enabled = -1;
@ -1182,7 +1182,7 @@ static int get_deinterlacing(struct MPContext *mpctx)
static void set_deinterlacing(struct MPContext *mpctx, bool enable) static void set_deinterlacing(struct MPContext *mpctx, bool enable)
{ {
vf_instance_t *vf = mpctx->sh_video->vfilter; vf_instance_t *vf = mpctx->d_video->vfilter;
if (vf_find_by_label(vf, VF_DEINTERLACE_LABEL)) { if (vf_find_by_label(vf, VF_DEINTERLACE_LABEL)) {
if (!enable) if (!enable)
edit_filters(mpctx, STREAM_VIDEO, "del", "@" VF_DEINTERLACE_LABEL); edit_filters(mpctx, STREAM_VIDEO, "del", "@" VF_DEINTERLACE_LABEL);
@ -1199,7 +1199,7 @@ static void set_deinterlacing(struct MPContext *mpctx, bool enable)
static int mp_property_deinterlace(m_option_t *prop, int action, static int mp_property_deinterlace(m_option_t *prop, int action,
void *arg, MPContext *mpctx) void *arg, MPContext *mpctx)
{ {
if (!mpctx->sh_video || !mpctx->sh_video->vfilter) if (!mpctx->d_video || !mpctx->d_video->vfilter)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
switch (action) { switch (action) {
case M_PROPERTY_GET: case M_PROPERTY_GET:
@ -1218,7 +1218,7 @@ static int video_refresh_property_helper(m_option_t *prop, int action,
{ {
int r = mp_property_generic_option(prop, action, arg, mpctx); int r = mp_property_generic_option(prop, action, arg, mpctx);
if (action == M_PROPERTY_SET) { if (action == M_PROPERTY_SET) {
if (mpctx->sh_video) { if (mpctx->d_video) {
reinit_video_filters(mpctx); reinit_video_filters(mpctx);
mp_force_video_refresh(mpctx); mp_force_video_refresh(mpctx);
} }
@ -1239,8 +1239,8 @@ static int mp_property_colormatrix(m_option_t *prop, int action, void *arg,
vo_control(mpctx->video_out, VOCTRL_GET_YUV_COLORSPACE, &vo_csp); vo_control(mpctx->video_out, VOCTRL_GET_YUV_COLORSPACE, &vo_csp);
struct mp_image_params vd_csp = {0}; struct mp_image_params vd_csp = {0};
if (mpctx->sh_video) if (mpctx->d_video)
vd_control(mpctx->sh_video, VDCTRL_GET_PARAMS, &vd_csp); video_vd_control(mpctx->d_video, VDCTRL_GET_PARAMS, &vd_csp);
char *res = talloc_asprintf(NULL, "%s", char *res = talloc_asprintf(NULL, "%s",
mp_csp_names[opts->requested_colorspace]); mp_csp_names[opts->requested_colorspace]);
@ -1273,8 +1273,8 @@ static int mp_property_colormatrix_input_range(m_option_t *prop, int action,
vo_control(mpctx->video_out, VOCTRL_GET_YUV_COLORSPACE, &vo_csp ); vo_control(mpctx->video_out, VOCTRL_GET_YUV_COLORSPACE, &vo_csp );
struct mp_image_params vd_csp = {0}; struct mp_image_params vd_csp = {0};
if (mpctx->sh_video) if (mpctx->d_video)
vd_control(mpctx->sh_video, VDCTRL_GET_PARAMS, &vd_csp); video_vd_control(mpctx->d_video, VDCTRL_GET_PARAMS, &vd_csp);
char *res = talloc_asprintf(NULL, "%s", char *res = talloc_asprintf(NULL, "%s",
mp_csp_levels_names[opts->requested_input_range]); mp_csp_levels_names[opts->requested_input_range]);
@ -1372,7 +1372,7 @@ static int mp_property_border(m_option_t *prop, int action, void *arg,
static int mp_property_framedrop(m_option_t *prop, int action, static int mp_property_framedrop(m_option_t *prop, int action,
void *arg, MPContext *mpctx) void *arg, MPContext *mpctx)
{ {
if (!mpctx->sh_video) if (!mpctx->d_video)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
return mp_property_generic_option(prop, action, arg, mpctx); return mp_property_generic_option(prop, action, arg, mpctx);
@ -1381,17 +1381,17 @@ static int mp_property_framedrop(m_option_t *prop, int action,
static int mp_property_video_color(m_option_t *prop, int action, void *arg, static int mp_property_video_color(m_option_t *prop, int action, void *arg,
MPContext *mpctx) MPContext *mpctx)
{ {
if (!mpctx->sh_video) if (!mpctx->d_video)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
switch (action) { switch (action) {
case M_PROPERTY_SET: { case M_PROPERTY_SET: {
if (set_video_colors(mpctx->sh_video, prop->name, *(int *) arg) <= 0) if (video_set_colors(mpctx->d_video, prop->name, *(int *) arg) <= 0)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
break; break;
} }
case M_PROPERTY_GET: case M_PROPERTY_GET:
if (get_video_colors(mpctx->sh_video, prop->name, (int *)arg) <= 0) if (video_get_colors(mpctx->d_video, prop->name, (int *)arg) <= 0)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
// Write new value to option variable // Write new value to option variable
mp_property_generic_option(prop, M_PROPERTY_SET, arg, mpctx); mp_property_generic_option(prop, M_PROPERTY_SET, arg, mpctx);
@ -1404,7 +1404,7 @@ static int mp_property_video_color(m_option_t *prop, int action, void *arg,
static int mp_property_video_format(m_option_t *prop, int action, static int mp_property_video_format(m_option_t *prop, int action,
void *arg, MPContext *mpctx) void *arg, MPContext *mpctx)
{ {
const char *c = mpctx->sh_video ? mpctx->sh_video->gsh->codec : NULL; const char *c = mpctx->d_video ? mpctx->d_video->header->codec : NULL;
return m_property_strdup_ro(prop, action, arg, c); return m_property_strdup_ro(prop, action, arg, c);
} }
@ -1412,7 +1412,7 @@ static int mp_property_video_format(m_option_t *prop, int action,
static int mp_property_video_codec(m_option_t *prop, int action, static int mp_property_video_codec(m_option_t *prop, int action,
void *arg, MPContext *mpctx) void *arg, MPContext *mpctx)
{ {
const char *c = mpctx->sh_video ? mpctx->sh_video->gsh->decoder_desc : NULL; const char *c = mpctx->d_video ? mpctx->d_video->decoder_desc : NULL;
return m_property_strdup_ro(prop, action, arg, c); return m_property_strdup_ro(prop, action, arg, c);
} }
@ -1421,42 +1421,44 @@ static int mp_property_video_codec(m_option_t *prop, int action,
static int mp_property_video_bitrate(m_option_t *prop, int action, static int mp_property_video_bitrate(m_option_t *prop, int action,
void *arg, MPContext *mpctx) void *arg, MPContext *mpctx)
{ {
if (!mpctx->sh_video) if (!mpctx->d_video)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
if (action == M_PROPERTY_PRINT) { if (action == M_PROPERTY_PRINT) {
*(char **)arg = format_bitrate(mpctx->sh_video->i_bps); *(char **)arg = format_bitrate(mpctx->d_video->i_bps);
return M_PROPERTY_OK; return M_PROPERTY_OK;
} }
return m_property_int_ro(prop, action, arg, mpctx->sh_video->i_bps); return m_property_int_ro(prop, action, arg, mpctx->d_video->i_bps);
} }
/// Video display width (RO) /// Video display width (RO)
static int mp_property_width(m_option_t *prop, int action, void *arg, static int mp_property_width(m_option_t *prop, int action, void *arg,
MPContext *mpctx) MPContext *mpctx)
{ {
struct sh_video *sh = mpctx->sh_video; struct dec_video *vd = mpctx->d_video;
if (!sh) if (!vd)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
struct sh_video *sh = vd->header->video;
return m_property_int_ro(prop, action, arg, return m_property_int_ro(prop, action, arg,
sh->vf_input ? sh->vf_input->w : sh->disp_w); vd->vf_input ? vd->vf_input->w : sh->disp_w);
} }
/// Video display height (RO) /// Video display height (RO)
static int mp_property_height(m_option_t *prop, int action, void *arg, static int mp_property_height(m_option_t *prop, int action, void *arg,
MPContext *mpctx) MPContext *mpctx)
{ {
struct sh_video *sh = mpctx->sh_video; struct dec_video *vd = mpctx->d_video;
if (!sh) if (!vd)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
struct sh_video *sh = vd->header->video;
return m_property_int_ro(prop, action, arg, return m_property_int_ro(prop, action, arg,
sh->vf_input ? sh->vf_input->h : sh->disp_h); vd->vf_input ? vd->vf_input->h : sh->disp_h);
} }
static int property_vo_wh(m_option_t *prop, int action, void *arg, static int property_vo_wh(m_option_t *prop, int action, void *arg,
MPContext *mpctx, bool get_w) MPContext *mpctx, bool get_w)
{ {
struct vo *vo = mpctx->video_out; struct vo *vo = mpctx->video_out;
if (!mpctx->sh_video && !vo || !vo->hasframe) if (!mpctx->d_video || !vo || !vo->hasframe)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
return m_property_int_ro(prop, action, arg, return m_property_int_ro(prop, action, arg,
get_w ? vo->aspdat.prew : vo->aspdat.preh); get_w ? vo->aspdat.prew : vo->aspdat.preh);
@ -1530,18 +1532,19 @@ static int mp_property_osd_par(m_option_t *prop, int action, void *arg,
static int mp_property_fps(m_option_t *prop, int action, void *arg, static int mp_property_fps(m_option_t *prop, int action, void *arg,
MPContext *mpctx) MPContext *mpctx)
{ {
if (!mpctx->sh_video) if (!mpctx->d_video)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
return m_property_float_ro(prop, action, arg, mpctx->sh_video->fps); return m_property_float_ro(prop, action, arg, mpctx->d_video->header->video->fps);
} }
/// Video aspect (RO) /// Video aspect (RO)
static int mp_property_aspect(m_option_t *prop, int action, void *arg, static int mp_property_aspect(m_option_t *prop, int action, void *arg,
MPContext *mpctx) MPContext *mpctx)
{ {
struct sh_video *sh_video = mpctx->sh_video; if (!mpctx->d_video)
if (!mpctx->sh_video)
return M_PROPERTY_UNAVAILABLE; return M_PROPERTY_UNAVAILABLE;
struct dec_video *d_video = mpctx->d_video;
struct sh_video *sh_video = d_video->header->video;
switch (action) { switch (action) {
case M_PROPERTY_SET: { case M_PROPERTY_SET: {
mpctx->opts->movie_aspect = *(float *)arg; mpctx->opts->movie_aspect = *(float *)arg;
@ -1551,7 +1554,7 @@ static int mp_property_aspect(m_option_t *prop, int action, void *arg,
} }
case M_PROPERTY_GET: { case M_PROPERTY_GET: {
float aspect = -1; float aspect = -1;
struct mp_image_params *params = sh_video->vf_input; struct mp_image_params *params = d_video->vf_input;
if (params && params->d_w && params->d_h) { if (params && params->d_w && params->d_h) {
aspect = (float)params->d_w / params->d_h; aspect = (float)params->d_w / params->d_h;
} else if (sh_video->disp_w && sh_video->disp_h) { } else if (sh_video->disp_w && sh_video->disp_h) {

View File

@ -99,8 +99,9 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
if (mask & INITIALIZED_VCODEC) { if (mask & INITIALIZED_VCODEC) {
mpctx->initialized_flags &= ~INITIALIZED_VCODEC; mpctx->initialized_flags &= ~INITIALIZED_VCODEC;
if (mpctx->sh_video) if (mpctx->d_video)
uninit_video(mpctx->sh_video); video_uninit(mpctx->d_video);
mpctx->d_video = NULL;
cleanup_demux_stream(mpctx, STREAM_VIDEO); cleanup_demux_stream(mpctx, STREAM_VIDEO);
mpctx->sync_audio_to_video = false; mpctx->sync_audio_to_video = false;
} }
@ -113,7 +114,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
mpctx->num_tracks = 0; mpctx->num_tracks = 0;
for (int t = 0; t < STREAM_TYPE_COUNT; t++) for (int t = 0; t < STREAM_TYPE_COUNT; t++)
mpctx->current_track[t] = NULL; mpctx->current_track[t] = NULL;
assert(!mpctx->sh_video && !mpctx->d_audio && !mpctx->sh_sub); assert(!mpctx->d_video && !mpctx->d_audio && !mpctx->sh_sub);
mpctx->master_demuxer = NULL; mpctx->master_demuxer = NULL;
for (int i = 0; i < mpctx->num_sources; i++) { for (int i = 0; i < mpctx->num_sources; i++) {
uninit_subs(mpctx->sources[i]); uninit_subs(mpctx->sources[i]);
@ -269,7 +270,6 @@ static void set_demux_field(struct MPContext *mpctx, enum stream_type type,
mpctx->sh[type] = s; mpctx->sh[type] = s;
// redundant fields for convenience access // redundant fields for convenience access
switch(type) { switch(type) {
case STREAM_VIDEO: mpctx->sh_video = s ? s->video : NULL; break;
case STREAM_SUB: mpctx->sh_sub = s ? s->sub : NULL; break; case STREAM_SUB: mpctx->sh_sub = s ? s->sub : NULL; break;
} }
} }
@ -348,7 +348,7 @@ bool timeline_set_part(struct MPContext *mpctx, int i, bool force)
if (n->source == p->source && !force) if (n->source == p->source && !force)
return false; return false;
enum stop_play_reason orig_stop_play = mpctx->stop_play; enum stop_play_reason orig_stop_play = mpctx->stop_play;
if (!mpctx->sh_video && mpctx->stop_play == KEEP_PLAYING) if (!mpctx->d_video && mpctx->stop_play == KEEP_PLAYING)
mpctx->stop_play = AT_END_OF_FILE; // let audio uninit drain data mpctx->stop_play = AT_END_OF_FILE; // let audio uninit drain data
uninit_player(mpctx, INITIALIZED_VCODEC | (mpctx->opts->fixed_vo ? 0 : INITIALIZED_VO) | (mpctx->opts->gapless_audio ? 0 : INITIALIZED_AO) | INITIALIZED_ACODEC | INITIALIZED_SUB); uninit_player(mpctx, INITIALIZED_VCODEC | (mpctx->opts->fixed_vo ? 0 : INITIALIZED_VO) | (mpctx->opts->gapless_audio ? 0 : INITIALIZED_AO) | INITIALIZED_ACODEC | INITIALIZED_SUB);
mpctx->stop_play = orig_stop_play; mpctx->stop_play = orig_stop_play;
@ -1050,7 +1050,7 @@ static void play_current_file(struct MPContext *mpctx)
assert(mpctx->stream == NULL); assert(mpctx->stream == NULL);
assert(mpctx->demuxer == NULL); assert(mpctx->demuxer == NULL);
assert(mpctx->d_audio == NULL); assert(mpctx->d_audio == NULL);
assert(mpctx->sh_video == NULL); assert(mpctx->d_video == NULL);
assert(mpctx->sh_sub == NULL); assert(mpctx->sh_sub == NULL);
char *stream_filename = mpctx->filename; char *stream_filename = mpctx->filename;
@ -1189,14 +1189,14 @@ goto_reopen_demuxer: ;
//================ SETUP STREAMS ========================== //================ SETUP STREAMS ==========================
if (opts->force_fps && mpctx->sh_video) { if (opts->force_fps && mpctx->d_video) {
mpctx->sh_video->fps = opts->force_fps; mpctx->d_video->header->video->fps = opts->force_fps;
MP_INFO(mpctx, "FPS forced to be %5.3f.\n", mpctx->sh_video->fps); MP_INFO(mpctx, "FPS forced to be %5.3f.\n", mpctx->d_video->header->video->fps);
} }
//==================== START PLAYING ======================= //==================== START PLAYING =======================
if (!mpctx->sh_video && !mpctx->d_audio) { if (!mpctx->d_video && !mpctx->d_audio) {
MP_FATAL(mpctx, "No video or audio streams selected.\n"); MP_FATAL(mpctx, "No video or audio streams selected.\n");
#if HAVE_DVBIN #if HAVE_DVBIN
if (mpctx->stream->type == STREAMTYPE_DVB) { if (mpctx->stream->type == STREAMTYPE_DVB) {

View File

@ -200,7 +200,7 @@ static bool handle_help_options(struct MPContext *mpctx)
opt_exit = 1; opt_exit = 1;
} }
if (opts->video_decoders && strcmp(opts->video_decoders, "help") == 0) { if (opts->video_decoders && strcmp(opts->video_decoders, "help") == 0) {
struct mp_decoder_list *list = mp_video_decoder_list(); struct mp_decoder_list *list = video_decoder_list();
mp_print_decoders(MSGT_CPLAYER, MSGL_INFO, "Video decoders:", list); mp_print_decoders(MSGT_CPLAYER, MSGL_INFO, "Video decoders:", list);
talloc_free(list); talloc_free(list);
opt_exit = 1; opt_exit = 1;

View File

@ -199,9 +199,9 @@ typedef struct MPContext {
struct track *current_track[STREAM_TYPE_COUNT]; struct track *current_track[STREAM_TYPE_COUNT];
struct sh_stream *sh[STREAM_TYPE_COUNT]; struct sh_stream *sh[STREAM_TYPE_COUNT];
struct sh_video *sh_video; // same as sh[STREAM_VIDEO]->video
struct sh_sub *sh_sub; // same as sh[STREAM_SUB]->sub struct sh_sub *sh_sub; // same as sh[STREAM_SUB]->sub
struct dec_video *d_video;
struct dec_audio *d_audio; struct dec_audio *d_audio;
// Uses: accessing metadata (consider ordered chapters case, where the main // Uses: accessing metadata (consider ordered chapters case, where the main

View File

@ -85,7 +85,6 @@ void write_status_line(struct MPContext *mpctx, const char *line)
void print_status(struct MPContext *mpctx) void print_status(struct MPContext *mpctx)
{ {
struct MPOpts *opts = mpctx->opts; struct MPOpts *opts = mpctx->opts;
sh_video_t * const sh_video = mpctx->sh_video;
update_window_title(mpctx, false); update_window_title(mpctx, false);
@ -110,7 +109,7 @@ void print_status(struct MPContext *mpctx)
if (mpctx->d_audio) if (mpctx->d_audio)
saddf(&line, "A"); saddf(&line, "A");
if (mpctx->sh_video) if (mpctx->d_video)
saddf(&line, "V"); saddf(&line, "V");
saddf(&line, ": "); saddf(&line, ": ");
@ -131,7 +130,7 @@ void print_status(struct MPContext *mpctx)
saddf(&line, " x%4.2f", opts->playback_speed); saddf(&line, " x%4.2f", opts->playback_speed);
// A-V sync // A-V sync
if (mpctx->d_audio && sh_video && mpctx->sync_audio_to_video) { if (mpctx->d_audio && mpctx->d_video && mpctx->sync_audio_to_video) {
if (mpctx->last_av_difference != MP_NOPTS_VALUE) if (mpctx->last_av_difference != MP_NOPTS_VALUE)
saddf(&line, " A-V:%7.3f", mpctx->last_av_difference); saddf(&line, " A-V:%7.3f", mpctx->last_av_difference);
else else
@ -152,7 +151,7 @@ void print_status(struct MPContext *mpctx)
#endif #endif
{ {
// VO stats // VO stats
if (sh_video && mpctx->drop_frame_cnt) if (mpctx->d_video && mpctx->drop_frame_cnt)
saddf(&line, " Late: %d", mpctx->drop_frame_cnt); saddf(&line, " Late: %d", mpctx->drop_frame_cnt);
} }

View File

@ -93,7 +93,7 @@ void pause_player(struct MPContext *mpctx)
mpctx->osd_function = 0; mpctx->osd_function = 0;
mpctx->paused_for_cache = false; mpctx->paused_for_cache = false;
if (mpctx->video_out && mpctx->sh_video && mpctx->video_out->config_ok) if (mpctx->video_out && mpctx->d_video && mpctx->video_out->config_ok)
vo_control(mpctx->video_out, VOCTRL_PAUSE, NULL); vo_control(mpctx->video_out, VOCTRL_PAUSE, NULL);
if (mpctx->ao && mpctx->d_audio) if (mpctx->ao && mpctx->d_audio)
@ -126,7 +126,7 @@ void unpause_player(struct MPContext *mpctx)
if (mpctx->ao && mpctx->d_audio) if (mpctx->ao && mpctx->d_audio)
ao_resume(mpctx->ao); ao_resume(mpctx->ao);
if (mpctx->video_out && mpctx->sh_video && mpctx->video_out->config_ok) if (mpctx->video_out && mpctx->d_video && mpctx->video_out->config_ok)
vo_control(mpctx->video_out, VOCTRL_RESUME, NULL); // resume video vo_control(mpctx->video_out, VOCTRL_RESUME, NULL); // resume video
(void)get_relative_time(mpctx); // ignore time that passed during pause (void)get_relative_time(mpctx); // ignore time that passed during pause
} }
@ -153,7 +153,7 @@ static bool redraw_osd(struct MPContext *mpctx)
void add_step_frame(struct MPContext *mpctx, int dir) void add_step_frame(struct MPContext *mpctx, int dir)
{ {
if (!mpctx->sh_video) if (!mpctx->d_video)
return; return;
if (dir > 0) { if (dir > 0) {
mpctx->step_frames += 1; mpctx->step_frames += 1;
@ -169,14 +169,14 @@ void add_step_frame(struct MPContext *mpctx, int dir)
static void seek_reset(struct MPContext *mpctx, bool reset_ao) static void seek_reset(struct MPContext *mpctx, bool reset_ao)
{ {
if (mpctx->sh_video) { if (mpctx->d_video) {
resync_video_stream(mpctx->sh_video); video_resync_stream(mpctx->d_video);
vo_seek_reset(mpctx->video_out); vo_seek_reset(mpctx->video_out);
if (mpctx->sh_video->vf_initialized == 1) if (mpctx->d_video->vf_initialized == 1)
vf_chain_seek_reset(mpctx->sh_video->vfilter); vf_chain_seek_reset(mpctx->d_video->vfilter);
mpctx->sh_video->num_buffered_pts = 0; mpctx->d_video->num_buffered_pts = 0;
mpctx->sh_video->last_pts = MP_NOPTS_VALUE; mpctx->d_video->last_pts = MP_NOPTS_VALUE;
mpctx->sh_video->pts = MP_NOPTS_VALUE; mpctx->d_video->pts = MP_NOPTS_VALUE;
mpctx->video_pts = MP_NOPTS_VALUE; mpctx->video_pts = MP_NOPTS_VALUE;
mpctx->delay = 0; mpctx->delay = 0;
mpctx->time_frame = 0; mpctx->time_frame = 0;
@ -589,7 +589,7 @@ do_seek:
static void update_avsync(struct MPContext *mpctx) static void update_avsync(struct MPContext *mpctx)
{ {
if (!mpctx->d_audio || !mpctx->sh_video) if (!mpctx->d_audio || !mpctx->d_video)
return; return;
double a_pos = playing_audio_pts(mpctx); double a_pos = playing_audio_pts(mpctx);
@ -624,7 +624,7 @@ static void adjust_sync(struct MPContext *mpctx, double frame_time)
return; return;
double a_pts = written_audio_pts(mpctx) - mpctx->delay; double a_pts = written_audio_pts(mpctx) - mpctx->delay;
double v_pts = mpctx->sh_video->pts; double v_pts = mpctx->d_video->pts;
double av_delay = a_pts - v_pts; double av_delay = a_pts - v_pts;
// Try to sync vo_flip() so it will *finish* at given time // Try to sync vo_flip() so it will *finish* at given time
av_delay += mpctx->last_vo_flip_duration; av_delay += mpctx->last_vo_flip_duration;
@ -797,7 +797,7 @@ static void handle_backstep(struct MPContext *mpctx)
double current_pts = mpctx->last_vo_pts; double current_pts = mpctx->last_vo_pts;
mpctx->backstep_active = false; mpctx->backstep_active = false;
bool demuxer_ok = mpctx->demuxer && mpctx->demuxer->accurate_seek; bool demuxer_ok = mpctx->demuxer && mpctx->demuxer->accurate_seek;
if (demuxer_ok && mpctx->sh_video && current_pts != MP_NOPTS_VALUE) { if (demuxer_ok && mpctx->d_video && current_pts != MP_NOPTS_VALUE) {
double seek_pts = find_previous_pts(mpctx, current_pts); double seek_pts = find_previous_pts(mpctx, current_pts);
if (seek_pts != MP_NOPTS_VALUE) { if (seek_pts != MP_NOPTS_VALUE) {
queue_seek(mpctx, MPSEEK_ABSOLUTE, seek_pts, 1); queue_seek(mpctx, MPSEEK_ABSOLUTE, seek_pts, 1);
@ -863,7 +863,7 @@ static void handle_keep_open(struct MPContext *mpctx)
void handle_force_window(struct MPContext *mpctx, bool reconfig) void handle_force_window(struct MPContext *mpctx, bool reconfig)
{ {
// Don't interfere with real video playback // Don't interfere with real video playback
if (mpctx->sh_video) if (mpctx->d_video)
return; return;
struct vo *vo = mpctx->video_out; struct vo *vo = mpctx->video_out;
@ -982,7 +982,7 @@ void run_playloop(struct MPContext *mpctx)
} }
double buffered_audio = -1; double buffered_audio = -1;
while (mpctx->sh_video) { // never loops, for "break;" only while (mpctx->d_video) { // never loops, for "break;" only
struct vo *vo = mpctx->video_out; struct vo *vo = mpctx->video_out;
update_fps(mpctx); update_fps(mpctx);
@ -990,7 +990,7 @@ void run_playloop(struct MPContext *mpctx)
if (!vo->frame_loaded && (!mpctx->paused || mpctx->restart_playback)) { if (!vo->frame_loaded && (!mpctx->paused || mpctx->restart_playback)) {
double frame_time = update_video(mpctx, endpts); double frame_time = update_video(mpctx, endpts);
mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "*** ftime=%5.3f ***\n", frame_time); mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "*** ftime=%5.3f ***\n", frame_time);
if (mpctx->sh_video->vf_initialized < 0) { if (mpctx->d_video->vf_initialized < 0) {
MP_FATAL(mpctx, "\nFATAL: Could not initialize video filters " MP_FATAL(mpctx, "\nFATAL: Could not initialize video filters "
"(-vf) or video output (-vo).\n"); "(-vf) or video output (-vo).\n");
int uninit = INITIALIZED_VCODEC; int uninit = INITIALIZED_VCODEC;
@ -1016,7 +1016,7 @@ void run_playloop(struct MPContext *mpctx)
} }
if (endpts != MP_NOPTS_VALUE) if (endpts != MP_NOPTS_VALUE)
video_left &= mpctx->sh_video->pts < endpts; video_left &= mpctx->d_video->pts < endpts;
handle_heartbeat_cmd(mpctx); handle_heartbeat_cmd(mpctx);
@ -1070,8 +1070,7 @@ void run_playloop(struct MPContext *mpctx)
//=================== FLIP PAGE (VIDEO BLT): ====================== //=================== FLIP PAGE (VIDEO BLT): ======================
vo_new_frame_imminent(vo); vo_new_frame_imminent(vo);
struct sh_video *sh_video = mpctx->sh_video; mpctx->video_pts = mpctx->d_video->pts;
mpctx->video_pts = sh_video->pts;
mpctx->last_vo_pts = mpctx->video_pts; mpctx->last_vo_pts = mpctx->video_pts;
mpctx->playback_pts = mpctx->video_pts; mpctx->playback_pts = mpctx->video_pts;
update_subtitles(mpctx); update_subtitles(mpctx);
@ -1182,7 +1181,7 @@ void run_playloop(struct MPContext *mpctx)
* should trigger after seek only, when we know there's no audio * should trigger after seek only, when we know there's no audio
* buffered. * buffered.
*/ */
if ((mpctx->d_audio || mpctx->sh_video) && !audio_left && !video_left if ((mpctx->d_audio || mpctx->d_video) && !audio_left && !video_left
&& (opts->gapless_audio || buffered_audio < 0.05) && (opts->gapless_audio || buffered_audio < 0.05)
&& (!mpctx->paused || was_restart)) { && (!mpctx->paused || was_restart)) {
if (end_is_chapter) { if (end_is_chapter) {

View File

@ -315,8 +315,8 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode)
struct voctrl_screenshot_args args = struct voctrl_screenshot_args args =
{ .full_window = (mode == MODE_FULL_WINDOW) }; { .full_window = (mode == MODE_FULL_WINDOW) };
if (mpctx->sh_video && mpctx->sh_video->vfilter) { if (mpctx->d_video && mpctx->d_video->vfilter) {
struct vf_instance *vfilter = mpctx->sh_video->vfilter; struct vf_instance *vfilter = mpctx->d_video->vfilter;
vfilter->control(vfilter, VFCTRL_SCREENSHOT, &args); vfilter->control(vfilter, VFCTRL_SCREENSHOT, &args);
} }

View File

@ -33,6 +33,7 @@
#include "sub/dec_sub.h" #include "sub/dec_sub.h"
#include "demux/demux.h" #include "demux/demux.h"
#include "video/mp_image.h" #include "video/mp_image.h"
#include "video/decode/dec_video.h"
#include "mp_core.h" #include "mp_core.h"
@ -83,8 +84,8 @@ void update_subtitles(struct MPContext *mpctx)
assert(track && sh_sub); assert(track && sh_sub);
struct dec_sub *dec_sub = sh_sub->dec_sub; struct dec_sub *dec_sub = sh_sub->dec_sub;
if (mpctx->sh_video && mpctx->sh_video->vf_input) { if (mpctx->d_video && mpctx->d_video->vf_input) {
struct mp_image_params params = *mpctx->sh_video->vf_input; struct mp_image_params params = *mpctx->d_video->vf_input;
sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, &params); sub_control(dec_sub, SD_CTRL_SET_VIDEO_PARAMS, &params);
} }
@ -194,9 +195,11 @@ void reinit_subs(struct MPContext *mpctx)
assert(dec_sub); assert(dec_sub);
if (!sub_is_initialized(dec_sub)) { if (!sub_is_initialized(dec_sub)) {
int w = mpctx->sh_video ? mpctx->sh_video->disp_w : 0; struct sh_video *sh_video =
int h = mpctx->sh_video ? mpctx->sh_video->disp_h : 0; mpctx->d_video ? mpctx->d_video->header->video : NULL;
float fps = mpctx->sh_video ? mpctx->sh_video->fps : 25; int w = sh_video ? sh_video->disp_w : 0;
int h = sh_video ? sh_video->disp_h : 0;
float fps = sh_video ? sh_video->fps : 25;
set_dvdsub_fake_extradata(dec_sub, track->demuxer->stream, w, h); set_dvdsub_fake_extradata(dec_sub, track->demuxer->stream, w, h);
sub_set_video_res(dec_sub, w, h); sub_set_video_res(dec_sub, w, h);

View File

@ -46,63 +46,64 @@
void update_fps(struct MPContext *mpctx) void update_fps(struct MPContext *mpctx)
{ {
#if HAVE_ENCODING #if HAVE_ENCODING
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
if (mpctx->encode_lavc_ctx && sh_video) if (mpctx->encode_lavc_ctx && d_video)
encode_lavc_set_video_fps(mpctx->encode_lavc_ctx, sh_video->fps); encode_lavc_set_video_fps(mpctx->encode_lavc_ctx, d_video->header->video->fps);
#endif #endif
} }
static void recreate_video_filters(struct MPContext *mpctx) static void recreate_video_filters(struct MPContext *mpctx)
{ {
struct MPOpts *opts = mpctx->opts; struct MPOpts *opts = mpctx->opts;
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
assert(sh_video); assert(d_video);
vf_uninit_filter_chain(sh_video->vfilter); vf_uninit_filter_chain(d_video->vfilter);
char *vf_arg[] = { char *vf_arg[] = {
"_oldargs_", (char *)mpctx->video_out, NULL "_oldargs_", (char *)mpctx->video_out, NULL
}; };
sh_video->vfilter = vf_open_filter(opts, NULL, "vo", vf_arg); d_video->vfilter = vf_open_filter(opts, NULL, "vo", vf_arg);
sh_video->vfilter = append_filters(sh_video->vfilter, opts->vf_settings); d_video->vfilter = append_filters(d_video->vfilter, opts->vf_settings);
struct vf_instance *vf = sh_video->vfilter; struct vf_instance *vf = d_video->vfilter;
mpctx->osd->render_subs_in_filter mpctx->osd->render_subs_in_filter
= vf->control(vf, VFCTRL_INIT_OSD, NULL) == VO_TRUE; = vf->control(vf, VFCTRL_INIT_OSD, NULL) == VO_TRUE;
} }
int reinit_video_filters(struct MPContext *mpctx) int reinit_video_filters(struct MPContext *mpctx)
{ {
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
if (!sh_video) if (!d_video)
return -2; return -2;
recreate_video_filters(mpctx); recreate_video_filters(mpctx);
video_reinit_vo(sh_video); video_reinit_vo(d_video);
return sh_video->vf_initialized > 0 ? 0 : -1; return d_video->vf_initialized > 0 ? 0 : -1;
} }
int reinit_video_chain(struct MPContext *mpctx) int reinit_video_chain(struct MPContext *mpctx)
{ {
struct MPOpts *opts = mpctx->opts; struct MPOpts *opts = mpctx->opts;
assert(!(mpctx->initialized_flags & INITIALIZED_VCODEC)); assert(!(mpctx->initialized_flags & INITIALIZED_VCODEC));
assert(!mpctx->d_video);
init_demux_stream(mpctx, STREAM_VIDEO); init_demux_stream(mpctx, STREAM_VIDEO);
sh_video_t *sh_video = mpctx->sh_video; struct sh_stream *sh = mpctx->sh[STREAM_VIDEO];
if (!sh_video) if (!sh)
goto no_video; goto no_video;
MP_VERBOSE(mpctx, "[V] fourcc:0x%X size:%dx%d fps:%5.3f\n", MP_VERBOSE(mpctx, "[V] fourcc:0x%X size:%dx%d fps:%5.3f\n",
mpctx->sh_video->format, sh->video->format,
mpctx->sh_video->disp_w, mpctx->sh_video->disp_h, sh->video->disp_w, sh->video->disp_h,
mpctx->sh_video->fps); sh->video->fps);
if (opts->force_fps) if (opts->force_fps)
mpctx->sh_video->fps = opts->force_fps; sh->video->fps = opts->force_fps;
update_fps(mpctx); update_fps(mpctx);
if (!mpctx->sh_video->fps && !opts->force_fps && !opts->correct_pts) { if (!sh->video->fps && !opts->force_fps && !opts->correct_pts) {
MP_ERR(mpctx, "FPS not specified in the " MP_ERR(mpctx, "FPS not specified in the "
"header or invalid, use the -fps option.\n"); "header or invalid, use the -fps option.\n");
} }
@ -121,26 +122,31 @@ int reinit_video_chain(struct MPContext *mpctx)
mpctx->initialized_flags |= INITIALIZED_VO; mpctx->initialized_flags |= INITIALIZED_VO;
} }
// dynamic allocation only to make stheader.h lighter
talloc_free(sh_video->hwdec_info);
sh_video->hwdec_info = talloc_zero(sh_video, struct mp_hwdec_info);
vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, sh_video->hwdec_info);
update_window_title(mpctx, true); update_window_title(mpctx, true);
if (stream_control(mpctx->sh_video->gsh->demuxer->stream, struct dec_video *d_video = talloc_zero(NULL, struct dec_video);
STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED) mpctx->d_video = d_video;
mpctx->sh_video->stream_aspect = ar; d_video->last_pts = MP_NOPTS_VALUE;
d_video->opts = mpctx->opts;
d_video->header = sh;
mpctx->initialized_flags |= INITIALIZED_VCODEC;
// dynamic allocation only to make stheader.h lighter
talloc_free(d_video->hwdec_info);
d_video->hwdec_info = talloc_zero(d_video, struct mp_hwdec_info);
vo_control(mpctx->video_out, VOCTRL_GET_HWDEC_INFO, d_video->hwdec_info);
if (stream_control(sh->demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar)
!= STREAM_UNSUPPORTED)
d_video->stream_aspect = ar;
recreate_video_filters(mpctx); recreate_video_filters(mpctx);
init_best_video_codec(sh_video, opts->video_decoders); video_init_best_codec(d_video, opts->video_decoders);
if (!sh_video->initialized) if (!d_video->initialized)
goto err_out; goto err_out;
mpctx->initialized_flags |= INITIALIZED_VCODEC;
bool saver_state = opts->pause || !opts->stop_screensaver; bool saver_state = opts->pause || !opts->stop_screensaver;
vo_control(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER vo_control(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER
: VOCTRL_KILL_SCREENSAVER, NULL); : VOCTRL_KILL_SCREENSAVER, NULL);
@ -148,12 +154,9 @@ int reinit_video_chain(struct MPContext *mpctx)
vo_control(mpctx->video_out, mpctx->paused ? VOCTRL_PAUSE vo_control(mpctx->video_out, mpctx->paused ? VOCTRL_PAUSE
: VOCTRL_RESUME, NULL); : VOCTRL_RESUME, NULL);
sh_video->last_pts = MP_NOPTS_VALUE;
sh_video->num_buffered_pts = 0;
sh_video->next_frame_time = 0;
mpctx->last_vf_reconfig_count = 0; mpctx->last_vf_reconfig_count = 0;
mpctx->restart_playback = true; mpctx->restart_playback = true;
mpctx->sync_audio_to_video = !sh_video->gsh->attached_picture; mpctx->sync_audio_to_video = !sh->attached_picture;
mpctx->delay = 0; mpctx->delay = 0;
mpctx->vo_pts_history_seek_ts++; mpctx->vo_pts_history_seek_ts++;
@ -185,10 +188,10 @@ void mp_force_video_refresh(struct MPContext *mpctx)
static bool filter_output_queued_frame(struct MPContext *mpctx) static bool filter_output_queued_frame(struct MPContext *mpctx)
{ {
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
struct vo *video_out = mpctx->video_out; struct vo *video_out = mpctx->video_out;
struct mp_image *img = vf_chain_output_queued_frame(sh_video->vfilter); struct mp_image *img = vf_chain_output_queued_frame(d_video->vfilter);
if (img) if (img)
vo_queue_image(video_out, img); vo_queue_image(video_out, img);
talloc_free(img); talloc_free(img);
@ -208,16 +211,16 @@ static bool load_next_vo_frame(struct MPContext *mpctx, bool eof)
static void init_filter_params(struct MPContext *mpctx) static void init_filter_params(struct MPContext *mpctx)
{ {
struct MPOpts *opts = mpctx->opts; struct MPOpts *opts = mpctx->opts;
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
// Note that the video decoder already initializes the filter chain. This // Note that the video decoder already initializes the filter chain. This
// might recreate the chain a second time, which is not very elegant, but // might recreate the chain a second time, which is not very elegant, but
// allows us to test whether enabling deinterlacing works with the current // allows us to test whether enabling deinterlacing works with the current
// video format and other filters. // video format and other filters.
if (sh_video->vf_initialized != 1) if (d_video->vf_initialized != 1)
return; return;
if (sh_video->vf_reconfig_count <= mpctx->last_vf_reconfig_count) { if (d_video->vf_reconfig_count <= mpctx->last_vf_reconfig_count) {
if (opts->deinterlace >= 0) { if (opts->deinterlace >= 0) {
mp_property_do("deinterlace", M_PROPERTY_SET, &opts->deinterlace, mp_property_do("deinterlace", M_PROPERTY_SET, &opts->deinterlace,
mpctx); mpctx);
@ -225,18 +228,18 @@ static void init_filter_params(struct MPContext *mpctx)
} }
// Setting filter params has to be "stable" (no change if params already // Setting filter params has to be "stable" (no change if params already
// set) - checking the reconfig count is just an optimization. // set) - checking the reconfig count is just an optimization.
mpctx->last_vf_reconfig_count = sh_video->vf_reconfig_count; mpctx->last_vf_reconfig_count = d_video->vf_reconfig_count;
} }
static void filter_video(struct MPContext *mpctx, struct mp_image *frame) static void filter_video(struct MPContext *mpctx, struct mp_image *frame)
{ {
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
init_filter_params(mpctx); init_filter_params(mpctx);
frame->pts = sh_video->pts; frame->pts = d_video->pts;
mp_image_set_params(frame, sh_video->vf_input); mp_image_set_params(frame, d_video->vf_input);
vf_filter_frame(sh_video->vfilter, frame); vf_filter_frame(d_video->vfilter, frame);
filter_output_queued_frame(mpctx); filter_output_queued_frame(mpctx);
} }
@ -249,8 +252,9 @@ static int check_framedrop(struct MPContext *mpctx, double frame_time)
{ {
float delay = opts->playback_speed * ao_get_delay(mpctx->ao); float delay = opts->playback_speed * ao_get_delay(mpctx->ao);
float d = delay - mpctx->delay; float d = delay - mpctx->delay;
float fps = mpctx->d_video->header->video->fps;
if (frame_time < 0) if (frame_time < 0)
frame_time = mpctx->sh_video->fps > 0 ? 1.0 / mpctx->sh_video->fps : 0; frame_time = fps > 0 ? 1.0 / fps : 0;
// we should avoid dropping too many frames in sequence unless we // we should avoid dropping too many frames in sequence unless we
// are too late. and we allow 100ms A-V delay here: // are too late. and we allow 100ms A-V delay here:
if (d < -mpctx->dropped_frames * frame_time - 0.100 && !mpctx->paused if (d < -mpctx->dropped_frames * frame_time - 0.100 && !mpctx->paused
@ -266,24 +270,25 @@ static int check_framedrop(struct MPContext *mpctx, double frame_time)
static struct demux_packet *video_read_frame(struct MPContext *mpctx) static struct demux_packet *video_read_frame(struct MPContext *mpctx)
{ {
sh_video_t *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
demuxer_t *demuxer = sh_video->gsh->demuxer; sh_video_t *sh_video = d_video->header->video;
float pts1 = sh_video->last_pts; demuxer_t *demuxer = d_video->header->demuxer;
float pts1 = d_video->last_pts;
struct demux_packet *pkt = demux_read_packet(sh_video->gsh); struct demux_packet *pkt = demux_read_packet(d_video->header);
if (!pkt) if (!pkt)
return NULL; // EOF return NULL; // EOF
if (pkt->pts != MP_NOPTS_VALUE) if (pkt->pts != MP_NOPTS_VALUE)
sh_video->last_pts = pkt->pts; d_video->last_pts = pkt->pts;
float frame_time = sh_video->fps > 0 ? 1.0f / sh_video->fps : 0; float frame_time = sh_video->fps > 0 ? 1.0f / sh_video->fps : 0;
// override frame_time for variable/unknown FPS formats: // override frame_time for variable/unknown FPS formats:
if (!mpctx->opts->force_fps) { if (!mpctx->opts->force_fps) {
double next_pts = demux_get_next_pts(sh_video->gsh); double next_pts = demux_get_next_pts(d_video->header);
double d = next_pts == MP_NOPTS_VALUE ? sh_video->last_pts - pts1 double d = next_pts == MP_NOPTS_VALUE ? d_video->last_pts - pts1
: next_pts - sh_video->last_pts; : next_pts - d_video->last_pts;
if (d >= 0) { if (d >= 0) {
if (demuxer->type == DEMUXER_TYPE_TV) { if (demuxer->type == DEMUXER_TYPE_TV) {
if (d > 0) if (d > 0)
@ -296,20 +301,20 @@ static struct demux_packet *video_read_frame(struct MPContext *mpctx)
} }
} }
sh_video->pts = sh_video->last_pts; d_video->pts = d_video->last_pts;
sh_video->next_frame_time = frame_time; d_video->next_frame_time = frame_time;
return pkt; return pkt;
} }
static double update_video_nocorrect_pts(struct MPContext *mpctx) static double update_video_nocorrect_pts(struct MPContext *mpctx)
{ {
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
double frame_time = 0; double frame_time = 0;
while (1) { while (1) {
// In nocorrect-pts mode there is no way to properly time these frames // In nocorrect-pts mode there is no way to properly time these frames
if (load_next_vo_frame(mpctx, false)) if (load_next_vo_frame(mpctx, false))
break; break;
frame_time = sh_video->next_frame_time; frame_time = d_video->next_frame_time;
if (mpctx->restart_playback) if (mpctx->restart_playback)
frame_time = 0; frame_time = 0;
struct demux_packet *pkt = video_read_frame(mpctx); struct demux_packet *pkt = video_read_frame(mpctx);
@ -321,8 +326,8 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
update_fps(mpctx); update_fps(mpctx);
int framedrop_type = check_framedrop(mpctx, frame_time); int framedrop_type = check_framedrop(mpctx, frame_time);
void *decoded_frame = decode_video(sh_video, pkt, framedrop_type, void *decoded_frame = video_decode(d_video, pkt, framedrop_type,
sh_video->pts); d_video->pts);
talloc_free(pkt); talloc_free(pkt);
if (decoded_frame) { if (decoded_frame) {
filter_video(mpctx, decoded_frame); filter_video(mpctx, decoded_frame);
@ -334,62 +339,61 @@ static double update_video_nocorrect_pts(struct MPContext *mpctx)
static double update_video_attached_pic(struct MPContext *mpctx) static double update_video_attached_pic(struct MPContext *mpctx)
{ {
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
// Try to decode the picture multiple times, until it is displayed. // Try to decode the picture multiple times, until it is displayed.
if (mpctx->video_out->hasframe) if (mpctx->video_out->hasframe)
return -1; return -1;
struct mp_image *decoded_frame = struct mp_image *decoded_frame =
decode_video(sh_video, sh_video->gsh->attached_picture, 0, 0); video_decode(d_video, d_video->header->attached_picture, 0, 0);
if (decoded_frame) if (decoded_frame)
filter_video(mpctx, decoded_frame); filter_video(mpctx, decoded_frame);
load_next_vo_frame(mpctx, true); load_next_vo_frame(mpctx, true);
mpctx->sh_video->pts = MP_NOPTS_VALUE; d_video->pts = MP_NOPTS_VALUE;
return 0; return 0;
} }
static void determine_frame_pts(struct MPContext *mpctx) static void determine_frame_pts(struct MPContext *mpctx)
{ {
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
struct MPOpts *opts = mpctx->opts; struct MPOpts *opts = mpctx->opts;
if (opts->user_pts_assoc_mode) if (opts->user_pts_assoc_mode)
sh_video->pts_assoc_mode = opts->user_pts_assoc_mode; d_video->pts_assoc_mode = opts->user_pts_assoc_mode;
else if (sh_video->pts_assoc_mode == 0) { else if (d_video->pts_assoc_mode == 0) {
if (mpctx->sh_video->gsh->demuxer->timestamp_type == TIMESTAMP_TYPE_PTS if (d_video->header->demuxer->timestamp_type == TIMESTAMP_TYPE_PTS
&& sh_video->codec_reordered_pts != MP_NOPTS_VALUE) && d_video->codec_reordered_pts != MP_NOPTS_VALUE)
sh_video->pts_assoc_mode = 1; d_video->pts_assoc_mode = 1;
else else
sh_video->pts_assoc_mode = 2; d_video->pts_assoc_mode = 2;
} else { } else {
int probcount1 = sh_video->num_reordered_pts_problems; int probcount1 = d_video->num_reordered_pts_problems;
int probcount2 = sh_video->num_sorted_pts_problems; int probcount2 = d_video->num_sorted_pts_problems;
if (sh_video->pts_assoc_mode == 2) { if (d_video->pts_assoc_mode == 2) {
int tmp = probcount1; int tmp = probcount1;
probcount1 = probcount2; probcount1 = probcount2;
probcount2 = tmp; probcount2 = tmp;
} }
if (probcount1 >= probcount2 * 1.5 + 2) { if (probcount1 >= probcount2 * 1.5 + 2) {
sh_video->pts_assoc_mode = 3 - sh_video->pts_assoc_mode; d_video->pts_assoc_mode = 3 - d_video->pts_assoc_mode;
MP_VERBOSE(mpctx, "Switching to pts association mode " MP_VERBOSE(mpctx, "Switching to pts association mode "
"%d.\n", sh_video->pts_assoc_mode); "%d.\n", d_video->pts_assoc_mode);
} }
} }
sh_video->pts = sh_video->pts_assoc_mode == 1 ? d_video->pts = d_video->pts_assoc_mode == 1 ?
sh_video->codec_reordered_pts : sh_video->sorted_pts; d_video->codec_reordered_pts : d_video->sorted_pts;
} }
double update_video(struct MPContext *mpctx, double endpts) double update_video(struct MPContext *mpctx, double endpts)
{ {
struct sh_video *sh_video = mpctx->sh_video; struct dec_video *d_video = mpctx->d_video;
struct vo *video_out = mpctx->video_out; struct vo *video_out = mpctx->video_out;
sh_video->vfilter->control(sh_video->vfilter, VFCTRL_SET_OSD_OBJ, vf_control(d_video->vfilter, VFCTRL_SET_OSD_OBJ, mpctx->osd); // for vf_sub
mpctx->osd); // for vf_sub
if (!mpctx->opts->correct_pts) if (!mpctx->opts->correct_pts)
return update_video_nocorrect_pts(mpctx); return update_video_nocorrect_pts(mpctx);
if (sh_video->gsh->attached_picture) if (d_video->header->attached_picture)
return update_video_attached_pic(mpctx); return update_video_attached_pic(mpctx);
double pts; double pts;
@ -400,7 +404,7 @@ double update_video(struct MPContext *mpctx, double endpts)
pts = MP_NOPTS_VALUE; pts = MP_NOPTS_VALUE;
struct demux_packet *pkt = NULL; struct demux_packet *pkt = NULL;
while (1) { while (1) {
pkt = demux_read_packet(mpctx->sh_video->gsh); pkt = demux_read_packet(d_video->header);
if (!pkt || pkt->len) if (!pkt || pkt->len)
break; break;
/* Packets with size 0 are assumed to not correspond to frames, /* Packets with size 0 are assumed to not correspond to frames,
@ -417,7 +421,7 @@ double update_video(struct MPContext *mpctx, double endpts)
int framedrop_type = mpctx->hrseek_active && mpctx->hrseek_framedrop ? int framedrop_type = mpctx->hrseek_active && mpctx->hrseek_framedrop ?
1 : check_framedrop(mpctx, -1); 1 : check_framedrop(mpctx, -1);
struct mp_image *decoded_frame = struct mp_image *decoded_frame =
decode_video(sh_video, pkt, framedrop_type, pts); video_decode(d_video, pkt, framedrop_type, pts);
talloc_free(pkt); talloc_free(pkt);
if (decoded_frame) { if (decoded_frame) {
determine_frame_pts(mpctx); determine_frame_pts(mpctx);
@ -436,9 +440,9 @@ double update_video(struct MPContext *mpctx, double endpts)
if (pts == MP_NOPTS_VALUE) { if (pts == MP_NOPTS_VALUE) {
MP_ERR(mpctx, "Video pts after filters MISSING\n"); MP_ERR(mpctx, "Video pts after filters MISSING\n");
// Try to use decoder pts from before filters // Try to use decoder pts from before filters
pts = sh_video->pts; pts = d_video->pts;
if (pts == MP_NOPTS_VALUE) if (pts == MP_NOPTS_VALUE)
pts = sh_video->last_pts; pts = d_video->last_pts;
} }
if (endpts == MP_NOPTS_VALUE || pts < endpts) if (endpts == MP_NOPTS_VALUE || pts < endpts)
add_frame_pts(mpctx, pts); add_frame_pts(mpctx, pts);
@ -447,29 +451,29 @@ double update_video(struct MPContext *mpctx, double endpts)
return 0; return 0;
} }
mpctx->hrseek_active = false; mpctx->hrseek_active = false;
sh_video->pts = pts; d_video->pts = pts;
if (sh_video->last_pts == MP_NOPTS_VALUE) if (d_video->last_pts == MP_NOPTS_VALUE) {
sh_video->last_pts = sh_video->pts; d_video->last_pts = d_video->pts;
else if (sh_video->last_pts > sh_video->pts) { } else if (d_video->last_pts > d_video->pts) {
MP_WARN(mpctx, "Decreasing video pts: %f < %f\n", MP_WARN(mpctx, "Decreasing video pts: %f < %f\n",
sh_video->pts, sh_video->last_pts); d_video->pts, d_video->last_pts);
/* If the difference in pts is small treat it as jitter around the /* If the difference in pts is small treat it as jitter around the
* right value (possibly caused by incorrect timestamp ordering) and * right value (possibly caused by incorrect timestamp ordering) and
* just show this frame immediately after the last one. * just show this frame immediately after the last one.
* Treat bigger differences as timestamp resets and start counting * Treat bigger differences as timestamp resets and start counting
* timing of later frames from the position of this one. */ * timing of later frames from the position of this one. */
if (sh_video->last_pts - sh_video->pts > 0.5) if (d_video->last_pts - d_video->pts > 0.5)
sh_video->last_pts = sh_video->pts; d_video->last_pts = d_video->pts;
else else
sh_video->pts = sh_video->last_pts; d_video->pts = d_video->last_pts;
} else if (sh_video->pts >= sh_video->last_pts + 60) { } else if (d_video->pts >= d_video->last_pts + 60) {
// Assume a PTS difference >= 60 seconds is a discontinuity. // Assume a PTS difference >= 60 seconds is a discontinuity.
MP_WARN(mpctx, "Jump in video pts: %f -> %f\n", MP_WARN(mpctx, "Jump in video pts: %f -> %f\n",
sh_video->last_pts, sh_video->pts); d_video->last_pts, d_video->pts);
sh_video->last_pts = sh_video->pts; d_video->last_pts = d_video->pts;
} }
double frame_time = sh_video->pts - sh_video->last_pts; double frame_time = d_video->pts - d_video->last_pts;
sh_video->last_pts = sh_video->pts; d_video->last_pts = d_video->pts;
if (mpctx->d_audio) if (mpctx->d_audio)
mpctx->delay -= frame_time; mpctx->delay -= frame_time;
return frame_time; return frame_time;

View File

@ -56,17 +56,17 @@ const vd_functions_t * const mpcodecs_vd_drivers[] = {
NULL NULL
}; };
int vd_control(struct sh_video *sh_video, int cmd, void *arg) int video_vd_control(struct dec_video *d_video, int cmd, void *arg)
{ {
const struct vd_functions *vd = sh_video->vd_driver; const struct vd_functions *vd = d_video->vd_driver;
if (vd) if (vd)
return vd->control(sh_video, cmd, arg); return vd->control(d_video, cmd, arg);
return CONTROL_UNKNOWN; return CONTROL_UNKNOWN;
} }
int set_video_colors(sh_video_t *sh_video, const char *item, int value) int video_set_colors(struct dec_video *d_video, const char *item, int value)
{ {
vf_instance_t *vf = sh_video->vfilter; vf_instance_t *vf = d_video->vfilter;
vf_equalizer_t data; vf_equalizer_t data;
data.item = item; data.item = item;
@ -83,9 +83,9 @@ int set_video_colors(sh_video_t *sh_video, const char *item, int value)
return 0; return 0;
} }
int get_video_colors(sh_video_t *sh_video, const char *item, int *value) int video_get_colors(struct dec_video *d_video, const char *item, int *value)
{ {
vf_instance_t *vf = sh_video->vfilter; vf_instance_t *vf = d_video->vfilter;
vf_equalizer_t data; vf_equalizer_t data;
data.item = item; data.item = item;
@ -101,55 +101,48 @@ int get_video_colors(sh_video_t *sh_video, const char *item, int *value)
return 0; return 0;
} }
void resync_video_stream(sh_video_t *sh_video) void video_resync_stream(struct dec_video *d_video)
{ {
vd_control(sh_video, VDCTRL_RESYNC_STREAM, NULL); video_vd_control(d_video, VDCTRL_RESYNC_STREAM, NULL);
sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE; d_video->prev_codec_reordered_pts = MP_NOPTS_VALUE;
sh_video->prev_sorted_pts = MP_NOPTS_VALUE; d_video->prev_sorted_pts = MP_NOPTS_VALUE;
} }
void video_reinit_vo(struct sh_video *sh_video) void video_reinit_vo(struct dec_video *d_video)
{ {
vd_control(sh_video, VDCTRL_REINIT_VO, NULL); video_vd_control(d_video, VDCTRL_REINIT_VO, NULL);
} }
int get_current_video_decoder_lag(sh_video_t *sh_video) void video_uninit(struct dec_video *d_video)
{ {
int ret = -1; if (d_video->initialized) {
vd_control(sh_video, VDCTRL_QUERY_UNSEEN_FRAMES, &ret); mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Uninit video.\n");
return ret; d_video->vd_driver->uninit(d_video);
}
talloc_free(d_video->priv);
d_video->priv = NULL;
vf_uninit_filter_chain(d_video->vfilter);
d_video->vfilter = NULL;
talloc_free(d_video);
} }
void uninit_video(sh_video_t *sh_video) static int init_video_codec(struct dec_video *d_video, const char *decoder)
{ {
if (!sh_video->initialized) assert(!d_video->initialized);
return;
mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Uninit video.\n");
sh_video->vd_driver->uninit(sh_video);
vf_uninit_filter_chain(sh_video->vfilter);
sh_video->vfilter = NULL;
talloc_free(sh_video->gsh->decoder_desc);
sh_video->gsh->decoder_desc = NULL;
sh_video->initialized = 0;
}
static int init_video_codec(sh_video_t *sh_video, const char *decoder) if (!d_video->vd_driver->init(d_video, decoder)) {
{
assert(!sh_video->initialized);
if (!sh_video->vd_driver->init(sh_video, decoder)) {
mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Video decoder init failed.\n"); mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Video decoder init failed.\n");
//uninit_video(sh_video); //uninit_video(d_video);
return 0; return 0;
} }
sh_video->initialized = 1; d_video->initialized = 1;
sh_video->prev_codec_reordered_pts = MP_NOPTS_VALUE; d_video->prev_codec_reordered_pts = MP_NOPTS_VALUE;
sh_video->prev_sorted_pts = MP_NOPTS_VALUE; d_video->prev_sorted_pts = MP_NOPTS_VALUE;
return 1; return 1;
} }
struct mp_decoder_list *mp_video_decoder_list(void) struct mp_decoder_list *video_decoder_list(void)
{ {
struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list); struct mp_decoder_list *list = talloc_zero(NULL, struct mp_decoder_list);
for (int i = 0; mpcodecs_vd_drivers[i] != NULL; i++) for (int i = 0; mpcodecs_vd_drivers[i] != NULL; i++)
@ -160,7 +153,7 @@ struct mp_decoder_list *mp_video_decoder_list(void)
static struct mp_decoder_list *mp_select_video_decoders(const char *codec, static struct mp_decoder_list *mp_select_video_decoders(const char *codec,
char *selection) char *selection)
{ {
struct mp_decoder_list *list = mp_video_decoder_list(); struct mp_decoder_list *list = video_decoder_list();
struct mp_decoder_list *new = mp_select_decoders(list, codec, selection); struct mp_decoder_list *new = mp_select_decoders(list, codec, selection);
talloc_free(list); talloc_free(list);
return new; return new;
@ -175,13 +168,13 @@ static const struct vd_functions *find_driver(const char *name)
return NULL; return NULL;
} }
int init_best_video_codec(sh_video_t *sh_video, char* video_decoders) int video_init_best_codec(struct dec_video *d_video, char* video_decoders)
{ {
assert(!sh_video->initialized); assert(!d_video->initialized);
struct mp_decoder_entry *decoder = NULL; struct mp_decoder_entry *decoder = NULL;
struct mp_decoder_list *list = struct mp_decoder_list *list =
mp_select_video_decoders(sh_video->gsh->codec, video_decoders); mp_select_video_decoders(d_video->header->codec, video_decoders);
mp_print_decoders(MSGT_DECVIDEO, MSGL_V, "Codec list:", list); mp_print_decoders(MSGT_DECVIDEO, MSGL_V, "Codec list:", list);
@ -192,42 +185,43 @@ int init_best_video_codec(sh_video_t *sh_video, char* video_decoders)
continue; continue;
mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Opening video decoder %s:%s\n", mp_tmsg(MSGT_DECVIDEO, MSGL_V, "Opening video decoder %s:%s\n",
sel->family, sel->decoder); sel->family, sel->decoder);
sh_video->vd_driver = driver; d_video->vd_driver = driver;
if (init_video_codec(sh_video, sel->decoder)) { if (init_video_codec(d_video, sel->decoder)) {
decoder = sel; decoder = sel;
break; break;
} }
sh_video->vd_driver = NULL; d_video->vd_driver = NULL;
mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "Video decoder init failed for " mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "Video decoder init failed for "
"%s:%s\n", sel->family, sel->decoder); "%s:%s\n", sel->family, sel->decoder);
} }
if (sh_video->initialized) { if (d_video->initialized) {
sh_video->gsh->decoder_desc = d_video->decoder_desc =
talloc_asprintf(NULL, "%s [%s:%s]", decoder->desc, decoder->family, talloc_asprintf(d_video, "%s [%s:%s]", decoder->desc, decoder->family,
decoder->decoder); decoder->decoder);
mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Selected video codec: %s\n", mp_msg(MSGT_DECVIDEO, MSGL_INFO, "Selected video codec: %s\n",
sh_video->gsh->decoder_desc); d_video->decoder_desc);
} else { } else {
mp_msg(MSGT_DECVIDEO, MSGL_ERR, mp_msg(MSGT_DECVIDEO, MSGL_ERR,
"Failed to initialize a video decoder for codec '%s'.\n", "Failed to initialize a video decoder for codec '%s'.\n",
sh_video->gsh->codec ? sh_video->gsh->codec : "<unknown>"); d_video->header->codec ? d_video->header->codec : "<unknown>");
} }
talloc_free(list); talloc_free(list);
return sh_video->initialized; return d_video->initialized;
} }
void *decode_video(sh_video_t *sh_video, struct demux_packet *packet, void *video_decode(struct dec_video *d_video, struct demux_packet *packet,
int drop_frame, double pts) int drop_frame, double pts)
{ {
mp_image_t *mpi = NULL; mp_image_t *mpi = NULL;
struct MPOpts *opts = sh_video->opts; struct MPOpts *opts = d_video->opts;
if (opts->correct_pts && pts != MP_NOPTS_VALUE) { if (opts->correct_pts && pts != MP_NOPTS_VALUE) {
int delay = get_current_video_decoder_lag(sh_video); int delay = -1;
video_vd_control(d_video, VDCTRL_QUERY_UNSEEN_FRAMES, &delay);
if (delay >= 0) { if (delay >= 0) {
if (delay > sh_video->num_buffered_pts) if (delay > d_video->num_buffered_pts)
#if 0 #if 0
// this is disabled because vd_ffmpeg reports the same lag // this is disabled because vd_ffmpeg reports the same lag
// after seek even when there are no buffered frames, // after seek even when there are no buffered frames,
@ -237,24 +231,24 @@ void *decode_video(sh_video_t *sh_video, struct demux_packet *packet,
; ;
#endif #endif
else else
sh_video->num_buffered_pts = delay; d_video->num_buffered_pts = delay;
} }
if (sh_video->num_buffered_pts == if (d_video->num_buffered_pts ==
sizeof(sh_video->buffered_pts) / sizeof(double)) sizeof(d_video->buffered_pts) / sizeof(double))
mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Too many buffered pts\n"); mp_msg(MSGT_DECVIDEO, MSGL_ERR, "Too many buffered pts\n");
else { else {
int i, j; int i, j;
for (i = 0; i < sh_video->num_buffered_pts; i++) for (i = 0; i < d_video->num_buffered_pts; i++)
if (sh_video->buffered_pts[i] < pts) if (d_video->buffered_pts[i] < pts)
break; break;
for (j = sh_video->num_buffered_pts; j > i; j--) for (j = d_video->num_buffered_pts; j > i; j--)
sh_video->buffered_pts[j] = sh_video->buffered_pts[j - 1]; d_video->buffered_pts[j] = d_video->buffered_pts[j - 1];
sh_video->buffered_pts[i] = pts; d_video->buffered_pts[i] = pts;
sh_video->num_buffered_pts++; d_video->num_buffered_pts++;
} }
} }
mpi = sh_video->vd_driver->decode(sh_video, packet, drop_frame, &pts); mpi = d_video->vd_driver->decode(d_video, packet, drop_frame, &pts);
//------------------------ frame decoded. -------------------- //------------------------ frame decoded. --------------------
@ -268,39 +262,41 @@ void *decode_video(sh_video_t *sh_video, struct demux_packet *packet,
else if (opts->field_dominance == 1) else if (opts->field_dominance == 1)
mpi->fields &= ~MP_IMGFIELD_TOP_FIRST; mpi->fields &= ~MP_IMGFIELD_TOP_FIRST;
double prevpts = sh_video->codec_reordered_pts; double prevpts = d_video->codec_reordered_pts;
sh_video->prev_codec_reordered_pts = prevpts; d_video->prev_codec_reordered_pts = prevpts;
sh_video->codec_reordered_pts = pts; d_video->codec_reordered_pts = pts;
if (prevpts != MP_NOPTS_VALUE && pts <= prevpts if (prevpts != MP_NOPTS_VALUE && pts <= prevpts
|| pts == MP_NOPTS_VALUE) || pts == MP_NOPTS_VALUE)
sh_video->num_reordered_pts_problems++; d_video->num_reordered_pts_problems++;
prevpts = sh_video->sorted_pts; prevpts = d_video->sorted_pts;
if (opts->correct_pts) { if (opts->correct_pts) {
if (sh_video->num_buffered_pts) { if (d_video->num_buffered_pts) {
sh_video->num_buffered_pts--; d_video->num_buffered_pts--;
sh_video->sorted_pts = d_video->sorted_pts =
sh_video->buffered_pts[sh_video->num_buffered_pts]; d_video->buffered_pts[d_video->num_buffered_pts];
} else { } else {
mp_msg(MSGT_CPLAYER, MSGL_ERR, mp_msg(MSGT_CPLAYER, MSGL_ERR,
"No pts value from demuxer to use for frame!\n"); "No pts value from demuxer to use for frame!\n");
sh_video->sorted_pts = MP_NOPTS_VALUE; d_video->sorted_pts = MP_NOPTS_VALUE;
} }
} }
pts = sh_video->sorted_pts; pts = d_video->sorted_pts;
if (prevpts != MP_NOPTS_VALUE && pts <= prevpts if (prevpts != MP_NOPTS_VALUE && pts <= prevpts
|| pts == MP_NOPTS_VALUE) || pts == MP_NOPTS_VALUE)
sh_video->num_sorted_pts_problems++; d_video->num_sorted_pts_problems++;
return mpi; return mpi;
} }
int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params) int mpcodecs_reconfig_vo(struct dec_video *d_video,
const struct mp_image_params *params)
{ {
struct MPOpts *opts = sh->opts; struct MPOpts *opts = d_video->opts;
vf_instance_t *vf = sh->vfilter; vf_instance_t *vf = d_video->vfilter;
int vocfg_flags = 0; int vocfg_flags = 0;
struct mp_image_params p = *params; struct mp_image_params p = *params;
struct sh_video *sh = d_video->header->video;
sh->vf_reconfig_count++; d_video->vf_reconfig_count++;
mp_msg(MSGT_DECVIDEO, MSGL_V, mp_msg(MSGT_DECVIDEO, MSGL_V,
"VIDEO: %dx%d %5.3f fps %5.1f kbps (%4.1f kB/s)\n", "VIDEO: %dx%d %5.3f fps %5.1f kbps (%4.1f kB/s)\n",
@ -336,24 +332,24 @@ int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params)
"e.g. -vf filter,scale instead of -vf filter.\n"); "e.g. -vf filter,scale instead of -vf filter.\n");
mp_tmsg(MSGT_VFILTER, MSGL_WARN, "Attempted filter chain:\n"); mp_tmsg(MSGT_VFILTER, MSGL_WARN, "Attempted filter chain:\n");
vf_print_filter_chain(MSGL_WARN, vf); vf_print_filter_chain(MSGL_WARN, vf);
sh->vf_initialized = -1; d_video->vf_initialized = -1;
return -1; // failed return -1; // failed
} }
sh->vfilter = vf; d_video->vfilter = vf;
// autodetect flipping // autodetect flipping
bool flip = opts->flip; bool flip = opts->flip;
if (flip && !(flags & VFCAP_FLIP)) { if (flip && !(flags & VFCAP_FLIP)) {
// we need to flip, but no flipping filter avail. // we need to flip, but no flipping filter avail.
vf_add_before_vo(&vf, "flip", NULL); vf_add_before_vo(&vf, "flip", NULL);
sh->vfilter = vf; d_video->vfilter = vf;
flip = false; flip = false;
} }
// time to do aspect ratio corrections... // time to do aspect ratio corrections...
float force_aspect = opts->movie_aspect; float force_aspect = opts->movie_aspect;
if (force_aspect > -1.0 && sh->stream_aspect != 0.0) if (force_aspect > -1.0 && d_video->stream_aspect != 0.0)
force_aspect = sh->stream_aspect; force_aspect = d_video->stream_aspect;
if (force_aspect >= 0) if (force_aspect >= 0)
vf_set_dar(&p.d_w, &p.d_h, p.w, p.h, force_aspect); vf_set_dar(&p.d_w, &p.d_h, p.w, p.h, force_aspect);
@ -386,29 +382,29 @@ int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params)
if (vf_reconfig_wrapper(vf, &p, vocfg_flags) < 0) { if (vf_reconfig_wrapper(vf, &p, vocfg_flags) < 0) {
mp_tmsg(MSGT_CPLAYER, MSGL_WARN, "FATAL: Cannot initialize video driver.\n"); mp_tmsg(MSGT_CPLAYER, MSGL_WARN, "FATAL: Cannot initialize video driver.\n");
sh->vf_initialized = -1; d_video->vf_initialized = -1;
return -1; return -1;
} }
mp_tmsg(MSGT_VFILTER, MSGL_V, "Video filter chain:\n"); mp_tmsg(MSGT_VFILTER, MSGL_V, "Video filter chain:\n");
vf_print_filter_chain(MSGL_V, vf); vf_print_filter_chain(MSGL_V, vf);
sh->vf_initialized = 1; d_video->vf_initialized = 1;
if (!sh->vf_input) if (!d_video->vf_input)
sh->vf_input = talloc(sh, struct mp_image_params); d_video->vf_input = talloc(sh, struct mp_image_params);
*sh->vf_input = p; *d_video->vf_input = p;
if (opts->gamma_gamma != 1000) if (opts->gamma_gamma != 1000)
set_video_colors(sh, "gamma", opts->gamma_gamma); video_set_colors(d_video, "gamma", opts->gamma_gamma);
if (opts->gamma_brightness != 1000) if (opts->gamma_brightness != 1000)
set_video_colors(sh, "brightness", opts->gamma_brightness); video_set_colors(d_video, "brightness", opts->gamma_brightness);
if (opts->gamma_contrast != 1000) if (opts->gamma_contrast != 1000)
set_video_colors(sh, "contrast", opts->gamma_contrast); video_set_colors(d_video, "contrast", opts->gamma_contrast);
if (opts->gamma_saturation != 1000) if (opts->gamma_saturation != 1000)
set_video_colors(sh, "saturation", opts->gamma_saturation); video_set_colors(d_video, "saturation", opts->gamma_saturation);
if (opts->gamma_hue != 1000) if (opts->gamma_hue != 1000)
set_video_colors(sh, "hue", opts->gamma_hue); video_set_colors(d_video, "hue", opts->gamma_hue);
return 0; return 0;
} }

View File

@ -20,24 +20,57 @@
#define MPLAYER_DEC_VIDEO_H #define MPLAYER_DEC_VIDEO_H
#include "demux/stheader.h" #include "demux/stheader.h"
#include "video/hwdec.h"
#include "video/mp_image.h"
struct osd_state; struct osd_state;
struct mp_decoder_list; struct mp_decoder_list;
struct mp_decoder_list *mp_video_decoder_list(void); struct dec_video {
struct MPOpts *opts;
struct vf_instance *vfilter; // video filter chain
const struct vd_functions *vd_driver;
int vf_initialized; // -1 failed, 0 not done, 1 done
long vf_reconfig_count; // incremented each mpcodecs_reconfig_vo() call
struct mp_image_params *vf_input; // video filter input params
struct mp_hwdec_info *hwdec_info; // video output hwdec handles
int initialized;
struct sh_stream *header;
int init_best_video_codec(sh_video_t *sh_video, char* video_decoders); char *decoder_desc;
void uninit_video(sh_video_t *sh_video);
void *priv;
float next_frame_time;
double last_pts;
double buffered_pts[32];
int num_buffered_pts;
double codec_reordered_pts;
double prev_codec_reordered_pts;
int num_reordered_pts_problems;
double sorted_pts;
double prev_sorted_pts;
int num_sorted_pts_problems;
int pts_assoc_mode;
double pts;
float stream_aspect; // aspect ratio in media headers (DVD IFO files)
int i_bps; // == bitrate (compressed bytes/sec)
};
struct mp_decoder_list *video_decoder_list(void);
int video_init_best_codec(struct dec_video *d_video, char* video_decoders);
void video_uninit(struct dec_video *d_video);
struct demux_packet; struct demux_packet;
void *decode_video(sh_video_t *sh_video, struct demux_packet *packet, void *video_decode(struct dec_video *d_video, struct demux_packet *packet,
int drop_frame, double pts); int drop_frame, double pts);
int get_video_colors(sh_video_t *sh_video, const char *item, int *value); int video_get_colors(struct dec_video *d_video, const char *item, int *value);
int set_video_colors(sh_video_t *sh_video, const char *item, int value); int video_set_colors(struct dec_video *d_video, const char *item, int value);
void resync_video_stream(sh_video_t *sh_video); void video_resync_stream(struct dec_video *d_video);
void video_reinit_vo(struct sh_video *sh_video); void video_reinit_vo(struct dec_video *d_video);
int get_current_video_decoder_lag(sh_video_t *sh_video); int video_vd_control(struct dec_video *d_video, int cmd, void *arg);
int vd_control(struct sh_video *sh_video, int cmd, void *arg);
#endif /* MPLAYER_DEC_VIDEO_H */ #endif /* MPLAYER_DEC_VIDEO_H */

View File

@ -136,8 +136,8 @@ static int alloc_buffer(FramePool *pool, AVCodecContext *s)
int mp_codec_get_buffer(AVCodecContext *s, AVFrame *frame) int mp_codec_get_buffer(AVCodecContext *s, AVFrame *frame)
{ {
sh_video_t *sh = s->opaque; struct dec_video *vd = s->opaque;
struct lavc_ctx *ctx = sh->context; struct lavc_ctx *ctx = vd->priv;
if (!ctx->dr1_buffer_pool) { if (!ctx->dr1_buffer_pool) {
ctx->dr1_buffer_pool = av_mallocz(sizeof(*ctx->dr1_buffer_pool)); ctx->dr1_buffer_pool = av_mallocz(sizeof(*ctx->dr1_buffer_pool));

View File

@ -21,6 +21,7 @@
#include "video/mp_image.h" #include "video/mp_image.h"
#include "demux/stheader.h" #include "demux/stheader.h"
#include "dec_video.h"
struct demux_packet; struct demux_packet;
struct mp_decoder_list; struct mp_decoder_list;
@ -30,10 +31,10 @@ typedef struct vd_functions
{ {
const char *name; const char *name;
void (*add_decoders)(struct mp_decoder_list *list); void (*add_decoders)(struct mp_decoder_list *list);
int (*init)(sh_video_t *sh, const char *decoder); int (*init)(struct dec_video *vd, const char *decoder);
void (*uninit)(sh_video_t *sh); void (*uninit)(struct dec_video *vd);
int (*control)(sh_video_t *sh, int cmd, void *arg); int (*control)(struct dec_video *vd, int cmd, void *arg);
struct mp_image *(*decode)(struct sh_video *sh, struct demux_packet *pkt, struct mp_image *(*decode)(struct dec_video *vd, struct demux_packet *pkt,
int flags, double *reordered_pts); int flags, double *reordered_pts);
} vd_functions_t; } vd_functions_t;
@ -47,6 +48,6 @@ enum vd_ctrl {
VDCTRL_REINIT_VO, // reinit filter/VO chain VDCTRL_REINIT_VO, // reinit filter/VO chain
}; };
int mpcodecs_reconfig_vo(sh_video_t *sh, const struct mp_image_params *params); int mpcodecs_reconfig_vo(struct dec_video *vd, const struct mp_image_params *params);
#endif /* MPLAYER_VD_H */ #endif /* MPLAYER_VD_H */

View File

@ -60,15 +60,15 @@
#include "mpvcore/m_option.h" #include "mpvcore/m_option.h"
static void init_avctx(sh_video_t *sh, const char *decoder, static void init_avctx(struct dec_video *vd, const char *decoder,
struct vd_lavc_hwdec *hwdec); struct vd_lavc_hwdec *hwdec);
static void uninit_avctx(sh_video_t *sh); static void uninit_avctx(struct dec_video *vd);
static void setup_refcounting_hw(struct AVCodecContext *s); static void setup_refcounting_hw(struct AVCodecContext *s);
static enum PixelFormat get_format_hwdec(struct AVCodecContext *avctx, static enum PixelFormat get_format_hwdec(struct AVCodecContext *avctx,
const enum PixelFormat *pix_fmt); const enum PixelFormat *pix_fmt);
static void uninit(struct sh_video *sh); static void uninit(struct dec_video *vd);
#define OPT_BASE_STRUCT struct MPOpts #define OPT_BASE_STRUCT struct MPOpts
@ -116,9 +116,9 @@ static struct vd_lavc_hwdec *find_hwcodec(enum hwdec_type api)
return NULL; return NULL;
} }
static bool hwdec_codec_allowed(sh_video_t *sh, const char *codec) static bool hwdec_codec_allowed(struct dec_video *vd, const char *codec)
{ {
bstr s = bstr0(sh->opts->hwdec_codecs); bstr s = bstr0(vd->opts->hwdec_codecs);
while (s.len) { while (s.len) {
bstr item; bstr item;
bstr_split_tok(s, ",", &item, &s); bstr_split_tok(s, ",", &item, &s);
@ -213,7 +213,7 @@ static int hwdec_probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info,
return r; return r;
} }
static bool probe_hwdec(sh_video_t *sh, bool autoprobe, enum hwdec_type api, static bool probe_hwdec(struct dec_video *vd, bool autoprobe, enum hwdec_type api,
const char *decoder, struct vd_lavc_hwdec **use_hwdec, const char *decoder, struct vd_lavc_hwdec **use_hwdec,
const char **use_decoder) const char **use_decoder)
{ {
@ -224,7 +224,7 @@ static bool probe_hwdec(sh_video_t *sh, bool autoprobe, enum hwdec_type api,
return false; return false;
} }
const char *hw_decoder = NULL; const char *hw_decoder = NULL;
int r = hwdec_probe(hwdec, sh->hwdec_info, decoder, &hw_decoder); int r = hwdec_probe(hwdec, vd->hwdec_info, decoder, &hw_decoder);
if (r >= 0) { if (r >= 0) {
*use_hwdec = hwdec; *use_hwdec = hwdec;
*use_decoder = hw_decoder; *use_decoder = hw_decoder;
@ -240,11 +240,11 @@ static bool probe_hwdec(sh_video_t *sh, bool autoprobe, enum hwdec_type api,
} }
static int init(sh_video_t *sh, const char *decoder) static int init(struct dec_video *vd, const char *decoder)
{ {
vd_ffmpeg_ctx *ctx; vd_ffmpeg_ctx *ctx;
ctx = sh->context = talloc_zero(NULL, vd_ffmpeg_ctx); ctx = vd->priv = talloc_zero(NULL, vd_ffmpeg_ctx);
ctx->opts = sh->opts; ctx->opts = vd->opts;
ctx->non_dr1_pool = talloc_steal(ctx, mp_image_pool_new(16)); ctx->non_dr1_pool = talloc_steal(ctx, mp_image_pool_new(16));
if (bstr_endswith0(bstr0(decoder), "_vdpau")) { if (bstr_endswith0(bstr0(decoder), "_vdpau")) {
@ -254,22 +254,22 @@ static int init(sh_video_t *sh, const char *decoder)
"option can be used to restrict which codecs are\nenabled, " "option can be used to restrict which codecs are\nenabled, "
"otherwise all hardware decoding is tried for all codecs.\n", "otherwise all hardware decoding is tried for all codecs.\n",
decoder); decoder);
uninit(sh); uninit(vd);
return 0; return 0;
} }
struct vd_lavc_hwdec *hwdec = NULL; struct vd_lavc_hwdec *hwdec = NULL;
const char *hw_decoder = NULL; const char *hw_decoder = NULL;
if (hwdec_codec_allowed(sh, decoder)) { if (hwdec_codec_allowed(vd, decoder)) {
if (sh->opts->hwdec_api == HWDEC_AUTO) { if (vd->opts->hwdec_api == HWDEC_AUTO) {
for (int n = 0; hwdec_list[n]; n++) { for (int n = 0; hwdec_list[n]; n++) {
if (probe_hwdec(sh, true, hwdec_list[n]->type, decoder, if (probe_hwdec(vd, true, hwdec_list[n]->type, decoder,
&hwdec, &hw_decoder)) &hwdec, &hw_decoder))
break; break;
} }
} else if (sh->opts->hwdec_api != HWDEC_NONE) { } else if (vd->opts->hwdec_api != HWDEC_NONE) {
probe_hwdec(sh, false, sh->opts->hwdec_api, decoder, probe_hwdec(vd, false, vd->opts->hwdec_api, decoder,
&hwdec, &hw_decoder); &hwdec, &hw_decoder);
} }
} else { } else {
@ -282,21 +282,21 @@ static int init(sh_video_t *sh, const char *decoder)
if (hw_decoder) if (hw_decoder)
decoder = hw_decoder; decoder = hw_decoder;
mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Trying to use hardware decoding.\n"); mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Trying to use hardware decoding.\n");
} else if (sh->opts->hwdec_api != HWDEC_NONE) { } else if (vd->opts->hwdec_api != HWDEC_NONE) {
mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Using software decoding.\n"); mp_tmsg(MSGT_DECVIDEO, MSGL_INFO, "Using software decoding.\n");
} }
init_avctx(sh, decoder, hwdec); init_avctx(vd, decoder, hwdec);
if (!ctx->avctx) { if (!ctx->avctx) {
if (ctx->software_fallback_decoder) { if (ctx->software_fallback_decoder) {
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error initializing hardware " mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error initializing hardware "
"decoding, falling back to software decoding.\n"); "decoding, falling back to software decoding.\n");
decoder = ctx->software_fallback_decoder; decoder = ctx->software_fallback_decoder;
ctx->software_fallback_decoder = NULL; ctx->software_fallback_decoder = NULL;
init_avctx(sh, decoder, NULL); init_avctx(vd, decoder, NULL);
} }
if (!ctx->avctx) { if (!ctx->avctx) {
uninit(sh); uninit(vd);
return 0; return 0;
} }
} }
@ -361,12 +361,13 @@ static void set_from_bih(AVCodecContext *avctx, uint32_t format,
avctx->coded_height = bih->biHeight; avctx->coded_height = bih->biHeight;
} }
static void init_avctx(sh_video_t *sh, const char *decoder, static void init_avctx(struct dec_video *vd, const char *decoder,
struct vd_lavc_hwdec *hwdec) struct vd_lavc_hwdec *hwdec)
{ {
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
struct lavc_param *lavc_param = &sh->opts->lavc_param; struct lavc_param *lavc_param = &vd->opts->lavc_param;
bool mp_rawvideo = false; bool mp_rawvideo = false;
struct sh_stream *sh = vd->header;
assert(!ctx->avctx); assert(!ctx->avctx);
@ -379,7 +380,7 @@ static void init_avctx(sh_video_t *sh, const char *decoder,
if (!lavc_codec) if (!lavc_codec)
return; return;
ctx->hwdec_info = sh->hwdec_info; ctx->hwdec_info = vd->hwdec_info;
ctx->do_dr1 = ctx->do_hw_dr1 = 0; ctx->do_dr1 = ctx->do_hw_dr1 = 0;
ctx->pix_fmt = PIX_FMT_NONE; ctx->pix_fmt = PIX_FMT_NONE;
@ -388,7 +389,7 @@ static void init_avctx(sh_video_t *sh, const char *decoder,
ctx->hwdec = hwdec; ctx->hwdec = hwdec;
ctx->avctx = avcodec_alloc_context3(lavc_codec); ctx->avctx = avcodec_alloc_context3(lavc_codec);
AVCodecContext *avctx = ctx->avctx; AVCodecContext *avctx = ctx->avctx;
avctx->opaque = sh; avctx->opaque = vd;
avctx->codec_type = AVMEDIA_TYPE_VIDEO; avctx->codec_type = AVMEDIA_TYPE_VIDEO;
avctx->codec_id = lavc_codec->id; avctx->codec_id = lavc_codec->id;
@ -409,7 +410,7 @@ static void init_avctx(sh_video_t *sh, const char *decoder,
avctx->get_format = get_format_hwdec; avctx->get_format = get_format_hwdec;
setup_refcounting_hw(avctx); setup_refcounting_hw(avctx);
if (ctx->hwdec->init && ctx->hwdec->init(ctx) < 0) { if (ctx->hwdec->init && ctx->hwdec->init(ctx) < 0) {
uninit_avctx(sh); uninit_avctx(vd);
return; return;
} }
} else { } else {
@ -445,7 +446,7 @@ static void init_avctx(sh_video_t *sh, const char *decoder,
mp_msg(MSGT_DECVIDEO, MSGL_ERR, mp_msg(MSGT_DECVIDEO, MSGL_ERR,
"Your options /%s/ look like gibberish to me pal\n", "Your options /%s/ look like gibberish to me pal\n",
lavc_param->avopt); lavc_param->avopt);
uninit_avctx(sh); uninit_avctx(vd);
return; return;
} }
} }
@ -453,33 +454,33 @@ static void init_avctx(sh_video_t *sh, const char *decoder,
// Do this after the above avopt handling in case it changes values // Do this after the above avopt handling in case it changes values
ctx->skip_frame = avctx->skip_frame; ctx->skip_frame = avctx->skip_frame;
avctx->codec_tag = sh->format; avctx->codec_tag = sh->video->format;
avctx->coded_width = sh->disp_w; avctx->coded_width = sh->video->disp_w;
avctx->coded_height = sh->disp_h; avctx->coded_height = sh->video->disp_h;
// demux_mkv // demux_mkv
if (sh->bih) if (sh->video->bih)
set_from_bih(avctx, sh->format, sh->bih); set_from_bih(avctx, sh->video->format, sh->video->bih);
if (mp_rawvideo && sh->format >= IMGFMT_START && sh->format < IMGFMT_END) { if (mp_rawvideo) {
avctx->pix_fmt = imgfmt2pixfmt(sh->format); avctx->pix_fmt = imgfmt2pixfmt(sh->video->format);
avctx->codec_tag = 0; avctx->codec_tag = 0;
} }
if (sh->gsh->lav_headers) if (sh->lav_headers)
mp_copy_lav_codec_headers(avctx, sh->gsh->lav_headers); mp_copy_lav_codec_headers(avctx, sh->lav_headers);
/* open it */ /* open it */
if (avcodec_open2(avctx, lavc_codec, NULL) < 0) { if (avcodec_open2(avctx, lavc_codec, NULL) < 0) {
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not open codec.\n"); mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not open codec.\n");
uninit_avctx(sh); uninit_avctx(vd);
return; return;
} }
} }
static void uninit_avctx(sh_video_t *sh) static void uninit_avctx(struct dec_video *vd)
{ {
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
AVCodecContext *avctx = ctx->avctx; AVCodecContext *avctx = ctx->avctx;
if (avctx) { if (avctx) {
@ -504,21 +505,19 @@ static void uninit_avctx(sh_video_t *sh)
ctx->last_sample_aspect_ratio = (AVRational){0, 0}; ctx->last_sample_aspect_ratio = (AVRational){0, 0};
} }
static void uninit(sh_video_t *sh) static void uninit(struct dec_video *vd)
{ {
vd_ffmpeg_ctx *ctx = sh->context; uninit_avctx(vd);
uninit_avctx(sh);
talloc_free(ctx);
} }
static void update_image_params(sh_video_t *sh, AVFrame *frame) static void update_image_params(struct dec_video *vd, AVFrame *frame)
{ {
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
int width = frame->width; int width = frame->width;
int height = frame->height; int height = frame->height;
float aspect = av_q2d(frame->sample_aspect_ratio) * width / height; float aspect = av_q2d(frame->sample_aspect_ratio) * width / height;
int pix_fmt = frame->format; int pix_fmt = frame->format;
struct sh_video *sh = vd->header->video;
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 40, 0) #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(54, 40, 0)
pix_fmt = ctx->avctx->pix_fmt; pix_fmt = ctx->avctx->pix_fmt;
@ -566,8 +565,8 @@ static void update_image_params(sh_video_t *sh, AVFrame *frame)
static enum PixelFormat get_format_hwdec(struct AVCodecContext *avctx, static enum PixelFormat get_format_hwdec(struct AVCodecContext *avctx,
const enum PixelFormat *fmt) const enum PixelFormat *fmt)
{ {
sh_video_t *sh = avctx->opaque; struct dec_video *vd = avctx->opaque;
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
mp_msg(MSGT_DECVIDEO, MSGL_V, "Pixel formats supported by decoder:"); mp_msg(MSGT_DECVIDEO, MSGL_V, "Pixel formats supported by decoder:");
for (int i = 0; fmt[i] != PIX_FMT_NONE; i++) for (int i = 0; fmt[i] != PIX_FMT_NONE; i++)
@ -587,9 +586,9 @@ static enum PixelFormat get_format_hwdec(struct AVCodecContext *avctx,
return PIX_FMT_NONE; return PIX_FMT_NONE;
} }
static struct mp_image *get_surface_hwdec(struct sh_video *sh, AVFrame *pic) static struct mp_image *get_surface_hwdec(struct dec_video *vd, AVFrame *pic)
{ {
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
/* Decoders using ffmpeg's hwaccel architecture (everything except vdpau) /* Decoders using ffmpeg's hwaccel architecture (everything except vdpau)
* can fall back to software decoding automatically. However, we don't * can fall back to software decoding automatically. However, we don't
@ -633,9 +632,9 @@ static void free_mpi(void *opaque, uint8_t *data)
static int get_buffer2_hwdec(AVCodecContext *avctx, AVFrame *pic, int flags) static int get_buffer2_hwdec(AVCodecContext *avctx, AVFrame *pic, int flags)
{ {
sh_video_t *sh = avctx->opaque; struct dec_video *vd = avctx->opaque;
struct mp_image *mpi = get_surface_hwdec(sh, pic); struct mp_image *mpi = get_surface_hwdec(vd, pic);
if (!mpi) if (!mpi)
return -1; return -1;
@ -653,9 +652,9 @@ static void setup_refcounting_hw(AVCodecContext *avctx)
static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic) static int get_buffer_hwdec(AVCodecContext *avctx, AVFrame *pic)
{ {
sh_video_t *sh = avctx->opaque; struct dec_video *vd = avctx->opaque;
struct mp_image *mpi = get_surface_hwdec(sh, pic); struct mp_image *mpi = get_surface_hwdec(vd, pic);
if (!mpi) if (!mpi)
return -1; return -1;
@ -694,9 +693,9 @@ static void setup_refcounting_hw(AVCodecContext *avctx)
#if HAVE_AVUTIL_REFCOUNTING #if HAVE_AVUTIL_REFCOUNTING
static struct mp_image *image_from_decoder(struct sh_video *sh) static struct mp_image *image_from_decoder(struct dec_video *vd)
{ {
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
AVFrame *pic = ctx->pic; AVFrame *pic = ctx->pic;
struct mp_image *img = mp_image_from_av_frame(pic); struct mp_image *img = mp_image_from_av_frame(pic);
@ -722,9 +721,9 @@ static bool fb_is_unique(void *b)
return mp_buffer_is_unique(b); return mp_buffer_is_unique(b);
} }
static struct mp_image *image_from_decoder(struct sh_video *sh) static struct mp_image *image_from_decoder(struct dec_video *vd)
{ {
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
AVFrame *pic = ctx->pic; AVFrame *pic = ctx->pic;
struct mp_image new = {0}; struct mp_image new = {0};
@ -749,12 +748,12 @@ static struct mp_image *image_from_decoder(struct sh_video *sh)
#endif /* HAVE_AVUTIL_REFCOUNTING */ #endif /* HAVE_AVUTIL_REFCOUNTING */
static int decode(struct sh_video *sh, struct demux_packet *packet, static int decode(struct dec_video *vd, struct demux_packet *packet,
int flags, double *reordered_pts, struct mp_image **out_image) int flags, double *reordered_pts, struct mp_image **out_image)
{ {
int got_picture = 0; int got_picture = 0;
int ret; int ret;
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
AVFrame *pic = ctx->pic; AVFrame *pic = ctx->pic;
AVCodecContext *avctx = ctx->avctx; AVCodecContext *avctx = ctx->avctx;
AVPacket pkt; AVPacket pkt;
@ -781,9 +780,9 @@ static int decode(struct sh_video *sh, struct demux_packet *packet,
if (!got_picture) if (!got_picture)
return 0; // skipped image return 0; // skipped image
update_image_params(sh, pic); update_image_params(vd, pic);
struct mp_image *mpi = image_from_decoder(sh); struct mp_image *mpi = image_from_decoder(vd);
assert(mpi->planes[0]); assert(mpi->planes[0]);
mp_image_set_params(mpi, &ctx->image_params); mp_image_set_params(mpi, &ctx->image_params);
@ -794,7 +793,7 @@ static int decode(struct sh_video *sh, struct demux_packet *packet,
mp_image_params_from_image(&vo_params, mpi); mp_image_params_from_image(&vo_params, mpi);
if (!mp_image_params_equals(&vo_params, &ctx->vo_image_params)) { if (!mp_image_params_equals(&vo_params, &ctx->vo_image_params)) {
if (mpcodecs_reconfig_vo(sh, &vo_params) < 0) { if (mpcodecs_reconfig_vo(vd, &vo_params) < 0) {
talloc_free(mpi); talloc_free(mpi);
return -1; return -1;
} }
@ -805,30 +804,30 @@ static int decode(struct sh_video *sh, struct demux_packet *packet,
return 1; return 1;
} }
static struct mp_image *decode_with_fallback(struct sh_video *sh, static struct mp_image *decode_with_fallback(struct dec_video *vd,
struct demux_packet *packet, struct demux_packet *packet,
int flags, double *reordered_pts) int flags, double *reordered_pts)
{ {
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
if (!ctx->avctx) if (!ctx->avctx)
return NULL; return NULL;
struct mp_image *mpi = NULL; struct mp_image *mpi = NULL;
int res = decode(sh, packet, flags, reordered_pts, &mpi); int res = decode(vd, packet, flags, reordered_pts, &mpi);
if (res >= 0) if (res >= 0)
return mpi; return mpi;
// Failed hardware decoding? Try again in software. // Failed hardware decoding? Try again in software.
if (ctx->software_fallback_decoder) { if (ctx->software_fallback_decoder) {
uninit_avctx(sh); uninit_avctx(vd);
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error using hardware " mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error using hardware "
"decoding, falling back to software decoding.\n"); "decoding, falling back to software decoding.\n");
const char *decoder = ctx->software_fallback_decoder; const char *decoder = ctx->software_fallback_decoder;
ctx->software_fallback_decoder = NULL; ctx->software_fallback_decoder = NULL;
init_avctx(sh, decoder, NULL); init_avctx(vd, decoder, NULL);
if (ctx->avctx) { if (ctx->avctx) {
mpi = NULL; mpi = NULL;
decode(sh, packet, flags, reordered_pts, &mpi); decode(vd, packet, flags, reordered_pts, &mpi);
return mpi; return mpi;
} }
} }
@ -836,9 +835,9 @@ static struct mp_image *decode_with_fallback(struct sh_video *sh,
return NULL; return NULL;
} }
static int control(sh_video_t *sh, int cmd, void *arg) static int control(struct dec_video *vd, int cmd, void *arg)
{ {
vd_ffmpeg_ctx *ctx = sh->context; vd_ffmpeg_ctx *ctx = vd->priv;
AVCodecContext *avctx = ctx->avctx; AVCodecContext *avctx = ctx->avctx;
switch (cmd) { switch (cmd) {
case VDCTRL_RESYNC_STREAM: case VDCTRL_RESYNC_STREAM:
@ -853,7 +852,7 @@ static int control(sh_video_t *sh, int cmd, void *arg)
return CONTROL_TRUE; return CONTROL_TRUE;
case VDCTRL_REINIT_VO: case VDCTRL_REINIT_VO:
if (ctx->vo_image_params.imgfmt) if (ctx->vo_image_params.imgfmt)
mpcodecs_reconfig_vo(sh, &ctx->vo_image_params); mpcodecs_reconfig_vo(vd, &ctx->vo_image_params);
return true; return true;
case VDCTRL_GET_PARAMS: case VDCTRL_GET_PARAMS:
*(struct mp_image_params *)arg = ctx->vo_image_params; *(struct mp_image_params *)arg = ctx->vo_image_params;

View File

@ -130,8 +130,8 @@ static void draw_slice_hwdec(struct AVCodecContext *s,
const AVFrame *src, int offset[4], const AVFrame *src, int offset[4],
int y, int type, int height) int y, int type, int height)
{ {
sh_video_t *sh = s->opaque; struct dec_video *vd = s->opaque;
struct lavc_ctx *ctx = sh->context; struct lavc_ctx *ctx = vd->priv;
struct priv *p = ctx->hwdec_priv; struct priv *p = ctx->hwdec_priv;
struct vdp_functions *vdp = p->vdp; struct vdp_functions *vdp = p->vdp;
VdpStatus vdp_st; VdpStatus vdp_st;