mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
Add VDPAU display preemption support.
This commit is contained in:
parent
e3681812bd
commit
9063b4e3ff
@ -1,3 +1,8 @@
|
|||||||
|
User johns
|
||||||
|
Date:
|
||||||
|
|
||||||
|
Add VDPAU display preemption support.
|
||||||
|
|
||||||
User m.Rcu
|
User m.Rcu
|
||||||
Date: Tue Jan 24 22:38:30 CET 2012
|
Date: Tue Jan 24 22:38:30 CET 2012
|
||||||
|
|
||||||
|
4
Todo
4
Todo
@ -27,6 +27,9 @@ missing:
|
|||||||
Option deinterlace off / deinterlace force!
|
Option deinterlace off / deinterlace force!
|
||||||
Make output drivers better modular (under construction).
|
Make output drivers better modular (under construction).
|
||||||
|
|
||||||
|
crash:
|
||||||
|
AudioPlayHandlerThread -> pthread_cond_wait
|
||||||
|
|
||||||
video:
|
video:
|
||||||
subtitle not cleared
|
subtitle not cleared
|
||||||
subtitle could be asyncron
|
subtitle could be asyncron
|
||||||
@ -36,7 +39,6 @@ video:
|
|||||||
(must detect video format to show image)
|
(must detect video format to show image)
|
||||||
|
|
||||||
vdpau:
|
vdpau:
|
||||||
VdpPreemptionCallback handling (under construction)
|
|
||||||
hard channel switch
|
hard channel switch
|
||||||
|
|
||||||
libva:
|
libva:
|
||||||
|
305
video.c
305
video.c
@ -292,7 +292,7 @@ static VideoZoomModes Video4to3ZoomMode;
|
|||||||
|
|
||||||
static char Video60HzMode; ///< handle 60hz displays
|
static char Video60HzMode; ///< handle 60hz displays
|
||||||
|
|
||||||
static xcb_atom_t WmDeleteWindowAtom; ///< WM delete message
|
static xcb_atom_t WmDeleteWindowAtom; ///< WM delete message atom
|
||||||
static xcb_atom_t NetWmState; ///< wm-state message atom
|
static xcb_atom_t NetWmState; ///< wm-state message atom
|
||||||
static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom
|
static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom
|
||||||
|
|
||||||
@ -1564,8 +1564,16 @@ static void VaapiCleanup(VaapiDecoder * decoder)
|
|||||||
///
|
///
|
||||||
static void VaapiDelDecoder(VaapiDecoder * decoder)
|
static void VaapiDelDecoder(VaapiDecoder * decoder)
|
||||||
{
|
{
|
||||||
VaapiDecoderN = 0;
|
int i;
|
||||||
VaapiDecoders[0] = NULL;
|
|
||||||
|
for (i = 0; i < VaapiDecoderN; ++i) {
|
||||||
|
if (VaapiDecoders[i] == decoder) {
|
||||||
|
VaapiDecoders[i] = NULL;
|
||||||
|
VaapiDecoderN--;
|
||||||
|
// FIXME: must copy last slot into empty slot and --
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VaapiCleanup(decoder);
|
VaapiCleanup(decoder);
|
||||||
|
|
||||||
@ -2024,7 +2032,7 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
|
|||||||
|
|
||||||
slow_path:
|
slow_path:
|
||||||
// no accelerated format found
|
// no accelerated format found
|
||||||
decoder->SurfacesNeeded = 1 + VIDEO_SURFACES_MAX;
|
decoder->SurfacesNeeded = VIDEO_SURFACES_MAX + 2;
|
||||||
video_ctx->hwaccel_context = NULL;
|
video_ctx->hwaccel_context = NULL;
|
||||||
return avcodec_default_get_format(video_ctx, fmt);
|
return avcodec_default_get_format(video_ctx, fmt);
|
||||||
}
|
}
|
||||||
@ -3539,7 +3547,8 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
|
|||||||
decoder->DropNextFrame = 1;
|
decoder->DropNextFrame = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
// debug audio/video sync
|
||||||
if (decoder->DupNextFrame || decoder->DropNextFrame
|
if (decoder->DupNextFrame || decoder->DropNextFrame
|
||||||
|| !(decoder->FramesDisplayed % (50 * 10))) {
|
|| !(decoder->FramesDisplayed % (50 * 10))) {
|
||||||
static int64_t last_video_clock;
|
static int64_t last_video_clock;
|
||||||
@ -3552,6 +3561,7 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
|
|||||||
|
|
||||||
last_video_clock = video_clock;
|
last_video_clock = video_clock;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -3674,7 +3684,7 @@ static int64_t VaapiGetClock(const VaapiDecoder * decoder)
|
|||||||
20 * 90 * (2 * atomic_read(&decoder->SurfacesFilled)
|
20 * 90 * (2 * atomic_read(&decoder->SurfacesFilled)
|
||||||
- decoder->SurfaceField);
|
- decoder->SurfaceField);
|
||||||
}
|
}
|
||||||
return decoder->PTS - 20 * 90 * (atomic_read(&decoder->SurfacesFilled) -
|
return decoder->PTS - 20 * 90 * (atomic_read(&decoder->SurfacesFilled) +
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3998,11 +4008,13 @@ typedef struct _vdpau_decoder_
|
|||||||
void *GlxSurface[2]; ///< VDPAU/GLX surface
|
void *GlxSurface[2]; ///< VDPAU/GLX surface
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
VdpDecoderProfile Profile; ///< vdp decoder profile
|
||||||
VdpDecoder VideoDecoder; ///< vdp video decoder
|
VdpDecoder VideoDecoder; ///< vdp video decoder
|
||||||
VdpVideoMixer VideoMixer; ///< vdp video mixer
|
VdpVideoMixer VideoMixer; ///< vdp video mixer
|
||||||
VdpChromaType ChromaType; ///< vdp video surface chroma format
|
VdpChromaType ChromaType; ///< vdp video surface chroma format
|
||||||
VdpProcamp Procamp; ///< vdp procamp parameterization data
|
VdpProcamp Procamp; ///< vdp procamp parameterization data
|
||||||
|
|
||||||
|
int SurfacesNeeded; ///< number of surface to request
|
||||||
int SurfaceUsedN; ///< number of used video surfaces
|
int SurfaceUsedN; ///< number of used video surfaces
|
||||||
/// used video surface ids
|
/// used video surface ids
|
||||||
VdpVideoSurface SurfacesUsed[CODEC_SURFACES_MAX];
|
VdpVideoSurface SurfacesUsed[CODEC_SURFACES_MAX];
|
||||||
@ -4030,6 +4042,7 @@ typedef struct _vdpau_decoder_
|
|||||||
} VdpauDecoder;
|
} VdpauDecoder;
|
||||||
|
|
||||||
static int VideoVdpauEnabled = 1; ///< use VDPAU decoder
|
static int VideoVdpauEnabled = 1; ///< use VDPAU decoder
|
||||||
|
static volatile char VdpauPreemption; ///< flag preemption happened.
|
||||||
|
|
||||||
static VdpauDecoder *VdpauDecoders[1]; ///< open decoder streams
|
static VdpauDecoder *VdpauDecoders[1]; ///< open decoder streams
|
||||||
static int VdpauDecoderN; ///< number of decoder streams
|
static int VdpauDecoderN; ///< number of decoder streams
|
||||||
@ -4130,11 +4143,16 @@ static VdpPresentationQueueBlockUntilSurfaceIdle
|
|||||||
*VdpauPresentationQueueBlockUntilSurfaceIdle;
|
*VdpauPresentationQueueBlockUntilSurfaceIdle;
|
||||||
static VdpPresentationQueueQuerySurfaceStatus
|
static VdpPresentationQueueQuerySurfaceStatus
|
||||||
*VdpauPresentationQueueQuerySurfaceStatus;
|
*VdpauPresentationQueueQuerySurfaceStatus;
|
||||||
|
static VdpPreemptionCallbackRegister *VdpauPreemptionCallbackRegister;
|
||||||
|
|
||||||
static VdpPresentationQueueTargetCreateX11 *
|
static VdpPresentationQueueTargetCreateX11 *
|
||||||
VdpauPresentationQueueTargetCreateX11;
|
VdpauPresentationQueueTargetCreateX11;
|
||||||
///@}
|
///@}
|
||||||
|
|
||||||
|
static void VdpauOsdInit(int, int); ///< forward definition
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Create surfaces for VDPAU decoder.
|
/// Create surfaces for VDPAU decoder.
|
||||||
///
|
///
|
||||||
@ -4146,11 +4164,17 @@ static void VdpauCreateSurfaces(VdpauDecoder * decoder, int width, int height)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (!decoder->SurfacesNeeded) {
|
||||||
|
Error(_("video/vaapi: surface needed not set\n"));
|
||||||
|
decoder->SurfacesNeeded = 3 + VIDEO_SURFACES_MAX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Debug(3, "video/vdpau: %s: %dx%d * %d\n", __FUNCTION__, width, height,
|
Debug(3, "video/vdpau: %s: %dx%d * %d\n", __FUNCTION__, width, height,
|
||||||
CODEC_SURFACES_DEFAULT);
|
decoder->SurfacesNeeded);
|
||||||
|
|
||||||
// FIXME: allocate only the number of needed surfaces
|
// allocate only the number of needed surfaces
|
||||||
decoder->SurfaceFreeN = CODEC_SURFACES_DEFAULT;
|
decoder->SurfaceFreeN = decoder->SurfacesNeeded;
|
||||||
for (i = 0; i < decoder->SurfaceFreeN; ++i) {
|
for (i = 0; i < decoder->SurfaceFreeN; ++i) {
|
||||||
VdpStatus status;
|
VdpStatus status;
|
||||||
|
|
||||||
@ -4516,15 +4540,18 @@ static VdpauDecoder *VdpauNewDecoder(void)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (VdpauDecoderN == 1) {
|
if (VdpauDecoderN == 1) {
|
||||||
Fatal(_("video/vdpau: out of decoders\n"));
|
Error(_("video/vdpau: out of decoders\n"));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(decoder = calloc(1, sizeof(*decoder)))) {
|
if (!(decoder = calloc(1, sizeof(*decoder)))) {
|
||||||
Fatal(_("video/vdpau: out of memory\n"));
|
Error(_("video/vdpau: out of memory\n"));
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
decoder->Device = VdpauDevice;
|
decoder->Device = VdpauDevice;
|
||||||
decoder->Window = VideoWindow;
|
decoder->Window = VideoWindow;
|
||||||
|
|
||||||
|
decoder->Profile = VDP_INVALID_HANDLE;
|
||||||
decoder->VideoDecoder = VDP_INVALID_HANDLE;
|
decoder->VideoDecoder = VDP_INVALID_HANDLE;
|
||||||
decoder->VideoMixer = VDP_INVALID_HANDLE;
|
decoder->VideoMixer = VDP_INVALID_HANDLE;
|
||||||
|
|
||||||
@ -4547,7 +4574,7 @@ static VdpauDecoder *VdpauNewDecoder(void)
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (VIDEO_SURFACES_MAX < 1 + 1 + 1 + 1) {
|
if (VIDEO_SURFACES_MAX < 1 + 1 + 1 + 1) {
|
||||||
Fatal(_
|
Error(_
|
||||||
("video/vdpau: need 1 future, 1 current, 1 back and 1 work surface\n"));
|
("video/vdpau: need 1 future, 1 current, 1 back and 1 work surface\n"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -4587,6 +4614,7 @@ static void VdpauCleanup(VdpauDecoder * decoder)
|
|||||||
VdpauGetErrorString(status));
|
VdpauGetErrorString(status));
|
||||||
}
|
}
|
||||||
decoder->VideoDecoder = VDP_INVALID_HANDLE;
|
decoder->VideoDecoder = VDP_INVALID_HANDLE;
|
||||||
|
decoder->Profile = VDP_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decoder->VideoMixer != VDP_INVALID_HANDLE) {
|
if (decoder->VideoMixer != VDP_INVALID_HANDLE) {
|
||||||
@ -4624,9 +4652,16 @@ static void VdpauCleanup(VdpauDecoder * decoder)
|
|||||||
///
|
///
|
||||||
static void VdpauDelDecoder(VdpauDecoder * decoder)
|
static void VdpauDelDecoder(VdpauDecoder * decoder)
|
||||||
{
|
{
|
||||||
// FIXME: hack
|
int i;
|
||||||
VdpauDecoderN = 0;
|
|
||||||
VdpauDecoders[0] = NULL;
|
for (i = 0; i < VdpauDecoderN; ++i) {
|
||||||
|
if (VdpauDecoders[i] == decoder) {
|
||||||
|
VdpauDecoders[i] = NULL;
|
||||||
|
VdpauDecoderN--;
|
||||||
|
// FIXME: must copy last slot into empty slot and --
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VdpauCleanup(decoder);
|
VdpauCleanup(decoder);
|
||||||
|
|
||||||
@ -4743,6 +4778,23 @@ static void VdpauExitOutputQueue(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Display preemption callback.
|
||||||
|
///
|
||||||
|
/// @param device device that had its display preempted
|
||||||
|
/// @param context client-supplied callback context
|
||||||
|
///
|
||||||
|
static void VdpauPreemptionCallback(VdpDevice device, __attribute__ ((unused))
|
||||||
|
void *context)
|
||||||
|
{
|
||||||
|
Debug(3, "video/vdpau: display preemption\n");
|
||||||
|
if (device != VdpauDevice) {
|
||||||
|
Error(_("video/vdpau preemption device not our device\n"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VdpauPreemption = 1; // set flag for video thread
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// VDPAU setup.
|
/// VDPAU setup.
|
||||||
///
|
///
|
||||||
@ -4929,16 +4981,20 @@ static void VdpauInit(const char *display_name)
|
|||||||
VdpauGetProc(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS,
|
VdpauGetProc(VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS,
|
||||||
&VdpauPresentationQueueQuerySurfaceStatus,
|
&VdpauPresentationQueueQuerySurfaceStatus,
|
||||||
"PresentationQueueQuerySurfaceStatus");
|
"PresentationQueueQuerySurfaceStatus");
|
||||||
#if 0
|
|
||||||
VdpauGetProc(VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER,
|
VdpauGetProc(VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER,
|
||||||
&VdpauPreemptionCallback, "PreemptionCallback");
|
&VdpauPreemptionCallbackRegister, "PreemptionCallbackRegister");
|
||||||
#endif
|
|
||||||
VdpauGetProc(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11,
|
VdpauGetProc(VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11,
|
||||||
&VdpauPresentationQueueTargetCreateX11,
|
&VdpauPresentationQueueTargetCreateX11,
|
||||||
"PresentationQueueTargetCreateX11");
|
"PresentationQueueTargetCreateX11");
|
||||||
|
|
||||||
// vdp_preemption_callback_register
|
status =
|
||||||
|
VdpauPreemptionCallbackRegister(VdpauDevice, VdpauPreemptionCallback,
|
||||||
|
NULL);
|
||||||
|
if (status != VDP_STATUS_OK) {
|
||||||
|
Error(_("video/vdpau: can't register preemption callback: %s\n"),
|
||||||
|
VdpauGetErrorString(status));
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// Look which levels of high quality scaling are supported
|
// Look which levels of high quality scaling are supported
|
||||||
//
|
//
|
||||||
@ -5140,7 +5196,6 @@ static void VdpauInit(const char *display_name)
|
|||||||
// Create presentation queue, only one queue pro window
|
// Create presentation queue, only one queue pro window
|
||||||
//
|
//
|
||||||
VdpauInitOutputQueue();
|
VdpauInitOutputQueue();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -5228,8 +5283,51 @@ static void VdpauUpdateOutput(VdpauDecoder * decoder)
|
|||||||
Debug(3, "video: aspect output %dx%d+%d+%d\n", decoder->OutputWidth,
|
Debug(3, "video: aspect output %dx%d+%d+%d\n", decoder->OutputWidth,
|
||||||
decoder->OutputHeight, decoder->OutputX, decoder->OutputY);
|
decoder->OutputHeight, decoder->OutputX, decoder->OutputY);
|
||||||
|
|
||||||
|
#ifdef USE_AUTOCROP
|
||||||
decoder->AutoCrop->State = 0;
|
decoder->AutoCrop->State = 0;
|
||||||
decoder->AutoCrop->Count = 0;
|
decoder->AutoCrop->Count = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Configure VDPAU for new video format.
|
||||||
|
///
|
||||||
|
/// @param decoder VDPAU hw decoder
|
||||||
|
///
|
||||||
|
static void VdpauSetupOutput(VdpauDecoder * decoder)
|
||||||
|
{
|
||||||
|
VdpStatus status;
|
||||||
|
VdpChromaType chroma_type;
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
|
||||||
|
// FIXME: need only to create and destroy surfaces for size changes
|
||||||
|
// or when number of needed surfaces changed!
|
||||||
|
decoder->Resolution =
|
||||||
|
VideoResolutionGroup(decoder->InputWidth, decoder->InputHeight,
|
||||||
|
decoder->Interlaced);
|
||||||
|
VdpauCreateSurfaces(decoder, decoder->InputWidth, decoder->InputHeight);
|
||||||
|
|
||||||
|
VdpauMixerCreate(decoder);
|
||||||
|
|
||||||
|
VdpauUpdateOutput(decoder); // update aspect/scaling
|
||||||
|
|
||||||
|
// get real surface size
|
||||||
|
status =
|
||||||
|
VdpauVideoSurfaceGetParameters(decoder->SurfacesFree[0], &chroma_type,
|
||||||
|
&width, &height);
|
||||||
|
if (status != VDP_STATUS_OK) {
|
||||||
|
Error(_("video/vdpau: can't get video surface parameters: %s\n"),
|
||||||
|
VdpauGetErrorString(status));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// vdpau can choose different sizes, must use them for putbits
|
||||||
|
if (chroma_type != decoder->ChromaType
|
||||||
|
|| width != (uint32_t) decoder->InputWidth
|
||||||
|
|| height != (uint32_t) decoder->InputHeight) {
|
||||||
|
// FIXME: must rewrite the code to support this case
|
||||||
|
Fatal(_("video/vdpau: video surface type/size mismatch\n"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -5383,17 +5481,17 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
|
|||||||
Debug(3, "video/vdpau: create decoder profile=%d %dx%d #%d refs\n",
|
Debug(3, "video/vdpau: create decoder profile=%d %dx%d #%d refs\n",
|
||||||
profile, video_ctx->width, video_ctx->height, max_refs);
|
profile, video_ctx->width, video_ctx->height, max_refs);
|
||||||
|
|
||||||
|
decoder->Profile = profile;
|
||||||
|
decoder->SurfacesNeeded = max_refs + VIDEO_SURFACES_MAX;
|
||||||
status =
|
status =
|
||||||
VdpauDecoderCreate(VdpauDevice, profile, video_ctx->width,
|
VdpauDecoderCreate(VdpauDevice, profile, video_ctx->width,
|
||||||
video_ctx->height, max_refs, &decoder->VideoDecoder);
|
video_ctx->height, max_refs, &decoder->VideoDecoder);
|
||||||
if (status != VDP_STATUS_OK) {
|
if (status != VDP_STATUS_OK) {
|
||||||
Error(_("video/vdpau: can't create decoder: %s\n"),
|
Error(_("video/vdpau: can't create decoder: %s\n"),
|
||||||
VdpauGetErrorString(status));
|
VdpauGetErrorString(status));
|
||||||
abort();
|
|
||||||
goto slow_path;
|
goto slow_path;
|
||||||
}
|
}
|
||||||
// FIXME: Combine this with VdpauSetup
|
// FIXME: combine this with VdpauSetupOutput and software decoder part
|
||||||
|
|
||||||
decoder->CropX = 0;
|
decoder->CropX = 0;
|
||||||
decoder->CropY = 0;
|
decoder->CropY = 0;
|
||||||
decoder->CropWidth = video_ctx->width;
|
decoder->CropWidth = video_ctx->width;
|
||||||
@ -5403,16 +5501,8 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
|
|||||||
decoder->InputWidth = video_ctx->width;
|
decoder->InputWidth = video_ctx->width;
|
||||||
decoder->InputHeight = video_ctx->height;
|
decoder->InputHeight = video_ctx->height;
|
||||||
decoder->InputAspect = video_ctx->sample_aspect_ratio;
|
decoder->InputAspect = video_ctx->sample_aspect_ratio;
|
||||||
VdpauUpdateOutput(decoder);
|
|
||||||
|
|
||||||
// FIXME: need only to create and destroy surfaces for size changes
|
VdpauSetupOutput(decoder);
|
||||||
// or when number of needed surfaces changed!
|
|
||||||
decoder->Resolution =
|
|
||||||
VideoResolutionGroup(video_ctx->width, video_ctx->height,
|
|
||||||
decoder->Interlaced);
|
|
||||||
VdpauCreateSurfaces(decoder, video_ctx->width, video_ctx->height);
|
|
||||||
|
|
||||||
VdpauMixerCreate(decoder);
|
|
||||||
|
|
||||||
Debug(3, "\t%#010x %s\n", fmt_idx[0], av_get_pix_fmt_name(fmt_idx[0]));
|
Debug(3, "\t%#010x %s\n", fmt_idx[0], av_get_pix_fmt_name(fmt_idx[0]));
|
||||||
|
|
||||||
@ -5420,54 +5510,11 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
|
|||||||
|
|
||||||
slow_path:
|
slow_path:
|
||||||
// no accelerated format found
|
// no accelerated format found
|
||||||
|
decoder->SurfacesNeeded = VIDEO_SURFACES_MAX;
|
||||||
video_ctx->hwaccel_context = NULL;
|
video_ctx->hwaccel_context = NULL;
|
||||||
return avcodec_default_get_format(video_ctx, fmt);
|
return avcodec_default_get_format(video_ctx, fmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
/// Configure VDPAU for new video format.
|
|
||||||
///
|
|
||||||
/// @param decoder VDPAU hw decoder
|
|
||||||
/// @param video_ctx ffmpeg video codec context
|
|
||||||
///
|
|
||||||
static void VdpauSetup(VdpauDecoder * decoder,
|
|
||||||
const AVCodecContext * video_ctx)
|
|
||||||
{
|
|
||||||
VdpStatus status;
|
|
||||||
VdpChromaType chroma_type;
|
|
||||||
uint32_t width;
|
|
||||||
uint32_t height;
|
|
||||||
|
|
||||||
// decoder->Input... already setup by caller
|
|
||||||
VdpauCleanup(decoder);
|
|
||||||
|
|
||||||
decoder->Resolution =
|
|
||||||
VideoResolutionGroup(video_ctx->width, video_ctx->height,
|
|
||||||
decoder->Interlaced);
|
|
||||||
VdpauCreateSurfaces(decoder, video_ctx->width, video_ctx->height);
|
|
||||||
|
|
||||||
VdpauMixerCreate(decoder);
|
|
||||||
|
|
||||||
// get real surface size
|
|
||||||
status =
|
|
||||||
VdpauVideoSurfaceGetParameters(decoder->SurfacesFree[0], &chroma_type,
|
|
||||||
&width, &height);
|
|
||||||
if (status != VDP_STATUS_OK) {
|
|
||||||
Error(_("video/vdpau: can't get video surface parameters: %s\n"),
|
|
||||||
VdpauGetErrorString(status));
|
|
||||||
}
|
|
||||||
// vdpau can choose different sizes, must use them for putbits
|
|
||||||
if (chroma_type != decoder->ChromaType
|
|
||||||
|| width != (uint32_t) video_ctx->width
|
|
||||||
|| height != (uint32_t) video_ctx->height) {
|
|
||||||
// FIXME: must rewrite the code to support this case
|
|
||||||
Fatal(_("video/vdpau: video surface type/size mismatch\n"));
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// When window output size changes update VdpauSurfacesRb
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef USE_GRAB
|
#ifdef USE_GRAB
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -5995,7 +6042,8 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
|
|||||||
decoder->SurfaceField = 0;
|
decoder->SurfaceField = 0;
|
||||||
// FIXME: I hope this didn't change in the middle of the stream
|
// FIXME: I hope this didn't change in the middle of the stream
|
||||||
|
|
||||||
VdpauSetup(decoder, video_ctx);
|
VdpauCleanup(decoder);
|
||||||
|
VdpauSetupOutput(decoder);
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// Copy data from frame to image
|
// Copy data from frame to image
|
||||||
@ -6092,6 +6140,7 @@ static void VdpauMixOsd(void)
|
|||||||
|
|
||||||
//start = GetMsTicks();
|
//start = GetMsTicks();
|
||||||
|
|
||||||
|
// FIXME: double buffered osd disabled
|
||||||
VdpauOsdSurfaceIndex = 1;
|
VdpauOsdSurfaceIndex = 1;
|
||||||
#ifdef USE_BITMAP
|
#ifdef USE_BITMAP
|
||||||
status =
|
status =
|
||||||
@ -6117,7 +6166,6 @@ static void VdpauMixOsd(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
//end = GetMsTicks();
|
//end = GetMsTicks();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Debug(4, "video:/vdpau: osd render %d %d ms\n", VdpauOsdSurfaceIndex,
|
Debug(4, "video:/vdpau: osd render %d %d ms\n", VdpauOsdSurfaceIndex,
|
||||||
end - start);
|
end - start);
|
||||||
@ -6511,6 +6559,9 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
|||||||
static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
|
static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
|
||||||
const AVCodecContext * video_ctx, const AVFrame * frame)
|
const AVCodecContext * video_ctx, const AVFrame * frame)
|
||||||
{
|
{
|
||||||
|
if (VdpauPreemption) { // display preempted
|
||||||
|
return;
|
||||||
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (!atomic_read(&decoder->SurfacesFilled)) {
|
if (!atomic_read(&decoder->SurfacesFilled)) {
|
||||||
Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch);
|
Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch);
|
||||||
@ -6553,6 +6604,9 @@ static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
|
|||||||
}
|
}
|
||||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||||
|
|
||||||
|
if (VdpauPreemption) { // display become preempted
|
||||||
|
return;
|
||||||
|
}
|
||||||
VdpauSyncDisplayFrame(decoder);
|
VdpauSyncDisplayFrame(decoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6580,6 +6634,54 @@ static int64_t VdpauGetClock(const VdpauDecoder * decoder)
|
|||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Recover from preemption.
|
||||||
|
///
|
||||||
|
static int VdpauPreemptionRecover(void)
|
||||||
|
{
|
||||||
|
VdpStatus status;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
VdpauPreemption = 0;
|
||||||
|
|
||||||
|
Debug(3, "video/vdpau: display preempted\n");
|
||||||
|
|
||||||
|
status =
|
||||||
|
vdp_device_create_x11(XlibDisplay, DefaultScreen(XlibDisplay),
|
||||||
|
&VdpauDevice, &VdpauGetProcAddress);
|
||||||
|
if (status != VDP_STATUS_OK) {
|
||||||
|
VdpauPreemption = 1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VdpauInitOutputQueue();
|
||||||
|
|
||||||
|
// mixer
|
||||||
|
for (i = 0; i < VdpauDecoderN; ++i) {
|
||||||
|
VdpauDecoders[i]->VideoDecoder = VDP_INVALID_HANDLE;
|
||||||
|
VdpauDecoders[i]->VideoMixer = VDP_INVALID_HANDLE;
|
||||||
|
VdpauDecoders[i]->SurfaceFreeN = 0;
|
||||||
|
VdpauDecoders[i]->SurfaceUsedN = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: codec has still some surfaces used
|
||||||
|
|
||||||
|
//
|
||||||
|
// invalid osd bitmap/output surfaces
|
||||||
|
//
|
||||||
|
for (i = 0; i < 1; ++i) {
|
||||||
|
#ifdef USE_BITMAP
|
||||||
|
VdpauOsdBitmapSurface[i] = VDP_INVALID_HANDLE;
|
||||||
|
#else
|
||||||
|
VdpauOsdOutputSurface[i] = VDP_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VdpauOsdInit(OsdWidth, OsdHeight);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_VIDEO_THREAD
|
#ifdef USE_VIDEO_THREAD
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -6597,6 +6699,13 @@ static void VdpauDisplayHandlerThread(void)
|
|||||||
if (!(decoder = VdpauDecoders[0])) { // no stream available
|
if (!(decoder = VdpauDecoders[0])) { // no stream available
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (VdpauPreemption) { // display preempted
|
||||||
|
if (VdpauPreemptionRecover()) {
|
||||||
|
usleep(15 * 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
//
|
//
|
||||||
// fill frame output ring buffer
|
// fill frame output ring buffer
|
||||||
//
|
//
|
||||||
@ -6670,6 +6779,9 @@ static void VdpauOsdClear(void)
|
|||||||
uint32_t pitches[1];
|
uint32_t pitches[1];
|
||||||
VdpRect dst_rect;
|
VdpRect dst_rect;
|
||||||
|
|
||||||
|
if (VdpauPreemption) { // display preempted
|
||||||
|
return;
|
||||||
|
}
|
||||||
// osd image available?
|
// osd image available?
|
||||||
#ifdef USE_BITMAP
|
#ifdef USE_BITMAP
|
||||||
if (VdpauOsdBitmapSurface[VdpauOsdSurfaceIndex] == VDP_INVALID_HANDLE) {
|
if (VdpauOsdBitmapSurface[VdpauOsdSurfaceIndex] == VDP_INVALID_HANDLE) {
|
||||||
@ -6743,6 +6855,9 @@ static void VdpauOsdDrawARGB(int x, int y, int width, int height,
|
|||||||
uint32_t start;
|
uint32_t start;
|
||||||
uint32_t end;
|
uint32_t end;
|
||||||
|
|
||||||
|
if (VdpauPreemption) { // display preempted
|
||||||
|
return;
|
||||||
|
}
|
||||||
// osd image available?
|
// osd image available?
|
||||||
#ifdef USE_BITMAP
|
#ifdef USE_BITMAP
|
||||||
if (VdpauOsdBitmapSurface[VdpauOsdSurfaceIndex] == VDP_INVALID_HANDLE) {
|
if (VdpauOsdBitmapSurface[VdpauOsdSurfaceIndex] == VDP_INVALID_HANDLE) {
|
||||||
@ -7449,6 +7564,8 @@ struct _video_hw_decoder_
|
|||||||
///
|
///
|
||||||
/// Allocate new video hw decoder.
|
/// Allocate new video hw decoder.
|
||||||
///
|
///
|
||||||
|
/// @returns a new initialized video hardware decoder.
|
||||||
|
///
|
||||||
VideoHwDecoder *VideoNewHwDecoder(void)
|
VideoHwDecoder *VideoNewHwDecoder(void)
|
||||||
{
|
{
|
||||||
if (!XlibDisplay || !VideoUsedModule) { // waiting for x11 start
|
if (!XlibDisplay || !VideoUsedModule) { // waiting for x11 start
|
||||||
@ -7460,7 +7577,7 @@ VideoHwDecoder *VideoNewHwDecoder(void)
|
|||||||
///
|
///
|
||||||
/// Destroy a video hw decoder.
|
/// Destroy a video hw decoder.
|
||||||
///
|
///
|
||||||
/// @param decoder video hw decoder
|
/// @param decoder video hardware decoder
|
||||||
///
|
///
|
||||||
void VideoDelHwDecoder(VideoHwDecoder * decoder)
|
void VideoDelHwDecoder(VideoHwDecoder * decoder)
|
||||||
{
|
{
|
||||||
@ -7472,7 +7589,7 @@ void VideoDelHwDecoder(VideoHwDecoder * decoder)
|
|||||||
///
|
///
|
||||||
/// Get a free hardware decoder surface.
|
/// Get a free hardware decoder surface.
|
||||||
///
|
///
|
||||||
/// @param decoder VDPAU video hardware decoder
|
/// @param decoder video hardware decoder
|
||||||
///
|
///
|
||||||
unsigned VideoGetSurface(VideoHwDecoder * decoder)
|
unsigned VideoGetSurface(VideoHwDecoder * decoder)
|
||||||
{
|
{
|
||||||
@ -7638,21 +7755,39 @@ struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder * decoder)
|
|||||||
///
|
///
|
||||||
/// Draw ffmpeg vdpau render state.
|
/// Draw ffmpeg vdpau render state.
|
||||||
///
|
///
|
||||||
/// @param decoder VDPAU hw decoder
|
/// @param decoder video hw decoder
|
||||||
/// @param vrs vdpau render state
|
/// @param vrs vdpau render state
|
||||||
///
|
///
|
||||||
void VideoDrawRenderState(VideoHwDecoder * decoder,
|
void VideoDrawRenderState(VideoHwDecoder * hw_decoder,
|
||||||
struct vdpau_render_state *vrs)
|
struct vdpau_render_state *vrs)
|
||||||
{
|
{
|
||||||
if (VideoVdpauEnabled) {
|
if (VideoVdpauEnabled) {
|
||||||
VdpStatus status;
|
VdpStatus status;
|
||||||
uint32_t start;
|
uint32_t start;
|
||||||
uint32_t end;
|
uint32_t end;
|
||||||
|
VdpauDecoder *decoder;
|
||||||
|
|
||||||
|
decoder = &hw_decoder->Vdpau;
|
||||||
|
if (decoder->VideoDecoder == VDP_INVALID_HANDLE) {
|
||||||
|
Debug(3, "video/vdpau: recover preemption\n");
|
||||||
|
status =
|
||||||
|
VdpauDecoderCreate(VdpauDevice, decoder->Profile,
|
||||||
|
decoder->InputWidth, decoder->InputHeight,
|
||||||
|
decoder->SurfacesNeeded - VIDEO_SURFACES_MAX,
|
||||||
|
&decoder->VideoDecoder);
|
||||||
|
if (status != VDP_STATUS_OK) {
|
||||||
|
Error(_("video/vdpau: can't create decoder: %s\n"),
|
||||||
|
VdpauGetErrorString(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
VdpauSetupOutput(decoder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Debug(4, "video/vdpau: decoder render to %#010x\n", vrs->surface);
|
Debug(4, "video/vdpau: decoder render to %#010x\n", vrs->surface);
|
||||||
start = GetMsTicks();
|
start = GetMsTicks();
|
||||||
status =
|
status =
|
||||||
VdpauDecoderRender(decoder->Vdpau.VideoDecoder, vrs->surface,
|
VdpauDecoderRender(decoder->VideoDecoder, vrs->surface,
|
||||||
(VdpPictureInfo const *)&vrs->info, vrs->bitstream_buffers_used,
|
(VdpPictureInfo const *)&vrs->info, vrs->bitstream_buffers_used,
|
||||||
vrs->bitstream_buffers);
|
vrs->bitstream_buffers);
|
||||||
end = GetMsTicks();
|
end = GetMsTicks();
|
||||||
@ -7667,8 +7802,6 @@ void VideoDrawRenderState(VideoHwDecoder * decoder,
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
(void)decoder;
|
|
||||||
(void)vrs;
|
|
||||||
Error(_("video/vdpau: draw render state, without vdpau enabled\n"));
|
Error(_("video/vdpau: draw render state, without vdpau enabled\n"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user