mirror of https://github.com/mpv-player/mpv
core: refactor MPContext.demuxer field accesses
Whenever the demuxer is accessed to retrieve metadata, use the newly introduced master_demuxer field instead. If a timeline is used, the master_demuxer will still refer to the main file, instead to segments. Instead of mpctx->demuxer->stream, access mpctx->stream; even though they are the same, the code becomes shorter. For the TV code, introduce a function get_tvh() to access the TV handle, instead of duplicating the code all over the place. Often the demuxer field is checked to determine whether something is currently played; prefer other methods over that. Note that the code before always accessed the current timeline segment, and would e.g. read file metadata of the current segment. Now it always returns metadata for the master file. This may have various wanted and unwanted effects.
This commit is contained in:
parent
1fb275b7de
commit
13482fb397
193
command.c
193
command.c
|
@ -296,27 +296,28 @@ static int mp_property_filename(m_option_t *prop, int action, void *arg,
|
|||
static int mp_property_demuxer(m_option_t *prop, int action, void *arg,
|
||||
MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->demuxer)
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
return m_property_string_ro(prop, action, arg,
|
||||
(char *) mpctx->demuxer->desc->name);
|
||||
return m_property_string_ro(prop, action, arg, (char *)demuxer->desc->name);
|
||||
}
|
||||
|
||||
/// Position in the stream (RW)
|
||||
static int mp_property_stream_pos(m_option_t *prop, int action, void *arg,
|
||||
MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->demuxer || !mpctx->demuxer->stream)
|
||||
struct stream *stream = mpctx->stream;
|
||||
if (!stream)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
if (!arg)
|
||||
return M_PROPERTY_ERROR;
|
||||
switch (action) {
|
||||
case M_PROPERTY_GET:
|
||||
*(off_t *) arg = stream_tell(mpctx->demuxer->stream);
|
||||
*(off_t *) arg = stream_tell(stream);
|
||||
return M_PROPERTY_OK;
|
||||
case M_PROPERTY_SET:
|
||||
M_PROPERTY_CLAMP(prop, *(off_t *) arg);
|
||||
stream_seek(mpctx->demuxer->stream, *(off_t *) arg);
|
||||
stream_seek(stream, *(off_t *) arg);
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
|
@ -326,11 +327,12 @@ static int mp_property_stream_pos(m_option_t *prop, int action, void *arg,
|
|||
static int mp_property_stream_start(m_option_t *prop, int action,
|
||||
void *arg, MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->demuxer || !mpctx->demuxer->stream)
|
||||
struct stream *stream = mpctx->stream;
|
||||
if (!stream)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
switch (action) {
|
||||
case M_PROPERTY_GET:
|
||||
*(off_t *) arg = mpctx->demuxer->stream->start_pos;
|
||||
*(off_t *) arg = stream->start_pos;
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
|
@ -340,11 +342,12 @@ static int mp_property_stream_start(m_option_t *prop, int action,
|
|||
static int mp_property_stream_end(m_option_t *prop, int action, void *arg,
|
||||
MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->demuxer || !mpctx->demuxer->stream)
|
||||
struct stream *stream = mpctx->stream;
|
||||
if (!stream)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
switch (action) {
|
||||
case M_PROPERTY_GET:
|
||||
*(off_t *) arg = mpctx->demuxer->stream->end_pos;
|
||||
*(off_t *) arg = stream->end_pos;
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
|
@ -354,12 +357,12 @@ static int mp_property_stream_end(m_option_t *prop, int action, void *arg,
|
|||
static int mp_property_stream_length(m_option_t *prop, int action,
|
||||
void *arg, MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->demuxer || !mpctx->demuxer->stream)
|
||||
struct stream *stream = mpctx->stream;
|
||||
if (!stream)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
switch (action) {
|
||||
case M_PROPERTY_GET:
|
||||
*(off_t *) arg =
|
||||
mpctx->demuxer->stream->end_pos - mpctx->demuxer->stream->start_pos;
|
||||
*(off_t *) arg = stream->end_pos - stream->start_pos;
|
||||
return M_PROPERTY_OK;
|
||||
}
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
|
@ -369,10 +372,14 @@ static int mp_property_stream_length(m_option_t *prop, int action,
|
|||
static int mp_property_stream_time_pos(m_option_t *prop, int action,
|
||||
void *arg, MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->demuxer || mpctx->demuxer->stream_pts == MP_NOPTS_VALUE)
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
double pts = demuxer->stream_pts;
|
||||
if (pts == MP_NOPTS_VALUE)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
return m_property_time_ro(prop, action, arg, mpctx->demuxer->stream_pts);
|
||||
return m_property_time_ro(prop, action, arg, pts);
|
||||
}
|
||||
|
||||
|
||||
|
@ -382,8 +389,7 @@ static int mp_property_length(m_option_t *prop, int action, void *arg,
|
|||
{
|
||||
double len;
|
||||
|
||||
if (!mpctx->demuxer ||
|
||||
!(int) (len = get_time_length(mpctx)))
|
||||
if (!(int) (len = get_time_length(mpctx)))
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
return m_property_time_ro(prop, action, arg, len);
|
||||
|
@ -395,7 +401,7 @@ static int mp_property_percent_pos(m_option_t *prop, int action,
|
|||
{
|
||||
int pos;
|
||||
|
||||
if (!mpctx->demuxer)
|
||||
if (!mpctx->num_sources)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
switch (action) {
|
||||
|
@ -424,7 +430,7 @@ static int mp_property_percent_pos(m_option_t *prop, int action,
|
|||
static int mp_property_time_pos(m_option_t *prop, int action,
|
||||
void *arg, MPContext *mpctx)
|
||||
{
|
||||
if (!(mpctx->sh_video || mpctx->sh_audio))
|
||||
if (!mpctx->num_sources)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
switch (action) {
|
||||
|
@ -448,12 +454,10 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg,
|
|||
MPContext *mpctx)
|
||||
{
|
||||
struct MPOpts *opts = &mpctx->opts;
|
||||
int chapter = -1;
|
||||
int step_all;
|
||||
char *chapter_name = NULL;
|
||||
|
||||
if (mpctx->demuxer)
|
||||
chapter = get_current_chapter(mpctx);
|
||||
int chapter = get_current_chapter(mpctx);
|
||||
if (chapter < -1)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
|
@ -514,18 +518,20 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg,
|
|||
static int mp_property_titles(m_option_t *prop, int action, void *arg,
|
||||
MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->demuxer)
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
if (mpctx->demuxer->num_titles == 0)
|
||||
stream_control(mpctx->demuxer->stream, STREAM_CTRL_GET_NUM_TITLES, &mpctx->demuxer->num_titles);
|
||||
return m_property_int_ro(prop, action, arg, mpctx->demuxer->num_titles);
|
||||
if (demuxer->num_titles == 0)
|
||||
stream_control(demuxer->stream, STREAM_CTRL_GET_NUM_TITLES,
|
||||
&demuxer->num_titles);
|
||||
return m_property_int_ro(prop, action, arg, demuxer->num_titles);
|
||||
}
|
||||
|
||||
/// Number of chapters in file
|
||||
static int mp_property_chapters(m_option_t *prop, int action, void *arg,
|
||||
MPContext *mpctx)
|
||||
{
|
||||
if (!mpctx->demuxer)
|
||||
if (!mpctx->num_sources)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
int count = get_chapter_count(mpctx);
|
||||
return m_property_int_ro(prop, action, arg, count);
|
||||
|
@ -536,14 +542,15 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg,
|
|||
MPContext *mpctx)
|
||||
{
|
||||
struct MPOpts *opts = &mpctx->opts;
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
int angle = -1;
|
||||
int angles;
|
||||
|
||||
if (mpctx->demuxer)
|
||||
angle = demuxer_get_current_angle(mpctx->demuxer);
|
||||
if (demuxer)
|
||||
angle = demuxer_get_current_angle(demuxer);
|
||||
if (angle < 0)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
angles = demuxer_angles_count(mpctx->demuxer);
|
||||
angles = demuxer_angles_count(demuxer);
|
||||
if (angles <= 1)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
|
@ -583,13 +590,13 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg,
|
|||
default:
|
||||
return M_PROPERTY_NOT_IMPLEMENTED;
|
||||
}
|
||||
angle = demuxer_set_angle(mpctx->demuxer, angle);
|
||||
angle = demuxer_set_angle(demuxer, angle);
|
||||
if (angle >= 0) {
|
||||
struct sh_video *sh_video = mpctx->demuxer->video->sh;
|
||||
struct sh_video *sh_video = demuxer->video->sh;
|
||||
if (sh_video)
|
||||
resync_video_stream(sh_video);
|
||||
|
||||
struct sh_audio *sh_audio = mpctx->demuxer->audio->sh;
|
||||
struct sh_audio *sh_audio = demuxer->audio->sh;
|
||||
if (sh_audio)
|
||||
resync_audio_stream(sh_audio);
|
||||
}
|
||||
|
@ -603,26 +610,28 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg,
|
|||
static int mp_property_metadata(m_option_t *prop, int action, void *arg,
|
||||
MPContext *mpctx)
|
||||
{
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
m_property_action_t *ka;
|
||||
char *meta;
|
||||
static const m_option_t key_type =
|
||||
{
|
||||
"metadata", NULL, CONF_TYPE_STRING, 0, 0, 0, NULL
|
||||
};
|
||||
if (!mpctx->demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
switch (action) {
|
||||
case M_PROPERTY_GET:
|
||||
if (!arg)
|
||||
return M_PROPERTY_ERROR;
|
||||
*(char ***)arg = mpctx->demuxer->info;
|
||||
*(char ***)arg = demuxer->info;
|
||||
return M_PROPERTY_OK;
|
||||
case M_PROPERTY_KEY_ACTION:
|
||||
if (!arg)
|
||||
return M_PROPERTY_ERROR;
|
||||
ka = arg;
|
||||
if (!(meta = demux_info_get(mpctx->demuxer, ka->key)))
|
||||
if (!(meta = demux_info_get(demuxer, ka->key)))
|
||||
return M_PROPERTY_UNKNOWN;
|
||||
switch (ka->action) {
|
||||
case M_PROPERTY_GET:
|
||||
|
@ -889,7 +898,7 @@ static int mp_property_audio(m_option_t *prop, int action, void *arg,
|
|||
MPContext *mpctx)
|
||||
{
|
||||
int current_id, tmp;
|
||||
if (!mpctx->demuxer || !mpctx->d_audio)
|
||||
if (!mpctx->num_sources)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
struct sh_audio *sh = mpctx->sh_audio;
|
||||
current_id = sh ? sh->aid : -2;
|
||||
|
@ -907,7 +916,7 @@ static int mp_property_audio(m_option_t *prop, int action, void *arg,
|
|||
if (!sh || current_id < 0)
|
||||
*(char **) arg = talloc_strdup(NULL, mp_gtext("disabled"));
|
||||
else {
|
||||
char *lang = demuxer_stream_lang(mpctx->demuxer, sh->gsh);
|
||||
char *lang = demuxer_stream_lang(sh->ds->demuxer, sh->gsh);
|
||||
if (!lang)
|
||||
lang = talloc_strdup(NULL, mp_gtext("unknown"));
|
||||
|
||||
|
@ -953,7 +962,7 @@ static int mp_property_video(m_option_t *prop, int action, void *arg,
|
|||
{
|
||||
struct MPOpts *opts = &mpctx->opts;
|
||||
int current_id, tmp;
|
||||
if (!mpctx->demuxer || !mpctx->d_video)
|
||||
if (!mpctx->num_sources)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
current_id = mpctx->sh_video ? mpctx->sh_video->vid : -2;
|
||||
|
||||
|
@ -1005,7 +1014,8 @@ static int mp_property_program(m_option_t *prop, int action, void *arg,
|
|||
{
|
||||
demux_program_t prog;
|
||||
|
||||
if (!mpctx->demuxer)
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
if (!demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
switch (action) {
|
||||
|
@ -1015,8 +1025,8 @@ static int mp_property_program(m_option_t *prop, int action, void *arg,
|
|||
prog.progid = *((int *) arg);
|
||||
else
|
||||
prog.progid = -1;
|
||||
if (demux_control(mpctx->demuxer, DEMUXER_CTRL_IDENTIFY_PROGRAM,
|
||||
&prog) == DEMUXER_CTRL_NOTIMPL)
|
||||
if (demux_control(demuxer, DEMUXER_CTRL_IDENTIFY_PROGRAM, &prog) ==
|
||||
DEMUXER_CTRL_NOTIMPL)
|
||||
return M_PROPERTY_ERROR;
|
||||
|
||||
if (prog.aid < 0 && prog.vid < 0) {
|
||||
|
@ -1354,7 +1364,7 @@ static int mp_property_gamma(m_option_t *prop, int action, void *arg,
|
|||
}
|
||||
|
||||
#ifdef CONFIG_TV
|
||||
if (mpctx->demuxer->type == DEMUXER_TYPE_TV) {
|
||||
if (mpctx->sh_video->ds->demuxer->type == DEMUXER_TYPE_TV) {
|
||||
int l = strlen(prop->name);
|
||||
char tv_prop[3 + l + 1];
|
||||
sprintf(tv_prop, "tv_%s", prop->name);
|
||||
|
@ -1534,7 +1544,7 @@ static int mp_property_sub(m_option_t *prop, int action, void *arg,
|
|||
}
|
||||
if (opts->sub_id >= 0 && mpctx->d_sub && mpctx->d_sub->sh) {
|
||||
struct sh_stream *sh = ((struct sh_sub *)mpctx->d_sub->sh)->gsh;
|
||||
char *lang = demuxer_stream_lang(mpctx->demuxer, sh);
|
||||
char *lang = demuxer_stream_lang(sh->common_header->ds->demuxer, sh);
|
||||
if (!lang)
|
||||
lang = talloc_strdup(NULL, mp_gtext("unknown"));
|
||||
if (sh->title)
|
||||
|
@ -2005,15 +2015,20 @@ static int mp_property_sub_scale(m_option_t *prop, int action, void *arg,
|
|||
|
||||
#ifdef CONFIG_TV
|
||||
|
||||
static tvi_handle_t *get_tvh(struct MPContext *mpctx)
|
||||
{
|
||||
if (!(mpctx->master_demuxer && mpctx->master_demuxer->type == DEMUXER_TYPE_TV))
|
||||
return NULL;
|
||||
return mpctx->master_demuxer->priv;
|
||||
}
|
||||
|
||||
/// TV color settings (RW)
|
||||
static int mp_property_tv_color(m_option_t *prop, int action, void *arg,
|
||||
MPContext *mpctx)
|
||||
{
|
||||
int r, val;
|
||||
if (!mpctx->demuxer)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
tvi_handle_t *tvh = mpctx->demuxer->priv;
|
||||
if (mpctx->demuxer->type != DEMUXER_TYPE_TV || !tvh)
|
||||
tvi_handle_t *tvh = get_tvh(mpctx);
|
||||
if (!tvh)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
switch (action) {
|
||||
|
@ -2499,7 +2514,7 @@ static char *format_time(double time)
|
|||
static void show_chapters_on_osd(MPContext *mpctx)
|
||||
{
|
||||
int count = get_chapter_count(mpctx);
|
||||
int cur = mpctx->demuxer ? get_current_chapter(mpctx) : -1;
|
||||
int cur = mpctx->num_sources ? get_current_chapter(mpctx) : -1;
|
||||
char *res = NULL;
|
||||
int n;
|
||||
|
||||
|
@ -2527,7 +2542,7 @@ static void show_chapters_on_osd(MPContext *mpctx)
|
|||
static void show_tracks_on_osd(MPContext *mpctx)
|
||||
{
|
||||
struct MPOpts *opts = &mpctx->opts;
|
||||
demuxer_t *demuxer = mpctx->demuxer;
|
||||
demuxer_t *demuxer = mpctx->master_demuxer;
|
||||
char *res = NULL;
|
||||
|
||||
if (!demuxer)
|
||||
|
@ -2557,7 +2572,7 @@ static void show_tracks_on_osd(MPContext *mpctx)
|
|||
res = talloc_asprintf_append(res, "(%d) ", sh->tid);
|
||||
if (sh->title)
|
||||
res = talloc_asprintf_append(res, "'%s' ", sh->title);
|
||||
char *lang = demuxer_stream_lang(mpctx->demuxer, sh);
|
||||
char *lang = demuxer_stream_lang(sh->common_header->ds->demuxer, sh);
|
||||
if (lang)
|
||||
res = talloc_asprintf_append(res, "(%s) ", lang);
|
||||
talloc_free(lang);
|
||||
|
@ -2888,53 +2903,50 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
|||
|
||||
#ifdef CONFIG_RADIO
|
||||
case MP_CMD_RADIO_STEP_CHANNEL:
|
||||
if (mpctx->demuxer && mpctx->demuxer->stream->type == STREAMTYPE_RADIO) {
|
||||
if (mpctx->stream && mpctx->stream->type == STREAMTYPE_RADIO) {
|
||||
int v = cmd->args[0].v.i;
|
||||
if (v > 0)
|
||||
radio_step_channel(mpctx->demuxer->stream,
|
||||
RADIO_CHANNEL_HIGHER);
|
||||
radio_step_channel(mpctx->stream, RADIO_CHANNEL_HIGHER);
|
||||
else
|
||||
radio_step_channel(mpctx->demuxer->stream,
|
||||
RADIO_CHANNEL_LOWER);
|
||||
if (radio_get_channel_name(mpctx->demuxer->stream)) {
|
||||
radio_step_channel(mpctx->stream, RADIO_CHANNEL_LOWER);
|
||||
if (radio_get_channel_name(mpctx->stream)) {
|
||||
set_osd_tmsg(OSD_MSG_RADIO_CHANNEL, 1, osd_duration,
|
||||
"Channel: %s",
|
||||
radio_get_channel_name(mpctx->demuxer->stream));
|
||||
radio_get_channel_name(mpctx->stream));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MP_CMD_RADIO_SET_CHANNEL:
|
||||
if (mpctx->demuxer && mpctx->demuxer->stream->type == STREAMTYPE_RADIO) {
|
||||
radio_set_channel(mpctx->demuxer->stream, cmd->args[0].v.s);
|
||||
if (radio_get_channel_name(mpctx->demuxer->stream)) {
|
||||
if (mpctx->stream && mpctx->stream->type == STREAMTYPE_RADIO) {
|
||||
radio_set_channel(mpctx->stream, cmd->args[0].v.s);
|
||||
if (radio_get_channel_name(mpctx->stream)) {
|
||||
set_osd_tmsg(OSD_MSG_RADIO_CHANNEL, 1, osd_duration,
|
||||
"Channel: %s",
|
||||
radio_get_channel_name(mpctx->demuxer->stream));
|
||||
radio_get_channel_name(mpctx->stream));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MP_CMD_RADIO_SET_FREQ:
|
||||
if (mpctx->demuxer && mpctx->demuxer->stream->type == STREAMTYPE_RADIO)
|
||||
radio_set_freq(mpctx->demuxer->stream, cmd->args[0].v.f);
|
||||
if (mpctx->stream && mpctx->stream->type == STREAMTYPE_RADIO)
|
||||
radio_set_freq(mpctx->stream, cmd->args[0].v.f);
|
||||
break;
|
||||
|
||||
case MP_CMD_RADIO_STEP_FREQ:
|
||||
if (mpctx->demuxer && mpctx->demuxer->stream->type == STREAMTYPE_RADIO)
|
||||
radio_step_freq(mpctx->demuxer->stream, cmd->args[0].v.f);
|
||||
if (mpctx->stream && mpctx->stream->type == STREAMTYPE_RADIO)
|
||||
radio_step_freq(mpctx->stream, cmd->args[0].v.f);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TV
|
||||
case MP_CMD_TV_START_SCAN:
|
||||
if (mpctx->demuxer && mpctx->file_format == DEMUXER_TYPE_TV)
|
||||
tv_start_scan((tvi_handle_t *) (mpctx->demuxer->priv), 1);
|
||||
if (get_tvh(mpctx))
|
||||
tv_start_scan(get_tvh(mpctx), 1);
|
||||
break;
|
||||
case MP_CMD_TV_SET_FREQ:
|
||||
if (mpctx->demuxer && mpctx->file_format == DEMUXER_TYPE_TV)
|
||||
tv_set_freq((tvi_handle_t *) (mpctx->demuxer->priv),
|
||||
cmd->args[0].v.f * 16.0);
|
||||
if (get_tvh(mpctx))
|
||||
tv_set_freq(get_tvh(mpctx), cmd->args[0].v.f * 16.0);
|
||||
#ifdef CONFIG_PVR
|
||||
else if (mpctx->stream && mpctx->stream->type == STREAMTYPE_PVR) {
|
||||
pvr_set_freq(mpctx->stream, ROUND(cmd->args[0].v.f));
|
||||
|
@ -2946,9 +2958,8 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
|||
break;
|
||||
|
||||
case MP_CMD_TV_STEP_FREQ:
|
||||
if (mpctx->demuxer && mpctx->file_format == DEMUXER_TYPE_TV)
|
||||
tv_step_freq((tvi_handle_t *) (mpctx->demuxer->priv),
|
||||
cmd->args[0].v.f * 16.0);
|
||||
if (get_tvh(mpctx))
|
||||
tv_step_freq(get_tvh(mpctx), cmd->args[0].v.f * 16.0);
|
||||
#ifdef CONFIG_PVR
|
||||
else if (mpctx->stream && mpctx->stream->type == STREAMTYPE_PVR) {
|
||||
pvr_force_freq_step(mpctx->stream, ROUND(cmd->args[0].v.f));
|
||||
|
@ -2960,22 +2971,17 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
|||
break;
|
||||
|
||||
case MP_CMD_TV_SET_NORM:
|
||||
if (mpctx->demuxer && mpctx->file_format == DEMUXER_TYPE_TV)
|
||||
tv_set_norm((tvi_handle_t *) (mpctx->demuxer->priv),
|
||||
cmd->args[0].v.s);
|
||||
if (get_tvh(mpctx))
|
||||
tv_set_norm(get_tvh(mpctx), cmd->args[0].v.s);
|
||||
break;
|
||||
|
||||
case MP_CMD_TV_STEP_CHANNEL:
|
||||
if (mpctx->demuxer && mpctx->file_format == DEMUXER_TYPE_TV) {
|
||||
if (get_tvh(mpctx)) {
|
||||
int v = cmd->args[0].v.i;
|
||||
if (v > 0) {
|
||||
tv_step_channel((tvi_handle_t *) (mpctx->
|
||||
demuxer->priv),
|
||||
TV_CHANNEL_HIGHER);
|
||||
tv_step_channel(get_tvh(mpctx), TV_CHANNEL_HIGHER);
|
||||
} else {
|
||||
tv_step_channel((tvi_handle_t *) (mpctx->
|
||||
demuxer->priv),
|
||||
TV_CHANNEL_LOWER);
|
||||
tv_step_channel(get_tvh(mpctx), TV_CHANNEL_LOWER);
|
||||
}
|
||||
if (tv_channel_list) {
|
||||
set_osd_tmsg(mpctx, OSD_MSG_TV_CHANNEL, 1, osd_duration,
|
||||
|
@ -3013,9 +3019,8 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
|||
break;
|
||||
|
||||
case MP_CMD_TV_SET_CHANNEL:
|
||||
if (mpctx->demuxer && mpctx->file_format == DEMUXER_TYPE_TV) {
|
||||
tv_set_channel((tvi_handle_t *) (mpctx->demuxer->priv),
|
||||
cmd->args[0].v.s);
|
||||
if (get_tvh(mpctx)) {
|
||||
tv_set_channel(get_tvh(mpctx), cmd->args[0].v.s);
|
||||
if (tv_channel_list) {
|
||||
set_osd_tmsg(mpctx, OSD_MSG_TV_CHANNEL, 1, osd_duration,
|
||||
"Channel: %s", tv_channel_current->name);
|
||||
|
@ -3047,8 +3052,8 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
|||
#endif /* CONFIG_DVBIN */
|
||||
|
||||
case MP_CMD_TV_LAST_CHANNEL:
|
||||
if (mpctx->demuxer && mpctx->file_format == DEMUXER_TYPE_TV) {
|
||||
tv_last_channel((tvi_handle_t *) (mpctx->demuxer->priv));
|
||||
if (get_tvh(mpctx)) {
|
||||
tv_last_channel(get_tvh(mpctx));
|
||||
if (tv_channel_list) {
|
||||
set_osd_tmsg(mpctx, OSD_MSG_TV_CHANNEL, 1, osd_duration,
|
||||
"Channel: %s", tv_channel_current->name);
|
||||
|
@ -3066,13 +3071,13 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
|||
break;
|
||||
|
||||
case MP_CMD_TV_STEP_NORM:
|
||||
if (mpctx->demuxer && mpctx->file_format == DEMUXER_TYPE_TV)
|
||||
tv_step_norm((tvi_handle_t *) (mpctx->demuxer->priv));
|
||||
if (get_tvh(mpctx))
|
||||
tv_step_norm(get_tvh(mpctx));
|
||||
break;
|
||||
|
||||
case MP_CMD_TV_STEP_CHANNEL_LIST:
|
||||
if (mpctx->demuxer && mpctx->file_format == DEMUXER_TYPE_TV)
|
||||
tv_step_chanlist((tvi_handle_t *) (mpctx->demuxer->priv));
|
||||
if (get_tvh(mpctx))
|
||||
tv_step_chanlist(get_tvh(mpctx));
|
||||
break;
|
||||
#endif /* CONFIG_TV */
|
||||
|
||||
|
|
|
@ -115,6 +115,11 @@ typedef struct MPContext {
|
|||
struct demux_stream *d_audio;
|
||||
struct demux_stream *d_video;
|
||||
struct demux_stream *d_sub;
|
||||
|
||||
// Uses: accessing metadata (consider ordered chapters case, where the main
|
||||
// demuxer defines metadata), or special purpose demuxers like TV.
|
||||
struct demuxer *master_demuxer;
|
||||
|
||||
mixer_t mixer;
|
||||
struct ao *ao;
|
||||
struct vo *video_out;
|
||||
|
|
76
mplayer.c
76
mplayer.c
|
@ -286,7 +286,7 @@ static int is_valid_metadata_type(struct MPContext *mpctx, metadata_t type)
|
|||
case META_INFO_COMMENT:
|
||||
case META_INFO_TRACK:
|
||||
case META_INFO_GENRE:
|
||||
if (!mpctx->demuxer)
|
||||
if (!mpctx->master_demuxer)
|
||||
return 0;
|
||||
break;
|
||||
|
||||
|
@ -299,7 +299,7 @@ static int is_valid_metadata_type(struct MPContext *mpctx, metadata_t type)
|
|||
|
||||
static char *get_demuxer_info(struct MPContext *mpctx, char *tag)
|
||||
{
|
||||
char **info = mpctx->demuxer->info;
|
||||
char **info = mpctx->master_demuxer->info;
|
||||
int n;
|
||||
|
||||
if (!info || !tag)
|
||||
|
@ -400,7 +400,7 @@ static void print_stream(struct MPContext *mpctx, struct sh_stream *s)
|
|||
}
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "[stream] ID %d: %s", s->demuxer_id, tname);
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " --%s=%d", selopt, s->tid);
|
||||
char *lang = demuxer_stream_lang(mpctx->demuxer, s);
|
||||
char *lang = demuxer_stream_lang(s->common_header->ds->demuxer, s);
|
||||
if (lang)
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, " --%s=%s", langopt, lang);
|
||||
talloc_free(lang);
|
||||
|
@ -448,9 +448,6 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename)
|
|||
double video_start_pts = MP_NOPTS_VALUE;
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILENAME=%s\n",
|
||||
filename);
|
||||
if (mpctx->demuxer)
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_DEMUXER=%s\n",
|
||||
mpctx->demuxer->desc->name);
|
||||
if (mpctx->sh_video) {
|
||||
/* Assume FOURCC if all bytes >= 0x20 (' ') */
|
||||
if (mpctx->sh_video->format >= 0x20202020)
|
||||
|
@ -498,11 +495,8 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename)
|
|||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_START_TIME=unknown\n");
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO,
|
||||
"ID_LENGTH=%.2f\n", get_time_length(mpctx));
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SEEKABLE=%d\n",
|
||||
mpctx->stream->seek
|
||||
&& (!mpctx->demuxer || mpctx->demuxer->seekable));
|
||||
if (mpctx->demuxer) {
|
||||
int chapter_count = get_chapter_count(mpctx);
|
||||
int chapter_count = get_chapter_count(mpctx);
|
||||
if (chapter_count >= 0) {
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTERS=%d\n", chapter_count);
|
||||
for (int i = 0; i < chapter_count; i++) {
|
||||
mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_CHAPTER_ID=%d\n", i);
|
||||
|
@ -517,8 +511,10 @@ static void print_file_properties(struct MPContext *mpctx, const char *filename)
|
|||
talloc_free(name);
|
||||
}
|
||||
}
|
||||
for (int n = 0; n < mpctx->demuxer->num_streams; n++)
|
||||
print_stream(mpctx, mpctx->demuxer->streams[n]);
|
||||
}
|
||||
if (mpctx->master_demuxer) {
|
||||
for (int n = 0; n < mpctx->master_demuxer->num_streams; n++)
|
||||
print_stream(mpctx, mpctx->master_demuxer->streams[n]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -563,6 +559,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
|
|||
|
||||
if (mask & INITIALIZED_DEMUXER) {
|
||||
mpctx->initialized_flags &= ~INITIALIZED_DEMUXER;
|
||||
mpctx->master_demuxer = NULL;
|
||||
if (mpctx->num_sources) {
|
||||
mpctx->demuxer = mpctx->sources[0];
|
||||
for (int i = 1; i < mpctx->num_sources; i++) {
|
||||
|
@ -2089,9 +2086,11 @@ int reinit_video_chain(struct MPContext *mpctx)
|
|||
|
||||
vo_update_window_title(mpctx);
|
||||
|
||||
if (stream_control(mpctx->demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO,
|
||||
&ar) != STREAM_UNSUPPORTED)
|
||||
assert(mpctx->sh_video == mpctx->d_video->sh);
|
||||
if (stream_control(mpctx->d_video->demuxer->stream,
|
||||
STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED)
|
||||
mpctx->sh_video->stream_aspect = ar;
|
||||
|
||||
{
|
||||
char *vf_arg[] = {
|
||||
"_oldargs_", (char *)mpctx->video_out, NULL
|
||||
|
@ -2353,7 +2352,7 @@ void pause_player(struct MPContext *mpctx)
|
|||
ao_pause(mpctx->ao); // pause audio, keep data if possible
|
||||
|
||||
// Only print status if there's actually a file being played.
|
||||
if (mpctx->demuxer)
|
||||
if (mpctx->num_sources)
|
||||
print_status(mpctx, MP_NOPTS_VALUE, false);
|
||||
|
||||
if (!mpctx->opts.quiet)
|
||||
|
@ -2621,7 +2620,6 @@ void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount,
|
|||
abort();
|
||||
}
|
||||
|
||||
|
||||
double get_time_length(struct MPContext *mpctx)
|
||||
{
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
|
@ -2710,9 +2708,9 @@ int get_current_chapter(struct MPContext *mpctx)
|
|||
break;
|
||||
return FFMAX(mpctx->last_chapter_seek, i - 1);
|
||||
}
|
||||
if (mpctx->demuxer)
|
||||
if (mpctx->master_demuxer)
|
||||
return FFMAX(mpctx->last_chapter_seek,
|
||||
demuxer_get_current_chapter(mpctx->demuxer, current_pts));
|
||||
demuxer_get_current_chapter(mpctx->master_demuxer, current_pts));
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
@ -2740,8 +2738,8 @@ char *chapter_name(struct MPContext *mpctx, int chapter)
|
|||
{
|
||||
if (mpctx->chapters)
|
||||
return talloc_strdup(NULL, mpctx->chapters[chapter].name);
|
||||
if (mpctx->demuxer)
|
||||
return demuxer_chapter_name(mpctx->demuxer, chapter);
|
||||
if (mpctx->master_demuxer)
|
||||
return demuxer_chapter_name(mpctx->master_demuxer, chapter);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -2750,8 +2748,8 @@ double chapter_start_time(struct MPContext *mpctx, int chapter)
|
|||
{
|
||||
if (mpctx->chapters)
|
||||
return mpctx->chapters[chapter].start;
|
||||
if (mpctx->demuxer)
|
||||
return demuxer_chapter_time(mpctx->demuxer, chapter, NULL);
|
||||
if (mpctx->master_demuxer)
|
||||
return demuxer_chapter_time(mpctx->master_demuxer, chapter, NULL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -2759,8 +2757,8 @@ int get_chapter_count(struct MPContext *mpctx)
|
|||
{
|
||||
if (mpctx->chapters)
|
||||
return mpctx->num_chapters;
|
||||
if (mpctx->demuxer)
|
||||
return demuxer_chapter_count(mpctx->demuxer);
|
||||
if (mpctx->master_demuxer)
|
||||
return demuxer_chapter_count(mpctx->master_demuxer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2777,11 +2775,12 @@ int seek_chapter(struct MPContext *mpctx, int chapter, double *seek_pts)
|
|||
mpctx->last_chapter_pts = *seek_pts;
|
||||
return chapter;
|
||||
}
|
||||
if (mpctx->demuxer) {
|
||||
int res = demuxer_seek_chapter(mpctx->demuxer, chapter, seek_pts);
|
||||
|
||||
if (mpctx->master_demuxer) {
|
||||
int res = demuxer_seek_chapter(mpctx->master_demuxer, chapter, seek_pts);
|
||||
if (res >= 0) {
|
||||
if (*seek_pts == -1)
|
||||
seek_reset(mpctx, true, true);
|
||||
seek_reset(mpctx, true, true); // for DVD
|
||||
else {
|
||||
mpctx->last_chapter_seek = res;
|
||||
mpctx->last_chapter_pts = *seek_pts;
|
||||
|
@ -3366,13 +3365,13 @@ static void play_current_file(struct MPContext *mpctx)
|
|||
|
||||
//============ Open & Sync STREAM --- fork cache2 ====================
|
||||
|
||||
mpctx->stream = NULL;
|
||||
mpctx->demuxer = NULL;
|
||||
mpctx->d_audio = NULL;
|
||||
mpctx->d_video = NULL;
|
||||
mpctx->d_sub = NULL;
|
||||
mpctx->sh_audio = NULL;
|
||||
mpctx->sh_video = NULL;
|
||||
assert(mpctx->stream == NULL);
|
||||
assert(mpctx->demuxer == NULL);
|
||||
assert(mpctx->d_audio == NULL);
|
||||
assert(mpctx->d_video == NULL);
|
||||
assert(mpctx->d_sub == NULL);
|
||||
assert(mpctx->sh_audio == NULL);
|
||||
assert(mpctx->sh_video == NULL);
|
||||
|
||||
mpctx->stream = open_stream(mpctx->filename, opts, &mpctx->file_format);
|
||||
if (!mpctx->stream) { // error...
|
||||
|
@ -3435,6 +3434,7 @@ goto_enable_cache:
|
|||
mpctx->demuxer = demux_open(opts, mpctx->stream, mpctx->file_format,
|
||||
opts->audio_id, opts->video_id, opts->sub_id,
|
||||
mpctx->filename);
|
||||
mpctx->master_demuxer = mpctx->demuxer;
|
||||
|
||||
if (!mpctx->demuxer) {
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "Failed to recognize file format.\n");
|
||||
|
@ -3484,7 +3484,7 @@ goto_enable_cache:
|
|||
} else {
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_V, "[V] filefmt:%d fourcc:0x%X "
|
||||
"size:%dx%d fps:%5.3f ftime:=%6.4f\n",
|
||||
mpctx->demuxer->file_format, mpctx->sh_video->format,
|
||||
mpctx->master_demuxer->file_format, mpctx->sh_video->format,
|
||||
mpctx->sh_video->disp_w, mpctx->sh_video->disp_h,
|
||||
mpctx->sh_video->fps, mpctx->sh_video->frametime);
|
||||
if (force_fps) {
|
||||
|
@ -3522,7 +3522,7 @@ goto_enable_cache:
|
|||
}
|
||||
|
||||
/* display clip info */
|
||||
demux_info_print(mpctx->demuxer);
|
||||
demux_info_print(mpctx->master_demuxer);
|
||||
|
||||
//================= Read SUBTITLES (DVD & TEXT) =========================
|
||||
if (vo_spudec == NULL && (mpctx->stream->type == STREAMTYPE_DVD))
|
||||
|
@ -3603,7 +3603,7 @@ goto_enable_cache:
|
|||
|
||||
mp_input_set_section(mpctx->input, NULL, 0);
|
||||
//TODO: add desired (stream-based) sections here
|
||||
if (mpctx->stream->type == STREAMTYPE_TV)
|
||||
if (mpctx->master_demuxer->type == DEMUXER_TYPE_TV)
|
||||
mp_input_set_section(mpctx->input, "tv", 0);
|
||||
|
||||
//==================== START PLAYING =======================
|
||||
|
|
Loading…
Reference in New Issue