Use only the needed number of surfaces.

Fix problem with video-xvba and too many surfaces used.
Prepare new audio driver "oss".
This commit is contained in:
Johns 2011-12-31 18:55:07 +01:00
parent c8c760a069
commit 0d63fac2e8
4 changed files with 61 additions and 17 deletions

View File

@ -21,6 +21,7 @@ CONFIG := #-DDEBUG
#CONFIG += -DHAVE_PTHREAD_NAME #CONFIG += -DHAVE_PTHREAD_NAME
CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI") CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")
CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU") CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU")
CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA")
### The C++ compiler and options: ### The C++ compiler and options:
@ -31,14 +32,27 @@ CFLAGS ?= -g -O2 -W -Wall -Wextra -Winit-self \
-Wdeclaration-after-statement -fPIC -Wdeclaration-after-statement -fPIC
#CFLAGS += -Werror #CFLAGS += -Werror
override CFLAGS += $(DEFINES) $(INCLUDES) \ override CFLAGS += $(DEFINES) $(INCLUDES) \
$(shell pkg-config --cflags alsa libavcodec libavformat) $(shell pkg-config --cflags libavcodec libavformat) \
`pkg-config --cflags x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
`pkg-config --cflags gl glu` \
$(if $(findstring USE_VDPAU,$(CONFIG)), \
`pkg-config --cflags vdpau`) \
$(if $(findstring USE_VAAPI,$(CONFIG)), \
`pkg-config --cflags libva-x11 libva-glx libva`) \
$(if $(findstring USE_ALSA,$(CONFIG)), \
`pkg-config --cflags alsa`)
override LDFLAGS += -lrt \ override LDFLAGS += -lrt \
$(shell pkg-config --libs alsa libavcodec libavformat) \ $(shell pkg-config --libs libavcodec libavformat) \
`pkg-config --libs x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\ `pkg-config --libs x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\ xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
`pkg-config --libs gl glu` \ `pkg-config --libs gl glu` \
`pkg-config --libs vdpau` \ $(if $(findstring USE_VDPAU,$(CONFIG)), \
`pkg-config --libs libva-x11 libva-glx libva` `pkg-config --libs vdpau`) \
$(if $(findstring USE_VAAPI,$(CONFIG)), \
`pkg-config --libs libva-x11 libva-glx libva`) \
$(if $(findstring USE_ALSA,$(CONFIG)), \
`pkg-config --libs alsa`)
### The directory environment: ### The directory environment:

2
Todo
View File

@ -9,6 +9,8 @@ missing:
multistream handling multistream handling
audio out with oss/oss4 audio out with oss/oss4
HDMI/SPDIF Passthrough HDMI/SPDIF Passthrough
disable screensaver
disable window cursor
vdpau: vdpau:
1080i with temporal spatial too slow GT 520 1080i with temporal spatial too slow GT 520

View File

@ -32,6 +32,8 @@
/// ///
#define USE_AUDIO_THREAD #define USE_AUDIO_THREAD
//#define USE_ALSA ///< enable alsa support
//#define USE_OSS ///< enable oss support
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
@ -41,7 +43,9 @@
#define _(str) gettext(str) ///< gettext shortcut #define _(str) gettext(str) ///< gettext shortcut
#define _N(str) str ///< gettext_noop shortcut #define _N(str) str ///< gettext_noop shortcut
#ifdef USE_ALSA
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#endif
#ifdef USE_AUDIO_THREAD #ifdef USE_AUDIO_THREAD
#ifndef __USE_GNU #ifndef __USE_GNU

50
video.c
View File

@ -167,7 +167,11 @@ typedef enum _video_zoom_modes_
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
#define CODEC_SURFACES_MAX 31 ///< maximal of surfaces #define CODEC_SURFACES_MAX 31 ///< maximal of surfaces
#define CODEC_SURFACES_DEFAULT (21+4) ///< default of surfaces #define CODEC_SURFACES_DEFAULT (21+4) ///< default of surfaces
// FIXME: video-xvba only supports 14
#define xCODEC_SURFACES_DEFAULT 14 ///< default of surfaces
#define CODEC_SURFACES_MPEG2 3 ///< 1 decode, up to 2 references #define CODEC_SURFACES_MPEG2 3 ///< 1 decode, up to 2 references
#define CODEC_SURFACES_MPEG4 3 ///< 1 decode, up to 2 references #define CODEC_SURFACES_MPEG4 3 ///< 1 decode, up to 2 references
#define CODEC_SURFACES_H264 21 ///< 1 decode, up to 20 references #define CODEC_SURFACES_H264 21 ///< 1 decode, up to 20 references
@ -760,6 +764,7 @@ struct _vaapi_decoder_
struct vaapi_context VaapiContext[1]; ///< ffmpeg VA-API context struct vaapi_context VaapiContext[1]; ///< ffmpeg VA-API context
int SurfacesNeeded; ///< number of surface to request
int SurfaceUsedN; ///< number of used surfaces int SurfaceUsedN; ///< number of used surfaces
/// used surface ids /// used surface ids
VASurfaceID SurfacesUsed[CODEC_SURFACES_MAX]; VASurfaceID SurfacesUsed[CODEC_SURFACES_MAX];
@ -819,11 +824,16 @@ static void VaapiBlackSurface(VaapiDecoder * decoder);
/// ///
static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height) static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
{ {
#ifdef DEBUG
if (!decoder->SurfacesNeeded) {
Error(_("video/vaapi: surface needed not set\n"));
decoder->SurfacesNeeded = 3 + VIDEO_SURFACES_MAX;
}
#endif
Debug(3, "video/vaapi: %s: %dx%d * %d\n", __FUNCTION__, width, height, Debug(3, "video/vaapi: %s: %dx%d * %d\n", __FUNCTION__, width, height,
CODEC_SURFACES_DEFAULT); decoder->SurfacesNeeded);
// FIXME: allocate only the number of needed surfaces decoder->SurfaceFreeN = decoder->SurfacesNeeded;
decoder->SurfaceFreeN = CODEC_SURFACES_DEFAULT;
// VA_RT_FORMAT_YUV420 VA_RT_FORMAT_YUV422 VA_RT_FORMAT_YUV444 // VA_RT_FORMAT_YUV420 VA_RT_FORMAT_YUV422 VA_RT_FORMAT_YUV444
if (vaCreateSurfaces(decoder->VaDisplay, width, height, if (vaCreateSurfaces(decoder->VaDisplay, width, height,
VA_RT_FORMAT_YUV420, decoder->SurfaceFreeN, VA_RT_FORMAT_YUV420, decoder->SurfaceFreeN,
@ -872,7 +882,7 @@ static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
Error(_("video/vaapi: can't associate subpicture\n")); Error(_("video/vaapi: can't associate subpicture\n"));
} }
for (i = 0; i < decoder->SurfaceFreeN; ++i) { for (i = 0; i < decoder->SurfaceFreeN; ++i) {
Debug(3, "video/vaapi: associate %08x\n", Debug(4, "video/vaapi: associate %#010x surface\n",
decoder->SurfacesFree[i]); decoder->SurfacesFree[i]);
} }
} }
@ -1483,14 +1493,19 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
// check profile // check profile
switch (video_ctx->codec_id) { switch (video_ctx->codec_id) {
case CODEC_ID_MPEG2VIDEO: case CODEC_ID_MPEG2VIDEO:
decoder->SurfacesNeeded =
CODEC_SURFACES_MPEG2 + VIDEO_SURFACES_MAX;
p = VaapiFindProfile(profiles, profile_n, VAProfileMPEG2Main); p = VaapiFindProfile(profiles, profile_n, VAProfileMPEG2Main);
break; break;
case CODEC_ID_MPEG4: case CODEC_ID_MPEG4:
case CODEC_ID_H263: case CODEC_ID_H263:
decoder->SurfacesNeeded =
CODEC_SURFACES_MPEG4 + VIDEO_SURFACES_MAX;
p = VaapiFindProfile(profiles, profile_n, p = VaapiFindProfile(profiles, profile_n,
VAProfileMPEG4AdvancedSimple); VAProfileMPEG4AdvancedSimple);
break; break;
case CODEC_ID_H264: case CODEC_ID_H264:
decoder->SurfacesNeeded = CODEC_SURFACES_H264 + VIDEO_SURFACES_MAX;
// try more simple formats, fallback to better // try more simple formats, fallback to better
if (video_ctx->profile == FF_PROFILE_H264_BASELINE) { if (video_ctx->profile == FF_PROFILE_H264_BASELINE) {
p = VaapiFindProfile(profiles, profile_n, p = VaapiFindProfile(profiles, profile_n,
@ -1507,9 +1522,11 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
} }
break; break;
case CODEC_ID_WMV3: case CODEC_ID_WMV3:
decoder->SurfacesNeeded = CODEC_SURFACES_VC1 + VIDEO_SURFACES_MAX;
p = VaapiFindProfile(profiles, profile_n, VAProfileVC1Main); p = VaapiFindProfile(profiles, profile_n, VAProfileVC1Main);
break; break;
case CODEC_ID_VC1: case CODEC_ID_VC1:
decoder->SurfacesNeeded = CODEC_SURFACES_VC1 + VIDEO_SURFACES_MAX;
p = VaapiFindProfile(profiles, profile_n, VAProfileVC1Advanced); p = VaapiFindProfile(profiles, profile_n, VAProfileVC1Advanced);
break; break;
default: default:
@ -1624,6 +1641,7 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
slow_path: slow_path:
// no accelerated format found // no accelerated format found
decoder->SurfacesNeeded = 1 + VIDEO_SURFACES_MAX;
video_ctx->hwaccel_context = NULL; video_ctx->hwaccel_context = NULL;
return avcodec_default_get_format(video_ctx, fmt); return avcodec_default_get_format(video_ctx, fmt);
} }
@ -2035,7 +2053,7 @@ static void VaapiQueueSurface(VaapiDecoder * decoder, VASurfaceID surface,
% VIDEO_SURFACES_MAX; % VIDEO_SURFACES_MAX;
atomic_inc(&decoder->SurfacesFilled); atomic_inc(&decoder->SurfacesFilled);
Debug(4, "video/vaapi: yy video surface %#x ready\n", surface); Debug(4, "video/vaapi: yy video surface %#010x ready\n", surface);
} }
#if 0 #if 0
@ -2103,7 +2121,7 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
start = GetMsTicks(); start = GetMsTicks();
} }
Debug(4, "video/vaapi: yy black video surface %#x displayed\n", Debug(4, "video/vaapi: yy black video surface %#010x displayed\n",
decoder->BlackSurface); decoder->BlackSurface);
sync = GetMsTicks(); sync = GetMsTicks();
xcb_flush(Connection); xcb_flush(Connection);
@ -2243,7 +2261,7 @@ static void VaapiCpuDeinterlace(VaapiDecoder * decoder, VASurfaceID surface)
vaPutImage(decoder->VaDisplay, surface, image->image_id, 0, 0, vaPutImage(decoder->VaDisplay, surface, image->image_id, 0, 0,
image->width, image->height, 0, 0, image->width, image->width, image->height, 0, 0, image->width,
image->height)) != VA_STATUS_SUCCESS) { image->height)) != VA_STATUS_SUCCESS) {
Fatal("video/vaapi: can't put image %d!\n", status); Error("video/vaapi: can't put image %d!\n", status);
} }
} }
@ -2301,7 +2319,7 @@ static void VaapiCpuDeinterlace(VaapiDecoder * decoder, VASurfaceID surface)
if (vaPutImage(VaDisplay, out1, img2->image_id, 0, 0, img2->width, if (vaPutImage(VaDisplay, out1, img2->image_id, 0, 0, img2->width,
img2->height, 0, 0, img2->width, img2->height, 0, 0, img2->width,
img2->height) != VA_STATUS_SUCCESS) { img2->height) != VA_STATUS_SUCCESS) {
Fatal("video/vaapi: can't put image!\n"); Error("video/vaapi: can't put image!\n");
} }
VaapiQueueSurface(decoder, out1, 1); VaapiQueueSurface(decoder, out1, 1);
if (0 && vaSyncSurface(decoder->VaDisplay, out1) != VA_STATUS_SUCCESS) { if (0 && vaSyncSurface(decoder->VaDisplay, out1) != VA_STATUS_SUCCESS) {
@ -2312,7 +2330,7 @@ static void VaapiCpuDeinterlace(VaapiDecoder * decoder, VASurfaceID surface)
if (vaPutImage(VaDisplay, out2, img3->image_id, 0, 0, img3->width, if (vaPutImage(VaDisplay, out2, img3->image_id, 0, 0, img3->width,
img3->height, 0, 0, img3->width, img3->height, 0, 0, img3->width,
img3->height) != VA_STATUS_SUCCESS) { img3->height) != VA_STATUS_SUCCESS) {
Fatal("video/vaapi: can't put image!\n"); Error("video/vaapi: can't put image!\n");
} }
VaapiQueueSurface(decoder, out2, 1); VaapiQueueSurface(decoder, out2, 1);
if (0 && vaSyncSurface(decoder->VaDisplay, out2) != VA_STATUS_SUCCESS) { if (0 && vaSyncSurface(decoder->VaDisplay, out2) != VA_STATUS_SUCCESS) {
@ -2433,6 +2451,9 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
VaapiSetup(decoder, video_ctx); VaapiSetup(decoder, video_ctx);
// FIXME: bad interlace like hw-part
// FIXME: aspect ratio
// //
// detect interlaced input // detect interlaced input
// //
@ -2451,7 +2472,7 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
// //
if (vaMapBuffer(VaDisplay, decoder->Image->buf, &va_image_data) if (vaMapBuffer(VaDisplay, decoder->Image->buf, &va_image_data)
!= VA_STATUS_SUCCESS) { != VA_STATUS_SUCCESS) {
Fatal("video/vaapi: can't map the image!\n"); Error(_("video/vaapi: can't map the image!\n"));
} }
for (i = 0; (unsigned)i < decoder->Image->num_planes; ++i) { for (i = 0; (unsigned)i < decoder->Image->num_planes; ++i) {
picture->data[i] = va_image_data + decoder->Image->offsets[i]; picture->data[i] = va_image_data + decoder->Image->offsets[i];
@ -2462,16 +2483,19 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
width, height); width, height);
if (vaUnmapBuffer(VaDisplay, decoder->Image->buf) != VA_STATUS_SUCCESS) { if (vaUnmapBuffer(VaDisplay, decoder->Image->buf) != VA_STATUS_SUCCESS) {
Fatal("video/vaapi: can't unmap the image!\n"); Error(_("video/vaapi: can't unmap the image!\n"));
} }
// get a free surface and upload the image // get a free surface and upload the image
surface = VaapiGetSurface(decoder); surface = VaapiGetSurface(decoder);
Debug(4, "video/vaapi: video surface %#010x displayed\n", surface);
Debug(4, "video/vaapi: buffer %dx%d <- %dx%d\n", decoder->Image->width,
decoder->Image->height, width, height);
// FIXME: intel didn't support put image. // FIXME: intel didn't support put image.
if ((i = vaPutImage(VaDisplay, surface, decoder->Image->image_id, 0, 0, if ((i = vaPutImage(VaDisplay, surface, decoder->Image->image_id, 0, 0,
width, height, 0, 0, width, height) width, height, 0, 0, width, height)
) != VA_STATUS_SUCCESS) { ) != VA_STATUS_SUCCESS) {
Fatal("video/vaapi: can't put image %d!\n", i); Error(_("video/vaapi: can't put image err:%d!\n"), i);
} }
VaapiQueueSurface(decoder, surface, 1); VaapiQueueSurface(decoder, surface, 1);
@ -2563,7 +2587,7 @@ static void VaapiDisplayFrame(void)
if (surface == VA_INVALID_ID) { if (surface == VA_INVALID_ID) {
printf(_("video/vaapi: invalid surface in ringbuffer\n")); printf(_("video/vaapi: invalid surface in ringbuffer\n"));
} }
Debug(4, "video/vaapi: yy video surface %#x displayed\n", surface); Debug(4, "video/vaapi: yy video surface %#010x displayed\n", surface);
#endif #endif
start = GetMsTicks(); start = GetMsTicks();