Browse Source

player: add on_next_frame_status

Rework input to send next-frame status via player callbacks. If not
listeners is registered, print the error via a dialog error.
work/string-cache
Thomas Guillem 9 months ago
committed by Jean-Baptiste Kempf
parent
commit
1619f2ae98
  1. 18
      include/vlc_player.h
  2. 1
      po/POTFILES.in
  3. 21
      src/input/decoder.c
  4. 3
      src/input/decoder.h
  5. 22
      src/input/es_out.c
  6. 17
      src/input/input.c
  7. 5
      src/input/input_internal.h
  8. 50
      src/player/input.c
  9. 6
      src/player/player.c

18
include/vlc_player.h

@ -477,6 +477,11 @@ vlc_player_Resume(vlc_player_t *player);
/**
* Pause and display the next video frame
*
* @note Works only on streams that can pause..
*
* @note listen to the vlc_player_cbs.on_next_frame_status to be notified when
* the next frame is displayed.
*
* @param player locked player instance
*/
VLC_API void
@ -3317,6 +3322,19 @@ struct vlc_player_cbs
void (*on_stopping_current_media)(vlc_player_t *player, input_item_t *current_media,
enum vlc_player_media_stopping_reason stopping_reason,
void *data);
/**
* Called when the next frame, following a call to
* `vlc_player_NextVideoFrame()`, is displayed.
*
* @see vlc_player_NextVideoFrame()
*
* @param player locked player instance
* @param status 0 in case of success, -EAGAIN on first call (paused),
* -EBUSY in case of video error, -ENOTSUP if can't pause,
* -EINVAL in case of invalid state
*/
void (*on_next_frame_status)(vlc_player_t *player, int status, void *data);
};
/**

1
po/POTFILES.in

@ -115,6 +115,7 @@ src/network/tls.c
src/network/udp.c
src/player/osd.c
src/player/player.c
src/player/input.c
src/stream_output/sap.c
src/stream_output/stream_output.c
src/stream_output/stream_output.h

21
src/input/decoder.c

@ -2732,19 +2732,24 @@ void vlc_input_decoder_Wait( vlc_input_decoder_t *p_owner )
void vlc_input_decoder_FrameNext( vlc_input_decoder_t *p_owner )
{
assert( p_owner->paused );
assert( p_owner->cat == VIDEO_ES );
vlc_fifo_Lock( p_owner->p_fifo );
p_owner->frames_countdown++;
vlc_fifo_Signal( p_owner->p_fifo );
vlc_fifo_Unlock( p_owner->p_fifo );
vlc_fifo_Lock(p_owner->p_fifo);
if( p_owner->cat == VIDEO_ES )
if( p_owner->video.vout == NULL )
{
if( p_owner->video.vout )
vout_NextPicture( p_owner->video.vout );
decoder_Notify( p_owner, frame_next_status, -EBUSY );
vlc_fifo_Unlock( p_owner->p_fifo );
return;
}
vlc_fifo_Unlock(p_owner->p_fifo);
p_owner->frames_countdown++;
vlc_fifo_Signal( p_owner->p_fifo );
vout_NextPicture( p_owner->video.vout );
/* TODO: it should be notified from the vout */
decoder_Notify( p_owner, frame_next_status, 0 );
vlc_fifo_Unlock( p_owner->p_fifo );
}
size_t vlc_input_decoder_GetFifoSize( vlc_input_decoder_t *p_owner )

3
src/input/decoder.h

