summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2012-02-01 16:50:48 +0100
committerJohns <johns98@gmx.net>2012-02-01 16:50:48 +0100
commit27e9a88e2ff02c9a84ca009c52d091062dbe5530 (patch)
treecaf09e2a16ffa87d049fb88e861a12e90c0f25ba
parent33e9c71aea853f1f5bb1ccc55394ecbaa4a01b18 (diff)
downloadvdr-plugin-softhddevice-27e9a88e2ff02c9a84ca009c52d091062dbe5530.tar.gz
vdr-plugin-softhddevice-27e9a88e2ff02c9a84ca009c52d091062dbe5530.tar.bz2
Video updates and bug fix.
Check if surface is ready in VaapiGetSurface. Set PTS/DTS only in the first split video packet. Add support for 4:3 output modes. Quicker auto-crop after channel switch. Add auto-crop support for Intel VA-API backend. Fix bug: Auto-Crop logo skip didn't use displayed width.
-rw-r--r--ChangeLog4
-rw-r--r--Todo1
-rw-r--r--softhddev.c5
-rw-r--r--softhddevice.cpp21
-rw-r--r--video.c523
-rw-r--r--video.h3
6 files changed, 332 insertions, 225 deletions
diff --git a/ChangeLog b/ChangeLog
index 8ede505..be1fcf2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,10 @@
User johns
Date:
+ Add support for 4:3 output modes.
+ Quicker auto-crop after channel switch.
+ Add auto-crop support for Intel VA-API backend.
+ Fix bug: Auto-Crop logo skip didn't use displayed width.
Workaround for mpeg2 FFMpeg + VA-API + Intel GPU hung.
Fix bug: Missing vaSyncSurface and vaDestroyImage.
Fix bug: Only black picture with VA-API hw decoder.
diff --git a/Todo b/Todo
index ab78d66..8de7201 100644
--- a/Todo
+++ b/Todo
@@ -127,5 +127,6 @@ future features (not planed for 1.0 - 1.5)
atmolight support
multistream handling
pip support
+ save and use auto-crop with channel zapping
upmix stereo to AC-3
diff --git a/softhddev.c b/softhddev.c
index 5cc5f34..8dadd84 100644
--- a/softhddev.c
+++ b/softhddev.c
@@ -507,7 +507,7 @@ void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
first = 1;
while (n > 4) {
- // scan for picture header
+ // scan for picture header 0x00000100
if (!p[0] && !p[1] && p[2] == 0x01 && !p[3]) {
if (first) {
first = 0;
@@ -518,6 +518,9 @@ void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
// packet has already an picture header
tmp->size = p - tmp->data;
CodecVideoDecode(MyVideoDecoder, tmp);
+ // time-stamp only valid for first packet
+ tmp->pts = AV_NOPTS_VALUE;
+ tmp->dts = AV_NOPTS_VALUE;
tmp->data = p;
tmp->size = n;
}
diff --git a/softhddevice.cpp b/softhddevice.cpp
index b77543c..cae7402 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -625,6 +625,7 @@ class cSoftHdDevice:public cDevice
virtual bool Poll(cPoller &, int = 0);
virtual bool Flush(int = 0);
virtual int64_t GetSTC(void);
+ virtual void SetVideoDisplayFormat(eVideoDisplayFormat);
virtual void GetVideoSize(int &, int &, double &);
virtual void GetOsdSize(int &, int &, double &);
virtual int PlayVideo(const uchar *, int);
@@ -848,6 +849,26 @@ bool cSoftHdDevice::Flush(int timeout_ms)
// ----------------------------------------------------------------------------
/**
+** Sets the video display format to the given one (only useful if this
+** device has an MPEG decoder).
+*/
+void cSoftHdDevice::SetVideoDisplayFormat(
+ eVideoDisplayFormat video_display_format)
+{
+ static int last = -1;
+
+ cDevice::SetVideoDisplayFormat(video_display_format);
+
+ dsyslog("[softhddev]%s: %d\n", __FUNCTION__, video_display_format);
+
+ // called on every channel switch, no need to kill osd...
+ if (last != video_display_format) {
+ last = video_display_format;
+ ::VideoSetDisplayFormat(video_display_format);
+ }
+}
+
+/**
** Returns the width, height and video_aspect ratio of the currently
** displayed video material.
**
diff --git a/video.c b/video.c
index c5e3508..b0e122a 100644
--- a/video.c
+++ b/video.c
@@ -190,7 +190,7 @@ typedef enum _video_zoom_modes_
{
VideoNormal, ///< normal
VideoStretch, ///< stretch to all edges
- VideoZoom, ///< zoom out
+ VideoCenterCutOut, ///< center and cut out
VideoAnamorphic, ///< anamorphic scaled (unsupported)
} VideoZoomModes;
@@ -332,14 +332,174 @@ static int OsdDirtyHeight; ///< osd dirty area height
static int64_t VideoDeltaPTS; ///< FIXME: fix pts
//----------------------------------------------------------------------------
-// Functions
+// Common Functions
//----------------------------------------------------------------------------
static void VideoThreadLock(void); ///< lock video thread
static void VideoThreadUnlock(void); ///< unlock video thread
- /// update video stream PTS
-static void VideoSetPts(int64_t *, int, const AVFrame *);
+///
+/// Update video pts.
+///
+/// @param pts_p pointer to pts
+/// @param interlaced interlaced flag (frame isn't right)
+/// @param frame frame to display
+///
+/// @note frame->interlaced_frame can't be used for interlace detection
+///
+static void VideoSetPts(int64_t * pts_p, int interlaced, const AVFrame * frame)
+{
+ int64_t pts;
+
+ // update video clock
+ if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
+ *pts_p += interlaced ? 40 * 90 : 20 * 90;
+ }
+ //pts = frame->best_effort_timestamp;
+ pts = frame->pkt_pts;
+ if ((uint64_t) pts == AV_NOPTS_VALUE || !pts) {
+ // libav: 0.8pre didn't set pts
+ pts = frame->pkt_dts;
+ }
+ // libav: sets only pkt_dts which can be 0
+ if (pts && (uint64_t) pts != AV_NOPTS_VALUE) {
+ // build a monotonic pts
+ if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
+ int64_t delta;
+
+ delta = pts - *pts_p;
+ // ignore negative jumps
+ if (delta > -600 * 90 && delta <= -40 * 90) {
+ if (-delta > VideoDeltaPTS) {
+ VideoDeltaPTS = -delta;
+ Debug(4,
+ "video: %#012" PRIx64 "->%#012" PRIx64 " delta+%4"
+ PRId64 " pts\n", *pts_p, pts, pts - *pts_p);
+ }
+ return;
+ }
+ }
+ if (*pts_p != pts) {
+ Debug(4,
+ "video: %#012" PRIx64 "->%#012" PRIx64 " delta=%4" PRId64
+ " pts\n", *pts_p, pts, pts - *pts_p);
+ *pts_p = pts;
+ }
+ }
+}
+
+///
+/// Update output for new size or aspect ratio.
+///
+/// @param input_aspect_ratio video stream aspect
+///
+static void VideoUpdateOutput(AVRational input_aspect_ratio, int input_width,
+ int input_height, int *output_x, int *output_y, int *output_width,
+ int *output_height, int *crop_x, int *crop_y, int *crop_width,
+ int *crop_height)
+{
+ AVRational display_aspect_ratio;
+
+ if (!input_aspect_ratio.num || !input_aspect_ratio.den) {
+ input_aspect_ratio.num = 1;
+ input_aspect_ratio.den = 1;
+ Debug(3, "video: aspect defaults to %d:%d\n", input_aspect_ratio.num,
+ input_aspect_ratio.den);
+ }
+
+ av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
+ input_width * input_aspect_ratio.num,
+ input_height * input_aspect_ratio.den, 1024 * 1024);
+
+ // InputWidth/Height can be zero = uninitialized
+ if (!display_aspect_ratio.num || !display_aspect_ratio.den) {
+ display_aspect_ratio.num = 1;
+ display_aspect_ratio.den = 1;
+ }
+
+ Debug(3, "video: aspect %d:%d\n", display_aspect_ratio.num,
+ display_aspect_ratio.den);
+
+ *crop_x = 0;
+ *crop_y = VideoSkipLines;
+ *crop_width = input_width;
+ *crop_height = input_height - VideoSkipLines * 2;
+
+ // FIXME: store different positions for the ratios
+ if (display_aspect_ratio.num == 4 && display_aspect_ratio.den == 3) {
+ switch (Video4to3ZoomMode) {
+ case VideoNormal:
+ goto normal;
+ case VideoStretch:
+ goto stretch;
+ case VideoCenterCutOut:
+ goto center_cut_out;
+ case VideoAnamorphic:
+ // FIXME: rest should be done by hardware
+ goto stretch;
+ }
+ }
+ // FIXME: this overwrites user choosen output position
+
+ normal:
+ *output_x = 0;
+ *output_y = 0;
+ *output_width = (VideoWindowHeight * display_aspect_ratio.num)
+ / display_aspect_ratio.den;
+ *output_height = (VideoWindowWidth * display_aspect_ratio.den)
+ / display_aspect_ratio.num;
+ if ((unsigned)*output_width > VideoWindowWidth) {
+ *output_width = VideoWindowWidth;
+ *output_y = (VideoWindowHeight - *output_height) / 2;
+ } else if ((unsigned)*output_height > VideoWindowHeight) {
+ *output_height = VideoWindowHeight;
+ *output_x = (VideoWindowWidth - *output_width) / 2;
+ }
+ Debug(3, "video: aspect output %dx%d+%d+%d\n", *output_width,
+ *output_height, *output_x, *output_y);
+ return;
+
+ stretch:
+ *output_x = 0;
+ *output_y = 0;
+ *output_width = VideoWindowWidth;
+ *output_height = VideoWindowHeight;
+ return;
+
+ center_cut_out:
+ *output_x = 0;
+ *output_y = 0;
+ *output_height = VideoWindowHeight;
+ *output_width = VideoWindowWidth;
+
+ *crop_width = (VideoWindowHeight * display_aspect_ratio.num)
+ / display_aspect_ratio.den;
+ *crop_height = (VideoWindowWidth * display_aspect_ratio.den)
+ / display_aspect_ratio.num;
+
+ // look which side must be cut
+ if ((unsigned)*crop_width > VideoWindowWidth) {
+ *crop_height = input_height;
+
+ // adjust scaiing
+ *crop_x = ((*crop_width - (signed)VideoWindowWidth) * input_width)
+ / (2 * VideoWindowWidth);
+ *crop_width = input_width - *crop_x * 2;
+ } else if ((unsigned)*crop_height > VideoWindowHeight) {
+ *crop_width = input_width;
+
+ // adjust scaiing
+ *crop_y = ((*crop_height - (signed)VideoWindowHeight) * input_height)
+ / (2 * VideoWindowHeight);
+ *crop_height = input_height - *crop_y * 2;
+ } else {
+ *crop_width = input_width;
+ *crop_height = input_height;
+ }
+ Debug(3, "video: aspect crop %dx%d+%d+%d\n", *crop_width, *crop_height,
+ *crop_x, *crop_y);
+ return;
+}
//----------------------------------------------------------------------------
// GLX
@@ -972,7 +1132,7 @@ static void AutoCropDetect(AutoCropCtx * autocrop, int width, int height,
//
for (y = SKIP_Y; y < y1; ++y) {
if (!AutoCropIsBlackLineY(data_y + logo_skip + y * length_y,
- (length_y - 2 * logo_skip) / 8, 8)) {
+ (width - 2 * logo_skip) / 8, 8)) {
if (y == SKIP_Y) {
y = 0;
}
@@ -985,7 +1145,7 @@ static void AutoCropDetect(AutoCropCtx * autocrop, int width, int height,
//
for (y = height - SKIP_Y - 1; y > y2; --y) {
if (!AutoCropIsBlackLineY(data_y + logo_skip + y * length_y,
- (length_y - 2 * logo_skip) / 8, 8)) {
+ (width - 2 * logo_skip) / 8, 8)) {
if (y == height - SKIP_Y - 1) {
y = height - 1;
}
@@ -1006,7 +1166,6 @@ static void AutoCropDetect(AutoCropCtx * autocrop, int width, int height,
break;
}
}
-
//
// search right
//
@@ -1084,7 +1243,7 @@ struct _vaapi_decoder_
VAImage DeintImages[5]; ///< deinterlace image buffers
- int PutImage; ///< flag put image can be used
+ int GetPutImage; ///< flag get/put image can be used
VAImage Image[1]; ///< image buffer to update surface
struct vaapi_context VaapiContext[1]; ///< ffmpeg VA-API context
@@ -1301,6 +1460,9 @@ static void VaapiDestroySurfaces(VaapiDecoder * decoder)
// FIXME surfaces used for output
}
+ /// forward definition release surface
+static void VaapiReleaseSurface(VaapiDecoder *, VASurfaceID);
+
///
/// Get a free surface.
///
@@ -1311,25 +1473,41 @@ static void VaapiDestroySurfaces(VaapiDecoder * decoder)
static VASurfaceID VaapiGetSurface(VaapiDecoder * decoder)
{
VASurfaceID surface;
+ VASurfaceStatus status;
int i;
- if (!decoder->SurfaceFreeN) {
- Error(_("video/vaapi: out of surfaces\n"));
- return VA_INVALID_ID;
- }
- // use oldest surface
- surface = decoder->SurfacesFree[0];
-
- decoder->SurfaceFreeN--;
+ // try to use oldest surface
for (i = 0; i < decoder->SurfaceFreeN; ++i) {
- decoder->SurfacesFree[i] = decoder->SurfacesFree[i + 1];
- }
- decoder->SurfacesFree[i] = VA_INVALID_ID;
+ surface = decoder->SurfacesFree[i];
+ if (vaQuerySurfaceStatus(decoder->VaDisplay, surface, &status)
+ != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: vaQuerySurface failed\n"));
+ status = VASurfaceReady;
+ }
+ // surface still in use, try next
+ if (status != VASurfaceReady) {
+ Debug("video/vaapi: surface %#010x not ready: %d\n", surface,
+ status);
+ if (!VaapiBuggyVdpau || i < 1) {
+ continue;
+ }
+ usleep(1 * 1000);
+ }
+ // copy remaining surfaces down
+ decoder->SurfaceFreeN--;
+ for (; i < decoder->SurfaceFreeN; ++i) {
+ decoder->SurfacesFree[i] = decoder->SurfacesFree[i + 1];
+ }
+ decoder->SurfacesFree[i] = VA_INVALID_ID;
- // save as used
- decoder->SurfacesUsed[decoder->SurfaceUsedN++] = surface;
+ // save as used
+ decoder->SurfacesUsed[decoder->SurfaceUsedN++] = surface;
- return surface;
+ return surface;
+ }
+
+ Error(_("video/vaapi: out of surfaces\n"));
+ return VA_INVALID_ID;
}
///
@@ -1351,7 +1529,7 @@ static void VaapiReleaseSurface(VaapiDecoder * decoder, VASurfaceID surface)
return;
}
}
- Error(_("video/vaapi: release surface %#x, which is not in use\n"),
+ Error(_("video/vaapi: release surface %#010x, which is not in use\n"),
surface);
}
@@ -1495,7 +1673,7 @@ static VaapiDecoder *VaapiNewDecoder(void)
decoder->OutputWidth = VideoWindowWidth;
decoder->OutputHeight = VideoWindowHeight;
- decoder->PutImage = !VaapiBuggyIntel;
+ decoder->GetPutImage = !VaapiBuggyIntel;
VaapiDecoders[VaapiDecoderN++] = decoder;
@@ -1746,64 +1924,15 @@ static void VaapiExit(void)
///
/// @param decoder VA-API decoder
///
-/// @todo combine VaapiUpdateOutput and VdpauUpdateOutput
-///
static void VaapiUpdateOutput(VaapiDecoder * decoder)
{
- AVRational input_aspect_ratio;
- AVRational display_aspect_ratio;
-
- input_aspect_ratio = decoder->InputAspect;
- if (!input_aspect_ratio.num || !input_aspect_ratio.den) {
- input_aspect_ratio.num = 1;
- input_aspect_ratio.den = 1;
- Debug(3, "video: aspect defaults to %d:%d\n", input_aspect_ratio.num,
- input_aspect_ratio.den);
- }
-
- av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
- decoder->InputWidth * input_aspect_ratio.num,
- decoder->InputHeight * input_aspect_ratio.den, 1024 * 1024);
-
- // InputWidth/Height can be zero = uninitialized
- if (!display_aspect_ratio.num || !display_aspect_ratio.den) {
- display_aspect_ratio.num = 1;
- display_aspect_ratio.den = 1;
- }
-
- Debug(3, "video: aspect %d:%d\n", display_aspect_ratio.num,
- display_aspect_ratio.den);
-
- // FIXME: store different positions for the ratios
- if (display_aspect_ratio.num == 4 && display_aspect_ratio.den == 3) {
- switch (Video4to3ZoomMode) {
- case VideoNormal:
- case VideoStretch:
- case VideoZoom:
- case VideoAnamorphic:
- break;
- }
- }
- // FIXME: this overwrites user choosen output position
- decoder->OutputX = 0;
- decoder->OutputY = 0;
- decoder->OutputWidth = (VideoWindowHeight * display_aspect_ratio.num)
- / display_aspect_ratio.den;
- decoder->OutputHeight = (VideoWindowWidth * display_aspect_ratio.den)
- / display_aspect_ratio.num;
- if ((unsigned)decoder->OutputWidth > VideoWindowWidth) {
- decoder->OutputWidth = VideoWindowWidth;
- decoder->OutputY = (VideoWindowHeight - decoder->OutputHeight) / 2;
- } else if ((unsigned)decoder->OutputHeight > VideoWindowHeight) {
- decoder->OutputHeight = VideoWindowHeight;
- decoder->OutputX = (VideoWindowWidth - decoder->OutputWidth) / 2;
- }
- Debug(3, "video: aspect output %dx%d+%d+%d\n", decoder->OutputWidth,
- decoder->OutputHeight, decoder->OutputX, decoder->OutputY);
-
+ VideoUpdateOutput(decoder->InputAspect, decoder->InputWidth,
+ decoder->InputHeight, &decoder->OutputX, &decoder->OutputY,
+ &decoder->OutputWidth, &decoder->OutputHeight, &decoder->CropX,
+ &decoder->CropY, &decoder->CropWidth, &decoder->CropHeight);
#ifdef USE_AUTOCROP
decoder->AutoCrop->State = 0;
- decoder->AutoCrop->Count = 0;
+ decoder->AutoCrop->Count = AutoCropDelay;
#endif
}
@@ -2027,12 +2156,7 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
goto slow_path;
}
- decoder->CropX = 0;
- decoder->CropY = VideoSkipLines;
- decoder->CropWidth = video_ctx->width;
- decoder->CropHeight = video_ctx->height - VideoSkipLines * 2;
-
- decoder->PixFmt = video_ctx->pix_fmt;
+ decoder->PixFmt = *fmt_idx;
decoder->InputWidth = video_ctx->width;
decoder->InputHeight = video_ctx->height;
decoder->InputAspect = video_ctx->sample_aspect_ratio;
@@ -2146,7 +2270,7 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface,
}
if (status != VASurfaceReady) {
Warning(_
- ("video/vaapi: surface %#x not ready: still displayed %d\n"),
+ ("video/vaapi: surface %#010x not ready: still displayed %d\n"),
surface, status);
return;
}
@@ -2359,7 +2483,8 @@ static void VaapiSetup(VaapiDecoder * decoder,
VaapiFindImageFormat(decoder, video_ctx->pix_fmt, format);
// FIXME: this image is only needed for software decoder and auto-crop
- if (vaCreateImage(VaDisplay, format, width, height,
+ if (decoder->GetPutImage
+ && vaCreateImage(VaDisplay, format, width, height,
decoder->Image) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't create image!\n"));
}
@@ -2417,7 +2542,8 @@ static void VaapiAutoCrop(VaapiDecoder * decoder)
width = decoder->InputWidth;
height = decoder->InputHeight;
- if (decoder->Image->image_id == VA_INVALID_ID) {
+ again:
+ if (decoder->GetPutImage && decoder->Image->image_id == VA_INVALID_ID) {
VAImageFormat format[1];
Debug(3, "video/vaapi: download image not available\n");
@@ -2439,7 +2565,16 @@ static void VaapiAutoCrop(VaapiDecoder * decoder)
1) % VIDEO_SURFACES_MAX];
// Copy data from frame to image
- if ((i = vaGetImage(decoder->VaDisplay, surface, 0, 0, decoder->InputWidth,
+ if (!decoder->GetPutImage
+ && vaDeriveImage(decoder->VaDisplay, surface,
+ decoder->Image) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: vaDeriveImage failed\n"));
+ decoder->GetPutImage = 1;
+ goto again;
+ }
+ if (decoder->GetPutImage
+ && (i =
+ vaGetImage(decoder->VaDisplay, surface, 0, 0, decoder->InputWidth,
decoder->InputHeight,
decoder->Image->image_id)) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't get auto-crop image %d\n"), i);
@@ -2462,6 +2597,13 @@ static void VaapiAutoCrop(VaapiDecoder * decoder)
if (vaUnmapBuffer(VaDisplay, decoder->Image->buf) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't unmap auto-crop image!\n"));
}
+ if (!decoder->GetPutImage) {
+ if (vaDestroyImage(VaDisplay, decoder->Image->image_id)
+ != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't destroy image!\n"));
+ }
+ decoder->Image->image_id = VA_INVALID_ID;
+ }
// FIXME: this a copy of vdpau, combine the two same things
// ignore black frames
@@ -2515,9 +2657,7 @@ static void VaapiAutoCrop(VaapiDecoder * decoder)
break;
}
- decoder->AutoCrop->Count = 0;
decoder->AutoCrop->State = next_state;
-
if (next_state) {
decoder->CropX = 0;
decoder->CropY = (next_state == 16 ? crop16 : crop14) + VideoSkipLines;
@@ -2526,6 +2666,7 @@ static void VaapiAutoCrop(VaapiDecoder * decoder)
// FIXME: this overwrites user choosen output position
// FIXME: resize kills the auto crop values
+ // FIXME: support other 4:3 zoom modes
decoder->OutputX = 0;
decoder->OutputY = 0;
decoder->OutputWidth = (VideoWindowHeight * next_state) / 9;
@@ -2541,13 +2682,10 @@ static void VaapiAutoCrop(VaapiDecoder * decoder)
decoder->InputWidth, decoder->InputHeight, decoder->OutputWidth,
decoder->OutputHeight, decoder->OutputX, decoder->OutputY);
} else {
- decoder->CropX = 0;
- decoder->CropY = VideoSkipLines;
- decoder->CropWidth = decoder->InputWidth;
- decoder->CropHeight = decoder->InputHeight - VideoSkipLines * 2;
-
+ // sets AutoCrop->Count
VaapiUpdateOutput(decoder);
}
+ decoder->AutoCrop->Count = 0;
}
///
@@ -2648,7 +2786,7 @@ static void VaapiQueueSurface(VaapiDecoder * decoder, VASurfaceID surface,
}
if (status != VASurfaceReady) {
Warning(_
- ("video/vaapi: surface %#x not ready: still displayed %d\n"),
+ ("video/vaapi: surface %#010x not ready: still displayed %d\n"),
old, status);
if (0
&& vaSyncSurface(decoder->VaDisplay,
@@ -3344,7 +3482,7 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
}
surface = (unsigned)(size_t) frame->data[3];
- Debug(4, "video/vaapi: hw render hw surface %#x\n", surface);
+ Debug(4, "video/vaapi: hw render hw surface %#010x\n", surface);
if (interlaced
&& VideoDeinterlace[decoder->Resolution] ==
@@ -3379,11 +3517,6 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
Debug(3,
"video/vaapi: stream <-> surface size/interlace mismatch\n");
- decoder->CropX = 0;
- decoder->CropY = VideoSkipLines;
- decoder->CropWidth = width;
- decoder->CropHeight = height - VideoSkipLines * 2;
-
decoder->PixFmt = video_ctx->pix_fmt;
// FIXME: aspect done above!
decoder->InputWidth = width;
@@ -3393,17 +3526,25 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
VaapiUpdateOutput(decoder);
}
// FIXME: Need to insert software deinterlace here
- // FIXME: can/must insert auto-crop here
+ // FIXME: can/must insert auto-crop here (is done after upload)
// get a free surface and upload the image
surface = VaapiGetSurface(decoder);
Debug(4, "video/vaapi: video surface %#010x displayed\n", surface);
- if (!decoder->PutImage
+ if (!decoder->GetPutImage
&& vaDeriveImage(decoder->VaDisplay, surface,
decoder->Image) != VA_STATUS_SUCCESS) {
+ VAImageFormat format[1];
+
Error(_("video/vaapi: vaDeriveImage failed\n"));
- decoder->PutImage = 1;
+
+ decoder->GetPutImage = 1;
+ VaapiFindImageFormat(decoder, video_ctx->pix_fmt, format);
+ if (vaCreateImage(VaDisplay, format, width, height,
+ decoder->Image) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't create image!\n"));
+ }
}
//
// Copy data from frame to image
@@ -3468,7 +3609,7 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
Debug(4, "video/vaapi: buffer %dx%d <- %dx%d\n", decoder->Image->width,
decoder->Image->height, width, height);
- if (decoder->PutImage
+ if (decoder->GetPutImage
&& (i =
vaPutImage(VaDisplay, surface, decoder->Image->image_id, 0, 0,
width, height, 0, 0, width,
@@ -3476,10 +3617,12 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
Error(_("video/vaapi: can't put image err:%d!\n"), i);
}
- if (!decoder->PutImage
- && vaDestroyImage(VaDisplay,
- decoder->Image->image_id) != VA_STATUS_SUCCESS) {
- Error(_("video/vaapi: can't destroy image!\n"));
+ if (!decoder->GetPutImage) {
+ if (vaDestroyImage(VaDisplay, decoder->Image->image_id)
+ != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't destroy image!\n"));
+ }
+ decoder->Image->image_id = VA_INVALID_ID;
}
VaapiQueueSurface(decoder, surface, 1);
@@ -4427,7 +4570,7 @@ static void VdpauReleaseSurface(VdpauDecoder * decoder, unsigned surface)
return;
}
}
- Error(_("video/vdpau: release surface %#x, which is not in use\n"),
+ Error(_("video/vdpau: release surface %#08x, which is not in use\n"),
surface);
}
@@ -5371,67 +5514,15 @@ static void VdpauExit(void)
///
/// @param decoder VDPAU hw decoder
///
-/// @todo combine VaapiUpdateOutput and VdpauUpdateOutput
-///
static void VdpauUpdateOutput(VdpauDecoder * decoder)
{
- AVRational input_aspect_ratio;
- AVRational display_aspect_ratio;
-
- input_aspect_ratio = decoder->InputAspect;
- Debug(3, "video: input aspect %d:%d\n", input_aspect_ratio.num,
- input_aspect_ratio.den);
- if (!input_aspect_ratio.num || !input_aspect_ratio.den) {
- input_aspect_ratio.num = 1;
- input_aspect_ratio.den = 1;
- Debug(3, "video: aspect defaults to %d:%d\n", input_aspect_ratio.num,
- input_aspect_ratio.den);
- }
-
- av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
- decoder->InputWidth * input_aspect_ratio.num,
- decoder->InputHeight * input_aspect_ratio.den, 1024 * 1024);
-
- // InputWidth/Height can be zero = uninitialized
- if (!display_aspect_ratio.num || !display_aspect_ratio.den) {
- display_aspect_ratio.num = 1;
- display_aspect_ratio.den = 1;
- }
-
- Debug(3, "video: aspect %d:%d\n", display_aspect_ratio.num,
- display_aspect_ratio.den);
-
- // FIXME: store different positions for the ratios
- if (display_aspect_ratio.num == 4 && display_aspect_ratio.den == 3) {
- switch (Video4to3ZoomMode) {
- case VideoNormal:
- case VideoStretch:
- case VideoZoom:
- case VideoAnamorphic:
- // AutoCrop
- break;
- }
- }
- // FIXME: this overwrites user choosen output position
- decoder->OutputX = 0;
- decoder->OutputY = 0;
- decoder->OutputWidth = (VideoWindowHeight * display_aspect_ratio.num)
- / display_aspect_ratio.den;
- decoder->OutputHeight = (VideoWindowWidth * display_aspect_ratio.den)
- / display_aspect_ratio.num;
- if ((unsigned)decoder->OutputWidth > VideoWindowWidth) {
- decoder->OutputWidth = VideoWindowWidth;
- decoder->OutputY = (VideoWindowHeight - decoder->OutputHeight) / 2;
- } else if ((unsigned)decoder->OutputHeight > VideoWindowHeight) {
- decoder->OutputHeight = VideoWindowHeight;
- decoder->OutputX = (VideoWindowWidth - decoder->OutputWidth) / 2;
- }
- Debug(3, "video: aspect output %dx%d+%d+%d\n", decoder->OutputWidth,
- decoder->OutputHeight, decoder->OutputX, decoder->OutputY);
-
+ VideoUpdateOutput(decoder->InputAspect, decoder->InputWidth,
+ decoder->InputHeight, &decoder->OutputX, &decoder->OutputY,
+ &decoder->OutputWidth, &decoder->OutputHeight, &decoder->CropX,
+ &decoder->CropY, &decoder->CropWidth, &decoder->CropHeight);
#ifdef USE_AUTOCROP
decoder->AutoCrop->State = 0;
- decoder->AutoCrop->Count = 0;
+ decoder->AutoCrop->Count = AutoCropDelay;
#endif
}
@@ -5645,7 +5736,7 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
decoder->CropWidth = video_ctx->width;
decoder->CropHeight = video_ctx->height - VideoSkipLines * 2;
- decoder->PixFmt = video_ctx->pix_fmt;
+ decoder->PixFmt = *fmt_idx;
decoder->InputWidth = video_ctx->width;
decoder->InputHeight = video_ctx->height;
decoder->InputAspect = video_ctx->sample_aspect_ratio;
@@ -5937,9 +6028,7 @@ static void VdpauAutoCrop(VdpauDecoder * decoder)
break;
}
- decoder->AutoCrop->Count = 0;
decoder->AutoCrop->State = next_state;
-
if (next_state) {
decoder->CropX = 0;
decoder->CropY = (next_state == 16 ? crop16 : crop14) + VideoSkipLines;
@@ -5948,6 +6037,7 @@ static void VdpauAutoCrop(VdpauDecoder * decoder)
// FIXME: this overwrites user choosen output position
// FIXME: resize kills the auto crop values
+ // FIXME: support other 4:3 zoom modes
decoder->OutputX = 0;
decoder->OutputY = 0;
decoder->OutputWidth = (VideoWindowHeight * next_state) / 9;
@@ -5968,8 +6058,10 @@ static void VdpauAutoCrop(VdpauDecoder * decoder)
decoder->CropWidth = decoder->InputWidth;
decoder->CropHeight = decoder->InputHeight - VideoSkipLines * 2;
+ // sets AutoCrop->Count
VdpauUpdateOutput(decoder);
}
+ decoder->AutoCrop->Count = 0;
}
///
@@ -6064,7 +6156,7 @@ static void VdpauQueueSurface(VdpauDecoder * decoder, VdpVideoSurface surface,
}
}
- Debug(4, "video/vdpau: yy video surface %#x@%d ready\n", surface,
+ Debug(4, "video/vdpau: yy video surface %#08x@%d ready\n", surface,
decoder->SurfaceWrite);
decoder->SurfacesRb[decoder->SurfaceWrite] = surface;
@@ -6145,7 +6237,7 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
vrs = (struct vdpau_render_state *)frame->data[0];
surface = vrs->surface;
- Debug(4, "video/vdpau: hw render hw surface %#x\n", surface);
+ Debug(4, "video/vdpau: hw render hw surface %#08x\n", surface);
if (VideoDeinterlace[decoder->Resolution] == VideoDeinterlaceSoftware
&& interlaced) {
@@ -6454,7 +6546,7 @@ static void VdpauMixVideo(VdpauDecoder * decoder)
VdpauGetErrorString(status));
}
- Debug(4, "video/vdpau: yy video surface %#x@%d displayed\n", current,
+ Debug(4, "video/vdpau: yy video surface %#08x@%d displayed\n", current,
decoder->SurfaceRead);
}
@@ -7823,56 +7915,6 @@ enum PixelFormat Video_get_format(VideoHwDecoder * decoder,
}
///
-/// Update video pts.
-///
-/// @param pts_p pointer to pts
-/// @param interlaced interlaced flag (frame isn't right)
-/// @param frame frame to display
-///
-/// @note frame->interlaced_frame can't be used for interlace detection
-///
-static void VideoSetPts(int64_t * pts_p, int interlaced, const AVFrame * frame)
-{
- int64_t pts;
-
- // update video clock
- if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
- *pts_p += interlaced ? 40 * 90 : 20 * 90;
- }
- //pts = frame->best_effort_timestamp;
- pts = frame->pkt_pts;
- if ((uint64_t) pts == AV_NOPTS_VALUE || !pts) {
- // libav: 0.8pre didn't set pts
- pts = frame->pkt_dts;
- }
- // libav: sets only pkt_dts which can be 0
- if (pts && (uint64_t) pts != AV_NOPTS_VALUE) {
- // build a monotonic pts
- if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
- int64_t delta;
-
- delta = pts - *pts_p;
- // ignore negative jumps
- if (delta > -600 * 90 && delta <= -40 * 90) {
- if (-delta > VideoDeltaPTS) {
- VideoDeltaPTS = -delta;
- Debug(4,
- "video: %#012" PRIx64 "->%#012" PRIx64 " delta+%4"
- PRId64 " pts\n", *pts_p, pts, pts - *pts_p);
- }
- return;
- }
- }
- if (*pts_p != pts) {
- Debug(4,
- "video: %#012" PRIx64 "->%#012" PRIx64 " delta=%4" PRId64
- " pts\n", *pts_p, pts, pts - *pts_p);
- *pts_p = pts;
- }
- }
-}
-
-///
/// Display a ffmpeg frame
///
/// @param decoder VDPAU video hardware decoder
@@ -8338,6 +8380,39 @@ void VideoSetVideoMode( __attribute__ ((unused))
}
///
+/// Set video display format.
+///
+void VideoSetDisplayFormat(int format)
+{
+ VideoOsdExit();
+ // FIXME: must tell VDR that the OsdSize has been changed!
+
+ if (VideoThread) {
+ VideoThreadLock();
+ }
+
+ switch (format) {
+ case 0: // pan&scan (we have no pan&scan)
+ Video4to3ZoomMode = VideoStretch;
+ break;
+ case 1: // letter box
+ Video4to3ZoomMode = VideoNormal;
+ break;
+ case 2: // center cut-out
+ Video4to3ZoomMode = VideoCenterCutOut;
+ break;
+ }
+
+ if (VideoUsedModule) {
+ VideoUsedModule->SetVideoMode();
+ }
+ if (VideoThread) {
+ VideoThreadUnlock();
+ }
+ VideoOsdInit();
+}
+
+///
/// Send fullscreen message to window.
///
/// @param onoff -1 toggle, true turn on, false turn off
diff --git a/video.h b/video.h
index 247006f..c8a1f46 100644
--- a/video.h
+++ b/video.h
@@ -80,6 +80,9 @@ extern void VideoSetOutputPosition(int, int, int, int);
/// Set video mode.
extern void VideoSetVideoMode(int, int, int, int);
+ /// Set display format.
+extern void VideoSetDisplayFormat(int);
+
/// Set video fullscreen mode.
extern void VideoSetFullscreen(int);