summaryrefslogtreecommitdiff
path: root/video.c
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2011-12-22 21:25:38 +0100
committerJohns <johns98@gmx.net>2011-12-22 21:25:38 +0100
commit18e9e2f69edbe242db100ce1b7a132f75d15cbc9 (patch)
treea5ef93eea0211c27678524f36867941ddc9126c1 /video.c
parentafd7dfe40218fba6172625c51798787a48fce9af (diff)
downloadvdr-plugin-softhddevice-18e9e2f69edbe242db100ce1b7a132f75d15cbc9.tar.gz
vdr-plugin-softhddevice-18e9e2f69edbe242db100ce1b7a132f75d15cbc9.tar.bz2
Initial vdpau osd support.
Diffstat (limited to 'video.c')
-rw-r--r--video.c417
1 files changed, 276 insertions, 141 deletions
diff --git a/video.c b/video.c
index 4628bc8..b4078ac 100644
--- a/video.c
+++ b/video.c
@@ -42,7 +42,7 @@
//#define USE_VAAPI ///< enable vaapi support
//#define USE_VDPAU ///< enable vdpau support
-#define noUSE_BITMAP
+#define noUSE_BITMAP ///< use vdpau bitmap surface
#define USE_VIDEO_THREAD
@@ -2799,11 +2799,11 @@ static void VaapiDisplayHandlerThread(void)
// VA-API OSD
//----------------------------------------------------------------------------
-/**
-** Clear subpicture image.
-**
-** @note looked by caller
-*/
+///
+/// Clear subpicture image.
+///
+/// @note looked by caller
+///
static void VaapiOsdClear(void)
{
void *image_buffer;
@@ -2829,11 +2829,17 @@ static void VaapiOsdClear(void)
}
}
-/**
-** Upload ARGB to subpicture image.
-**
-** @note looked by caller
-*/
+///
+/// Upload ARGB to subpicture image.
+///
+/// @param x x position of image in osd
+/// @param y y position of image in osd
+/// @param width width of image
+/// @param height height of image
+/// @param argb argb image
+///
+/// @note looked by caller
+///
static void VaapiUploadImage(int x, int y, int width, int height,
const uint8_t * argb)
{
@@ -2869,11 +2875,14 @@ static void VaapiUploadImage(int x, int y, int width, int height,
}
}
-/**
-** VA-API initialize OSD.
-**
-** @note subpicture is unusable, it can be scaled with the video image.
-*/
+///
+/// VA-API initialize OSD.
+///
+/// @param width osd width
+/// @param height osd height
+///
+/// @note subpicture is unusable, it can be scaled with the video image.
+///
static void VaapiOsdInit(int width, int height)
{
VAImageFormat *formats;
@@ -2888,7 +2897,6 @@ static void VaapiOsdInit(int width, int height)
Debug(3, "video/vaapi: osd already setup\n");
return;
}
-
if (!VaDisplay) {
Debug(3, "video/vaapi: va-api not setup\n");
return;
@@ -2937,6 +2945,7 @@ static void VaapiOsdInit(int width, int height)
//VaapiUnscaledOsd = 0;
//Info(_("video/vaapi: unscaled osd disabled\n"));
+ // FIXME: lock
if (vaCreateImage(VaDisplay, &formats[u], width, height,
&VaOsdImage) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't create osd image\n"));
@@ -2957,6 +2966,7 @@ static void VaapiOsdInit(int width, int height)
// FIXME: must store format, to convert ARGB to it.
VaapiOsdClear();
+ // FIXME: unlock
}
#endif
@@ -3048,6 +3058,22 @@ static VdpOutputSurface VdpauSurfacesRb[OUTPUT_SURFACES_MAX];
static int VdpauSurfaceIndex; ///< current display surface
static int VdpauSurfaceNotStart; ///< not the first surface
+static int VdpauOsdWidth; ///< width of osd surface
+static int VdpauOsdHeight; ///< height of osd surface
+
+#ifdef USE_BITMAP
+ /// bitmap surfaces for osd
+static VdpBitmapSurface VdpauOsdBitmapSurface[2] = {
+ VDP_INVALID_HANDLE, VDP_INVALID_HANDLE
+};
+#else
+ /// output surfaces for osd
+static VdpOutputSurface VdpauOsdOutputSurface[2] = {
+ VDP_INVALID_HANDLE, VDP_INVALID_HANDLE
+};
+#endif
+static int VdpauOsdSurfaceIndex; ///< index into double buffered osd
+
///
/// Function pointer of the VDPAU device.
///
@@ -4038,13 +4064,13 @@ static void VdpauSetup(VdpauDecoder * decoder,
// FIXME: reset output ring buffer
}
-/**
-** Render a ffmpeg frame.
-**
-** @param decoder VDPAU decoder
-** @param video_ctx ffmpeg video codec context
-** @param frame frame to display
-*/
+///
+/// Render a ffmpeg frame.
+///
+/// @param decoder VDPAU decoder
+/// @param video_ctx ffmpeg video codec context
+/// @param frame frame to display
+///
static void VdpauRenderFrame(VdpauDecoder * decoder,
const AVCodecContext * video_ctx, const AVFrame * frame)
{
@@ -4180,105 +4206,18 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
atomic_inc(&decoder->SurfacesFilled);
}
-#if 0
-
///
/// Render osd surface to output surface.
///
-/// FIXME: must split render / upload / display
-///
static void VdpauMixOsd(void)
{
VdpOutputSurfaceRenderBlendState blend_state;
VdpRect source_rect;
VdpRect output_rect;
VdpStatus status;
- static char *image;
- void const *data[1];
- uint32_t pitches[1];
- static int count;
- static int surface_index;
- int i;
-
-#ifdef USE_BITMAP
- static VdpBitmapSurface bitmap_surface[2];
-
- if (!bitmap_surface[0]) {
- for (i = 0; i < 2; ++i) {
- status =
- VdpauBitmapSurfaceCreate(VdpauDevice, VDP_RGBA_FORMAT_B8G8R8A8,
- OsdWidth, OsdHeight, VDP_TRUE, bitmap_surface + i);
- if (status != VDP_STATUS_OK) {
- Error(_("video/vdpau: can't create bitmap surface: %s\n"),
- VdpauGetErrorString(status));
- }
- }
- }
-#else
- static VdpOutputSurface output_surface[2];
-
- if (!output_surface[0]) {
- for (i = 0; i < 2; ++i) {
- status =
- VdpauOutputSurfaceCreate(VdpauDevice, VDP_RGBA_FORMAT_B8G8R8A8,
- OsdWidth, OsdHeight, output_surface + i);
- if (status != VDP_STATUS_OK) {
- Fatal(_("video/vdpau: can't create output surface: %s\n"),
- VdpauGetErrorString(status));
- }
- }
- }
-#endif
- if (!image) {
- image = calloc(4, OsdWidth * OsdHeight);
- }
- if (1 || count < 10) {
- memset(image, 0x00, 4 * OsdWidth * OsdHeight);
- //GfxConvert(image, 0, OsdWidth * 4);
-
- //
- // upload changed osd image (99ms for a 1920x1080 !frequently_accessed)
- // (5ms - 10ms with frequently_accessed = true)
- //
- if (0) {
- count++;
- source_rect.x0 = 0;
- source_rect.y0 = (OsdHeight * (count & 7)) / 8;
- source_rect.x1 = source_rect.x0 + OsdWidth;
- source_rect.y1 = source_rect.y0 + OsdHeight / 8;
- data[0] = image + ((OsdHeight * (count & 7)) / 8) * OsdWidth * 4;
- } else {
- source_rect.x0 = 0;
- source_rect.y0 = 0;
- source_rect.x1 = source_rect.x0 + OsdWidth;
- source_rect.y1 = source_rect.y0 + OsdHeight;
- data[0] = image;
- }
-
- pitches[0] = OsdWidth * 4;
- uint32_t start = GetMsTicks();
-
-#ifdef USE_BITMAP
- status =
- VdpauBitmapSurfacePutBitsNative(bitmap_surface[surface_index],
- data, pitches, &source_rect);
- if (status != VDP_STATUS_OK) {
- Error(_("video/vdpau: bitmap surface put bits failed: %s\n"),
- VdpauGetErrorString(status));
- }
-#else
- status =
- VdpauOutputSurfacePutBitsNative(output_surface[surface_index],
- data, pitches, &source_rect);
- if (status != VDP_STATUS_OK) {
- Error(_("video/vdpau: output surface put bits failed: %s\n"),
- VdpauGetErrorString(status));
- }
-#endif
- uint32_t end = GetMsTicks();
+ uint32_t start;
+ uint32_t end;
- Debug(3, "upload %d ms\n", end - start);
- }
//
// blend overlay over output
//
@@ -4298,44 +4237,45 @@ static void VdpauMixOsd(void)
source_rect.x0 = 0;
source_rect.y0 = 0;
- source_rect.x1 = OsdWidth;
- source_rect.y1 = OsdHeight;
+ source_rect.x1 = VdpauOsdWidth;
+ source_rect.y1 = VdpauOsdHeight;
output_rect.x0 = 0;
output_rect.y0 = 0;
output_rect.x1 = VideoWindowWidth;
output_rect.y1 = VideoWindowHeight;
- uint32_t start = GetMsTicks();
+ start = GetMsTicks();
+ VdpauOsdSurfaceIndex = 1;
#ifdef USE_BITMAP
status =
- VdpauOutputSurfaceRenderBitmapSurface(VdpauSurfacesRb
- [VdpauSurfaceIndex], &output_rect, bitmap_surface[!surface_index],
- &source_rect, NULL, &blend_state, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
+ VdpauOutputSurfaceRenderBitmapSurface(dpauSurfacesRb
+ [VdpauSurfaceIndex], &output_rect,
+ VdpauOsdBitmapSurface[!VdpauOsdSurfaceIndex], &source_rect, NULL,
+ &blend_state, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
if (status != VDP_STATUS_OK) {
Error(_("video/vdpau: can't render bitmap surface: %s\n"),
VdpauGetErrorString(status));
}
#else
- status
+ status =
VdpauOutputSurfaceRenderOutputSurface(VdpauSurfacesRb
- [VdpauSurfaceIndex], &output_rect, output_surface[!surface_index],
- &source_rect, NULL, &blend_state, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
+ [VdpauSurfaceIndex], &output_rect,
+ VdpauOsdOutputSurface[!VdpauOsdSurfaceIndex], &source_rect, NULL,
+ &blend_state, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
if (status != VDP_STATUS_OK) {
Error(_("video/vdpau: can't render output surface: %s\n"),
VdpauGetErrorString(status));
}
#endif
- uint32_t end = GetMsTicks();
+ end = GetMsTicks();
- Debug(3, "render %d ms\n", end - start);
+ //Debug(3, "video:/vdpau: osd render %d ms\n", end - start);
- surface_index = !surface_index;
+ VdpauOsdSurfaceIndex = !VdpauOsdSurfaceIndex;
}
-#endif
-
///
/// Render video surface to output surface.
///
@@ -4513,11 +4453,10 @@ static void VdpauDisplayFrame(void)
}
}
-#if 0
- if (OsdShow) {
- VdpauMixOsd();
- }
-#endif
+ //
+ // add osd to surface
+ //
+ VdpauMixOsd();
//
// place surface in presentation queue
@@ -4706,6 +4645,176 @@ static void VdpauDisplayHandlerThread(void)
#endif
+//----------------------------------------------------------------------------
+// VDPAU OSD
+//----------------------------------------------------------------------------
+
+///
+/// Clear subpicture image.
+///
+/// @note looked by caller
+///
+static void VdpauOsdClear(void)
+{
+ VdpStatus status;
+ void *image;
+ void const *data[1];
+ uint32_t pitches[1];
+ VdpRect dst_rect;
+
+ // osd image available?
+#ifdef USE_BITMAP
+ if (VdpauOsdBitmapSurface[VdpauOsdSurfaceIndex] == VDP_INVALID_HANDLE) {
+ return;
+ }
+#else
+ if (VdpauOsdOutputSurface[VdpauOsdSurfaceIndex] == VDP_INVALID_HANDLE) {
+ return;
+ }
+#endif
+
+ Debug(3, "video/vdpau: clear image\n");
+
+ image = calloc(4, VdpauOsdWidth * VdpauOsdHeight);
+
+ dst_rect.x0 = 0;
+ dst_rect.y0 = 0;
+ dst_rect.x1 = dst_rect.x0 + VdpauOsdWidth;
+ dst_rect.y1 = dst_rect.y0 + VdpauOsdHeight;
+ data[0] = image;
+ pitches[0] = VdpauOsdWidth * 4;
+
+#ifdef USE_BITMAP
+ status =
+ VdpauBitmapSurfacePutBitsNative(VdpauOsdBitmapSurface
+ [VdpauOsdSurfaceIndex], data, pitches, &dst_rect);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: bitmap surface put bits failed: %s\n"),
+ VdpauGetErrorString(status));
+ }
+#else
+ status =
+ VdpauOutputSurfacePutBitsNative(VdpauOsdOutputSurface
+ [VdpauOsdSurfaceIndex], data, pitches, &dst_rect);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: output surface put bits failed: %s\n"),
+ VdpauGetErrorString(status));
+ }
+#endif
+
+ free(image);
+}
+
+///
+/// Upload ARGB to subpicture image.
+///
+/// @param x x position of image in osd
+/// @param y y position of image in osd
+/// @param width width of image
+/// @param height height of image
+/// @param argb argb image
+///
+/// @note looked by caller
+///
+static void VdpauUploadImage(int x, int y, int width, int height,
+ const uint8_t * argb)
+{
+ VdpStatus status;
+ void const *data[1];
+ uint32_t pitches[1];
+ VdpRect dst_rect;
+
+ // osd image available?
+#ifdef USE_BITMAP
+ if (VdpauOsdBitmapSurface[VdpauOsdSurfaceIndex] == VDP_INVALID_HANDLE) {
+ return;
+ }
+#else
+ if (VdpauOsdOutputSurface[VdpauOsdSurfaceIndex] == VDP_INVALID_HANDLE) {
+ return;
+ }
+#endif
+
+ Debug(3, "video/vdpau: upload image\n");
+
+ dst_rect.x0 = x;
+ dst_rect.y0 = y;
+ dst_rect.x1 = dst_rect.x0 + width;
+ dst_rect.y1 = dst_rect.y0 + height;
+ data[0] = argb;
+ pitches[0] = width * 4;
+
+#ifdef USE_BITMAP
+ status =
+ VdpauBitmapSurfacePutBitsNative(VdpauOsdBitmapSurface
+ [VdpauOsdSurfaceIndex], data, pitches, &dst_rect);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: bitmap surface put bits failed: %s\n"),
+ VdpauGetErrorString(status));
+ }
+#else
+ status =
+ VdpauOutputSurfacePutBitsNative(VdpauOsdOutputSurface
+ [VdpauOsdSurfaceIndex], data, pitches, &dst_rect);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: output surface put bits failed: %s\n"),
+ VdpauGetErrorString(status));
+ }
+#endif
+}
+
+///
+/// VDPAU initialize OSD.
+///
+/// @param width osd width
+/// @param height osd height
+///
+static void VdpauOsdInit(int width, int height)
+{
+ int i;
+ VdpStatus status;
+
+ if (!VdpauDevice) {
+ Debug(3, "video/vdpau: vdpau not setup\n");
+ }
+
+ VdpauOsdWidth = width;
+ VdpauOsdHeight = height;
+
+ //
+ // create bitmap/surface for osd
+ //
+#ifdef USE_BITMAP
+ if (VdpauOsdBitmapSurface[0] == VDP_INVALID_HANDLE) {
+ for (i = 0; i < 2; ++i) {
+ status =
+ VdpauBitmapSurfaceCreate(VdpauDevice, VDP_RGBA_FORMAT_B8G8R8A8,
+ width, height, VDP_TRUE, VdpauOsdBitmapSurface + i);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: can't create bitmap surface: %s\n"),
+ VdpauGetErrorString(status));
+ }
+ }
+ }
+#else
+ if (VdpauOsdOutputSurface[0] == VDP_INVALID_HANDLE) {
+ for (i = 0; i < 2; ++i) {
+ status =
+ VdpauOutputSurfaceCreate(VdpauDevice, VDP_RGBA_FORMAT_B8G8R8A8,
+ width, height, VdpauOsdOutputSurface + i);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: can't create output surface: %s\n"),
+ VdpauGetErrorString(status));
+ }
+ }
+ }
+#endif
+
+ Debug(3, "video/vdpau: osd surfaces created\n");
+
+ VdpauOsdClear();
+}
+
#endif
//----------------------------------------------------------------------------
@@ -4716,12 +4825,12 @@ static void VdpauDisplayHandlerThread(void)
static int OsdWidth; ///< osd width
static int OsdHeight; ///< osd height
-/**
-** Clear the OSD.
-**
-** @todo I use glTexImage2D to clear the texture, are there faster and
-** better ways to clear a texture?
-*/
+///
+/// Clear the OSD.
+///
+/// @todo I use glTexImage2D to clear the texture, are there faster and
+/// better ways to clear a texture?
+///
void VideoOsdClear(void)
{
VideoThreadLock();
@@ -4748,12 +4857,25 @@ void VideoOsdClear(void)
return;
}
#endif
+#ifdef USE_VDPAU
+ if (VideoVdpauEnabled) {
+ VdpauOsdClear();
+ VideoThreadUnlock();
+ return;
+ }
+#endif
VideoThreadUnlock();
}
-/**
-** Draw an OSD ARGB image.
-*/
+///
+/// Draw an OSD ARGB image.
+///
+/// @param x x position of image in osd
+/// @param y y position of image in osd
+/// @param width width of image
+/// @param height height of image
+/// @param argb argb image
+///
void VideoOsdDrawARGB(int x, int y, int height, int width,
const uint8_t * argb)
{
@@ -4773,6 +4895,13 @@ void VideoOsdDrawARGB(int x, int y, int height, int width,
return;
}
#endif
+#ifdef USE_VDPAU
+ if (VideoVdpauEnabled) {
+ VdpauUploadImage(x, y, height, width, argb);
+ VideoThreadUnlock();
+ return;
+ }
+#endif
(void)x;
(void)y;
(void)height;
@@ -4832,6 +4961,12 @@ void VideoOsdInit(void)
return;
}
#endif
+#ifdef USE_VDPAU
+ if (VideoVdpauEnabled) {
+ VdpauOsdInit(OsdWidth, OsdHeight);
+ return;
+ }
+#endif
}
#if 0