mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
Add video/audio sync to vdpau.
This commit is contained in:
parent
18e9e2f69e
commit
9f637f986e
149
video.c
149
video.c
@ -2448,9 +2448,9 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
///
|
||||||
** Advance displayed frame.
|
/// Advance displayed frame.
|
||||||
*/
|
///
|
||||||
static void VaapiAdvanceFrame(void)
|
static void VaapiAdvanceFrame(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -2703,12 +2703,12 @@ static void VaapiSyncRenderFrame(VaapiDecoder * decoder,
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
/**
|
///
|
||||||
** Update video pts.
|
/// Update video pts.
|
||||||
**
|
///
|
||||||
** @param decoder VA-API decoder
|
/// @param decoder VA-API decoder
|
||||||
** @param frame frame to display
|
/// @param frame frame to display
|
||||||
*/
|
///
|
||||||
static void VaapiSetPts(VaapiDecoder * decoder, const AVFrame * frame)
|
static void VaapiSetPts(VaapiDecoder * decoder, const AVFrame * frame)
|
||||||
{
|
{
|
||||||
int64_t pts;
|
int64_t pts;
|
||||||
@ -2746,6 +2746,27 @@ static void VaapiSetPts(VaapiDecoder * decoder, const AVFrame * frame)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Get VA-API decoder video clock.
|
||||||
|
///
|
||||||
|
/// @param decoder VA-API decoder
|
||||||
|
///
|
||||||
|
static int64_t VaapiGetClock(const VaapiDecoder * decoder)
|
||||||
|
{
|
||||||
|
// pts is the timestamp of the latest decoded frame
|
||||||
|
if ((uint64_t) decoder->PTS == AV_NOPTS_VALUE) {
|
||||||
|
return AV_NOPTS_VALUE;
|
||||||
|
}
|
||||||
|
// subtract buffered decoded frames
|
||||||
|
if (decoder->Interlaced) {
|
||||||
|
return decoder->PTS -
|
||||||
|
20 * 90 * (2 * atomic_read(&decoder->SurfacesFilled)
|
||||||
|
- decoder->SurfaceField);
|
||||||
|
}
|
||||||
|
return decoder->PTS - 20 * 90 * (atomic_read(&decoder->SurfacesFilled) -
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_VIDEO_THREAD
|
#ifdef USE_VIDEO_THREAD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2998,6 +3019,7 @@ typedef struct _vdpau_decoder_
|
|||||||
int InputY; ///< input y
|
int InputY; ///< input y
|
||||||
int InputWidth; ///< input width
|
int InputWidth; ///< input width
|
||||||
int InputHeight; ///< input height
|
int InputHeight; ///< input height
|
||||||
|
AVRational InputAspect; ///< input aspect ratio
|
||||||
|
|
||||||
#ifdef noyetUSE_GLX
|
#ifdef noyetUSE_GLX
|
||||||
GLuint GlTexture[2]; ///< gl texture for VDPAU
|
GLuint GlTexture[2]; ///< gl texture for VDPAU
|
||||||
@ -4165,7 +4187,7 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
|
|||||||
// place in output queue
|
// place in output queue
|
||||||
// I place it here, for later thread support
|
// I place it here, for later thread support
|
||||||
|
|
||||||
if (0) { // can't wait for output queue empty
|
if (1) { // can't wait for output queue empty
|
||||||
if (atomic_read(&decoder->SurfacesFilled) >= VIDEO_SURFACES_MAX) {
|
if (atomic_read(&decoder->SurfacesFilled) >= VIDEO_SURFACES_MAX) {
|
||||||
Warning(_
|
Warning(_
|
||||||
("video/vdpau: output buffer full, dropping frame (%d/%d)\n"),
|
("video/vdpau: output buffer full, dropping frame (%d/%d)\n"),
|
||||||
@ -4373,6 +4395,43 @@ static void VdpauMixVideo(VdpauDecoder * decoder)
|
|||||||
decoder->SurfaceRead);
|
decoder->SurfaceRead);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Advance displayed frame.
|
||||||
|
///
|
||||||
|
static void VdpauAdvanceFrame(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < VdpauDecoderN; ++i) {
|
||||||
|
int filled;
|
||||||
|
VdpauDecoder *decoder;
|
||||||
|
|
||||||
|
decoder = VdpauDecoders[i];
|
||||||
|
|
||||||
|
// next field
|
||||||
|
if (decoder->Interlaced) {
|
||||||
|
decoder->SurfaceField ^= 1;
|
||||||
|
}
|
||||||
|
// next surface, if complete frame is displayed
|
||||||
|
if (!decoder->SurfaceField) {
|
||||||
|
// check decoder, if new surface is available
|
||||||
|
// need 2 frames for progressive
|
||||||
|
// need 4 frames for interlaced
|
||||||
|
filled = atomic_read(&decoder->SurfacesFilled);
|
||||||
|
if (filled <= 1 + 2 * decoder->Interlaced) {
|
||||||
|
// keep use of last surface
|
||||||
|
++decoder->FramesDuped;
|
||||||
|
VdpauPrintFrames(decoder);
|
||||||
|
decoder->SurfaceField = decoder->Interlaced;
|
||||||
|
} else {
|
||||||
|
decoder->SurfaceRead = (decoder->SurfaceRead + 1)
|
||||||
|
% VIDEO_SURFACES_MAX;
|
||||||
|
atomic_dec(&decoder->SurfacesFilled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Display a video frame.
|
/// Display a video frame.
|
||||||
///
|
///
|
||||||
@ -4421,36 +4480,17 @@ static void VdpauDisplayFrame(void)
|
|||||||
VdpauDecoder *decoder;
|
VdpauDecoder *decoder;
|
||||||
|
|
||||||
decoder = VdpauDecoders[i];
|
decoder = VdpauDecoders[i];
|
||||||
|
decoder->FramesDisplayed++;
|
||||||
|
|
||||||
filled = atomic_read(&decoder->SurfacesFilled);
|
filled = atomic_read(&decoder->SurfacesFilled);
|
||||||
// need 1 frame for progressive, 3 frames for interlaced
|
// need 1 frame for progressive, 3 frames for interlaced
|
||||||
if (filled < 1 + 2 * decoder->Interlaced) {
|
if (filled < 1 + 2 * decoder->Interlaced) {
|
||||||
// FIXME: render black surface
|
// FIXME: render black surface
|
||||||
|
// FIXME: or rewrite MixVideo to support less surfaces
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
VdpauMixVideo(decoder);
|
VdpauMixVideo(decoder);
|
||||||
|
|
||||||
// next field
|
|
||||||
if (decoder->Interlaced) {
|
|
||||||
decoder->SurfaceField ^= 1;
|
|
||||||
}
|
|
||||||
// next surface, if complete frame is displayed
|
|
||||||
if (!decoder->SurfaceField) {
|
|
||||||
// check decoder, if new surface is available
|
|
||||||
// need 2 frames for progressive
|
|
||||||
// need 4 frames for interlaced
|
|
||||||
if (filled <= 1 + 2 * decoder->Interlaced) {
|
|
||||||
// keep use of last surface
|
|
||||||
++decoder->FramesDuped;
|
|
||||||
VdpauPrintFrames(decoder);
|
|
||||||
decoder->SurfaceField = decoder->Interlaced;
|
|
||||||
} else {
|
|
||||||
decoder->SurfaceRead = (decoder->SurfaceRead + 1)
|
|
||||||
% VIDEO_SURFACES_MAX;
|
|
||||||
atomic_dec(&decoder->SurfacesFilled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -4481,15 +4521,13 @@ static void VdpauDisplayFrame(void)
|
|||||||
///
|
///
|
||||||
static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
||||||
{
|
{
|
||||||
VdpauDisplayFrame();
|
|
||||||
#if 0
|
|
||||||
int filled;
|
int filled;
|
||||||
int64_t audio_clock;
|
int64_t audio_clock;
|
||||||
int64_t video_clock;
|
int64_t video_clock;
|
||||||
|
|
||||||
if (!decoder->DupNextFrame && (!Video60HzMode
|
if (!decoder->DupNextFrame && (!Video60HzMode
|
||||||
|| decoder->FramesDisplayed % 6)) {
|
|| decoder->FramesDisplayed % 6)) {
|
||||||
VaapiAdvanceFrame();
|
VdpauAdvanceFrame();
|
||||||
}
|
}
|
||||||
// debug duplicate frames
|
// debug duplicate frames
|
||||||
filled = atomic_read(&decoder->SurfacesFilled);
|
filled = atomic_read(&decoder->SurfacesFilled);
|
||||||
@ -4498,11 +4536,11 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
|||||||
Warning(_("video: display buffer empty, duping frame (%d/%d)\n"),
|
Warning(_("video: display buffer empty, duping frame (%d/%d)\n"),
|
||||||
decoder->FramesDuped, decoder->FrameCounter);
|
decoder->FramesDuped, decoder->FrameCounter);
|
||||||
if (!(decoder->FramesDisplayed % 333)) {
|
if (!(decoder->FramesDisplayed % 333)) {
|
||||||
VaapiPrintFrames(decoder);
|
VdpauPrintFrames(decoder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VaapiDisplayFrame();
|
VdpauDisplayFrame();
|
||||||
|
|
||||||
//
|
//
|
||||||
// audio/video sync
|
// audio/video sync
|
||||||
@ -4541,7 +4579,6 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
|||||||
|
|
||||||
last_video_clock = video_clock;
|
last_video_clock = video_clock;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -4596,6 +4633,27 @@ static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
|
|||||||
VdpauRenderFrame(decoder, video_ctx, frame);
|
VdpauRenderFrame(decoder, video_ctx, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Get VDPAU decoder video clock.
|
||||||
|
///
|
||||||
|
/// @param decoder VDPAU decoder
|
||||||
|
///
|
||||||
|
static int64_t VdpauGetClock(const VdpauDecoder * decoder)
|
||||||
|
{
|
||||||
|
// pts is the timestamp of the latest decoded frame
|
||||||
|
if ((uint64_t) decoder->PTS == AV_NOPTS_VALUE) {
|
||||||
|
return AV_NOPTS_VALUE;
|
||||||
|
}
|
||||||
|
// subtract buffered decoded frames
|
||||||
|
if (decoder->Interlaced) {
|
||||||
|
return decoder->PTS -
|
||||||
|
20 * 90 * (2 * atomic_read(&decoder->SurfacesFilled)
|
||||||
|
- decoder->SurfaceField);
|
||||||
|
}
|
||||||
|
return decoder->PTS - 20 * 90 * (atomic_read(&decoder->SurfacesFilled) -
|
||||||
|
1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_VIDEO_THREAD
|
#ifdef USE_VIDEO_THREAD
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -5557,29 +5615,18 @@ void VideoDisplayHandler(void)
|
|||||||
**
|
**
|
||||||
** @note this isn't monoton, decoding reorders frames,
|
** @note this isn't monoton, decoding reorders frames,
|
||||||
** setter keeps it monotonic
|
** setter keeps it monotonic
|
||||||
|
** @todo we have multiple clocks, for multiple stream
|
||||||
*/
|
*/
|
||||||
int64_t VideoGetClock(void)
|
int64_t VideoGetClock(void)
|
||||||
{
|
{
|
||||||
#ifdef USE_VAAPI
|
#ifdef USE_VAAPI
|
||||||
if (VideoVaapiEnabled) {
|
if (VideoVaapiEnabled) {
|
||||||
// FIXME: VaapiGetClock();
|
return VaapiGetClock(VaapiDecoders[0]);
|
||||||
|
|
||||||
// pts is the timestamp of the latest decoded frame
|
|
||||||
if ((uint64_t) VaapiDecoders[0]->PTS == AV_NOPTS_VALUE) {
|
|
||||||
return AV_NOPTS_VALUE;
|
|
||||||
}
|
|
||||||
if (VaapiDecoders[0]->Interlaced) {
|
|
||||||
return VaapiDecoders[0]->PTS -
|
|
||||||
20 * 90 * (2 * atomic_read(&VaapiDecoders[0]->SurfacesFilled)
|
|
||||||
- VaapiDecoders[0]->SurfaceField);
|
|
||||||
}
|
|
||||||
return VaapiDecoders[0]->PTS -
|
|
||||||
20 * 90 * (atomic_read(&VaapiDecoders[0]->SurfacesFilled) - 1);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_VDPAU
|
#ifdef USE_VDPAU
|
||||||
if (VideoVdpauEnabled) {
|
if (VideoVdpauEnabled) {
|
||||||
return 0L;
|
return VdpauGetClock(VdpauDecoders[0]);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return 0L;
|
return 0L;
|
||||||
|
Loading…
Reference in New Issue
Block a user