@ -52,7 +52,8 @@ struct vlc_input_decoder_callbacks {
void *userdata);
void (*on_new_audio_stats)(vlc_input_decoder_t *decoder, unsigned decoded,
unsigned lost, unsigned played, void *userdata);
void (*frame_next_status)(vlc_input_decoder_t *decoder, int status,
void *userdata);
/* requests */
int (*get_attachments)(vlc_input_decoder_t *decoder,
input_attachment_t ***ppp_attachment,

22
src/input/es_out.c

@ -502,6 +502,27 @@ decoder_on_new_audio_stats(vlc_input_decoder_t *decoder, unsigned decoded, unsig
memory_order_relaxed);
}
static void
decoder_frame_next_status(vlc_input_decoder_t *decoder, int status,
void *userdata)
{
(void) decoder;
es_out_id_t *id = userdata;
struct vlc_input_es_out *out = id->out;
es_out_sys_t *p_sys = container_of(out, es_out_sys_t, out);
if (!p_sys->p_input)
return;
const struct vlc_input_event event = {
.type = INPUT_EVENT_FRAME_NEXT_STATUS,
.frame_next_status = status,
};
input_SendEvent(p_sys->p_input, &event);
}
static int
decoder_get_attachments(vlc_input_decoder_t *decoder,
input_attachment_t ***ppp_attachment,
@ -526,6 +547,7 @@ static const struct vlc_input_decoder_callbacks decoder_cbs = {
.on_thumbnail_ready = decoder_on_thumbnail_ready,
.on_new_video_stats = decoder_on_new_video_stats,
.on_new_audio_stats = decoder_on_new_audio_stats,
.frame_next_status = decoder_frame_next_status,
.get_attachments = decoder_get_attachments,
};

17
src/input/input.c

@ -2316,6 +2316,14 @@ static bool Control( input_thread_t *p_input,
}
case INPUT_CONTROL_SET_FRAME_NEXT:
if (!priv->master->b_can_pause)
{
input_SendEvent(p_input, &(struct vlc_input_event) {
.type = INPUT_EVENT_FRAME_NEXT_STATUS,
.frame_next_status = -ENOTSUP,
});
break;
}
if( priv->i_state == PAUSE_S )
{
es_out_SetFrameNext( priv->p_es_out );
@ -2323,10 +2331,17 @@ static bool Control( input_thread_t *p_input,
else if( priv->i_state == PLAYING_S )
{
ControlPause( p_input, i_control_date );
input_SendEvent(p_input, &(struct vlc_input_event) {
.type = INPUT_EVENT_FRAME_NEXT_STATUS,
.frame_next_status = -EAGAIN,
});
}
else
{
msg_Err( p_input, "invalid state for frame next" );
input_SendEvent(p_input, &(struct vlc_input_event) {
.type = INPUT_EVENT_FRAME_NEXT_STATUS,
.frame_next_status = -EINVAL,
});
}
b_force_update = true;
break;

5
src/input/input_internal.h

@ -159,6 +159,9 @@ typedef enum input_event_type_e
/* Mouse event */
INPUT_EVENT_MOUSE_LEFT,
/* frame-next status */
INPUT_EVENT_FRAME_NEXT_STATUS,
} input_event_type_e;
#define VLC_INPUT_CAPABILITIES_SEEKABLE (1<<0)
@ -347,6 +350,8 @@ struct vlc_input_event
struct vlc_input_event_attachments attachments;
/* INPUT_EVENT_NAV_FAILED */
int nav_type;
/* INPUT_EVENT_FRAME_NEXT_STATUS */
int frame_next_status;
};
};

50
src/player/input.c

@ -24,6 +24,7 @@
#include <vlc_common.h>
#include <vlc_memstream.h>
#include <vlc_dialog.h>
#include "player.h"
struct vlc_player_track_priv *
@ -878,6 +879,51 @@ vlc_player_input_MouseFallback(struct vlc_player_input *input)
vlc_player_TogglePause(player);
}
static void
vlc_player_DisplayFrameError(vlc_player_t *player,
const char *title, const char *title_error,
int status)
{
static const char ebusy[] = {N_("no video found")};
static const char enotusp[] = {N_("can't pause/seek/pace")};
static const char einval[] = {N_("invalid state")};
switch (status)
{
case 0:
vlc_player_osd_Message(player, title);
break;
case -EAGAIN:
break;
case -EBUSY:
vlc_dialog_display_error(player, title_error, ebusy);
break;
case -ENOTSUP:
vlc_dialog_display_error(player, title_error, enotusp);
break;
default:
case -EINVAL:
vlc_dialog_display_error(player, title_error, einval);
break;
}
}
static void
vlc_player_input_FrameNextStatus(struct vlc_player_input *input, int status)
{
vlc_player_t *player = input->player;
unsigned count;
vlc_player_SendEventCount(player, on_next_frame_status, count, status);
/* Don't display errors if status is handled by the player user */
if (count != 0)
return;
vlc_player_DisplayFrameError(player, _("Next frame"),
_("Next frame error"), status);
}
static bool
input_thread_Events(input_thread_t *input_thread,
const struct vlc_input_event *event, void *user_data)
@ -1100,6 +1146,10 @@ input_thread_Events(input_thread_t *input_thread,
case INPUT_EVENT_MOUSE_LEFT:
vlc_player_input_MouseFallback(input);
break;
case INPUT_EVENT_FRAME_NEXT_STATUS:
vlc_player_input_FrameNextStatus(input,
event->frame_next_status);
break;
default:
handled = false;
break;

6
src/player/player.c

@ -1334,10 +1334,8 @@ vlc_player_NextVideoFrame(vlc_player_t *player)
struct vlc_player_input *input = vlc_player_get_input_locked(player);
if (!input)
return;
int ret = input_ControlPushHelper(input->thread,
INPUT_CONTROL_SET_FRAME_NEXT, NULL);
if (ret == VLC_SUCCESS)
vlc_player_osd_Message(player, _("Next frame"));
input_ControlPushHelper(input->thread,
INPUT_CONTROL_SET_FRAME_NEXT, NULL);
}
enum vlc_player_state

Loading…
Cancel
Save