summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--video.c306
1 files changed, 263 insertions, 43 deletions
diff --git a/video.c b/video.c
index 0743c89..6f42e5f 100644
--- a/video.c
+++ b/video.c
@@ -1859,6 +1859,7 @@ static void Vaapi1080i(void)
VAConfigID config_id;
VAContextID context_id;
VASurfaceID surfaces[32];
+ VAImage image[1];
int n;
uint32_t start_tick;
uint32_t tick;
@@ -1906,9 +1907,27 @@ static void Vaapi1080i(void)
Error(_("codec: can't create context"));
return;
}
+#if 1
+ // without this 1080i will crash
+ image->image_id = VA_INVALID_ID;
+ if (vaDeriveImage(VaDisplay, surfaces[0], image)
+ != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: vaDeriveImage failed\n"));
+ }
+ if (image->image_id != VA_INVALID_ID) {
+ if (vaDestroyImage(VaDisplay, image->image_id) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't destroy image!\n"));
+ }
+ }
+#else
+ vaBeginPicture(VaDisplay, context_id, surfaces[0]);
+ vaRenderPicture(VaDisplay, context_id, NULL, 0);
+ // aborts without valid buffers upload
+ vaEndPicture(VaDisplay, context_id);
+#endif
start_tick = GetMsTicks();
- for (n = 1; n < 10000; ++n) {
+ for (n = 1; n < 2; ++n) {
if (vaPutSurface(VaDisplay, surfaces[0], VideoWindow,
// decoder src
0, 0, 1920, 1080,
@@ -1926,7 +1945,7 @@ static void Vaapi1080i(void)
Error(_("video/vaapi: vaPutSurface failed\n"));
}
tick = GetMsTicks();
- if (!(n % 100)) {
+ if (!(n % 10)) {
fprintf(stderr, "%d ms / frame\n", (tick - start_tick) / n);
}
}
@@ -1941,7 +1960,7 @@ static void Vaapi1080i(void)
if (vaDestroyConfig(VaDisplay, config_id) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't destroy config!\n"));
}
- printf("done\n");
+ fprintf(stderr, "done\n");
}
///
@@ -1970,13 +1989,13 @@ static int VaapiInit(const char *display_name)
VaDisplay = vaGetDisplay(XlibDisplay);
}
if (!VaDisplay) {
- Error(_("video/vaapi: Can't connect VA-API to X11 server on '%s'"),
+ Error(_("video/vaapi: Can't connect VA-API to X11 server on '%s'\n"),
display_name);
return 0;
}
if (vaInitialize(VaDisplay, &major, &minor) != VA_STATUS_SUCCESS) {
- Error(_("video/vaapi: Can't inititialize VA-API on '%s'"),
+ Error(_("video/vaapi: Can't inititialize VA-API on '%s'\n"),
display_name);
vaTerminate(VaDisplay);
VaDisplay = NULL;
@@ -2300,14 +2319,14 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
if (vaCreateSurfaceGLX(decoder->VaDisplay, GL_TEXTURE_2D,
decoder->GlTexture[0], &decoder->GlxSurface[0])
!= VA_STATUS_SUCCESS) {
- Fatal(_("video/glx: can't create glx surfaces"));
+ Fatal(_("video/glx: can't create glx surfaces\n"));
}
// FIXME: this isn't usable with vdpau-backend
/*
if (vaCreateSurfaceGLX(decoder->VaDisplay, GL_TEXTURE_2D,
decoder->GlTexture[1], &decoder->GlxSurface[1])
!= VA_STATUS_SUCCESS) {
- Fatal(_("video/glx: can't create glx surfaces"));
+ Fatal(_("video/glx: can't create glx surfaces\n"));
}
*/
}
@@ -2640,13 +2659,13 @@ static void VaapiSetup(VaapiDecoder * decoder,
if (vaCreateSurfaceGLX(decoder->VaDisplay, GL_TEXTURE_2D,
decoder->GlTexture[0], &decoder->GlxSurface[0])
!= VA_STATUS_SUCCESS) {
- Fatal(_("video/glx: can't create glx surfaces"));
+ Fatal(_("video/glx: can't create glx surfaces\n"));
}
/*
if (vaCreateSurfaceGLX(decoder->VaDisplay, GL_TEXTURE_2D,
decoder->GlTexture[1], &decoder->GlxSurface[1])
!= VA_STATUS_SUCCESS) {
- Fatal(_("video/glx: can't create glx surfaces"));
+ Fatal(_("video/glx: can't create glx surfaces\n"));
}
*/
}
@@ -2985,27 +3004,6 @@ static void VaapiQueueSurface(VaapiDecoder * decoder, VASurfaceID surface,
Debug(4, "video/vaapi: yy video surface %#010x ready\n", surface);
}
-#if 0
-
- /// Return the absolute value of an integer.
-#define ABS(i) ((i) >= 0 ? (i) : (-(i)))
-
-///
-/// ELA Edge-based Line Averaging
-/// Low-Complexity Interpolation Method
-///
-/// abcdefg abcdefg abcdefg abcdefg abcdefg
-/// x x x x x
-/// hijklmn hijklmn hijklmn hijklmn hijklmn
-///
-static void FilterLine(const uint8_t * past, const uint8_t * cur,
- const uint8_t * future, int width, int above, int below)
-{
- int a, b, c, d, e, f, g, h, i, j, k, l, m, n;
-}
-
-#endif
-
///
/// Create and display a black empty surface.
///
@@ -3129,6 +3127,216 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
usleep(1 * 1000);
}
+ /// Return the absolute value of an integer.
+#define ABS(i) ((i) >= 0 ? (i) : (-(i)))
+
+///
+/// ELA Edge-based Line Averaging
+/// Low-Complexity Interpolation Method
+///
+/// abcdefg abcdefg abcdefg abcdefg abcdefg
+/// x x x x x
+/// hijklmn hijklmn hijklmn hijklmn hijklmn
+///
+static void FilterLineSpatial(uint8_t * dst, const uint8_t * cur, int width,
+ int above, int below, int next)
+{
+ int a, b, c, d, e, f, g, h, i, j, k, l, m, n;
+ int spatial_pred;
+ int spatial_score;
+ int score;
+ int x;
+
+ for (x = 0; x < width; ++x) {
+ a = cur[above + x - 3 * next]; // ignore bound violation
+ b = cur[above + x - 2 * next];
+ c = cur[above + x - 1 * next];
+ d = cur[above + x + 0 * next];
+ e = cur[above + x + 1 * next];
+ f = cur[above + x + 2 * next];
+ g = cur[above + x + 3 * next];
+
+ h = cur[below + x - 3 * next];
+ i = cur[below + x - 2 * next];
+ j = cur[below + x - 1 * next];
+ k = cur[below + x + 0 * next];
+ l = cur[below + x + 1 * next];
+ m = cur[below + x + 2 * next];
+ n = cur[below + x + 3 * next];
+
+ spatial_pred = (d + k) / 2; // 0 pixel
+ spatial_score = ABS(c - j) + ABS(d - k) + ABS(e - l);
+
+ score = ABS(b - k) + ABS(c - l) + ABS(d - m);
+ if (score < spatial_score) {
+ spatial_pred = (c + l) / 2; // 1 pixel
+ spatial_score = score;
+ score = ABS(a - l) + ABS(b - m) + ABS(c - n);
+ if (score < spatial_score) {
+ spatial_pred = (b + m) / 2; // 2 pixel
+ spatial_score = score;
+ }
+ }
+ score = ABS(d - i) + ABS(e - j) + ABS(f - k);
+ if (score < spatial_score) {
+ spatial_pred = (e + j) / 2; // -1 pixel
+ spatial_score = score;
+ score = ABS(e - h) + ABS(f - i) + ABS(g - j);
+ if (score < spatial_score) {
+ spatial_pred = (f + i) / 2; // -2 pixel
+ spatial_score = score;
+ }
+ }
+
+ dst[x + 0] = spatial_pred;
+ }
+}
+
+///
+/// Vaapi spatial deinterlace.
+///
+/// @note FIXME: use common software deinterlace functions.
+///
+static void VaapiSpatial(VaapiDecoder * decoder, VAImage * src, VAImage * dst1,
+ VAImage * dst2)
+{
+ uint32_t tick1;
+ uint32_t tick2;
+ uint32_t tick3;
+ uint32_t tick4;
+ uint32_t tick5;
+ uint32_t tick6;
+ uint32_t tick7;
+ uint32_t tick8;
+ void *src_base;
+ void *dst1_base;
+ void *dst2_base;
+ unsigned y;
+ unsigned p;
+ uint8_t *tmp;
+ int pitch;
+ int width;
+
+ tick1 = GetMsTicks();
+ if (vaMapBuffer(decoder->VaDisplay, src->buf,
+ &src_base) != VA_STATUS_SUCCESS) {
+ Fatal("video/vaapi: can't map the image!\n");
+ }
+ tick2 = GetMsTicks();
+ if (vaMapBuffer(decoder->VaDisplay, dst1->buf,
+ &dst1_base) != VA_STATUS_SUCCESS) {
+ Fatal("video/vaapi: can't map the image!\n");
+ }
+ tick3 = GetMsTicks();
+ if (vaMapBuffer(decoder->VaDisplay, dst2->buf,
+ &dst2_base) != VA_STATUS_SUCCESS) {
+ Fatal("video/vaapi: can't map the image!\n");
+ }
+ tick4 = GetMsTicks();
+
+ if (0) { // test all updated
+ memset(dst1_base, 0x00, dst1->data_size);
+ memset(dst2_base, 0xFF, dst2->data_size);
+ }
+ // use tmp copy
+ tmp = malloc(src->data_size);
+ memcpy(tmp, src_base, src->data_size);
+
+ if (src->num_planes == 2) { // NV12
+ pitch = src->pitches[0];
+ width = src->width;
+ for (y = 0; y < (unsigned)src->height; y++) { // Y
+ const uint8_t *cur;
+
+ cur = tmp + src->offsets[0] + y * pitch;
+ if (y & 1) {
+ // copy to 2nd
+ memcpy(dst2_base + src->offsets[0] + y * pitch, cur, width);
+ // create 1st
+ FilterLineSpatial(dst1_base + src->offsets[0] + y * pitch, cur,
+ width, y ? -pitch : pitch,
+ y + 1 < (unsigned)src->height ? pitch : -pitch, 1);
+ } else {
+ // copy to 1st
+ memcpy(dst1_base + src->offsets[0] + y * pitch, cur, width);
+ // create 2nd
+ FilterLineSpatial(dst2_base + src->offsets[0] + y * pitch, cur,
+ width, y ? -pitch : pitch,
+ y + 1 < (unsigned)src->height ? pitch : -pitch, 1);
+ }
+ }
+ for (y = 0; y < (unsigned)src->height / 2; y++) { // UV
+ const uint8_t *cur;
+
+ cur = tmp + src->offsets[1] + y * pitch;
+ if (y & 1) {
+ // copy to 2nd
+ memcpy(dst2_base + src->offsets[1] + y * pitch, cur, width);
+ // create 1st
+ FilterLineSpatial(dst1_base + src->offsets[1] + y * pitch, cur,
+ width, y ? -pitch : pitch,
+ y + 1 < (unsigned)src->height / 2 ? pitch : -pitch, 2);
+ } else {
+ // copy to 1st
+ memcpy(dst1_base + src->offsets[1] + y * pitch, cur, width);
+ // create 2nd
+ FilterLineSpatial(dst2_base + src->offsets[1] + y * pitch, cur,
+ width, y ? -pitch : pitch,
+ y + 1 < (unsigned)src->height / 2 ? pitch : -pitch, 2);
+ }
+ }
+ } else {
+ for (p = 0; p < src->num_planes; ++p) {
+ pitch = src->pitches[p];
+ width = src->width >> (p != 0);
+ for (y = 0; y < (unsigned)(src->height >> (p != 0)); y++) {
+ const uint8_t *cur;
+
+ cur = tmp + src->offsets[p] + y * pitch;
+ if (y & 1) {
+ // copy to 2nd
+ memcpy(dst2_base + src->offsets[p] + y * pitch, cur,
+ width);
+ // create 1st
+ FilterLineSpatial(dst1_base + src->offsets[p] + y * pitch,
+ cur, width, y ? -pitch : pitch,
+ y + 1 < (unsigned)(src->height >> (p != 0))
+ ? pitch : -pitch, 1);
+ } else {
+ // copy to 1st
+ memcpy(dst1_base + src->offsets[p] + y * pitch, cur,
+ width);
+ // create 2nd
+ FilterLineSpatial(dst2_base + src->offsets[p] + y * pitch,
+ cur, width, y ? -pitch : pitch,
+ y + 1 < (unsigned)(src->height >> (p != 0))
+ ? pitch : -pitch, 1);
+ }
+ }
+ }
+ }
+ free(tmp);
+
+ tick5 = GetMsTicks();
+
+ if (vaUnmapBuffer(decoder->VaDisplay, dst2->buf) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't unmap image buffer\n"));
+ }
+ tick6 = GetMsTicks();
+ if (vaUnmapBuffer(decoder->VaDisplay, dst1->buf) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't unmap image buffer\n"));
+ }
+ tick7 = GetMsTicks();
+ if (vaUnmapBuffer(decoder->VaDisplay, src->buf) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't unmap image buffer\n"));
+ }
+ tick8 = GetMsTicks();
+
+ Debug(4, "video/vaapi: map=%2d/%2d/%2d deint=%2d umap=%2d/%2d/%2d\n",
+ tick2 - tick1, tick3 - tick2, tick4 - tick3, tick5 - tick4,
+ tick6 - tick5, tick7 - tick6, tick8 - tick7);
+}
+
///
/// Vaapi bob deinterlace.
///
@@ -3299,7 +3507,7 @@ static void VaapiBob(VaapiDecoder * decoder, VAImage * src, VAImage * dst1,
}
tick8 = GetMsTicks();
- Debug(3, "video/vaapi: map=%2d/%2d/%2d deint=%2d umap=%2d/%2d/%2d\n",
+ Debug(4, "video/vaapi: map=%2d/%2d/%2d deint=%2d umap=%2d/%2d/%2d\n",
tick2 - tick1, tick3 - tick2, tick4 - tick3, tick5 - tick4,
tick6 - tick5, tick7 - tick6, tick8 - tick7);
}
@@ -3421,7 +3629,8 @@ static void VaapiCpuDerive(VaapiDecoder * decoder, VASurfaceID surface)
}
tick4 = GetMsTicks();
- VaapiBob(decoder, image, dest1, dest2);
+ //VaapiBob(decoder, image, dest1, dest2);
+ VaapiSpatial(decoder, image, dest1, dest2);
tick5 = GetMsTicks();
if (vaDestroyImage(VaDisplay, image->image_id) != VA_STATUS_SUCCESS) {
@@ -3492,7 +3701,8 @@ static void VaapiCpuPut(VaapiDecoder * decoder, VASurfaceID surface)
// FIXME: handle top_field_first
- VaapiBob(decoder, img1, img2, img3);
+ //VaapiBob(decoder, img1, img2, img3);
+ VaapiSpatial(decoder, img1, img2, img3);
tick3 = GetMsTicks();
// get a free surface and upload the image
@@ -3544,10 +3754,10 @@ static void VaapiCpuPut(VaapiDecoder * decoder, VASurfaceID surface)
///
static void VaapiCpuDeinterlace(VaapiDecoder * decoder, VASurfaceID surface)
{
- if (VaapiBuggyIntel) {
- VaapiCpuDerive(decoder, surface);
- } else {
+ if (decoder->GetPutImage) {
VaapiCpuPut(decoder, surface);
+ } else {
+ VaapiCpuDerive(decoder, surface);
}
// FIXME: must release software input surface
}
@@ -4490,6 +4700,7 @@ static int VdpauInverseTelecine; ///< inverse telecine deint. supported
static int VdpauNoiseReduction; ///< noise reduction supported
static int VdpauSharpness; ///< sharpness supported
static int VdpauSkipChroma; ///< skip chroma deint. supported
+static VdpChromaType VdpauChromaType; ///< best video surface chroma format
/// display surface ring buffer
static VdpOutputSurface VdpauSurfacesRb[OUTPUT_SURFACES_MAX];
@@ -4928,8 +5139,7 @@ static void VdpauMixerCreate(VdpauDecoder * decoder)
features[feature_n++] = i;
}
- decoder->ChromaType = chroma_type = VDP_CHROMA_TYPE_420;
- // FIXME: use best chroma
+ decoder->ChromaType = chroma_type = VdpauChromaType;
//
// Setup parameter/value tables
@@ -5533,6 +5743,7 @@ static int VdpauInit(const char *display_name)
if (flag) {
Info(_("video/vdpau: 4:2:0 chroma format with %dx%d supported\n"),
max_width, max_height);
+ VdpauChromaType = VDP_CHROMA_TYPE_420;
}
flag = VDP_FALSE;
status =
@@ -5545,6 +5756,7 @@ static int VdpauInit(const char *display_name)
if (flag) {
Info(_("video/vdpau: 4:2:2 chroma format with %dx%d supported\n"),
max_width, max_height);
+ VdpauChromaType = VDP_CHROMA_TYPE_422;
}
flag = VDP_FALSE;
status =
@@ -5557,7 +5769,12 @@ static int VdpauInit(const char *display_name)
if (flag) {
Info(_("video/vdpau: 4:4:4 chroma format with %dx%d supported\n"),
max_width, max_height);
+ VdpauChromaType = VDP_CHROMA_TYPE_444;
}
+ // FIXME: check if all chroma-types failed
+ // FIXME: vdpau didn't support decode of other chroma types
+ VdpauChromaType = VDP_CHROMA_TYPE_420;
+
// FIXME: does only check for chroma formats, but no action
status =
VdpauVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpauDevice,
@@ -5706,11 +5923,14 @@ static void VdpauSetupOutput(VdpauDecoder * decoder)
return;
}
// vdpau can choose different sizes, must use them for putbits
- if (chroma_type != decoder->ChromaType
- || width != (uint32_t) decoder->InputWidth
+ if (chroma_type != decoder->ChromaType) {
+ // I request 422 if supported, but get only 420
+ Warning(_("video/vdpau: video surface chroma type mismatch\n"));
+ }
+ if (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"));
+ Fatal(_("video/vdpau: video surface size mismatch\n"));
}
}
@@ -8729,13 +8949,13 @@ void VideoInit(const char *display_name)
}
}
if (!(XlibDisplay = XOpenDisplay(display_name))) {
- Fatal(_("video: Can't connect to X11 server on '%s'"), display_name);
+ Fatal(_("video: Can't connect to X11 server on '%s'\n"), display_name);
// FIXME: we need to retry connection
}
// XInitThreads();
// Convert XLIB display to XCB connection
if (!(Connection = XGetXCBConnection(XlibDisplay))) {
- Fatal(_("video: Can't convert XLIB display to XCB connection"));
+ Fatal(_("video: Can't convert XLIB display to XCB connection\n"));
}
// prefetch extensions
//xcb_prefetch_extension_data(Connection, &xcb_big_requests_id);