mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
Software deinterlacer (config/skip chroma deint):
Add support for skip chroma deinterlace to software deinterlacer. Type of software deinterlacer now configurable from setup menu.
This commit is contained in:
parent
8c16466d31
commit
d8f63adaad
@ -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.
|
||||
|
@ -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)"),
|
||||
|
163
video.c
163
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,30 +3306,57 @@ static void VaapiSpatial(VaapiDecoder * decoder, VAImage * src, VAImage * dst1,
|
||||
y + 1 < (unsigned)src->height ? pitch : -pitch, 1);
|
||||
}
|
||||
}
|
||||
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;
|
||||
// copy to 1st
|
||||
memcpy(dst1_base + src->offsets[1] + y * pitch, cur, width);
|
||||
// copy to 2nd
|
||||
memcpy(dst2_base + src->offsets[1] + y * pitch, cur, width);
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
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,
|
||||
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);
|
||||
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,
|
||||
FilterLineSpatial(dst2_base + src->offsets[1] + y * pitch,
|
||||
cur, width, y ? -pitch : pitch,
|
||||
y + 1 < (unsigned)src->height / 2 ? pitch : -pitch, 2);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
}
|
||||
} 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;
|
||||
|
||||
@ -3298,8 +3366,8 @@ static void VaapiSpatial(VaapiDecoder * decoder, VAImage * src, VAImage * dst1,
|
||||
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,
|
||||
FilterLineSpatial(dst1_base + src->offsets[p] +
|
||||
y * pitch, cur, width, y ? -pitch : pitch,
|
||||
y + 1 < (unsigned)(src->height >> (p != 0))
|
||||
? pitch : -pitch, 1);
|
||||
} else {
|
||||
@ -3307,14 +3375,15 @@ static void VaapiSpatial(VaapiDecoder * decoder, VAImage * src, VAImage * dst1,
|
||||
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,
|
||||
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();
|
||||
@ -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);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
///
|
||||
|
Loading…
Reference in New Issue
Block a user