summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2012-02-09 21:22:42 +0100
committerJohns <johns98@gmx.net>2012-02-09 21:22:42 +0100
commitd8f63adaad4cf50d9c18adaea734acc85e8ad404 (patch)
treef1e77d95f01fc2c75482baec649c28737d3b94a0
parent8c16466d318350b769615ee365ecc2b6a85dda5d (diff)
downloadvdr-plugin-softhddevice-d8f63adaad4cf50d9c18adaea734acc85e8ad404.tar.gz
vdr-plugin-softhddevice-d8f63adaad4cf50d9c18adaea734acc85e8ad404.tar.bz2
Software deinterlacer (config/skip chroma deint):
Add support for skip chroma deinterlace to software deinterlacer. Type of software deinterlacer now configurable from setup menu.
-rw-r--r--ChangeLog2
-rw-r--r--softhddevice.cpp5
-rw-r--r--video.c205
3 files changed, 162 insertions, 50 deletions
diff --git a/ChangeLog b/ChangeLog
index 7afc013..4dce0eb 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,8 @@
User johns
Date:
+ Add support for skip chroma deinterlace to software deinterlacer.
+ Type of software deinterlacer now configurable from setup menu.
Mixer channel could be set through command line option.
Fix bug: LFE moved to wrong position.
Guard suspend/resume against multiple calls.
diff --git a/softhddevice.cpp b/softhddevice.cpp
index 934e1e0..9854d97 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -423,7 +423,8 @@ static inline cOsdItem *SeparatorItem(const char *label)
cMenuSetupSoft::cMenuSetupSoft(void)
{
static const char *const deinterlace[] = {
- "Bob", "Weave/None", "Temporal", "TemporalSpatial", "Software"
+ "Bob", "Weave/None", "Temporal", "TemporalSpatial", "Software Bob",
+ "Software Spatial",
};
static const char *const scaling[] = {
"Normal", "Fast", "HQ", "Anamorphic"
@@ -458,7 +459,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
Scaling[i] = ConfigVideoScaling[i];
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling[i], 4, scaling));
Deinterlace[i] = ConfigVideoDeinterlace[i];
- Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace[i], 5,
+ Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace[i], 6,
deinterlace));
SkipChromaDeinterlace[i] = ConfigVideoSkipChromaDeinterlace[i];
Add(new cMenuEditBoolItem(tr("SkipChromaDeinterlace (vdpau)"),
diff --git a/video.c b/video.c
index 6f42e5f..53a7dd9 100644
--- a/video.c
+++ b/video.c
@@ -169,7 +169,8 @@ typedef enum _video_deinterlace_modes_
VideoDeinterlaceWeave, ///< weave deinterlace
VideoDeinterlaceTemporal, ///< temporal deinterlace
VideoDeinterlaceTemporalSpatial, ///< temporal spatial deinterlace
- VideoDeinterlaceSoftware, ///< software deinterlace
+ VideoDeinterlaceSoftBob, ///< software bob deinterlace
+ VideoDeinterlaceSoftSpatial, ///< software spatial deinterlace
} VideoDeinterlaceModes;
///
@@ -1232,6 +1233,7 @@ static void AutoCropDetect(AutoCropCtx * autocrop, int width, int height,
static int VaapiBuggyVdpau; ///< fix libva-driver-vdpau bugs
static int VaapiBuggyIntel; ///< fix libva-driver-intel bugs
+static int VaapiNewIntel; ///< new libva-driver-intel driver
static VADisplay *VaDisplay; ///< VA-API display
@@ -1506,7 +1508,7 @@ static VASurfaceID VaapiGetSurface(VaapiDecoder * decoder)
}
// surface still in use, try next
if (status != VASurfaceReady) {
- Debug(3, "video/vaapi: surface %#010x not ready: %d\n", surface,
+ Debug(4, "video/vaapi: surface %#010x not ready: %d\n", surface,
status);
if (!VaapiBuggyVdpau || i < 1) {
continue;
@@ -1625,7 +1627,7 @@ static void VaapiInitSurfaceFlags(VaapiDecoder * decoder)
//FIXME: private hack
//decoder->SurfaceFlagsTable[i] |= 0x00006000;
break;
- case VideoDeinterlaceSoftware:
+ default:
break;
}
}
@@ -1693,6 +1695,8 @@ static VaapiDecoder *VaapiNewDecoder(void)
decoder->OutputWidth = VideoWindowWidth;
decoder->OutputHeight = VideoWindowHeight;
+ // get/put still not working
+ //decoder->GetPutImage = !VaapiBuggyIntel || VaapiNewIntel;
decoder->GetPutImage = !VaapiBuggyIntel;
VaapiDecoders[VaapiDecoderN++] = decoder;
@@ -2015,6 +2019,9 @@ static int VaapiInit(const char *display_name)
if (strstr(s, "Intel i965")) {
VaapiBuggyIntel = 1;
}
+ if (strstr(s, "Intel i965 driver - 1.0.16.")) {
+ VaapiNewIntel = 1;
+ }
//
// check if driver makes a copy of the VA surface for display.
//
@@ -2365,7 +2372,7 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface,
// deinterlace
if (interlaced
- && VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceSoftware
+ && VideoDeinterlace[decoder->Resolution] < VideoDeinterlaceSoftBob
&& VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceWeave) {
if (top_field_first) {
if (field) {
@@ -3127,6 +3134,38 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
usleep(1 * 1000);
}
+#define noUSE_VECTOR ///< use gcc vector extension
+#ifdef USE_VECTOR
+
+typedef int8_t v16qi __attribute__ ((vector_size(16)));
+typedef int16_t v4hi __attribute__ ((vector_size(8)));
+
+///
+/// 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 x;
+
+ // 8/16 128bit xmm register
+
+ for (x = 0; x < width; x += 16) {
+ v16qi a;
+
+ // ignore bound violation
+ a = *(v16qi *) & cur[above + x];
+ *(v16qi *) & dst[x] = a;
+ }
+}
+
+#else
+
/// Return the absolute value of an integer.
#define ABS(i) ((i) >= 0 ? (i) : (-(i)))
@@ -3192,6 +3231,8 @@ static void FilterLineSpatial(uint8_t * dst, const uint8_t * cur, int width,
}
}
+#endif
+
///
/// Vaapi spatial deinterlace.
///
@@ -3238,7 +3279,7 @@ static void VaapiSpatial(VaapiDecoder * decoder, VAImage * src, VAImage * dst1,
memset(dst1_base, 0x00, dst1->data_size);
memset(dst2_base, 0xFF, dst2->data_size);
}
- // use tmp copy
+ // use tmp copy FIXME: only for intel needed
tmp = malloc(src->data_size);
memcpy(tmp, src_base, src->data_size);
@@ -3265,52 +3306,80 @@ static void VaapiSpatial(VaapiDecoder * decoder, VAImage * src, VAImage * dst1,
y + 1 < (unsigned)src->height ? pitch : -pitch, 1);
}
}
- for (y = 0; y < (unsigned)src->height / 2; y++) { // UV
- const uint8_t *cur;
+ if (VideoSkipChromaDeinterlace[decoder->Resolution]) {
+ 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 {
+ cur = tmp + src->offsets[1] + y * pitch;
// 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);
+ // copy to 2nd
+ memcpy(dst2_base + src->offsets[1] + y * pitch, cur, width);
}
- }
- } 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++) {
+ } else {
+ for (y = 0; y < (unsigned)src->height / 2; y++) { // UV
const uint8_t *cur;
- cur = tmp + src->offsets[p] + y * pitch;
+ cur = tmp + src->offsets[1] + y * pitch;
if (y & 1) {
// copy to 2nd
- memcpy(dst2_base + src->offsets[p] + y * pitch, cur,
+ memcpy(dst2_base + src->offsets[1] + y * pitch, cur,
width);
// create 1st
- FilterLineSpatial(dst1_base + src->offsets[p] + y * pitch,
+ FilterLineSpatial(dst1_base + src->offsets[1] + y * pitch,
cur, width, y ? -pitch : pitch,
- y + 1 < (unsigned)(src->height >> (p != 0))
- ? pitch : -pitch, 1);
+ y + 1 < (unsigned)src->height / 2 ? pitch : -pitch, 2);
} else {
// copy to 1st
- memcpy(dst1_base + src->offsets[p] + y * pitch, cur,
+ memcpy(dst1_base + src->offsets[1] + y * pitch, cur,
width);
// create 2nd
- FilterLineSpatial(dst2_base + src->offsets[p] + y * pitch,
+ FilterLineSpatial(dst2_base + src->offsets[1] + y * pitch,
cur, width, y ? -pitch : pitch,
- y + 1 < (unsigned)(src->height >> (p != 0))
- ? pitch : -pitch, 1);
+ y + 1 < (unsigned)src->height / 2 ? pitch : -pitch, 2);
+ }
+ }
+ }
+ } else { // YV12 or I420
+ for (p = 0; p < src->num_planes; ++p) {
+ pitch = src->pitches[p];
+ width = src->width >> (p != 0);
+ if (VideoSkipChromaDeinterlace[decoder->Resolution] && p) {
+ for (y = 0; y < (unsigned)(src->height >> 1); y++) {
+ const uint8_t *cur;
+
+ cur = tmp + src->offsets[p] + y * pitch;
+ // copy to 1st
+ memcpy(dst1_base + src->offsets[p] + y * pitch, cur,
+ width);
+ // copy to 2nd
+ memcpy(dst2_base + src->offsets[p] + y * pitch, cur,
+ width);
+ }
+ } else {
+ 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);
+ }
}
}
}
@@ -3592,6 +3661,27 @@ static void VaapiCpuDerive(VaapiDecoder * decoder, VASurfaceID surface)
VASurfaceID out2;
tick1 = GetMsTicks();
+#if 0
+ // get image test
+ if (decoder->Image->image_id == VA_INVALID_ID) {
+ VAImageFormat format[1];
+
+ VaapiFindImageFormat(decoder, PIX_FMT_NV12, format);
+ if (vaCreateImage(VaDisplay, format, decoder->InputWidth,
+ decoder->InputHeight, decoder->Image) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't create image!\n"));
+ }
+ }
+ if (vaGetImage(decoder->VaDisplay, surface, 0, 0, decoder->InputWidth,
+ decoder->InputHeight, decoder->Image->image_id)
+ != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't get source image\n"));
+ VaapiQueueSurface(decoder, surface, 0);
+ VaapiQueueSurface(decoder, surface, 0);
+ return;
+ }
+ *image = *decoder->Image;
+#else
if ((status =
vaDeriveImage(decoder->VaDisplay, surface,
image)) != VA_STATUS_SUCCESS) {
@@ -3600,6 +3690,7 @@ static void VaapiCpuDerive(VaapiDecoder * decoder, VASurfaceID surface)
VaapiQueueSurface(decoder, surface, 0);
return;
}
+#endif
tick2 = GetMsTicks();
Debug(4, "video/vaapi: %c%c%c%c %dx%d*%d\n", image->format.fourcc,
@@ -3629,13 +3720,22 @@ static void VaapiCpuDerive(VaapiDecoder * decoder, VASurfaceID surface)
}
tick4 = GetMsTicks();
- //VaapiBob(decoder, image, dest1, dest2);
- VaapiSpatial(decoder, image, dest1, dest2);
+ switch (VideoDeinterlace[decoder->Resolution]) {
+ case VideoDeinterlaceSoftBob:
+ default:
+ VaapiBob(decoder, image, dest1, dest2);
+ break;
+ case VideoDeinterlaceSoftSpatial:
+ VaapiSpatial(decoder, image, dest1, dest2);
+ break;
+ }
tick5 = GetMsTicks();
+#if 1
if (vaDestroyImage(VaDisplay, image->image_id) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't destroy image!\n"));
}
+#endif
if (vaDestroyImage(VaDisplay, dest1->image_id) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't destroy image!\n"));
}
@@ -3701,8 +3801,15 @@ static void VaapiCpuPut(VaapiDecoder * decoder, VASurfaceID surface)
// FIXME: handle top_field_first
- //VaapiBob(decoder, img1, img2, img3);
- VaapiSpatial(decoder, img1, img2, img3);
+ switch (VideoDeinterlace[decoder->Resolution]) {
+ case VideoDeinterlaceSoftBob:
+ default:
+ VaapiBob(decoder, img1, img2, img3);
+ break;
+ case VideoDeinterlaceSoftSpatial:
+ VaapiSpatial(decoder, img1, img2, img3);
+ break;
+ }
tick3 = GetMsTicks();
// get a free surface and upload the image
@@ -3714,7 +3821,7 @@ static void VaapiCpuPut(VaapiDecoder * decoder, VASurfaceID surface)
vaPutImage(VaDisplay, out, img2->image_id, 0, 0, img2->width,
img2->height, 0, 0, img2->width,
img2->height)) != VA_STATUS_SUCCESS) {
- Error("video/vaapi: can't put image: %d!\n", status);
+ Error(_("video/vaapi: can't put image: %d!\n"), status);
abort();
}
VaapiQueueSurface(decoder, out, 1);
@@ -3734,7 +3841,7 @@ static void VaapiCpuPut(VaapiDecoder * decoder, VASurfaceID surface)
if (vaPutImage(VaDisplay, out, img3->image_id, 0, 0, img3->width,
img3->height, 0, 0, img3->width,
img3->height) != VA_STATUS_SUCCESS) {
- Error("video/vaapi: can't put image!\n");
+ Error(_("video/vaapi: can't put image!\n"));
}
VaapiQueueSurface(decoder, out, 1);
if (0 && vaSyncSurface(decoder->VaDisplay, out) != VA_STATUS_SUCCESS) {
@@ -3843,8 +3950,8 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
Debug(4, "video/vaapi: hw render hw surface %#010x\n", surface);
if (interlaced
- && VideoDeinterlace[decoder->Resolution] ==
- VideoDeinterlaceSoftware) {
+ && VideoDeinterlace[decoder->Resolution] >=
+ VideoDeinterlaceSoftBob) {
VaapiCpuDeinterlace(decoder, surface);
} else {
VaapiQueueSurface(decoder, surface, 0);
@@ -4010,7 +4117,7 @@ static void VaapiAdvanceFrame(void)
// 0 -> 1
// 1 -> 0 + advance
- if (VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceSoftware
+ if (VideoDeinterlace[decoder->Resolution] < VideoDeinterlaceSoftBob
&& decoder->Interlaced) {
// FIXME: first frame is never shown
if (decoder->SurfaceField) {
@@ -4292,7 +4399,7 @@ static int64_t VaapiGetClock(const VaapiDecoder * decoder)
- decoder->SurfaceField);
}
return decoder->PTS - 20 * 90 * (atomic_read(&decoder->SurfacesFilled) +
- 1);
+ 2);
}
///
@@ -6609,10 +6716,12 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
surface = vrs->surface;
Debug(4, "video/vdpau: hw render hw surface %#08x\n", surface);
- if (VideoDeinterlace[decoder->Resolution] == VideoDeinterlaceSoftware
- && interlaced) {
+ if (interlaced
+ && VideoDeinterlace[decoder->Resolution] >=
+ VideoDeinterlaceSoftBob) {
// FIXME: software deinterlace avpicture_deinterlace
// FIXME: VdpauCpuDeinterlace(decoder, surface);
+ VdpauQueueSurface(decoder, surface, 0);
} else {
VdpauQueueSurface(decoder, surface, 0);
}
@@ -7247,7 +7356,7 @@ static int64_t VdpauGetClock(const VdpauDecoder * decoder)
- decoder->SurfaceField);
}
return decoder->PTS - 20 * 90 * (atomic_read(&decoder->SurfacesFilled) +
- 1);
+ 2);
}
///