From 5603ab424468b9746394b6d902107d8d1920e2ae Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 29 Nov 2008 16:51:15 +0000 Subject: Adding vo_vdpau. --- configure.ac | 17 + src/video_out/Makefile.am | 9 + src/video_out/video_out_vdpau.c | 743 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 769 insertions(+) create mode 100644 src/video_out/video_out_vdpau.c diff --git a/configure.ac b/configure.ac index d334f93c1..5c876eae8 100644 --- a/configure.ac +++ b/configure.ac @@ -863,6 +863,20 @@ AM_CONDITIONAL(HAVE_XVMC, test "x$ac_have_xvmc" = "xyes") AC_SUBST(XVMC_LIBS) +dnl --------------------------------------------- +dnl Check for VDPAU +dnl --------------------------------------------- +AC_ARG_WITH([vdpau], AS_HELP_STRING([--without-vdpau], [Doesn't build VDPAU plugins])) +if test "x$with_vdpau" != "xno"; then + AC_CHECK_HEADERS([vdpau/vdpau_x11.h], [have_vdpau=yes], [have_vdpau=no]) + if test "x$have_vdpau" = "xyes"; then + AC_CHECK_LIB(vdpau, vdp_device_create_x11, have_vdpau="yes", [have_vdpau="no"], [$X_LIBS $X_PRE_LIBS -lXext $X_EXTRA_LIBS]) + fi +fi + +AM_CONDITIONAL(HAVE_VDPAU, test "x$have_vdpau" = "xyes" ) + + dnl --------------------------------------------- dnl Check for xcb dnl --------------------------------------------- @@ -3066,6 +3080,9 @@ if test "x$have_xcb" = "xyes"; then echo " - xcb-xv (XVideo using XCB)" fi fi +if test "x$have_vdpau" = "xyes"; then + echo " - vdpau (X11 VDPAU)" +fi if test "x$no_aalib" != "xyes"; then echo " - aa (Ascii ART)" fi diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index 80dd1e92c..8d8753659 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -36,6 +36,10 @@ endif endif endif +if HAVE_VDPAU +vdpau_module = xineplug_vo_out_vdpau.la +endif + if HAVE_XCB XCBOSD = xcbosd.c if HAVE_XCBSHM @@ -100,9 +104,14 @@ xineplug_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) \ $(xxmc_module) \ $(xcbshm_module) \ $(xcbxv_module) \ + $(vdpau_module) \ xineplug_vo_out_raw.la \ xineplug_vo_out_none.la +xineplug_vo_out_vdpau_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_vdpau.c +xineplug_vo_out_vdpau_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(PTHREAD_LIBS) $(X_LIBS) $(LTLIBINTL) -lvdpau +xineplug_vo_out_vdpau_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(X_CFLAGS) + xineplug_vo_out_xcbshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_xcbshm.c $(XCBOSD) xineplug_vo_out_xcbshm_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(PTHREAD_LIBS) $(XCB_LIBS) $(XCBSHM_LIBS) $(LTLIBINTL) xineplug_vo_out_xcbshm_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(XCB_CFLAGS) $(XCBSHM_CFLAGS) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c new file mode 100644 index 000000000..ccda264bd --- /dev/null +++ b/src/video_out/video_out_vdpau.c @@ -0,0 +1,743 @@ +/* + * Copyright (C) 2008 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * + * video_out_vdpau.c, a video output plugin using VDPAU (Video Decode and Presentation Api for Unix) + * + * Christophe Thommeret + * + */ + +/* #define LOG */ +#define LOG_MODULE "video_out_vdpau" + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xine.h" +#include "video_out.h" +#include "vo_scale.h" +#include "xine_internal.h" +#include "yuv2rgb.h" +#include "xineutils.h" + +#include + + + +VdpDevice vdp_device; +VdpPresentationQueue vdp_queue; +VdpPresentationQueueTarget vdp_queue_target; + +VdpGetProcAddress *vdp_get_proc_address; + +VdpGetApiVersion *vdp_get_api_version; +VdpGetInformationString *vdp_get_information_string; +VdpGetErrorString *vdp_get_error_string; + +VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_get_put_bits_ycbcr_capabilities; +VdpVideoSurfaceCreate *vdp_video_surface_create; +VdpVideoSurfaceDestroy *vdp_video_surface_destroy; +VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_putbits_ycbcr; + +VdpOutputSurfaceCreate *vdp_output_surface_create; +VdpOutputSurfaceDestroy *vdp_output_surface_destroy; + +VdpVideoMixerCreate *vdp_video_mixer_create; +VdpVideoMixerDestroy *vdp_video_mixer_destroy; +VdpVideoMixerRender *vdp_video_mixer_render; + +VdpPresentationQueueTargetCreateX11 *vdp_queue_target_create_x11; +VdpPresentationQueueTargetDestroy *vdp_queue_target_destroy; +VdpPresentationQueueCreate *vdp_queue_create; +VdpPresentationQueueDestroy *vdp_queue_destroy; +VdpPresentationQueueDisplay *vdp_queue_display; +VdpPresentationQueueSetBackgroundColor *vdp_queue_set_backgroung_color; + + +typedef struct { + vo_frame_t vo_frame; + + int width, height, format, flags; + double ratio; + uint8_t *chunk[3]; /* mem alloc by xmalloc_aligned */ +} vdpau_frame_t; + + +typedef struct { + vo_driver_t vo_driver; + vo_scale_t sc; + + Display *display; + int screen; + Drawable drawable; + + config_values_t *config; + + int ovl_changed; + raw_overlay_t overlay; + yuv2rgb_t *ovl_yuv2rgb; + + VdpVideoSurface soft_surface; + uint32_t soft_surface_width; + uint32_t soft_surface_height; + int soft_surface_format; + + VdpOutputSurface output_surface; + + VdpVideoMixer video_mixer; + + xine_t *xine; +} vdpau_driver_t; + + +typedef struct { + video_driver_class_t driver_class; + xine_t *xine; +} vdpau_class_t; + + + +static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *overlay, vdpau_frame_t *frame) +{ + int i; + clut_t* clut = (clut_t*) overlay->color; + + if (!overlay->rgb_clut) { + for ( i=0; icolor)/sizeof(overlay->color[0]); i++ ) { + *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); + } + overlay->rgb_clut++; + } + if (!overlay->hili_rgb_clut) { + clut = (clut_t*) overlay->hili_color; + for ( i=0; icolor)/sizeof(overlay->color[0]); i++) { + *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); + } + overlay->hili_rgb_clut++; + } +} + + +static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) +{ + raw_overlay_t *ovl = &this_gen->overlay; + + if ( overlay->width<=0 || overlay->height<=0 ) + return 0; + + if ( (overlay->width*overlay->height)!=(ovl->ovl_w*ovl->ovl_h) ) + ovl->ovl_rgba = (uint8_t*)realloc( ovl->ovl_rgba, overlay->width*overlay->height*4 ); + ovl->ovl_w = overlay->width; + ovl->ovl_h = overlay->height; + ovl->ovl_x = overlay->x; + ovl->ovl_y = overlay->y; + + int num_rle = overlay->num_rle; + rle_elem_t *rle = overlay->rle; + uint8_t *rgba = ovl->ovl_rgba; + clut_t *low_colors = (clut_t*)overlay->color; + clut_t *hili_colors = (clut_t*)overlay->hili_color; + uint8_t *low_trans = overlay->trans; + uint8_t *hili_trans = overlay->hili_trans; + clut_t *colors; + uint8_t *trans; + uint8_t alpha; + int rlelen = 0; + uint8_t clr = 0; + int i, pos=0, x, y; + + while ( num_rle>0 ) { + x = pos%ovl->ovl_w; + y = pos/ovl->ovl_w; + if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) { + colors = hili_colors; + trans = hili_trans; + } + else { + colors = low_colors; + trans = low_trans; + } + rlelen = rle->len; + clr = rle->color; + alpha = trans[clr]; + for ( i=0; iovl_changed;*/ +} + + +static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) +{ + /*vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; + + if ( !this->ovl_changed ) + return; + + if (overlay->rle) { + if (!overlay->rgb_clut || !overlay->hili_rgb_clut) + vdpau_overlay_clut_yuv2rgb (this, overlay, frame); + if ( vdpau_process_ovl( this, overlay ) ) + ++this->ovl_changed; + }*/ +} + + +static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) +{ + /*vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + if ( !this->ovl_changed ) + return; + + this->raw_overlay_cb( this->user_data, this->ovl_changed-1, this->overlays ); + + this->ovl_changed = 0;*/ +} + + +static void vdpau_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) +{ + vdpau_frame_t *frame = (vdpau_frame_t *) vo_img ; + + vo_img->proc_called = 1; + + if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || + frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) + { + /* TODO: ?!? */ + return; + } +} + + + +static void vdpau_frame_field (vo_frame_t *vo_img, int which_field) +{ +} + + + +static void vdpau_frame_dispose (vo_frame_t *vo_img) +{ + vdpau_frame_t *frame = (vdpau_frame_t *) vo_img ; + + free (frame->chunk[0]); + free (frame->chunk[1]); + free (frame->chunk[2]); + free (frame); +} + + + +static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) +{ + vdpau_frame_t *frame; + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + frame = (vdpau_frame_t *) calloc(1, sizeof(vdpau_frame_t)); + + if (!frame) + return NULL; + + pthread_mutex_init (&frame->vo_frame.mutex, NULL); + + /* + * supply required functions/fields + */ + frame->vo_frame.proc_slice = vdpau_frame_proc_slice; + frame->vo_frame.proc_frame = NULL; + frame->vo_frame.field = vdpau_frame_field; + frame->vo_frame.dispose = vdpau_frame_dispose; + frame->vo_frame.driver = this_gen; + + frame->width = frame->height = 0; + + return (vo_frame_t *) frame; +} + + + +static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, + uint32_t width, uint32_t height, double ratio, int format, int flags) +{ + vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; + + /* Check frame size and format and reallocate if necessary */ + if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->flags != flags)) { + /*lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */ + + /* (re-) allocate render space */ + free (frame->chunk[0]); + free (frame->chunk[1]); + free (frame->chunk[2]); + + if (format == XINE_IMGFMT_YV12) { + frame->vo_frame.pitches[0] = 8*((width + 7) / 8); + frame->vo_frame.pitches[1] = 8*((width + 15) / 16); + frame->vo_frame.pitches[2] = 8*((width + 15) / 16); + frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); + frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]); + frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]); + } else { + frame->vo_frame.pitches[0] = 8*((width + 3) / 4); + frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); + frame->chunk[1] = NULL; + frame->chunk[2] = NULL; + } + + frame->width = width; + frame->height = height; + frame->format = format; + + vdpau_frame_field ((vo_frame_t *)frame, flags); + } + + frame->ratio = ratio; +} + + + +static int vdpau_redraw_needed (vo_driver_t *this_gen) +{ + return 0; +} + + + +static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; + VdpStatus st; + + if ( frame->width != this->soft_surface_width || frame->height != this->soft_surface_height || frame->format != this->soft_surface_format ) { + /* recreate the surface to match frame changes */ + vdp_video_surface_destroy( this->soft_surface ); + VdpChromaType chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; + vdp_video_surface_create( vdp_device, chroma, frame->width, frame->height, &this->soft_surface ); + this->soft_surface_format = frame->format; + this->soft_surface_width = frame->width; + this->soft_surface_height = frame->height; + printf( "vo_vdpau: soft_surface redim\n" ); + + /* recreate video mixer to match video surface */ + vdp_video_mixer_destroy( this->video_mixer ); + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE }; + void const *param_values[] = { &this->soft_surface_width, &this->soft_surface_height, &chroma }; + st = vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); + } + + /* FIXME: have to swap U and V planes to get correct colors !! nvidia ? */ + uint32_t pitches[] = { frame->vo_frame.pitches[0], frame->vo_frame.pitches[2], frame->vo_frame.pitches[1] }; + void* data[] = { frame->vo_frame.base[0], frame->vo_frame.base[2], frame->vo_frame.base[1] }; + if ( frame->format==XINE_IMGFMT_YV12 ) { + st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YV12, &data, &pitches ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YV12 error : %s\n", vdp_get_error_string( st ) ); + } + else if ( frame->format==XINE_IMGFMT_YUY2 ){ + st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YUYV, &data, &pitches ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YUY2 error : %s\n", vdp_get_error_string( st ) ); + } + + VdpRect rect; + rect.x0 = 0; + rect.y0 = 0; + rect.x1 = 800; + rect.y1 = 600; + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, 0, 0, this->soft_surface, 0, 0, 0, this->output_surface, &rect, &rect, 0, 0 ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + + XLockDisplay( this->display ); + vdp_queue_display( vdp_queue, this->output_surface, 0, 0, 0 ) ; + XUnlockDisplay( this->display ); + + frame->vo_frame.free( &frame->vo_frame ); +} + + + +static int vdpau_get_property (vo_driver_t *this_gen, int property) +{ + switch (property) { + case VO_PROP_ASPECT_RATIO: + return XINE_VO_ASPECT_AUTO; + case VO_PROP_MAX_NUM_FRAMES: + return 15; + case VO_PROP_BRIGHTNESS: + return 0; + case VO_PROP_CONTRAST: + return 128; + case VO_PROP_SATURATION: + return 128; + case VO_PROP_WINDOW_WIDTH: + return 0; + case VO_PROP_WINDOW_HEIGHT: + return 0; + default: + return 0; + } +} + + + +static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) +{ + return value; +} + + + +static void vdpau_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) +{ + *min = 0; + *max = 0; +} + + + +static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) +{ + return 0; +} + + + +static uint32_t vdpau_get_capabilities (vo_driver_t *this_gen) +{ + uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP; + return capabilities; +} + + + +static void vdpau_dispose (vo_driver_t *this_gen) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + int i; + + free( this->overlay.ovl_rgba ); + + free (this); +} + + + +static int vdpau_init_error( VdpStatus st, const char *msg, vo_driver_t *driver, int error_string ) +{ + if ( st != VDP_STATUS_OK ) { + if ( error_string ) + printf( "vo_vdpau: %s : %s\n", msg, vdp_get_error_string( st ) ); + else + printf( "vo_vdpau: %s\n", msg ); + vdpau_dispose( driver ); + return 1; + } + return 0; +} + + + +static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) +{ + vdpau_class_t *class = (vdpau_class_t *) class_gen; + x11_visual_t *visual = (x11_visual_t *) visual_gen; + vdpau_driver_t *this; + config_values_t *config = class->xine->config; + int i; + + this = (vdpau_driver_t *) calloc(1, sizeof(vdpau_driver_t)); + + if (!this) + return NULL; + + this->display = visual->display; + this->screen = visual->screen; + this->drawable = visual->d; + + _x_vo_scale_init (&this->sc, 0, 0, config); + this->sc.frame_output_cb = visual->frame_output_cb; + this->sc.dest_size_cb = visual->dest_size_cb; + this->sc.user_data = visual->user_data; + this->sc.user_ratio = XINE_VO_ASPECT_AUTO; + + this->ovl_changed = 0; + this->xine = class->xine; + this->config = config; + + this->vo_driver.get_capabilities = vdpau_get_capabilities; + this->vo_driver.alloc_frame = vdpau_alloc_frame; + this->vo_driver.update_frame_format = vdpau_update_frame_format; + this->vo_driver.overlay_begin = vdpau_overlay_begin; + this->vo_driver.overlay_blend = vdpau_overlay_blend; + this->vo_driver.overlay_end = vdpau_overlay_end; + this->vo_driver.display_frame = vdpau_display_frame; + this->vo_driver.get_property = vdpau_get_property; + this->vo_driver.set_property = vdpau_set_property; + this->vo_driver.get_property_min_max = vdpau_get_property_min_max; + this->vo_driver.gui_data_exchange = vdpau_gui_data_exchange; + this->vo_driver.dispose = vdpau_dispose; + this->vo_driver.redraw_needed = vdpau_redraw_needed; + + this->overlay.ovl_w = this->overlay.ovl_h = 2; + this->overlay.ovl_rgba = (uint8_t*)malloc(2*2*4); + this->overlay.ovl_x = this->overlay.ovl_y = 0; + + /* overlay converter */ + yuv2rgb_factory_t *factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); + this->ovl_yuv2rgb = factory->create_converter( factory ); + factory->dispose( factory ); + + VdpStatus st = vdp_device_create_x11( visual->display, visual->screen, &vdp_device, &vdp_get_proc_address ); + if ( st != VDP_STATUS_OK ) { + printf( "vo_vdpau: Can't create vdp device : " ); + if ( st == VDP_STATUS_NO_IMPLEMENTATION ) + printf( "No vdpau implementation.\n" ); + else + printf( "unsupported GPU?\n" ); + vdpau_dispose( &this->vo_driver ); + return NULL; + } + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GET_ERROR_STRING , (void*)&vdp_get_error_string ); + if ( vdpau_init_error( st, "Can't get GET_ERROR_STRING proc address !!", &this->vo_driver, 0 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GET_API_VERSION , (void*)&vdp_get_api_version ); + if ( vdpau_init_error( st, "Can't get GET_API_VERSION proc address !!", &this->vo_driver, 1 ) ) + return NULL; + uint32_t tmp; + vdp_get_api_version( &tmp ); + printf( "vo_vdpau: vdpau API version : %d\n", tmp ); + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GET_INFORMATION_STRING , (void*)&vdp_get_information_string ); + if ( vdpau_init_error( st, "Can't get GET_INFORMATION_STRING proc address !!", &this->vo_driver, 1 ) ) + return NULL; + const char *s; + st = vdp_get_information_string( &s ); + printf( "vo_vdpau: vdpau implementation description : %s\n", s ); + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES , (void*)&vdp_video_surface_query_get_put_bits_ycbcr_capabilities ); + if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + VdpBool ok; + st = vdp_video_surface_query_get_put_bits_ycbcr_capabilities( vdp_device, VDP_CHROMA_TYPE_422, VDP_YCBCR_FORMAT_YUYV, &ok ); + if ( vdpau_init_error( st, "Failed to check vdpau yuy2 capability", &this->vo_driver, 1 ) ) + return NULL; + if ( !ok ) { + printf( "vo_vdpau: VideoSurface doesn't support yuy2, sorry.\n"); + vdpau_dispose( &this->vo_driver ); + return NULL; + } + + st = vdp_video_surface_query_get_put_bits_ycbcr_capabilities( vdp_device, VDP_CHROMA_TYPE_420, VDP_YCBCR_FORMAT_YV12, &ok ); + if ( vdpau_init_error( st, "Failed to check vdpau yv12 capability", &this->vo_driver, 1 ) ) + return NULL; + if ( !ok ) { + printf( "vo_vdpau: VideoSurface doesn't support yv12, sorry.\n"); + vdpau_dispose( &this->vo_driver ); + return NULL; + } + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_CREATE , (void*)&vdp_video_surface_create ); + if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , (void*)&vdp_video_surface_destroy ); + if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , (void*)&vdp_video_surface_putbits_ycbcr ); + if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_PUT_BITS_Y_CB_CR proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , (void*)&vdp_output_surface_create ); + if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , (void*)&vdp_output_surface_destroy ); + if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_CREATE , (void*)&vdp_video_mixer_create ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_CREATE proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_DESTROY , (void*)&vdp_video_mixer_destroy ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_DESTROY proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_RENDER , (void*)&vdp_video_mixer_render ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_RENDER proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 , (void*)&vdp_queue_target_create_x11 ); + if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_TARGET_CREATE_X11 proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY , (void*)&vdp_queue_target_destroy ); + if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_TARGET_DESTROY proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE , (void*)&vdp_queue_create ); + if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_CREATE proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY , (void*)&vdp_queue_destroy ); + if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_DESTROY proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY , (void*)&vdp_queue_display ); + if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_DISPLAY proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR , (void*)&vdp_queue_set_backgroung_color ); + if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_SET_BACKGROUND_COLOR proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); + if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); + if ( vdpau_init_error( st, "Can't create presentation queue !!", &this->vo_driver, 1 ) ) + return NULL; + + VdpColor backColor; + backColor.red = backColor.green = backColor.blue = 0; + backColor.alpha = 1; + vdp_queue_set_backgroung_color( vdp_queue, &backColor ); + + this->soft_surface_width = 800; + this->soft_surface_height = 600; + this->soft_surface_format = XINE_IMGFMT_YV12; + st = vdp_video_surface_create( vdp_device, VDP_CHROMA_TYPE_420, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); + if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, 800, 600, &this->output_surface ); + if ( vdpau_init_error( st, "Can't create output surface !!", &this->vo_driver, 1 ) ) { + vdp_video_surface_destroy( this->soft_surface ); + return NULL; + } + + VdpChromaType chroma = VDP_CHROMA_TYPE_420; + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE }; + void const *param_values[] = { &this->soft_surface_width, &this->soft_surface_height, &chroma }; + st = vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); + if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { + vdp_video_surface_destroy( this->soft_surface ); + vdp_output_surface_destroy( this->output_surface ); + return NULL; + } + + return &this->vo_driver; +} + +/* + * class functions + */ + +static char* vdpau_get_identifier (video_driver_class_t *this_gen) +{ + return "vdpau"; +} + + + +static char* vdpau_get_description (video_driver_class_t *this_gen) +{ + return _("xine video output plugin using VDPAU hardware acceleration"); +} + + + +static void vdpau_dispose_class (video_driver_class_t *this_gen) +{ + vdpau_class_t *this = (vdpau_class_t *) this_gen; + free (this); +} + + + +static void *vdpau_init_class (xine_t *xine, void *visual_gen) +{ + vdpau_class_t *this = (vdpau_class_t *) calloc(1, sizeof(vdpau_class_t)); + + this->driver_class.open_plugin = vdpau_open_plugin; + this->driver_class.get_identifier = vdpau_get_identifier; + this->driver_class.get_description = vdpau_get_description; + this->driver_class.dispose = vdpau_dispose_class; + this->xine = xine; + + return this; +} + + + +static const vo_info_t vo_info_vdpau = { + 11, /* priority */ + XINE_VISUAL_TYPE_X11 /* visual type */ +}; + + +/* + * exported plugin catalog entry + */ + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_VIDEO_OUT, 21, "vdpau", XINE_VERSION_CODE, &vo_info_vdpau, vdpau_init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; \ No newline at end of file -- cgit v1.2.3 From f785e0e89ec8a616561f54b442bc6400141c55b3 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 29 Nov 2008 19:54:48 +0000 Subject: Initial nal parser code for grabbing the data for VdpPictureInfoH264. --- src/libxinevdec/nal_parser.c | 652 +++++++++++++++++++++++++++++++++++++++++++ src/libxinevdec/nal_parser.h | 215 ++++++++++++++ 2 files changed, 867 insertions(+) create mode 100644 src/libxinevdec/nal_parser.c create mode 100644 src/libxinevdec/nal_parser.h diff --git a/src/libxinevdec/nal_parser.c b/src/libxinevdec/nal_parser.c new file mode 100644 index 000000000..916595cad --- /dev/null +++ b/src/libxinevdec/nal_parser.c @@ -0,0 +1,652 @@ +#include +#include +#include + +#include "nal_parser.h" + +struct buf_reader { + uint8_t *buf; + uint8_t *cur_pos; + int len; + int cur_offset; +}; + +static inline uint32_t read_bits(struct buf_reader *buf, int len); +uint32_t read_exp_golomb(struct buf_reader *buf); +int32_t read_exp_golomb_s(struct buf_reader *buf); +void skip_scaling_list(struct buf_reader *buf, int size); +int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal); +uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps); +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal); + + +static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) +{ + uint8_t *end = &buf[buf_len]; + uint8_t *pos = malloc(buf_len); + + *ret = pos; + while(buf < end) { + if(buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 && + buf[2] == 0x03) { + + *pos++ = 0x00; + *pos++ = 0x00; + + buf += 3; + continue; + } + *pos++ = *buf++; + } + + *len_ret = pos - *ret; +} + +/*uint32_t read_bits(struct buf_reader *buf, int len) +{ + uint32_t bits = 0x00; + int i, j; + for(i=0, j=0; icur_offset >= 8) { + buf->cur_pos++; + buf->cur_offset -= 8; + } + uint8_t bit = (*buf->cur_pos >> (7 - buf->cur_offset)) & 0x01; + bits |= ((uint32_t)bit) << i; + buf->cur_offset++; + } +printf("ret: 0x%08x\n", bits); + return bits; +}*/ + +static inline uint32_t read_bits (struct buf_reader *buf, int len) +{ + static uint32_t i_mask[33] = + { 0x00, + 0x01, 0x03, 0x07, 0x0f, + 0x1f, 0x3f, 0x7f, 0xff, + 0x1ff, 0x3ff, 0x7ff, 0xfff, + 0x1fff, 0x3fff, 0x7fff, 0xffff, + 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, + 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, + 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, + 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff}; + + int i_shr; + uint32_t bits = 0; + + while(len > 0 && (buf->cur_pos - buf->buf) < buf->len) { + if((i_shr = buf->cur_offset-len) >= 0) { + bits |= (*buf->cur_pos >> i_shr)&i_mask[len]; + buf->cur_offset -= len; + if(buf->cur_offset == 0) { + buf->cur_pos++; + buf->cur_offset = 8; + } + return bits; + } else { + bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; + len -= buf->cur_offset; + buf->cur_pos++; + buf->cur_offset = 8; + } + } + return bits; +} + +/* determines if following bits are rtsb_trailing_bits */ +static inline uint8_t rbsp_trailing_bits(struct buf_reader *buf) +{ + // store the offset and pos in buffer + // to revert this afterwards. + int last_offset; + uint8_t *last_pos; + + uint8_t rbsp_trailing_bits = 1; + + offset = buf->cur_offset; + pos = buf->cur_pos; + + if(read_bits(buf, 1) == 1) + { + while(buf->cur_offset != 8) + if(read_bits(buf, 1) == 1) + rbsp_trailing_bits = 0; + } + + // revert buffer + buf->cur_offset = offset; + buf->cur_pos = pos; + + return rbsp_trailing_bits; +} + +uint32_t read_exp_golomb(struct buf_reader *buf) +{ + int leading_zero_bits = 0; + + while(read_bits(buf, 1) == 0 && leading_zero_bits < 32) + leading_zero_bits++; + + uint32_t code = (1<len < 1) + return -1; + int ret = -1; + + nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; + nal->nal_unit_type = buf->buf[0] & 0x1f; + + buf->cur_pos = buf->buf + 1; + //printf("NAL: %d\n", nal->nal_unit_type); + + struct buf_reader ibuf; + ibuf.cur_offset = 8; + + switch(nal->nal_unit_type) { + case NAL_SPS: + decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len-1); + ibuf.cur_pos = ibuf.buf; + if(!nal->sps) + nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + else + memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); + + parse_sps(&ibuf, nal->sps); + free(ibuf.buf); + ret = NAL_SPS; + break; + case NAL_PPS: + if(!nal->pps) + nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + else + memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); + + parse_pps(buf, nal->pps); + ret = NAL_PPS; + break; + case NAL_SLICE: + case NAL_PART_A: + case NAL_PART_B: + case NAL_PART_C: + case NAL_SLICE_IDR: + if(nal->sps && nal->pps) { + if(!nal->slc) + nal->slc = malloc(sizeof(struct slice_header)); + else + memset(nal->slc, 0x00, sizeof(struct slice_header)); + + parse_slice_header(buf, nal); + ret = nal->nal_unit_type; + } + break; + default: + ret = nal->nal_unit_type; + break; + } + + return ret; +} + +void skip_scaling_list(struct buf_reader *buf, int size) +{ + int i; + for(i = 0; i < size; i++) { + read_exp_golomb_s(buf); + } +} + +void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index) +{ + int last_scale = 8; + int next_scale = 8; + int32_t delta_scale; + uint8_t use_default_scaling_matrix_flag = 0; + int i; + + for(i = 0; i < length; i++) { + if(next_scale != 0) { + delta_scale = read_exp_golomb_s(buf); + next_scale = (last_scale + delta_scale + 256) % 256; + if(i == 0 && next_scale == 0) { + use_default_scaling_matrix_flag = 1; + break; + } + } + scaling_list = (next_scale == 0) ? last_scale : next_scale; + last_scale = scaling_list->scaling_list[i]; + } + + if(use_default_scaling_matrix_flag) { + switch(index) { + case 0: + case 1: + case 2: + memcpy(scaling_list, length, default_4x4_intra); + break; + case 3: + case 4: + case 5: + memcpy(scaling_list, length, default_4x4_inter); + break; + case 6: + memcpy(scaling_list, length, default_8x8_intra); + break; + case 7: + memcpy(scaling_list, length, default_8x8_inter); + break; + } + } +} + +uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) +{ + sps->profile_idc = buf->buf[0]; + sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; + sps->level_idc = buf->buf[2]; + + buf->cur_pos = buf->buf+3; + sps->seq_parameter_set_id = read_exp_golomb(buf); + if(sps->profile_idc == 100 || sps->profile_idc == 110 || + sps->profile_idc == 122 || sps->profile_idc == 144) { + sps->chroma_format_idc = read_exp_golomb(buf); + if(sps->chroma_format_idc == 3) { + sps->residual_colour_transform_flag = read_bits(buf, 1); + } + + sps->bit_depth_luma_minus8 = read_exp_golomb(buf); + sps->bit_depth_chroma_minus8 = read_exp_golomb(buf); + sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); + sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); + if(sps->seq_scaling_matrix_present_flag) { + int i; + for(i = 0; i < 8; i++) { + sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); + + if(sps->seq_scaling_list_present_flag[i]) { + if(i < 6) + parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, sps->scaling_lists_8x8[i-6], 64, i); + } + } + } + } + + sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); + + sps->pic_order_cnt_type = read_exp_golomb(buf); + if(!sps->pic_order_cnt_type) + sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf); + else { + sps->delta_pic_order_always_zero_flag = read_bits(buf, 1); + sps->offset_for_non_ref_pic = read_exp_golomb_s(buf); + sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf); + sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf); + int i; + for(i=0; inum_ref_frames_in_pic_order_cnt_cycle; i++) { + sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf); + } + } + sps->num_ref_frames = read_exp_golomb(buf); + sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1); + + /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf); + sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/ + sps->pic_width = 16 * (read_exp_golomb(buf) + 1); + sps->pic_height = 16 * (read_exp_golomb(buf) + 1); + + sps->frame_mbs_only_flag = read_bits(buf, 1); + + /* compute the height correctly even for interlaced material */ + sps->pic_height = (2-sps->frame_mbs_only_flag) * sps->pic_height; + if(sps->pic_height == 1088) + sps->pic_height = 1080; + //printf("res: %dx%d\n", sps->pic_width, sps->pic_height); + + if(!sps->frame_mbs_only_flag) + sps->mb_adaptive_frame_field_flag = read_bits(buf, 1); + + sps->direct_8x8_inference_flag = read_bits(buf, 1); + sps->frame_cropping_flag = read_bits(buf, 1); + if(sps->frame_cropping_flag) { + sps->frame_crop_left_offset = read_exp_golomb(buf); + sps->frame_crop_right_offset = read_exp_golomb(buf); + sps->frame_crop_top_offset = read_exp_golomb(buf); + sps->frame_crop_bottom_offset = read_exp_golomb(buf); + } + sps->vui_parameters_present_flag = read_bits(buf, 1); + /*if(sps->vui_parameters_present_flag) + printf("ERROR: vui_parameters is not implemented\n");*/ + + return 0; +} + +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) +{ + pps->pic_parameter_set_id = read_exp_golomb(buf); + pps->seq_parameter_set_id = read_exp_golomb(buf); + pps->entropy_coding_mode_flag = read_bits(buf, 1); + pps->pic_order_present_flag = read_bits(buf, 1); + + pps->num_slice_groups_minus1 = read_exp_golomp(buf); + if(pps->num_slice_groups_minus1 > 0) { + pps->slice_group_map_type = read_exp_golomb(buf); + if(pps->slice_group_map_type == 0) { + int i_group; + for(i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { + if(i_group < 64) + pps->run_length_minus1[i_group] = read_exp_golomb(buf); + else { // FIXME: skips if more than 64 groups exist + fprintf(stderr, "Error: Only 64 slice_groups are supported\n"); + read_exp_golomb(buf); + } + } + } else if(pps->slice_group_map_type == 3 || + pps->slice_group_map_type == 4 || + pps->slice_group_map_type == 5) { + pps->slice_group_change_direction_flag = read_bits(buf, 1); + pps->slice_group_change_rate_minus1 = read_exp_golomb(buf); + } else if(pps->slice_group_map_type == 6) { + pps->pic_size_in_map_units_minus1 = read_exp_golomb(buf); + int i_group; + for(i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { + pps->slice_group_id[i_group] = + read_bits(buf, ceil(log2(pps->num_slice_groups_minus1 + 1))); + } + } + } + + pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); + pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); + pps->weighted_pred_flag = read_bits(buf, 1); + pps->weighted_bipred_flag = read_bits(buf, 2); + pps->pic_init_qp_minus26 = read_exp_golomb_s(buf); + pps->pic_init_qs_minus26 = read_exp_golomb_s(buf); + pps->chroma_qp_index_offset = read_exp_golomb_s(buf); + pps->deblocking_filter_control_present_flag = read_bits(buf, 1); + pps->constrained_intra_pred_flag = read_bits(buf, 1); + pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); + + if(!rbsp_trailing_bits(buf)) { + pps->transform_8x8_mode_flag = read_bits(buf, 1); + pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); + if(pps->pic_scaling_matrix_present_flag) { + int i; + for(i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { + pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); + + if(pps->pic_scaling_list_present_flag[i]) { + if(i < 6) + parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, pps->scaling_lists_8x8[i-6], 64, i); + } + } + } + + pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); + } + + return 0; +} + +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if(!sps || !pps) + return -1; + + slc->first_mb_in_slice = read_exp_golomb(buf); + slc->slice_type = read_exp_golomb(buf); + slc->pic_parameter_set_id = read_exp_golomb(buf); + slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); + if(!sps->frame_mbs_only_flag) { + slc->field_pic_flag = read_bits(buf, 1); + if(slc->field_pic_flag) + slc->bottom_field_flag = read_bits(buf, 1); + else + slc->bottom_field_flag = -1; + } else { + slc->field_pic_flag = 0; + slc->bottom_field_flag = -1; + } + + if(nal->nal_unit_type == NAL_SLICE_IDR) + slc->idr_pic_id = read_exp_golomb(buf); + + if(!sps->pic_order_cnt_type) { + slc->pic_order_cnt_lsb = read_bits(buf, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + if(pps->pic_order_present_flag && !slc->field_pic_flag) + slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf); + } else if (sps->pic_order_cnt_type == 1) { + slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf); + if(pps->pic_order_present_flag && !slc->field_pic_flag) + slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); + } + /* do not need more information for packetizing */ + + return 0; +} + + + +/* ----------------- NAL parser ----------------- */ + +struct nal_parser* init_parser() +{ + struct nal_parser *parser = malloc(sizeof(struct nal_parser)); + memset(parser->buf, 0x00, MAX_FRAME_SIZE); + parser->buf_len = 0; + parser->found_sps = 0; + parser->found_pps = 0; + parser->nal0 = malloc(sizeof(struct nal_unit)); + memset(parser->nal0, 0x00, sizeof(struct nal_unit)); + parser->nal1 = malloc(sizeof(struct nal_unit)); + memset(parser->nal1, 0x00, sizeof(struct nal_unit)); + parser->current_nal = parser->nal0; + parser->last_nal = parser->nal1; + + parser->last_nal_res = 0; + parser->slice = 0; + parser->field = -1; + parser->have_top = 0; + + return parser; +} + +void free_parser(struct nal_parser *parser) +{ + free(parser->nal0); + free(parser->nal1); + free(parser); +} + +int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, + uint8_t **ret_buf, int *ret_len) +{ + int next_nal; + int parsed_len = 0; + int search_offset = 0; + + while((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len)) >= 0) { + // save buffer up to the nal-start + if(parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) { + printf("buf underrun!!\n"); + *ret_len = 0; + *ret_buf = NULL; + return parsed_len; + } + //if(parser->last_nal_res != 1) { + xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, next_nal+search_offset); + parser->buf_len += next_nal+search_offset; + //} + inbuf += next_nal+search_offset; + parsed_len += next_nal+search_offset; + + if((parser->last_nal_res = parse_nal(inbuf+4, inbuf_len-parsed_len, parser)) == 1 + && parser->buf_len>0) { + // parse_nal returned 1 --> detected a frame_boundary + *ret_buf = malloc(parser->buf_len); + xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); + *ret_len = parser->buf_len; + + //memset(parser->buf, 0x00, parser->buf_len); + parser->buf_len = 0; + parser->last_nal_res = 0; + return parsed_len; + } + + search_offset = 4; + } + + // no further NAL found, copy the rest of the stream + // into the buffer +// if(parser->last_nal_res != 1) { + xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len-parsed_len); + parser->buf_len += inbuf_len-parsed_len; +// } + + parsed_len += (inbuf_len-parsed_len); + *ret_len = 0; + *ret_buf = NULL; + + return parsed_len; +} + +int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) +{ + struct buf_reader bufr; + + bufr.buf = buf; + bufr.cur_pos = buf; + bufr.cur_offset = 8; + bufr.len = buf_len; + + struct nal_unit *nal = parser->current_nal; + struct nal_unit *last_nal = parser->last_nal; + + int res = parse_nal_header(&bufr, nal); + + if(res >= NAL_SLICE && res <= NAL_SLICE_IDR) { + // now detect if it's a new frame! + int ret = 0; + if(nal->slc->field_pic_flag == 1) + parser->field = nal->slc->bottom_field_flag; + else { + parser->have_top = 1; + parser->field = -1; + } + + if(nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0) + parser->have_top = 1; + + parser->slice = 1; + + if(nal->slc == NULL || last_nal->slc == NULL) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->slc->frame_num != last_nal->slc->frame_num)) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->slc->pic_parameter_set_id != last_nal->slc->pic_parameter_set_id)) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->slc->field_pic_flag != last_nal->slc->field_pic_flag)) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->slc->bottom_field_flag != -1 && + last_nal->slc->bottom_field_flag != -1 && + nal->slc->bottom_field_flag != last_nal->slc->bottom_field_flag)) { + ret = 1; + } + if(nal->nal_ref_idc != last_nal->nal_ref_idc && + (nal->nal_ref_idc == 0 || last_nal->nal_ref_idc == 0)) { + ret = 1; + } + if(nal->sps && nal->slc && last_nal->slc && + (nal->sps->pic_order_cnt_type == 0 && + (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb || + nal->slc->delta_pic_order_cnt_bottom != last_nal->slc->delta_pic_order_cnt_bottom))) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->sps->pic_order_cnt_type == 1 && + (nal->slc->delta_pic_order_cnt[0] != last_nal->slc->delta_pic_order_cnt[0] || + nal->slc->delta_pic_order_cnt[1] != last_nal->slc->delta_pic_order_cnt[1]))) { + ret = 1; + } + if(nal->nal_unit_type != last_nal->nal_unit_type && + (nal->nal_unit_type == 5 || last_nal->nal_unit_type == 5)) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->nal_unit_type == 5 && last_nal->nal_unit_type == 5 && + nal->slc->idr_pic_id != last_nal->slc->idr_pic_id)) { + ret = 1; + } + + if(parser->current_nal == parser->nal0) { + parser->current_nal = parser->nal1; + parser->last_nal = parser->nal0; + } + else { + parser->current_nal = parser->nal0; + parser->last_nal = parser->nal1; + } + if(parser->current_nal->sps == NULL) + parser->current_nal->sps = parser->last_nal->sps; + if(parser->current_nal->pps == NULL) + parser->current_nal->pps = parser->last_nal->pps; + + /*if(ret) + parser->slice = 0;*/ + /*if(parser->slice && parser->have_top && parser->field != 0) { + parser->have_frame = 1; + parser->have_top = 0; + parser->slice = 0; + return ret; + }*/ + return 0; + } else if(res == NAL_PPS || res == NAL_SPS) { + return 1; + } else if (res == NAL_AU_DELIMITER || res == NAL_SEI || + (res >= 13 && res <= 18)) { + //printf("New Frame\n"); + return 1; + } + + return 0; +} + +int seek_for_nal(uint8_t *buf, int buf_len) +{ + int i; + for(i=0; i + +#include "xine_internal.h" + +enum nal_unit_types { + NAL_UNSPECIFIED = 0, + NAL_SLICE, + NAL_PART_A, + NAL_PART_B, + NAL_PART_C, + NAL_SLICE_IDR, + NAL_SEI, + NAL_SPS, + NAL_PPS, + NAL_AU_DELIMITER, + NAL_END_OF_SEQUENCE, + NAL_END_OF_STREAM, + NAL_FILLER_DATA, + NAL_SPS_EXT +}; + +/* default scaling_lists according to Table 7-2 */ +uint8_t default_4x4_intra[16] = + { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42 }; + +uint8_t default_4x4_inter[16] = + { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34}; + +uint8_t default_8x8_intra[64] = + { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 32, + 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, + 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, + 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; + +uint8_t default_8x8_inter[64] = + { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, + 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, + 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, + 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; + + +struct nal_unit { + uint8_t nal_ref_idc; // 0x03 + uint8_t nal_unit_type; // 0x1f + + struct seq_parameter_set_rbsp *sps; + struct pic_parameter_set_rbsp *pps; + struct slice_header *slc; +}; + +struct seq_parameter_set_rbsp { + uint8_t profile_idc; // 0xff + uint8_t constraint_setN_flag; // 0x0f + uint8_t level_idc; // 0xff + uint32_t seq_parameter_set_id; + uint32_t chroma_format_idc; + uint8_t residual_colour_transform_flag; // 0x01 + uint32_t bit_depth_luma_minus8; + uint32_t bit_depth_chroma_minus8; + uint8_t qpprime_y_zero_transform_bypass_flag; + uint8_t seq_scaling_matrix_present_flag; + + /* if(seq_scaling_matrix_present_flag) */ + { + uint8_t seq_scaling_list_present_flag[8]; + + uint8_t scaling_lists_4x4[6][16]; + uint8_t scaling_lists_8x8[2][64]; + } + + uint32_t log2_max_frame_num_minus4; + uint32_t pic_order_cnt_type; + // if pic_order_cnt_type==0 + uint32_t log2_max_pic_order_cnt_lsb_minus4; + // else + uint8_t delta_pic_order_always_zero_flag; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + uint8_t num_ref_frames_in_pic_order_cnt_cycle; + int32_t offset_for_ref_frame[256]; + // TODO: some more ignored here + uint32_t num_ref_frames; + uint8_t gaps_in_frame_num_value_allowed_flag; + /*uint32_t pic_width_in_mbs_minus1; + uint32_t pic_height_in_map_units_minus1;*/ + uint32_t pic_width; + uint32_t pic_height; + uint8_t frame_mbs_only_flag; + uint8_t mb_adaptive_frame_field_flag; + uint8_t direct_8x8_inference_flag; + uint8_t frame_cropping_flag; + uint32_t frame_crop_left_offset; + uint32_t frame_crop_right_offset; + uint32_t frame_crop_top_offset; + uint32_t frame_crop_bottom_offset; + uint8_t vui_parameters_present_flag; + // TODO: add vui_parameters, rtbsp_trailing_bits + +}; + +struct pic_parameter_set_rbsp { + uint32_t pic_parameter_set_id; + uint32_t seq_parameter_set_id; + uint8_t entropy_coding_mode_flag; + uint8_t pic_order_present_flag; + + uint32_t num_slice_groups_minus1; + + /* num_slice_groups_minus1 > 0 */ + { + uint32_t slice_group_map_type; + + /* slice_group_map_type == 1 */ + { + uint32_t run_length_minus1[64]; + } + + /* slice_group_map_type == 2 */ + { + uint32_t top_left[64]; + uint32_t bottom_right[64]; + } + + /* slice_group_map_type == 3,4,5 */ + { + uint8_t slice_group_change_direction_flag; + uint32_t slice_group_change_rate_minus1; + } + + /* slice_group_map_type == 6 */ + { + uint32_t pic_size_in_map_units_minus1; + uint8_t slice_group_id[64]; + } + } + + uint32_t num_ref_idx_l0_active_minus1; + uint32_t num_ref_idx_l1_active_minus1; + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_idc; + int32_t pic_init_qp_minus26; + int32_t pic_init_qs_minus26; + int32_t chroma_qp_index_offset; + uint8_t deblocking_filter_control_present_flag; + uint8_t constrained_intra_pred_flag; + uint8_t redundant_pic_cnt_present_flag; + + /* if(more_rbsp_data) */ + uint8_t transform_8x8_mode_flag; + uint8_t pic_scaling_matrix_present_flag; + + /* if(pic_scaling_matrix_present_flag) */ + { + uint8_t pic_scaling_list_present_flag[8]; + + uint8_t scaling_lists_4x4[6][16]; + uint8_t scaling_lists_8x8[2][64]; + + int32_t second_chroma_qp_index_offset; + } +}; + +struct slice_header { + uint32_t first_mb_in_slice; + uint32_t slice_type; + uint32_t pic_parameter_set_id; + uint32_t frame_num; + int8_t field_pic_flag; + int8_t bottom_field_flag; + uint32_t idr_pic_id; + + /* sps->pic_order_cnt_type == 0 */ + uint32_t pic_order_cnt_lsb; + int32_t delta_pic_order_cnt_bottom; + /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */ + int32_t delta_pic_order_cnt[2]; + + /* not needed for packetizing */ + /*int32_t redundant_pic_cnt; + uint8_t direct_spatial_mv_pred_flag;*/ + +}; + + +#define MAX_FRAME_SIZE 1024*1024 + +struct nal_parser { + uint8_t buf[MAX_FRAME_SIZE]; + int buf_len; + int found_sps; + int found_pps; + int last_nal_res; + int field; // 0=top, 1=bottom, -1=both + int slice; + int have_top; + int have_frame; + struct nal_unit *nal0; + struct nal_unit *nal1; + struct nal_unit *current_nal; + struct nal_unit *last_nal; +}; + +int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); + +int seek_for_nal(uint8_t *buf, int buf_len); + +struct nal_parser* init_parser(); +void free_parser(struct nal_parser *parser); +int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, + uint8_t **ret_buf, int *ret_len); + +#endif -- cgit v1.2.3 From 90f583c4ac8c40dcfdf3ae3f02ff78ed7ca65b67 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 30 Nov 2008 09:22:33 +0000 Subject: Add scaling, cropping & recreate presentation_queue after drawable change (fullscreen). --- src/video_out/video_out_vdpau.c | 206 +++++++++++++++++++++++++++++++++++----- 1 file changed, 182 insertions(+), 24 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index ccda264bd..65f276660 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -107,9 +107,11 @@ typedef struct { VdpVideoSurface soft_surface; uint32_t soft_surface_width; uint32_t soft_surface_height; - int soft_surface_format; + int soft_surface_format; VdpOutputSurface output_surface; + uint32_t output_surface_width; + uint32_t output_surface_height; VdpVideoMixer video_mixer; @@ -347,6 +349,13 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ static int vdpau_redraw_needed (vo_driver_t *this_gen) { + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + _x_vo_scale_compute_ideal_size( &this->sc ); + if ( _x_vo_scale_redraw_needed( &this->sc ) ) { + _x_vo_scale_compute_output_size( &this->sc ); + return 1; + } return 0; } @@ -357,44 +366,70 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_driver_t *this = (vdpau_driver_t *) this_gen; vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; VdpStatus st; + VdpChromaType chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; - if ( frame->width != this->soft_surface_width || frame->height != this->soft_surface_height || frame->format != this->soft_surface_format ) { - /* recreate the surface to match frame changes */ - vdp_video_surface_destroy( this->soft_surface ); - VdpChromaType chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; - vdp_video_surface_create( vdp_device, chroma, frame->width, frame->height, &this->soft_surface ); - this->soft_surface_format = frame->format; + if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) || (frame->ratio != this->sc.delivered_ratio) ) { + this->sc.force_redraw = 1; /* trigger re-calc of output size */ + } + + this->sc.delivered_height = frame->height; + this->sc.delivered_width = frame->width; + this->sc.delivered_ratio = frame->ratio; + this->sc.crop_left = frame->vo_frame.crop_left; + this->sc.crop_right = frame->vo_frame.crop_right; + this->sc.crop_top = frame->vo_frame.crop_top; + this->sc.crop_bottom = frame->vo_frame.crop_bottom; + + vdpau_redraw_needed( this_gen ); + + if ( (frame->width > this->soft_surface_width) | (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { + printf( "vo_vdpau: soft_surface size update\n" ); + /* recreate surface and mixer to match frame changes */ this->soft_surface_width = frame->width; this->soft_surface_height = frame->height; - printf( "vo_vdpau: soft_surface redim\n" ); + this->soft_surface_format = frame->format; + + vdp_video_surface_destroy( this->soft_surface ); + vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); - /* recreate video mixer to match video surface */ vdp_video_mixer_destroy( this->video_mixer ); VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE }; void const *param_values[] = { &this->soft_surface_width, &this->soft_surface_height, &chroma }; - st = vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); + vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); + } + + if ( (this->sc.gui_width > this->output_surface_width) || (this->sc.gui_height > this->output_surface_height) ) { + /* recreate output surface to match window size */ + printf( "vo_vdpau: output_surface size update\n" ); + this->output_surface_width = this->sc.gui_width; + this->output_surface_height = this->sc.gui_height; + + vdp_output_surface_destroy( this->output_surface ); + vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width, this->output_surface_height, &this->output_surface ); } /* FIXME: have to swap U and V planes to get correct colors !! nvidia ? */ uint32_t pitches[] = { frame->vo_frame.pitches[0], frame->vo_frame.pitches[2], frame->vo_frame.pitches[1] }; void* data[] = { frame->vo_frame.base[0], frame->vo_frame.base[2], frame->vo_frame.base[1] }; if ( frame->format==XINE_IMGFMT_YV12 ) { - st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YV12, &data, &pitches ); + st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YV12, &data, pitches ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YV12 error : %s\n", vdp_get_error_string( st ) ); } else if ( frame->format==XINE_IMGFMT_YUY2 ){ - st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YUYV, &data, &pitches ); + st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YUYV, &data, pitches ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YUY2 error : %s\n", vdp_get_error_string( st ) ); } - VdpRect rect; - rect.x0 = 0; - rect.y0 = 0; - rect.x1 = 800; - rect.y1 = 600; - st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, 0, 0, this->soft_surface, 0, 0, 0, this->output_surface, &rect, &rect, 0, 0 ); + VdpRect vid_source = { this->sc.crop_left, this->sc.crop_top, this->sc.delivered_width-this->sc.crop_right, this->sc.delivered_height-this->sc.crop_bottom }; + VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; + VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height }; + + /*printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 );*/ + + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, + 0, 0, this->soft_surface, 0, 0, &vid_source, this->output_surface, &out_dest, &vid_dest, 0, 0 ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); @@ -433,6 +468,25 @@ static int vdpau_get_property (vo_driver_t *this_gen, int property) static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) { + vdpau_driver_t *this = (vdpau_driver_t*)this_gen; + + /*switch (property) { + case VO_PROP_ZOOM_X: + if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { + this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; + _x_vo_scale_compute_ideal_size( &this->sc ); + this->sc.force_redraw = 1; /* trigger re-calc of output size */ + /*} + break; + case VO_PROP_ZOOM_Y: + if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { + this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP; + _x_vo_scale_compute_ideal_size( &this->sc ); + this->sc.force_redraw = 1; /* trigger re-calc of output size */ + /*} + break; + }*/ + return value; } @@ -448,6 +502,108 @@ static void vdpau_get_property_min_max (vo_driver_t *this_gen, int property, int static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) { + vdpau_driver_t *this = (vdpau_driver_t*)this_gen; + + switch (data_type) { +#ifndef XINE_DISABLE_DEPRECATED_FEATURES + case XINE_GUI_SEND_COMPLETION_EVENT: + break; +#endif + + case XINE_GUI_SEND_EXPOSE_EVENT: { + /* XExposeEvent * xev = (XExposeEvent *) data; */ + + /*if (this->cur_frame) { + int i; + + LOCK_DISPLAY(this); + + if (this->use_shm) { + XvShmPutImage(this->display, this->xv_port, + this->drawable, this->gc, this->cur_frame->image, + this->sc.displayed_xoffset, this->sc.displayed_yoffset, + this->sc.displayed_width, this->sc.displayed_height, + this->sc.output_xoffset, this->sc.output_yoffset, + this->sc.output_width, this->sc.output_height, True); + } else { + XvPutImage(this->display, this->xv_port, + this->drawable, this->gc, this->cur_frame->image, + this->sc.displayed_xoffset, this->sc.displayed_yoffset, + this->sc.displayed_width, this->sc.displayed_height, + this->sc.output_xoffset, this->sc.output_yoffset, + this->sc.output_width, this->sc.output_height); + } + + XSetForeground (this->display, this->gc, this->black.pixel); + + for( i = 0; i < 4; i++ ) { + if( this->sc.border[i].w && this->sc.border[i].h ) { + XFillRectangle(this->display, this->drawable, this->gc, + this->sc.border[i].x, this->sc.border[i].y, + this->sc.border[i].w, this->sc.border[i].h); + } + } + + if(this->xoverlay) + x11osd_expose(this->xoverlay); + + XSync(this->display, False); + UNLOCK_DISPLAY(this); + }*/ + } + break; + + case XINE_GUI_SEND_DRAWABLE_CHANGED: { + VdpStatus st; + XLockDisplay( this->display ); + this->drawable = (Drawable) data; + vdp_queue_destroy( vdp_queue ); + vdp_queue_target_destroy( vdp_queue_target ); + st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); + if ( st != VDP_STATUS_OK ) { + printf( "vo_vdpau: FATAL !! Can't recreate presentation queue target after drawable change !!\n" ); + break; + } + st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); + if ( st != VDP_STATUS_OK ) { + printf( "vo_vdpau: FATAL !! Can't recreate presentation queue after drawable change !!\n" ); + break; + } + VdpColor backColor; + backColor.red = backColor.green = backColor.blue = 0; + backColor.alpha = 1; + vdp_queue_set_backgroung_color( vdp_queue, &backColor ); + XUnlockDisplay( this->display ); + this->sc.force_redraw = 1; + break; + } + + case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: + /*{ + int x1, y1, x2, y2; + x11_rectangle_t *rect = data; + + _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y, + &x1, &y1); + _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h, + &x2, &y2); + rect->x = x1; + rect->y = y1; + rect->w = x2-x1; + rect->h = y2-y1; + + /* onefield_xv divide by 2 the number of lines */ + /*if (this->deinterlace_enabled + && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) + && (this->cur_frame->format == XINE_IMGFMT_YV12)) { + rect->y = rect->y * 2; + rect->h = rect->h * 2; + } + + }*/ + break; + } + return 0; } @@ -505,7 +661,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->screen = visual->screen; this->drawable = visual->d; - _x_vo_scale_init (&this->sc, 0, 0, config); + _x_vo_scale_init(&this->sc, 1, 0, config); this->sc.frame_output_cb = visual->frame_output_cb; this->sc.dest_size_cb = visual->dest_size_cb; this->sc.user_data = visual->user_data; @@ -659,20 +815,22 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo backColor.alpha = 1; vdp_queue_set_backgroung_color( vdp_queue, &backColor ); - this->soft_surface_width = 800; - this->soft_surface_height = 600; + this->soft_surface_width = 720; + this->soft_surface_height = 576; this->soft_surface_format = XINE_IMGFMT_YV12; - st = vdp_video_surface_create( vdp_device, VDP_CHROMA_TYPE_420, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); + VdpChromaType chroma = VDP_CHROMA_TYPE_420; + st = vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, 800, 600, &this->output_surface ); + this->output_surface_width = 720; + this->output_surface_height = 576; + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width, this->output_surface_height, &this->output_surface ); if ( vdpau_init_error( st, "Can't create output surface !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); return NULL; } - VdpChromaType chroma = VDP_CHROMA_TYPE_420; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE }; void const *param_values[] = { &this->soft_surface_width, &this->soft_surface_height, &chroma }; st = vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); -- cgit v1.2.3 From 29aee11d7d5f5df3c430324e31bb2436ce17a9eb Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 30 Nov 2008 20:29:04 +0000 Subject: Add imgfmt and vo_cap to headers. --- include/xine.h.in | 1 + src/xine-engine/video_out.h | 1 + 2 files changed, 2 insertions(+) diff --git a/include/xine.h.in b/include/xine.h.in index 33844a0e2..3bbfb7667 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -482,6 +482,7 @@ int xine_get_current_frame_data (xine_stream_t *stream, #define XINE_IMGFMT_YUY2 (('2'<<24)|('Y'<<16)|('U'<<8)|'Y') #define XINE_IMGFMT_XVMC (('C'<<24)|('M'<<16)|('v'<<8)|'X') #define XINE_IMGFMT_XXMC (('C'<<24)|('M'<<16)|('x'<<8)|'X') +#define XINE_IMGFMT_VDPAU (('U'<<32)|('A'<<24)|('P'<<16)|('D'<<8)|'V') /* get current xine's virtual presentation timestamp (1/90000 sec) * note: this is mostly internal data. diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index fb01805df..77a7134fc 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -280,6 +280,7 @@ struct xine_video_port_s { #define VO_CAP_UNSCALED_OVERLAY 0x00000010 /* driver can blend overlay at output resolution */ #define VO_CAP_CROP 0x00000020 /* driver can crop */ #define VO_CAP_XXMC 0x00000040 /* driver can use extended XvMC */ +#define VO_CAP_VDPAU_H264 0x00000080 /* driver can use Nvidia VDPAU for H264 */ /* -- cgit v1.2.3 From df4b394c2f4fd9d648764d484289d1f3098230f8 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 30 Nov 2008 20:29:49 +0000 Subject: Add initial h264 decoder plugin structure (almost empty for now). --- src/libvdpau/vdpau_h264.c | 311 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 src/libvdpau/vdpau_h264.c diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c new file mode 100644 index 000000000..638eb749a --- /dev/null +++ b/src/libvdpau/vdpau_h264.c @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2008 Julian Scheel + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * foovideo.c: This is a reference video decoder for the xine multimedia + * player. It really works too! It will output frames of packed YUY2 data + * where each byte in the map is the same value, which is 3 larger than the + * value from the last frame. This creates a slowly rotating solid color + * frame when the frames are played in succession. + */ + +#include +#include +#include +#include +#include +#include + +#include "xine_internal.h" +#include "video_out.h" +#include "buffer.h" +#include "xineutils.h" +#include "bswap.h" + +#define VIDEOBUFSIZE 128*1024 + +typedef struct { + video_decoder_class_t decoder_class; +} vdpau_h264_class_t; + +typedef struct vdpau_h264_decoder_s { + video_decoder_t video_decoder; /* parent video decoder structure */ + + vdpau_h264_class_t *class; + xine_stream_t *stream; + + /* these are traditional variables in a video decoder object */ + uint64_t video_step; /* frame duration in pts units */ + int decoder_ok; /* current decoder status */ + int decoder_initialized; /* vdpau init state */ + int skipframes; + + unsigned char *buf; /* the accumulated buffer data */ + int bufsize; /* the maximum size of buf */ + int size; /* the current size of buf */ + + int width; /* the width of a video frame */ + int height; /* the height of a video frame */ + double ratio; /* the width to height ratio */ + + struct nal_parser *nal_parser /* h264 nal parser. extracts stream data for vdpau */ + VdpPictureInfoH264 vdp_picture_info; + + + /* these are variables exclusive to the foo video decoder */ + unsigned char current_yuv_byte; + +} vdpau_h264_decoder_t; + +/************************************************************************** + * vdpau_h264 specific decode functions + *************************************************************************/ + +/************************************************************************** + * xine video plugin functions + *************************************************************************/ + +/* + * This function receives a buffer of data from the demuxer layer and + * figures out how to handle it based on its header flags. + */ +static void vdpau_h264_decode_data (video_decoder_t *this_gen, + buf_element_t *buf) { + + vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; + xine_bmiheader *bih; + + vo_frame_t *img; /* video out frame */ + + /* a video decoder does not care about this flag (?) */ + if (buf->decoder_flags & BUF_FLAG_PREVIEW) + return; + + if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { + this->video_step = buf->decoder_info[0]; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); + } + + if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ + (this->stream->video_out->open) (this->stream->video_out, this->stream); + + if(this->buf) + free(this->buf); + + bih = (xine_bmiheader *) buf->content; + this->width = bih->biWidth; + this->height = bih->biHeight; + this->ratio = (double)this->width/(double)this->height; + + if (this->buf) + free (this->buf); + this->bufsize = VIDEOBUFSIZE; + this->buf = malloc(this->bufsize); + this->size = 0; + + /* take this opportunity to load the stream/meta info */ + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "foovideo"); + + /* do anything else relating to initializing this decoder */ + this->current_yuv_byte = 0; + + this->decoder_ok = 1; + + return; + } else if (this->decoder_ok) { + + if (this->size + buf->size > this->bufsize) { + this->bufsize = this->size + 2 * buf->size; + this->buf = realloc (this->buf, this->bufsize); + } + + xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); + + this->size += buf->size; + + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { + + img = this->stream->video_out->get_frame (this->stream->video_out, + this->width, this->height, + this->ratio, + XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); + + img->duration = this->video_step; + img->pts = buf->pts; + img->bad_frame = 0; + + memset(img->base[0], this->current_yuv_byte, + this->width * this->height * 2); + this->current_yuv_byte += 3; + + img->draw(img, this->stream); + img->free(img); + + this->size = 0; + } + } +} + +/* + * This function is called when xine needs to flush the system. + */ +static void vdpau_h264_flush (video_decoder_t *this_gen) { +} + +/* + * This function resets the video decoder. + */ +static void vdpau_h264_reset (video_decoder_t *this_gen) { + vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; + + this->size = 0; +} + +/* + * The decoder should forget any stored pts values here. + */ +static void vdpau_h264_discontinuity (video_decoder_t *this_gen) { + vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; + +} + +/* + * This function frees the video decoder instance allocated to the decoder. + */ +static void vdpau_h264_dispose (video_decoder_t *this_gen) { + + vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; + + if (this->buf) { + free (this->buf); + this->buf = NULL; + } + + if (this->decoder_ok) { + this->decoder_ok = 0; + this->stream->video_out->close(this->stream->video_out, this->stream); + } + + free (this_gen); +} + +/* + * This function allocates, initializes, and returns a private video + * decoder structure. + */ +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { + + vdpau_h264_decoder_t *this ; + + this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t)); + + /* the videoout must be vdpau-capable to support this decoder */ + if(!stream->video_driver->get_capabilities() & VO_CAP_VDPAU_H264) + return NULL; + + this->video_decoder.decode_data = vdpau_h264_decode_data; + this->video_decoder.flush = vdpau_h264_flush; + this->video_decoder.reset = vdpau_h264_reset; + this->video_decoder.discontinuity = vdpau_h264_discontinuity; + this->video_decoder.dispose = vdpau_h264_dispose; + this->size = 0; + + this->stream = stream; + this->class = (vdpau_h264_class_t *) class_gen; + + this->decoder_ok = 0; + this->buf = NULL; + + return &this->video_decoder; +} + +/* + * This function returns a brief string that describes (usually with the + * decoder's most basic name) the video decoder plugin. + */ +static char *get_identifier (video_decoder_class_t *this) { + return "vdpau_h264"; +} + +/* + * This function returns a slightly longer string describing the video + * decoder plugin. + */ +static char *get_description (video_decoder_class_t *this) { + return "vdpau_h264: h264 decoder plugin using VDPAU hardware decoding.\n" + "Must be used along with video_out_vdpau."; +} + +/* + * This function frees the video decoder class and any other memory that was + * allocated. + */ +static void dispose_class (video_decoder_class_t *this) { + free (this); +} + +/* + * This function allocates a private video decoder class and initializes + * the class's member functions. + */ +static void *init_plugin (xine_t *xine, void *data) { + + vdpau_h264_class_t *this; + + this = (vdpau_h264_class_t *) calloc(1, sizeof(vdpau_h264_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; + + return this; +} + +/* + * This is a list of all of the internal xine video buffer types that + * this decoder is able to handle. Check src/xine-engine/buffer.h for a + * list of valid buffer types (and add a new one if the one you need does + * not exist). Terminate the list with a 0. + */ +static const uint32_t video_types[] = { + /* BUF_VIDEO_FOOVIDEO, */ + BUF_VIDEO_H264, + 0 +}; + +/* + * This data structure combines the list of supported xine buffer types and + * the priority that the plugin should be given with respect to other + * plugins that handle the same buffer type. A plugin with priority (n+1) + * will be used instead of a plugin with priority (n). + */ +static const decoder_info_t dec_info_video = { + video_types, /* supported types */ + 5 /* priority */ +}; + +/* + * The plugin catalog entry. This is the only information that this plugin + * will export to the public. + */ +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* { type, API, "name", version, special_info, init_function } */ + { PLUGIN_VIDEO_DECODER, 18, "vdpau_h264", XINE_VERSION_CODE, &dec_info_video, init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; -- cgit v1.2.3 From 31e7460ff80ac48b11e6d2947fa96a031af92bce Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 30 Nov 2008 20:29:49 +0000 Subject: Fix a few glitches in nal_parser. Still slicing needs to be fixed. --HG-- rename : src/libxinevdec/nal_parser.c => src/libvdpau/nal_parser.c rename : src/libxinevdec/nal_parser.h => src/libvdpau/nal_parser.h --- src/libvdpau/nal_parser.c | 661 +++++++++++++++++++++++++++++++++++++++++++ src/libvdpau/nal_parser.h | 216 ++++++++++++++ src/libxinevdec/nal_parser.c | 652 ------------------------------------------ src/libxinevdec/nal_parser.h | 215 -------------- 4 files changed, 877 insertions(+), 867 deletions(-) create mode 100644 src/libvdpau/nal_parser.c create mode 100644 src/libvdpau/nal_parser.h delete mode 100644 src/libxinevdec/nal_parser.c delete mode 100644 src/libxinevdec/nal_parser.h diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c new file mode 100644 index 000000000..8b3265337 --- /dev/null +++ b/src/libvdpau/nal_parser.c @@ -0,0 +1,661 @@ +#include +#include +#include + +#include "nal_parser.h" + +struct buf_reader { + uint8_t *buf; + uint8_t *cur_pos; + int len; + int cur_offset; +}; + +static inline uint32_t read_bits(struct buf_reader *buf, int len); +uint32_t read_exp_golomb(struct buf_reader *buf); +int32_t read_exp_golomb_s(struct buf_reader *buf); +void skip_scaling_list(struct buf_reader *buf, int size); +int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal); +uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps); +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal); + + +static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) +{ + uint8_t *end = &buf[buf_len]; + uint8_t *pos = malloc(buf_len); + + *ret = pos; + while(buf < end) { + if(buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 && + buf[2] == 0x03) { + + *pos++ = 0x00; + *pos++ = 0x00; + + buf += 3; + continue; + } + *pos++ = *buf++; + } + + *len_ret = pos - *ret; +} + +/*uint32_t read_bits(struct buf_reader *buf, int len) +{ + uint32_t bits = 0x00; + int i, j; + for(i=0, j=0; icur_offset >= 8) { + buf->cur_pos++; + buf->cur_offset -= 8; + } + uint8_t bit = (*buf->cur_pos >> (7 - buf->cur_offset)) & 0x01; + bits |= ((uint32_t)bit) << i; + buf->cur_offset++; + } +printf("ret: 0x%08x\n", bits); + return bits; +}*/ + +static inline uint32_t read_bits (struct buf_reader *buf, int len) +{ + static uint32_t i_mask[33] = + { 0x00, + 0x01, 0x03, 0x07, 0x0f, + 0x1f, 0x3f, 0x7f, 0xff, + 0x1ff, 0x3ff, 0x7ff, 0xfff, + 0x1fff, 0x3fff, 0x7fff, 0xffff, + 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, + 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, + 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, + 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff}; + + int i_shr; + uint32_t bits = 0; + + while(len > 0 && (buf->cur_pos - buf->buf) < buf->len) { + if((i_shr = buf->cur_offset-len) >= 0) { + bits |= (*buf->cur_pos >> i_shr)&i_mask[len]; + buf->cur_offset -= len; + if(buf->cur_offset == 0) { + buf->cur_pos++; + buf->cur_offset = 8; + } + return bits; + } else { + bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; + len -= buf->cur_offset; + buf->cur_pos++; + buf->cur_offset = 8; + } + } + return bits; +} + +/* determines if following bits are rtsb_trailing_bits */ +static inline uint8_t rbsp_trailing_bits(struct buf_reader *buf) +{ + // store the offset and pos in buffer + // to revert this afterwards. + int last_offset; + uint8_t *last_pos; + + uint8_t rbsp_trailing_bits = 1; + + offset = buf->cur_offset; + pos = buf->cur_pos; + + if(read_bits(buf, 1) == 1) + { + while(buf->cur_offset != 8) + if(read_bits(buf, 1) == 1) + rbsp_trailing_bits = 0; + } + + // revert buffer + buf->cur_offset = offset; + buf->cur_pos = pos; + + return rbsp_trailing_bits; +} + +uint32_t read_exp_golomb(struct buf_reader *buf) +{ + int leading_zero_bits = 0; + + while(read_bits(buf, 1) == 0 && leading_zero_bits < 32) + leading_zero_bits++; + + uint32_t code = (1<len < 1) + return -1; + int ret = -1; + + nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; + nal->nal_unit_type = buf->buf[0] & 0x1f; + + buf->cur_pos = buf->buf + 1; + //printf("NAL: %d\n", nal->nal_unit_type); + + struct buf_reader ibuf; + ibuf.cur_offset = 8; + + switch(nal->nal_unit_type) { + case NAL_SPS: + decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len-1); + ibuf.cur_pos = ibuf.buf; + if(!nal->sps) + nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + else + memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); + + parse_sps(&ibuf, nal->sps); + free(ibuf.buf); + ret = NAL_SPS; + break; + case NAL_PPS: + if(!nal->pps) + nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + else + memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); + + parse_pps(buf, nal->pps); + ret = NAL_PPS; + break; + case NAL_SLICE: + case NAL_PART_A: + case NAL_PART_B: + case NAL_PART_C: + case NAL_SLICE_IDR: + if(nal->sps && nal->pps) { + if(!nal->slc) + nal->slc = malloc(sizeof(struct slice_header)); + else + memset(nal->slc, 0x00, sizeof(struct slice_header)); + + parse_slice_header(buf, nal); + ret = nal->nal_unit_type; + } + break; + default: + ret = nal->nal_unit_type; + break; + } + + return ret; +} + +void skip_scaling_list(struct buf_reader *buf, int size) +{ + int i; + for(i = 0; i < size; i++) { + read_exp_golomb_s(buf); + } +} + +void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index) +{ + int last_scale = 8; + int next_scale = 8; + int32_t delta_scale; + uint8_t use_default_scaling_matrix_flag = 0; + int i; + + for(i = 0; i < length; i++) { + if(next_scale != 0) { + delta_scale = read_exp_golomb_s(buf); + next_scale = (last_scale + delta_scale + 256) % 256; + if(i == 0 && next_scale == 0) { + use_default_scaling_matrix_flag = 1; + break; + } + } + scaling_list = (next_scale == 0) ? last_scale : next_scale; + last_scale = scaling_list->scaling_list[i]; + } + + if(use_default_scaling_matrix_flag) { + switch(index) { + case 0: + case 1: + case 2: + memcpy(scaling_list, length, default_4x4_intra); + break; + case 3: + case 4: + case 5: + memcpy(scaling_list, length, default_4x4_inter); + break; + case 6: + memcpy(scaling_list, length, default_8x8_intra); + break; + case 7: + memcpy(scaling_list, length, default_8x8_inter); + break; + } + } +} + +uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) +{ + sps->profile_idc = buf->buf[0]; + sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; + sps->level_idc = buf->buf[2]; + + buf->cur_pos = buf->buf+3; + sps->seq_parameter_set_id = read_exp_golomb(buf); + if(sps->profile_idc == 100 || sps->profile_idc == 110 || + sps->profile_idc == 122 || sps->profile_idc == 144) { + sps->chroma_format_idc = read_exp_golomb(buf); + if(sps->chroma_format_idc == 3) { + sps->residual_colour_transform_flag = read_bits(buf, 1); + } + + sps->bit_depth_luma_minus8 = read_exp_golomb(buf); + sps->bit_depth_chroma_minus8 = read_exp_golomb(buf); + sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); + sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); + if(sps->seq_scaling_matrix_present_flag) { + int i; + for(i = 0; i < 8; i++) { + sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); + + if(sps->seq_scaling_list_present_flag[i]) { + if(i < 6) + parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, sps->scaling_lists_8x8[i-6], 64, i); + } + } + } + } + + sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); + + sps->pic_order_cnt_type = read_exp_golomb(buf); + if(!sps->pic_order_cnt_type) + sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf); + else { + sps->delta_pic_order_always_zero_flag = read_bits(buf, 1); + sps->offset_for_non_ref_pic = read_exp_golomb_s(buf); + sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf); + sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf); + int i; + for(i=0; inum_ref_frames_in_pic_order_cnt_cycle; i++) { + sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf); + } + } + sps->num_ref_frames = read_exp_golomb(buf); + sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1); + + /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf); + sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/ + sps->pic_width = 16 * (read_exp_golomb(buf) + 1); + sps->pic_height = 16 * (read_exp_golomb(buf) + 1); + + sps->frame_mbs_only_flag = read_bits(buf, 1); + + /* compute the height correctly even for interlaced material */ + sps->pic_height = (2-sps->frame_mbs_only_flag) * sps->pic_height; + if(sps->pic_height == 1088) + sps->pic_height = 1080; + //printf("res: %dx%d\n", sps->pic_width, sps->pic_height); + + if(!sps->frame_mbs_only_flag) + sps->mb_adaptive_frame_field_flag = read_bits(buf, 1); + + sps->direct_8x8_inference_flag = read_bits(buf, 1); + sps->frame_cropping_flag = read_bits(buf, 1); + if(sps->frame_cropping_flag) { + sps->frame_crop_left_offset = read_exp_golomb(buf); + sps->frame_crop_right_offset = read_exp_golomb(buf); + sps->frame_crop_top_offset = read_exp_golomb(buf); + sps->frame_crop_bottom_offset = read_exp_golomb(buf); + } + sps->vui_parameters_present_flag = read_bits(buf, 1); + /*if(sps->vui_parameters_present_flag) + printf("ERROR: vui_parameters is not implemented\n");*/ + + return 0; +} + +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) +{ + pps->pic_parameter_set_id = read_exp_golomb(buf); + pps->seq_parameter_set_id = read_exp_golomb(buf); + pps->entropy_coding_mode_flag = read_bits(buf, 1); + pps->pic_order_present_flag = read_bits(buf, 1); + + pps->num_slice_groups_minus1 = read_exp_golomp(buf); + if(pps->num_slice_groups_minus1 > 0) { + pps->slice_group_map_type = read_exp_golomb(buf); + if(pps->slice_group_map_type == 0) { + int i_group; + for(i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { + if(i_group < 64) + pps->run_length_minus1[i_group] = read_exp_golomb(buf); + else { // FIXME: skips if more than 64 groups exist + fprintf(stderr, "Error: Only 64 slice_groups are supported\n"); + read_exp_golomb(buf); + } + } + } else if(pps->slice_group_map_type == 3 || + pps->slice_group_map_type == 4 || + pps->slice_group_map_type == 5) { + pps->slice_group_change_direction_flag = read_bits(buf, 1); + pps->slice_group_change_rate_minus1 = read_exp_golomb(buf); + } else if(pps->slice_group_map_type == 6) { + pps->pic_size_in_map_units_minus1 = read_exp_golomb(buf); + int i_group; + for(i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { + pps->slice_group_id[i_group] = + read_bits(buf, ceil(log2(pps->num_slice_groups_minus1 + 1))); + } + } + } + + pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); + pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); + pps->weighted_pred_flag = read_bits(buf, 1); + pps->weighted_bipred_flag = read_bits(buf, 2); + pps->pic_init_qp_minus26 = read_exp_golomb_s(buf); + pps->pic_init_qs_minus26 = read_exp_golomb_s(buf); + pps->chroma_qp_index_offset = read_exp_golomb_s(buf); + pps->deblocking_filter_control_present_flag = read_bits(buf, 1); + pps->constrained_intra_pred_flag = read_bits(buf, 1); + pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); + + if(!rbsp_trailing_bits(buf)) { + pps->transform_8x8_mode_flag = read_bits(buf, 1); + pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); + if(pps->pic_scaling_matrix_present_flag) { + int i; + for(i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { + pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); + + if(pps->pic_scaling_list_present_flag[i]) { + if(i < 6) + parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, pps->scaling_lists_8x8[i-6], 64, i); + } + } + } + + pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); + } + + return 0; +} + +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if(!sps || !pps) + return -1; + + slc->first_mb_in_slice = read_exp_golomb(buf); + slc->slice_type = read_exp_golomb(buf); + slc->pic_parameter_set_id = read_exp_golomb(buf); + slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); + if(!sps->frame_mbs_only_flag) { + slc->field_pic_flag = read_bits(buf, 1); + if(slc->field_pic_flag) + slc->bottom_field_flag = read_bits(buf, 1); + else + slc->bottom_field_flag = -1; + } else { + slc->field_pic_flag = 0; + slc->bottom_field_flag = -1; + } + + if(nal->nal_unit_type == NAL_SLICE_IDR) + slc->idr_pic_id = read_exp_golomb(buf); + + if(!sps->pic_order_cnt_type) { + slc->pic_order_cnt_lsb = read_bits(buf, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + if(pps->pic_order_present_flag && !slc->field_pic_flag) + slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf); + } else if (sps->pic_order_cnt_type == 1) { + slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf); + if(pps->pic_order_present_flag && !slc->field_pic_flag) + slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); + } + /* do not need more information for packetizing */ + + return 0; +} + + + +/* ----------------- NAL parser ----------------- */ + +struct nal_parser* init_parser() +{ + struct nal_parser *parser = malloc(sizeof(struct nal_parser)); + memset(parser->buf, 0x00, MAX_FRAME_SIZE); + parser->buf_len = 0; + parser->found_sps = 0; + parser->found_pps = 0; + parser->nal0 = malloc(sizeof(struct nal_unit)); + memset(parser->nal0, 0x00, sizeof(struct nal_unit)); + parser->nal1 = malloc(sizeof(struct nal_unit)); + memset(parser->nal1, 0x00, sizeof(struct nal_unit)); + parser->current_nal = parser->nal0; + parser->last_nal = parser->nal1; + + parser->last_nal_res = 0; + parser->slice = 0; + parser->slice_cnt = 0; + parser->field = -1; + parser->have_top = 0; + + return parser; +} + +void free_parser(struct nal_parser *parser) +{ + free(parser->nal0); + free(parser->nal1); + free(parser); +} + +int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, + uint8_t **ret_buf, int *ret_len, int *ret_slice_cnt) +{ + int next_nal; + int parsed_len = 0; + int search_offset = 0; + + while((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len)) >= 0) { + // save buffer up to the nal-start + if(parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) { + printf("buf underrun!!\n"); + *ret_len = 0; + *ret_buf = NULL; + return parsed_len; + } + //if(parser->last_nal_res != 1) { + xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, next_nal+search_offset); + parser->buf_len += next_nal+search_offset; + //} + inbuf += next_nal+search_offset; + parsed_len += next_nal+search_offset; + + if((parser->last_nal_res = parse_nal(inbuf+4, inbuf_len-parsed_len, parser)) == 1 + && parser->buf_len>0) { + // parse_nal returned 1 --> detected a frame_boundary + *ret_buf = malloc(parser->buf_len); + xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); + *ret_len = parser->buf_len; + *ret_slice_cnt = parser->slice_cnt; + + //memset(parser->buf, 0x00, parser->buf_len); + parser->buf_len = 0; + parser->last_nal_res = 0; + parser->slice_cnt = 0; + return parsed_len; + } + + search_offset = 4; + } + + // no further NAL found, copy the rest of the stream + // into the buffer +// if(parser->last_nal_res != 1) { + xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len-parsed_len); + parser->buf_len += inbuf_len-parsed_len; +// } + + parsed_len += (inbuf_len-parsed_len); + *ret_len = 0; + *ret_buf = NULL; + + return parsed_len; +} + +int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) +{ + struct buf_reader bufr; + + bufr.buf = buf; + bufr.cur_pos = buf; + bufr.cur_offset = 8; + bufr.len = buf_len; + + struct nal_unit *nal = parser->current_nal; + struct nal_unit *last_nal = parser->last_nal; + + int res = parse_nal_header(&bufr, nal); + + if(res >= NAL_SLICE && res <= NAL_SLICE_IDR) { + // now detect if it's a new frame! + int ret = 0; + if(nal->slc->field_pic_flag == 1) + parser->field = nal->slc->bottom_field_flag; + else { + parser->have_top = 1; + parser->field = -1; + } + + if(nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0) + parser->have_top = 1; + + parser->slice = 1; + + if(nal->slc == NULL || last_nal->slc == NULL) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->slc->frame_num != last_nal->slc->frame_num)) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->slc->pic_parameter_set_id != last_nal->slc->pic_parameter_set_id)) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->slc->field_pic_flag != last_nal->slc->field_pic_flag)) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->slc->bottom_field_flag != -1 && + last_nal->slc->bottom_field_flag != -1 && + nal->slc->bottom_field_flag != last_nal->slc->bottom_field_flag)) { + ret = 1; + } + if(nal->nal_ref_idc != last_nal->nal_ref_idc && + (nal->nal_ref_idc == 0 || last_nal->nal_ref_idc == 0)) { + ret = 1; + } + if(nal->sps && nal->slc && last_nal->slc && + (nal->sps->pic_order_cnt_type == 0 && last_nal->sps->pic_order_cnt_type == 0 && + (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb || + nal->slc->delta_pic_order_cnt_bottom != last_nal->slc->delta_pic_order_cnt_bottom))) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->sps->pic_order_cnt_type == 1 && last_nal->sps->pic_order_cnt_type == 1 && + (nal->slc->delta_pic_order_cnt[0] != last_nal->slc->delta_pic_order_cnt[0] || + nal->slc->delta_pic_order_cnt[1] != last_nal->slc->delta_pic_order_cnt[1]))) { + ret = 1; + } + if(nal->nal_unit_type != last_nal->nal_unit_type && + (nal->nal_unit_type == 5 || last_nal->nal_unit_type == 5)) { + ret = 1; + } + if(nal->slc && last_nal->slc && + (nal->nal_unit_type == 5 && last_nal->nal_unit_type == 5 && + nal->slc->idr_pic_id != last_nal->slc->idr_pic_id)) { + ret = 1; + } + + if(parser->current_nal == parser->nal0) { + parser->current_nal = parser->nal1; + parser->last_nal = parser->nal0; + } + else { + parser->current_nal = parser->nal0; + parser->last_nal = parser->nal1; + } + + if(parser->current_nal->sps == NULL) + parser->current_nal->sps = parser->last_nal->sps; + if(parser->current_nal->pps == NULL) + parser->current_nal->pps = parser->last_nal->pps; + + /*if(ret) + parser->slice = 0;*/ + /*if(parser->slice && parser->have_top && parser->field != 0) { + parser->have_frame = 1; + parser->have_top = 0; + parser->slice = 0; + return ret; + }*/ + + /* increase the slice_cnt until a new frame is detected */ + if(!ret) + parser->slice_cnt++; + + return ret; + } else if(res == NAL_PPS || res == NAL_SPS) { + return 1; + } else if (res == NAL_AU_DELIMITER || res == NAL_SEI || + (res >= 13 && res <= 18)) { + //printf("New Frame\n"); + return 1; + } + + return 0; +} + +int seek_for_nal(uint8_t *buf, int buf_len) +{ + int i; + for(i=0; i + +#include "xine_internal.h" + +enum nal_unit_types { + NAL_UNSPECIFIED = 0, + NAL_SLICE, + NAL_PART_A, + NAL_PART_B, + NAL_PART_C, + NAL_SLICE_IDR, + NAL_SEI, + NAL_SPS, + NAL_PPS, + NAL_AU_DELIMITER, + NAL_END_OF_SEQUENCE, + NAL_END_OF_STREAM, + NAL_FILLER_DATA, + NAL_SPS_EXT +}; + +/* default scaling_lists according to Table 7-2 */ +uint8_t default_4x4_intra[16] = + { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42 }; + +uint8_t default_4x4_inter[16] = + { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34}; + +uint8_t default_8x8_intra[64] = + { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 32, + 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, + 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, + 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; + +uint8_t default_8x8_inter[64] = + { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, + 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, + 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, + 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; + + +struct nal_unit { + uint8_t nal_ref_idc; // 0x03 + uint8_t nal_unit_type; // 0x1f + + struct seq_parameter_set_rbsp *sps; + struct pic_parameter_set_rbsp *pps; + struct slice_header *slc; +}; + +struct seq_parameter_set_rbsp { + uint8_t profile_idc; // 0xff + uint8_t constraint_setN_flag; // 0x0f + uint8_t level_idc; // 0xff + uint32_t seq_parameter_set_id; + uint32_t chroma_format_idc; + uint8_t residual_colour_transform_flag; // 0x01 + uint32_t bit_depth_luma_minus8; + uint32_t bit_depth_chroma_minus8; + uint8_t qpprime_y_zero_transform_bypass_flag; + uint8_t seq_scaling_matrix_present_flag; + + /* if(seq_scaling_matrix_present_flag) */ + { + uint8_t seq_scaling_list_present_flag[8]; + + uint8_t scaling_lists_4x4[6][16]; + uint8_t scaling_lists_8x8[2][64]; + } + + uint32_t log2_max_frame_num_minus4; + uint32_t pic_order_cnt_type; + // if pic_order_cnt_type==0 + uint32_t log2_max_pic_order_cnt_lsb_minus4; + // else + uint8_t delta_pic_order_always_zero_flag; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + uint8_t num_ref_frames_in_pic_order_cnt_cycle; + int32_t offset_for_ref_frame[256]; + // TODO: some more ignored here + uint32_t num_ref_frames; + uint8_t gaps_in_frame_num_value_allowed_flag; + /*uint32_t pic_width_in_mbs_minus1; + uint32_t pic_height_in_map_units_minus1;*/ + uint32_t pic_width; + uint32_t pic_height; + uint8_t frame_mbs_only_flag; + uint8_t mb_adaptive_frame_field_flag; + uint8_t direct_8x8_inference_flag; + uint8_t frame_cropping_flag; + uint32_t frame_crop_left_offset; + uint32_t frame_crop_right_offset; + uint32_t frame_crop_top_offset; + uint32_t frame_crop_bottom_offset; + uint8_t vui_parameters_present_flag; + // TODO: add vui_parameters, rtbsp_trailing_bits + +}; + +struct pic_parameter_set_rbsp { + uint32_t pic_parameter_set_id; + uint32_t seq_parameter_set_id; + uint8_t entropy_coding_mode_flag; + uint8_t pic_order_present_flag; + + uint32_t num_slice_groups_minus1; + + /* num_slice_groups_minus1 > 0 */ + { + uint32_t slice_group_map_type; + + /* slice_group_map_type == 1 */ + { + uint32_t run_length_minus1[64]; + } + + /* slice_group_map_type == 2 */ + { + uint32_t top_left[64]; + uint32_t bottom_right[64]; + } + + /* slice_group_map_type == 3,4,5 */ + { + uint8_t slice_group_change_direction_flag; + uint32_t slice_group_change_rate_minus1; + } + + /* slice_group_map_type == 6 */ + { + uint32_t pic_size_in_map_units_minus1; + uint8_t slice_group_id[64]; + } + } + + uint32_t num_ref_idx_l0_active_minus1; + uint32_t num_ref_idx_l1_active_minus1; + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_idc; + int32_t pic_init_qp_minus26; + int32_t pic_init_qs_minus26; + int32_t chroma_qp_index_offset; + uint8_t deblocking_filter_control_present_flag; + uint8_t constrained_intra_pred_flag; + uint8_t redundant_pic_cnt_present_flag; + + /* if(more_rbsp_data) */ + uint8_t transform_8x8_mode_flag; + uint8_t pic_scaling_matrix_present_flag; + + /* if(pic_scaling_matrix_present_flag) */ + { + uint8_t pic_scaling_list_present_flag[8]; + + uint8_t scaling_lists_4x4[6][16]; + uint8_t scaling_lists_8x8[2][64]; + + int32_t second_chroma_qp_index_offset; + } +}; + +struct slice_header { + uint32_t first_mb_in_slice; + uint32_t slice_type; + uint32_t pic_parameter_set_id; + uint32_t frame_num; + int8_t field_pic_flag; + int8_t bottom_field_flag; + uint32_t idr_pic_id; + + /* sps->pic_order_cnt_type == 0 */ + uint32_t pic_order_cnt_lsb; + int32_t delta_pic_order_cnt_bottom; + /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */ + int32_t delta_pic_order_cnt[2]; + + /* not needed for packetizing */ + /*int32_t redundant_pic_cnt; + uint8_t direct_spatial_mv_pred_flag;*/ + +}; + + +#define MAX_FRAME_SIZE 1024*1024 + +struct nal_parser { + uint8_t buf[MAX_FRAME_SIZE]; + int buf_len; + int found_sps; + int found_pps; + int last_nal_res; + int field; /* 0=top, 1=bottom, -1=both */ + int slice; + int slice_cnt; + int have_top; + int have_frame; + struct nal_unit *nal0; + struct nal_unit *nal1; + struct nal_unit *current_nal; + struct nal_unit *last_nal; +}; + +int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); + +int seek_for_nal(uint8_t *buf, int buf_len); + +struct nal_parser* init_parser(); +void free_parser(struct nal_parser *parser); +int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, + uint8_t **ret_buf, int *ret_len); + +#endif diff --git a/src/libxinevdec/nal_parser.c b/src/libxinevdec/nal_parser.c deleted file mode 100644 index 916595cad..000000000 --- a/src/libxinevdec/nal_parser.c +++ /dev/null @@ -1,652 +0,0 @@ -#include -#include -#include - -#include "nal_parser.h" - -struct buf_reader { - uint8_t *buf; - uint8_t *cur_pos; - int len; - int cur_offset; -}; - -static inline uint32_t read_bits(struct buf_reader *buf, int len); -uint32_t read_exp_golomb(struct buf_reader *buf); -int32_t read_exp_golomb_s(struct buf_reader *buf); -void skip_scaling_list(struct buf_reader *buf, int size); -int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal); -uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); -uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps); -uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal); - - -static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) -{ - uint8_t *end = &buf[buf_len]; - uint8_t *pos = malloc(buf_len); - - *ret = pos; - while(buf < end) { - if(buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 && - buf[2] == 0x03) { - - *pos++ = 0x00; - *pos++ = 0x00; - - buf += 3; - continue; - } - *pos++ = *buf++; - } - - *len_ret = pos - *ret; -} - -/*uint32_t read_bits(struct buf_reader *buf, int len) -{ - uint32_t bits = 0x00; - int i, j; - for(i=0, j=0; icur_offset >= 8) { - buf->cur_pos++; - buf->cur_offset -= 8; - } - uint8_t bit = (*buf->cur_pos >> (7 - buf->cur_offset)) & 0x01; - bits |= ((uint32_t)bit) << i; - buf->cur_offset++; - } -printf("ret: 0x%08x\n", bits); - return bits; -}*/ - -static inline uint32_t read_bits (struct buf_reader *buf, int len) -{ - static uint32_t i_mask[33] = - { 0x00, - 0x01, 0x03, 0x07, 0x0f, - 0x1f, 0x3f, 0x7f, 0xff, - 0x1ff, 0x3ff, 0x7ff, 0xfff, - 0x1fff, 0x3fff, 0x7fff, 0xffff, - 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, - 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, - 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, - 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff}; - - int i_shr; - uint32_t bits = 0; - - while(len > 0 && (buf->cur_pos - buf->buf) < buf->len) { - if((i_shr = buf->cur_offset-len) >= 0) { - bits |= (*buf->cur_pos >> i_shr)&i_mask[len]; - buf->cur_offset -= len; - if(buf->cur_offset == 0) { - buf->cur_pos++; - buf->cur_offset = 8; - } - return bits; - } else { - bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; - len -= buf->cur_offset; - buf->cur_pos++; - buf->cur_offset = 8; - } - } - return bits; -} - -/* determines if following bits are rtsb_trailing_bits */ -static inline uint8_t rbsp_trailing_bits(struct buf_reader *buf) -{ - // store the offset and pos in buffer - // to revert this afterwards. - int last_offset; - uint8_t *last_pos; - - uint8_t rbsp_trailing_bits = 1; - - offset = buf->cur_offset; - pos = buf->cur_pos; - - if(read_bits(buf, 1) == 1) - { - while(buf->cur_offset != 8) - if(read_bits(buf, 1) == 1) - rbsp_trailing_bits = 0; - } - - // revert buffer - buf->cur_offset = offset; - buf->cur_pos = pos; - - return rbsp_trailing_bits; -} - -uint32_t read_exp_golomb(struct buf_reader *buf) -{ - int leading_zero_bits = 0; - - while(read_bits(buf, 1) == 0 && leading_zero_bits < 32) - leading_zero_bits++; - - uint32_t code = (1<len < 1) - return -1; - int ret = -1; - - nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; - nal->nal_unit_type = buf->buf[0] & 0x1f; - - buf->cur_pos = buf->buf + 1; - //printf("NAL: %d\n", nal->nal_unit_type); - - struct buf_reader ibuf; - ibuf.cur_offset = 8; - - switch(nal->nal_unit_type) { - case NAL_SPS: - decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len-1); - ibuf.cur_pos = ibuf.buf; - if(!nal->sps) - nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); - else - memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); - - parse_sps(&ibuf, nal->sps); - free(ibuf.buf); - ret = NAL_SPS; - break; - case NAL_PPS: - if(!nal->pps) - nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); - else - memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); - - parse_pps(buf, nal->pps); - ret = NAL_PPS; - break; - case NAL_SLICE: - case NAL_PART_A: - case NAL_PART_B: - case NAL_PART_C: - case NAL_SLICE_IDR: - if(nal->sps && nal->pps) { - if(!nal->slc) - nal->slc = malloc(sizeof(struct slice_header)); - else - memset(nal->slc, 0x00, sizeof(struct slice_header)); - - parse_slice_header(buf, nal); - ret = nal->nal_unit_type; - } - break; - default: - ret = nal->nal_unit_type; - break; - } - - return ret; -} - -void skip_scaling_list(struct buf_reader *buf, int size) -{ - int i; - for(i = 0; i < size; i++) { - read_exp_golomb_s(buf); - } -} - -void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index) -{ - int last_scale = 8; - int next_scale = 8; - int32_t delta_scale; - uint8_t use_default_scaling_matrix_flag = 0; - int i; - - for(i = 0; i < length; i++) { - if(next_scale != 0) { - delta_scale = read_exp_golomb_s(buf); - next_scale = (last_scale + delta_scale + 256) % 256; - if(i == 0 && next_scale == 0) { - use_default_scaling_matrix_flag = 1; - break; - } - } - scaling_list = (next_scale == 0) ? last_scale : next_scale; - last_scale = scaling_list->scaling_list[i]; - } - - if(use_default_scaling_matrix_flag) { - switch(index) { - case 0: - case 1: - case 2: - memcpy(scaling_list, length, default_4x4_intra); - break; - case 3: - case 4: - case 5: - memcpy(scaling_list, length, default_4x4_inter); - break; - case 6: - memcpy(scaling_list, length, default_8x8_intra); - break; - case 7: - memcpy(scaling_list, length, default_8x8_inter); - break; - } - } -} - -uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) -{ - sps->profile_idc = buf->buf[0]; - sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; - sps->level_idc = buf->buf[2]; - - buf->cur_pos = buf->buf+3; - sps->seq_parameter_set_id = read_exp_golomb(buf); - if(sps->profile_idc == 100 || sps->profile_idc == 110 || - sps->profile_idc == 122 || sps->profile_idc == 144) { - sps->chroma_format_idc = read_exp_golomb(buf); - if(sps->chroma_format_idc == 3) { - sps->residual_colour_transform_flag = read_bits(buf, 1); - } - - sps->bit_depth_luma_minus8 = read_exp_golomb(buf); - sps->bit_depth_chroma_minus8 = read_exp_golomb(buf); - sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); - sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); - if(sps->seq_scaling_matrix_present_flag) { - int i; - for(i = 0; i < 8; i++) { - sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); - - if(sps->seq_scaling_list_present_flag[i]) { - if(i < 6) - parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); - else - parse_scaling_list(buf, sps->scaling_lists_8x8[i-6], 64, i); - } - } - } - } - - sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); - - sps->pic_order_cnt_type = read_exp_golomb(buf); - if(!sps->pic_order_cnt_type) - sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf); - else { - sps->delta_pic_order_always_zero_flag = read_bits(buf, 1); - sps->offset_for_non_ref_pic = read_exp_golomb_s(buf); - sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf); - sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf); - int i; - for(i=0; inum_ref_frames_in_pic_order_cnt_cycle; i++) { - sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf); - } - } - sps->num_ref_frames = read_exp_golomb(buf); - sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1); - - /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf); - sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/ - sps->pic_width = 16 * (read_exp_golomb(buf) + 1); - sps->pic_height = 16 * (read_exp_golomb(buf) + 1); - - sps->frame_mbs_only_flag = read_bits(buf, 1); - - /* compute the height correctly even for interlaced material */ - sps->pic_height = (2-sps->frame_mbs_only_flag) * sps->pic_height; - if(sps->pic_height == 1088) - sps->pic_height = 1080; - //printf("res: %dx%d\n", sps->pic_width, sps->pic_height); - - if(!sps->frame_mbs_only_flag) - sps->mb_adaptive_frame_field_flag = read_bits(buf, 1); - - sps->direct_8x8_inference_flag = read_bits(buf, 1); - sps->frame_cropping_flag = read_bits(buf, 1); - if(sps->frame_cropping_flag) { - sps->frame_crop_left_offset = read_exp_golomb(buf); - sps->frame_crop_right_offset = read_exp_golomb(buf); - sps->frame_crop_top_offset = read_exp_golomb(buf); - sps->frame_crop_bottom_offset = read_exp_golomb(buf); - } - sps->vui_parameters_present_flag = read_bits(buf, 1); - /*if(sps->vui_parameters_present_flag) - printf("ERROR: vui_parameters is not implemented\n");*/ - - return 0; -} - -uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) -{ - pps->pic_parameter_set_id = read_exp_golomb(buf); - pps->seq_parameter_set_id = read_exp_golomb(buf); - pps->entropy_coding_mode_flag = read_bits(buf, 1); - pps->pic_order_present_flag = read_bits(buf, 1); - - pps->num_slice_groups_minus1 = read_exp_golomp(buf); - if(pps->num_slice_groups_minus1 > 0) { - pps->slice_group_map_type = read_exp_golomb(buf); - if(pps->slice_group_map_type == 0) { - int i_group; - for(i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { - if(i_group < 64) - pps->run_length_minus1[i_group] = read_exp_golomb(buf); - else { // FIXME: skips if more than 64 groups exist - fprintf(stderr, "Error: Only 64 slice_groups are supported\n"); - read_exp_golomb(buf); - } - } - } else if(pps->slice_group_map_type == 3 || - pps->slice_group_map_type == 4 || - pps->slice_group_map_type == 5) { - pps->slice_group_change_direction_flag = read_bits(buf, 1); - pps->slice_group_change_rate_minus1 = read_exp_golomb(buf); - } else if(pps->slice_group_map_type == 6) { - pps->pic_size_in_map_units_minus1 = read_exp_golomb(buf); - int i_group; - for(i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { - pps->slice_group_id[i_group] = - read_bits(buf, ceil(log2(pps->num_slice_groups_minus1 + 1))); - } - } - } - - pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); - pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); - pps->weighted_pred_flag = read_bits(buf, 1); - pps->weighted_bipred_flag = read_bits(buf, 2); - pps->pic_init_qp_minus26 = read_exp_golomb_s(buf); - pps->pic_init_qs_minus26 = read_exp_golomb_s(buf); - pps->chroma_qp_index_offset = read_exp_golomb_s(buf); - pps->deblocking_filter_control_present_flag = read_bits(buf, 1); - pps->constrained_intra_pred_flag = read_bits(buf, 1); - pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); - - if(!rbsp_trailing_bits(buf)) { - pps->transform_8x8_mode_flag = read_bits(buf, 1); - pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); - if(pps->pic_scaling_matrix_present_flag) { - int i; - for(i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { - pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); - - if(pps->pic_scaling_list_present_flag[i]) { - if(i < 6) - parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); - else - parse_scaling_list(buf, pps->scaling_lists_8x8[i-6], 64, i); - } - } - } - - pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); - } - - return 0; -} - -uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal) -{ - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; - struct slice_header *slc = nal->slc; - if(!sps || !pps) - return -1; - - slc->first_mb_in_slice = read_exp_golomb(buf); - slc->slice_type = read_exp_golomb(buf); - slc->pic_parameter_set_id = read_exp_golomb(buf); - slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); - if(!sps->frame_mbs_only_flag) { - slc->field_pic_flag = read_bits(buf, 1); - if(slc->field_pic_flag) - slc->bottom_field_flag = read_bits(buf, 1); - else - slc->bottom_field_flag = -1; - } else { - slc->field_pic_flag = 0; - slc->bottom_field_flag = -1; - } - - if(nal->nal_unit_type == NAL_SLICE_IDR) - slc->idr_pic_id = read_exp_golomb(buf); - - if(!sps->pic_order_cnt_type) { - slc->pic_order_cnt_lsb = read_bits(buf, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - if(pps->pic_order_present_flag && !slc->field_pic_flag) - slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf); - } else if (sps->pic_order_cnt_type == 1) { - slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf); - if(pps->pic_order_present_flag && !slc->field_pic_flag) - slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); - } - /* do not need more information for packetizing */ - - return 0; -} - - - -/* ----------------- NAL parser ----------------- */ - -struct nal_parser* init_parser() -{ - struct nal_parser *parser = malloc(sizeof(struct nal_parser)); - memset(parser->buf, 0x00, MAX_FRAME_SIZE); - parser->buf_len = 0; - parser->found_sps = 0; - parser->found_pps = 0; - parser->nal0 = malloc(sizeof(struct nal_unit)); - memset(parser->nal0, 0x00, sizeof(struct nal_unit)); - parser->nal1 = malloc(sizeof(struct nal_unit)); - memset(parser->nal1, 0x00, sizeof(struct nal_unit)); - parser->current_nal = parser->nal0; - parser->last_nal = parser->nal1; - - parser->last_nal_res = 0; - parser->slice = 0; - parser->field = -1; - parser->have_top = 0; - - return parser; -} - -void free_parser(struct nal_parser *parser) -{ - free(parser->nal0); - free(parser->nal1); - free(parser); -} - -int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, - uint8_t **ret_buf, int *ret_len) -{ - int next_nal; - int parsed_len = 0; - int search_offset = 0; - - while((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len)) >= 0) { - // save buffer up to the nal-start - if(parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; - } - //if(parser->last_nal_res != 1) { - xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, next_nal+search_offset); - parser->buf_len += next_nal+search_offset; - //} - inbuf += next_nal+search_offset; - parsed_len += next_nal+search_offset; - - if((parser->last_nal_res = parse_nal(inbuf+4, inbuf_len-parsed_len, parser)) == 1 - && parser->buf_len>0) { - // parse_nal returned 1 --> detected a frame_boundary - *ret_buf = malloc(parser->buf_len); - xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); - *ret_len = parser->buf_len; - - //memset(parser->buf, 0x00, parser->buf_len); - parser->buf_len = 0; - parser->last_nal_res = 0; - return parsed_len; - } - - search_offset = 4; - } - - // no further NAL found, copy the rest of the stream - // into the buffer -// if(parser->last_nal_res != 1) { - xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len-parsed_len); - parser->buf_len += inbuf_len-parsed_len; -// } - - parsed_len += (inbuf_len-parsed_len); - *ret_len = 0; - *ret_buf = NULL; - - return parsed_len; -} - -int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) -{ - struct buf_reader bufr; - - bufr.buf = buf; - bufr.cur_pos = buf; - bufr.cur_offset = 8; - bufr.len = buf_len; - - struct nal_unit *nal = parser->current_nal; - struct nal_unit *last_nal = parser->last_nal; - - int res = parse_nal_header(&bufr, nal); - - if(res >= NAL_SLICE && res <= NAL_SLICE_IDR) { - // now detect if it's a new frame! - int ret = 0; - if(nal->slc->field_pic_flag == 1) - parser->field = nal->slc->bottom_field_flag; - else { - parser->have_top = 1; - parser->field = -1; - } - - if(nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0) - parser->have_top = 1; - - parser->slice = 1; - - if(nal->slc == NULL || last_nal->slc == NULL) { - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->slc->frame_num != last_nal->slc->frame_num)) { - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->slc->pic_parameter_set_id != last_nal->slc->pic_parameter_set_id)) { - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->slc->field_pic_flag != last_nal->slc->field_pic_flag)) { - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->slc->bottom_field_flag != -1 && - last_nal->slc->bottom_field_flag != -1 && - nal->slc->bottom_field_flag != last_nal->slc->bottom_field_flag)) { - ret = 1; - } - if(nal->nal_ref_idc != last_nal->nal_ref_idc && - (nal->nal_ref_idc == 0 || last_nal->nal_ref_idc == 0)) { - ret = 1; - } - if(nal->sps && nal->slc && last_nal->slc && - (nal->sps->pic_order_cnt_type == 0 && - (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb || - nal->slc->delta_pic_order_cnt_bottom != last_nal->slc->delta_pic_order_cnt_bottom))) { - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->sps->pic_order_cnt_type == 1 && - (nal->slc->delta_pic_order_cnt[0] != last_nal->slc->delta_pic_order_cnt[0] || - nal->slc->delta_pic_order_cnt[1] != last_nal->slc->delta_pic_order_cnt[1]))) { - ret = 1; - } - if(nal->nal_unit_type != last_nal->nal_unit_type && - (nal->nal_unit_type == 5 || last_nal->nal_unit_type == 5)) { - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->nal_unit_type == 5 && last_nal->nal_unit_type == 5 && - nal->slc->idr_pic_id != last_nal->slc->idr_pic_id)) { - ret = 1; - } - - if(parser->current_nal == parser->nal0) { - parser->current_nal = parser->nal1; - parser->last_nal = parser->nal0; - } - else { - parser->current_nal = parser->nal0; - parser->last_nal = parser->nal1; - } - if(parser->current_nal->sps == NULL) - parser->current_nal->sps = parser->last_nal->sps; - if(parser->current_nal->pps == NULL) - parser->current_nal->pps = parser->last_nal->pps; - - /*if(ret) - parser->slice = 0;*/ - /*if(parser->slice && parser->have_top && parser->field != 0) { - parser->have_frame = 1; - parser->have_top = 0; - parser->slice = 0; - return ret; - }*/ - return 0; - } else if(res == NAL_PPS || res == NAL_SPS) { - return 1; - } else if (res == NAL_AU_DELIMITER || res == NAL_SEI || - (res >= 13 && res <= 18)) { - //printf("New Frame\n"); - return 1; - } - - return 0; -} - -int seek_for_nal(uint8_t *buf, int buf_len) -{ - int i; - for(i=0; i - -#include "xine_internal.h" - -enum nal_unit_types { - NAL_UNSPECIFIED = 0, - NAL_SLICE, - NAL_PART_A, - NAL_PART_B, - NAL_PART_C, - NAL_SLICE_IDR, - NAL_SEI, - NAL_SPS, - NAL_PPS, - NAL_AU_DELIMITER, - NAL_END_OF_SEQUENCE, - NAL_END_OF_STREAM, - NAL_FILLER_DATA, - NAL_SPS_EXT -}; - -/* default scaling_lists according to Table 7-2 */ -uint8_t default_4x4_intra[16] = - { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42 }; - -uint8_t default_4x4_inter[16] = - { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34}; - -uint8_t default_8x8_intra[64] = - { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 32, - 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, - 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, - 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; - -uint8_t default_8x8_inter[64] = - { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, - 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, - 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, - 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; - - -struct nal_unit { - uint8_t nal_ref_idc; // 0x03 - uint8_t nal_unit_type; // 0x1f - - struct seq_parameter_set_rbsp *sps; - struct pic_parameter_set_rbsp *pps; - struct slice_header *slc; -}; - -struct seq_parameter_set_rbsp { - uint8_t profile_idc; // 0xff - uint8_t constraint_setN_flag; // 0x0f - uint8_t level_idc; // 0xff - uint32_t seq_parameter_set_id; - uint32_t chroma_format_idc; - uint8_t residual_colour_transform_flag; // 0x01 - uint32_t bit_depth_luma_minus8; - uint32_t bit_depth_chroma_minus8; - uint8_t qpprime_y_zero_transform_bypass_flag; - uint8_t seq_scaling_matrix_present_flag; - - /* if(seq_scaling_matrix_present_flag) */ - { - uint8_t seq_scaling_list_present_flag[8]; - - uint8_t scaling_lists_4x4[6][16]; - uint8_t scaling_lists_8x8[2][64]; - } - - uint32_t log2_max_frame_num_minus4; - uint32_t pic_order_cnt_type; - // if pic_order_cnt_type==0 - uint32_t log2_max_pic_order_cnt_lsb_minus4; - // else - uint8_t delta_pic_order_always_zero_flag; - int32_t offset_for_non_ref_pic; - int32_t offset_for_top_to_bottom_field; - uint8_t num_ref_frames_in_pic_order_cnt_cycle; - int32_t offset_for_ref_frame[256]; - // TODO: some more ignored here - uint32_t num_ref_frames; - uint8_t gaps_in_frame_num_value_allowed_flag; - /*uint32_t pic_width_in_mbs_minus1; - uint32_t pic_height_in_map_units_minus1;*/ - uint32_t pic_width; - uint32_t pic_height; - uint8_t frame_mbs_only_flag; - uint8_t mb_adaptive_frame_field_flag; - uint8_t direct_8x8_inference_flag; - uint8_t frame_cropping_flag; - uint32_t frame_crop_left_offset; - uint32_t frame_crop_right_offset; - uint32_t frame_crop_top_offset; - uint32_t frame_crop_bottom_offset; - uint8_t vui_parameters_present_flag; - // TODO: add vui_parameters, rtbsp_trailing_bits - -}; - -struct pic_parameter_set_rbsp { - uint32_t pic_parameter_set_id; - uint32_t seq_parameter_set_id; - uint8_t entropy_coding_mode_flag; - uint8_t pic_order_present_flag; - - uint32_t num_slice_groups_minus1; - - /* num_slice_groups_minus1 > 0 */ - { - uint32_t slice_group_map_type; - - /* slice_group_map_type == 1 */ - { - uint32_t run_length_minus1[64]; - } - - /* slice_group_map_type == 2 */ - { - uint32_t top_left[64]; - uint32_t bottom_right[64]; - } - - /* slice_group_map_type == 3,4,5 */ - { - uint8_t slice_group_change_direction_flag; - uint32_t slice_group_change_rate_minus1; - } - - /* slice_group_map_type == 6 */ - { - uint32_t pic_size_in_map_units_minus1; - uint8_t slice_group_id[64]; - } - } - - uint32_t num_ref_idx_l0_active_minus1; - uint32_t num_ref_idx_l1_active_minus1; - uint8_t weighted_pred_flag; - uint8_t weighted_bipred_idc; - int32_t pic_init_qp_minus26; - int32_t pic_init_qs_minus26; - int32_t chroma_qp_index_offset; - uint8_t deblocking_filter_control_present_flag; - uint8_t constrained_intra_pred_flag; - uint8_t redundant_pic_cnt_present_flag; - - /* if(more_rbsp_data) */ - uint8_t transform_8x8_mode_flag; - uint8_t pic_scaling_matrix_present_flag; - - /* if(pic_scaling_matrix_present_flag) */ - { - uint8_t pic_scaling_list_present_flag[8]; - - uint8_t scaling_lists_4x4[6][16]; - uint8_t scaling_lists_8x8[2][64]; - - int32_t second_chroma_qp_index_offset; - } -}; - -struct slice_header { - uint32_t first_mb_in_slice; - uint32_t slice_type; - uint32_t pic_parameter_set_id; - uint32_t frame_num; - int8_t field_pic_flag; - int8_t bottom_field_flag; - uint32_t idr_pic_id; - - /* sps->pic_order_cnt_type == 0 */ - uint32_t pic_order_cnt_lsb; - int32_t delta_pic_order_cnt_bottom; - /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */ - int32_t delta_pic_order_cnt[2]; - - /* not needed for packetizing */ - /*int32_t redundant_pic_cnt; - uint8_t direct_spatial_mv_pred_flag;*/ - -}; - - -#define MAX_FRAME_SIZE 1024*1024 - -struct nal_parser { - uint8_t buf[MAX_FRAME_SIZE]; - int buf_len; - int found_sps; - int found_pps; - int last_nal_res; - int field; // 0=top, 1=bottom, -1=both - int slice; - int have_top; - int have_frame; - struct nal_unit *nal0; - struct nal_unit *nal1; - struct nal_unit *current_nal; - struct nal_unit *last_nal; -}; - -int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); - -int seek_for_nal(uint8_t *buf, int buf_len); - -struct nal_parser* init_parser(); -void free_parser(struct nal_parser *parser); -int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, - uint8_t **ret_buf, int *ret_len); - -#endif -- cgit v1.2.3 From 9b8b18236adf6ab7abf540946075eb8ff9c6c790 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 1 Dec 2008 15:12:00 +0000 Subject: Introduce vdpau_accel_t. --- src/video_out/video_out_vdpau.c | 40 ++++++++++++++++++++++++- src/xine-engine/accel_vdpau.h | 65 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/xine-engine/accel_vdpau.h diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 65f276660..dcbea5d8b 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -48,6 +48,7 @@ #include "xineutils.h" #include +#include "accel_vdpau.h" @@ -80,6 +81,11 @@ VdpPresentationQueueDestroy *vdp_queue_destroy; VdpPresentationQueueDisplay *vdp_queue_display; VdpPresentationQueueSetBackgroundColor *vdp_queue_set_backgroung_color; +VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; +VdpDecoderCreate *vdp_decoder_create; +VdpDecoderDestroy *vdp_decoder_destroy; +VdpDecoderRender *vdp_decoder_render; + typedef struct { vo_frame_t vo_frame; @@ -87,6 +93,8 @@ typedef struct { int width, height, format, flags; double ratio; uint8_t *chunk[3]; /* mem alloc by xmalloc_aligned */ + + vdpau_accel_t vdpau_accel_data; } vdpau_frame_t; @@ -289,6 +297,8 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) if (!frame) return NULL; + frame->vo_frame.accel_data = &frame->vdpau_accel_data; + pthread_mutex_init (&frame->vo_frame.mutex, NULL); /* @@ -300,6 +310,14 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vo_frame.dispose = vdpau_frame_dispose; frame->vo_frame.driver = this_gen; + frame->vdpau_accel_data.vdp_device = vdp_device; + frame->vdpau_accel_data.surface = 0; + frame->vdpau_accel_data.vdp_video_surface_create = vdp_video_surface_create; + frame->vdpau_accel_data.vdp_video_surface_destroy = vdp_video_surface_destroy; + frame->vdpau_accel_data.vdp_decoder_create = vdp_decoder_create; + frame->vdpau_accel_data.vdp_decoder_destroy = vdp_decoder_destroy; + frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render; + frame->width = frame->height = 0; return (vo_frame_t *) frame; @@ -421,6 +439,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YUY2 error : %s\n", vdp_get_error_string( st ) ); } + else { + frame->vo_frame.free( &frame->vo_frame ); + return; + } VdpRect vid_source = { this->sc.crop_left, this->sc.crop_top, this->sc.delivered_width-this->sc.crop_right, this->sc.delivered_height-this->sc.crop_bottom }; VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; @@ -429,7 +451,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) /*printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 );*/ st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, - 0, 0, this->soft_surface, 0, 0, &vid_source, this->output_surface, &out_dest, &vid_dest, 0, 0 ); + 0, 0, this->soft_surface, 1, &this->soft_surface, &vid_source, this->output_surface, &out_dest, &vid_dest, 0, 0 ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); @@ -802,6 +824,22 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_SET_BACKGROUND_COLOR proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , (void*)&vdp_decoder_query_capabilities ); + if ( vdpau_init_error( st, "Can't get DECODER_QUERY_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_CREATE , (void*)&vdp_decoder_create ); + if ( vdpau_init_error( st, "Can't get DECODER_CREATE proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_DESTROY , (void*)&vdp_decoder_destroy ); + if ( vdpau_init_error( st, "Can't get DECODER_DESTROY proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_RENDER , (void*)&vdp_decoder_render ); + if ( vdpau_init_error( st, "Can't get DECODER_RENDER proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) ) return NULL; diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h new file mode 100644 index 000000000..39231314c --- /dev/null +++ b/src/xine-engine/accel_vdpau.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2008 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * + * Common acceleration definitions for vdpau + * + * + */ + +#ifndef HAVE_XINE_ACCEL_VDPAU_H +#define HAVE_XINE_ACCEL_VDPAU_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + + +typedef struct { + + VdpDevice vdp_device; + + VdpVideoSurfaceCreate *vdp_video_surface_create; + VdpVideoSurfaceDestroy *vdp_video_surface_destroy; + VdpDecoderCreate *vdp_decoder_create; + VdpDecoderDestroy *vdp_decoder_destroy; + VdpDecoderRender *vdp_decoder_render; + + VdpVideoSurface surface; + + union _VdpPictureInfo { + VdpPictureInfoMPEG1Or2 mpeg; + VdpPictureInfoH264 h264; + VdpPictureInfoVC1 vc1; + } info; + +} vdpau_accel_t; + +#ifdef __cplusplus +} +#endif + +#endif + -- cgit v1.2.3 From a2e278c82f3ceb787f4946bf5eb8a0ceabedd84d Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 1 Dec 2008 18:24:19 +0000 Subject: Enable display of XINE_IMGFMT_VDPAU. --- include/xine.h.in | 2 +- src/video_out/video_out_vdpau.c | 110 +++++++++++++++++++++++++++------------- 2 files changed, 75 insertions(+), 37 deletions(-) diff --git a/include/xine.h.in b/include/xine.h.in index 3bbfb7667..ced7a8757 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -482,7 +482,7 @@ int xine_get_current_frame_data (xine_stream_t *stream, #define XINE_IMGFMT_YUY2 (('2'<<24)|('Y'<<16)|('U'<<8)|'Y') #define XINE_IMGFMT_XVMC (('C'<<24)|('M'<<16)|('v'<<8)|'X') #define XINE_IMGFMT_XXMC (('C'<<24)|('M'<<16)|('x'<<8)|'X') -#define XINE_IMGFMT_VDPAU (('U'<<32)|('A'<<24)|('P'<<16)|('D'<<8)|'V') +#define XINE_IMGFMT_VDPAU (('A'<<24)|('P'<<16)|('D'<<8)|'V') /* get current xine's virtual presentation timestamp (1/90000 sec) * note: this is mostly internal data. diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index dcbea5d8b..5bbbd5784 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -121,8 +121,12 @@ typedef struct { uint32_t output_surface_width; uint32_t output_surface_height; - VdpVideoMixer video_mixer; + VdpVideoMixer video_mixer; + VdpChromaType video_mixer_chroma; + uint32_t video_mixer_width; + uint32_t video_mixer_height; + uint32_t capabilities; xine_t *xine; } vdpau_driver_t; @@ -283,6 +287,8 @@ static void vdpau_frame_dispose (vo_frame_t *vo_img) free (frame->chunk[1]); free (frame->chunk[2]); free (frame); + if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) + vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); } @@ -311,7 +317,7 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vo_frame.driver = this_gen; frame->vdpau_accel_data.vdp_device = vdp_device; - frame->vdpau_accel_data.surface = 0; + frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; frame->vdpau_accel_data.vdp_video_surface_create = vdp_video_surface_create; frame->vdpau_accel_data.vdp_video_surface_destroy = vdp_video_surface_destroy; frame->vdpau_accel_data.vdp_decoder_create = vdp_decoder_create; @@ -346,13 +352,20 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]); frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]); - } else { + } else if (format == XINE_IMGFMT_YUY2){ frame->vo_frame.pitches[0] = 8*((width + 3) / 4); frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); frame->chunk[1] = NULL; frame->chunk[2] = NULL; } + if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) { + if ( (frame->width != width) || (frame->height != height) || (frame->format != XINE_IMGFMT_VDPAU) ) { + vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); + frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; + } + } + frame->width = width; frame->height = height; frame->format = format; @@ -384,7 +397,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_driver_t *this = (vdpau_driver_t *) this_gen; vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; VdpStatus st; - VdpChromaType chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; + VdpVideoSurface surface; + VdpChromaType chroma = this->video_mixer_chroma; + uint32_t mix_w = this->video_mixer_width; + uint32_t mix_h = this->video_mixer_height; if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) || (frame->ratio != this->sc.delivered_ratio) ) { this->sc.force_redraw = 1; /* trigger re-calc of output size */ @@ -400,19 +416,48 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_redraw_needed( this_gen ); - if ( (frame->width > this->soft_surface_width) | (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { - printf( "vo_vdpau: soft_surface size update\n" ); - /* recreate surface and mixer to match frame changes */ - this->soft_surface_width = frame->width; - this->soft_surface_height = frame->height; - this->soft_surface_format = frame->format; - - vdp_video_surface_destroy( this->soft_surface ); - vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); + if ( (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) ) { + surface = this->soft_surface; + chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; + if ( (frame->width > this->soft_surface_width) | (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { + printf( "vo_vdpau: soft_surface size update\n" ); + /* recreate surface and mixer to match frame changes */ + mix_w = this->soft_surface_width = frame->width; + mix_h = this->soft_surface_height = frame->height; + this->soft_surface_format = frame->format; + vdp_video_surface_destroy( this->soft_surface ); + vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); + } + /* FIXME: have to swap U and V planes to get correct colors !! nvidia ? */ + uint32_t pitches[] = { frame->vo_frame.pitches[0], frame->vo_frame.pitches[2], frame->vo_frame.pitches[1] }; + void* data[] = { frame->vo_frame.base[0], frame->vo_frame.base[2], frame->vo_frame.base[1] }; + if ( frame->format==XINE_IMGFMT_YV12 ) { + st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YV12, &data, pitches ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YV12 error : %s\n", vdp_get_error_string( st ) ); + } + else { + st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YUYV, &data, pitches ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YUY2 error : %s\n", vdp_get_error_string( st ) ); + } + } + else if (frame->format == XINE_IMGFMT_VDPAU) { + surface = frame->vdpau_accel_data.surface; + mix_w = frame->width; + mix_h = frame->height; + chroma = VDP_CHROMA_TYPE_420; + } + else { + /* unknown format */ + frame->vo_frame.free( &frame->vo_frame ); + return; + } + if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma) ) { vdp_video_mixer_destroy( this->video_mixer ); VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE }; - void const *param_values[] = { &this->soft_surface_width, &this->soft_surface_height, &chroma }; + void const *param_values[] = { &mix_w, &mix_h, &chroma }; vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); } @@ -426,24 +471,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width, this->output_surface_height, &this->output_surface ); } - /* FIXME: have to swap U and V planes to get correct colors !! nvidia ? */ - uint32_t pitches[] = { frame->vo_frame.pitches[0], frame->vo_frame.pitches[2], frame->vo_frame.pitches[1] }; - void* data[] = { frame->vo_frame.base[0], frame->vo_frame.base[2], frame->vo_frame.base[1] }; - if ( frame->format==XINE_IMGFMT_YV12 ) { - st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YV12, &data, pitches ); - if ( st != VDP_STATUS_OK ) - printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YV12 error : %s\n", vdp_get_error_string( st ) ); - } - else if ( frame->format==XINE_IMGFMT_YUY2 ){ - st = vdp_video_surface_putbits_ycbcr( this->soft_surface, VDP_YCBCR_FORMAT_YUYV, &data, pitches ); - if ( st != VDP_STATUS_OK ) - printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YUY2 error : %s\n", vdp_get_error_string( st ) ); - } - else { - frame->vo_frame.free( &frame->vo_frame ); - return; - } - VdpRect vid_source = { this->sc.crop_left, this->sc.crop_top, this->sc.delivered_width-this->sc.crop_right, this->sc.delivered_height-this->sc.crop_bottom }; VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height }; @@ -451,7 +478,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) /*printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 );*/ st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, - 0, 0, this->soft_surface, 1, &this->soft_surface, &vid_source, this->output_surface, &out_dest, &vid_dest, 0, 0 ); + 0, 0, surface, 0, 0, &vid_source, this->output_surface, &out_dest, &vid_dest, 0, 0 ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); @@ -633,8 +660,9 @@ static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void * static uint32_t vdpau_get_capabilities (vo_driver_t *this_gen) { - uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP; - return capabilities; + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + return this->capabilities; } @@ -869,8 +897,11 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } + this->video_mixer_chroma = chroma; + this->video_mixer_width = this->soft_surface_width; + this->video_mixer_height = this->soft_surface_height; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE }; - void const *param_values[] = { &this->soft_surface_width, &this->soft_surface_height, &chroma }; + void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma }; st = vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); @@ -878,6 +909,13 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } + this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP; + ok = 0; + uint32_t dummy; + vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_H264_BASELINE, &ok, &dummy, &dummy, &dummy, &dummy ); + if ( ok ) + this->capabilities |= VO_CAP_VDPAU_H264; + return &this->vo_driver; } -- cgit v1.2.3 From 0bd66ea5009e84048bc2d0bfa99960802f1dae03 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 1 Dec 2008 18:36:41 +0000 Subject: Decoder initialising (WIP). --- src/Makefile.am | 1 + src/libvdpau/Makefile.am | 17 ++++++++ src/libvdpau/vdpau_h264.c | 98 ++++++++++++++++++++++++++++++++----------- src/xine-engine/accel_vdpau.h | 6 --- 4 files changed, 91 insertions(+), 31 deletions(-) create mode 100644 src/libvdpau/Makefile.am diff --git a/src/Makefile.am b/src/Makefile.am index 6718b4805..cb6236033 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,5 +25,6 @@ SUBDIRS = \ libreal \ libfaad \ libmusepack \ + libvdpau \ post \ combined diff --git a/src/libvdpau/Makefile.am b/src/libvdpau/Makefile.am new file mode 100644 index 000000000..9fb5527bf --- /dev/null +++ b/src/libvdpau/Makefile.am @@ -0,0 +1,17 @@ +include $(top_srcdir)/misc/Makefile.common + +AM_CFLAGS = $(VISIBILITY_FLAG) +AM_LDFLAGS = $(xineplug_ldflags) + +EXTRA_DIST = vdpau_h264.c + +if HAVE_VDPAU +vdpau_h264_module = xineplug_decode_vdpau_h264.la +endif + +xineplug_LTLIBRARIES = $(vdpau_h264_module) \ + xineplug_decode_vdpau_h264.la \ + +xineplug_decode_image_la_SOURCES = nal_parser.c vdpau_h264.c +xineplug_decode_image_la_CFLAGS = $(AM_CFLAGS) $(WAND_CFLAGS) +xineplug_decode_image_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) $(WAND_LIBS) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 638eb749a..afd4561c6 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -36,6 +36,7 @@ #include "buffer.h" #include "xineutils.h" #include "bswap.h" +#include "accel_vdpau.h" #define VIDEOBUFSIZE 128*1024 @@ -63,12 +64,14 @@ typedef struct vdpau_h264_decoder_s { int height; /* the height of a video frame */ double ratio; /* the width to height ratio */ - struct nal_parser *nal_parser /* h264 nal parser. extracts stream data for vdpau */ - VdpPictureInfoH264 vdp_picture_info; + struct nal_parser *nal_parser; /* h264 nal parser. extracts stream data for vdpau */ - /* these are variables exclusive to the foo video decoder */ - unsigned char current_yuv_byte; + VdpDecoderProfile profile; + VdpPictureInfoH264 vdp_picture_info; + vdpau_accel_t *vdpau_accel; + + xine_t *xine } vdpau_h264_decoder_t; @@ -88,7 +91,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; - xine_bmiheader *bih; + + VdpBitstreamBuffer vdp_buffer; + vdp_buffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; vo_frame_t *img; /* video out frame */ @@ -102,32 +107,72 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ - (this->stream->video_out->open) (this->stream->video_out, this->stream); + return; + } - if(this->buf) - free(this->buf); + if (!this->decoder_ok) { + /* parse the first nal packages to retrieve profile type */ + int len = 0; - bih = (xine_bmiheader *) buf->content; - this->width = bih->biWidth; - this->height = bih->biHeight; - this->ratio = (double)this->width/(double)this->height; + while(len < buf->size) { + len += parse_frame(this->parser, buf->content + len, buf->size - len, + &vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes); - if (this->buf) - free (this->buf); - this->bufsize = VIDEOBUFSIZE; - this->buf = malloc(this->bufsize); - this->size = 0; + if(this->nal_parser->current_nal->sps != NULL) { + printf("SPS PARSED\n"); - /* take this opportunity to load the stream/meta info */ - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "foovideo"); + this->width = this->nal_parser->current_nal->sps->pic_width; + this->height = this->nal_parser->current_nal->sps->pic_height; - /* do anything else relating to initializing this decoder */ - this->current_yuv_byte = 0; + /* FIXME: ratio should be calculated in some other way to + * support anamorph codings... + */ + this->ratio = (double)this->width / (double)this->height; - this->decoder_ok = 1; + switch(this->nal_parser->current_nal->sps->profile_idc) { + case 100: + this->profile = VDP_DECODER_PROFILE_H264_HIGH; + break; + case 77: + this->profile = VDP_DECODER_PROFILE_H264_MAIN; + break; + case 66: + default: + this->profile = VDP_DECODER_PROFILE_H264_BASELINE; + break; + } - return; - } else if (this->decoder_ok) { + /* get the vdpau context from vo */ + (this->stream->video_out->open) (this->stream->video_out, this->stream); + img = this->stream->video_out->get_frame (this->stream->video_out, + this->width, this->height, + this->ratio, + XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + + this->vdpau_accel = (vdpau_accel_t*)img->accel_data; + + VdpBool is_supported; + uint32_t max_level, max_references, max_width, max_height; + + VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, + this->profile, &is_supported, &max_level, &max_references, + &max_width, &max_height); + + if(status != OK) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%d)\n", status); + + if(!is_supported) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Profile not supported by VDPAU decoder.\n"); + + if(max_width < this->width || max_height < this->height) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Image size not supported by VDPAU decoder.\n"); + } + + } + + } + + if (this->decoder_ok) { if (this->size + buf->size > this->bufsize) { this->bufsize = this->size + 2 * buf->size; @@ -143,7 +188,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, - XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); + XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); img->duration = this->video_step; img->pts = buf->pts; @@ -226,9 +271,12 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->size = 0; this->stream = stream; + this->xine = stream->xine; this->class = (vdpau_h264_class_t *) class_gen; this->decoder_ok = 0; + this->decoder_initialized = 0; + this->nal_parser = init_parser(); this->buf = NULL; return &this->video_decoder; diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h index 39231314c..ef76fe5ee 100644 --- a/src/xine-engine/accel_vdpau.h +++ b/src/xine-engine/accel_vdpau.h @@ -49,12 +49,6 @@ typedef struct { VdpVideoSurface surface; - union _VdpPictureInfo { - VdpPictureInfoMPEG1Or2 mpeg; - VdpPictureInfoH264 h264; - VdpPictureInfoVC1 vc1; - } info; - } vdpau_accel_t; #ifdef __cplusplus -- cgit v1.2.3 From 1fc8bf061e3de659d84ba84db7265a2b66910284 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 1 Dec 2008 19:47:03 +0000 Subject: First compiling vdpau_h264 decoder. --- src/libvdpau/Makefile.am | 12 +++++------- src/libvdpau/nal_parser.c | 49 +++++++++++++++++++++++++++++++++-------------- src/libvdpau/nal_parser.h | 39 +++---------------------------------- src/libvdpau/vdpau_h264.c | 28 ++++++++++++++------------- 4 files changed, 58 insertions(+), 70 deletions(-) diff --git a/src/libvdpau/Makefile.am b/src/libvdpau/Makefile.am index 9fb5527bf..31afca222 100644 --- a/src/libvdpau/Makefile.am +++ b/src/libvdpau/Makefile.am @@ -3,15 +3,13 @@ include $(top_srcdir)/misc/Makefile.common AM_CFLAGS = $(VISIBILITY_FLAG) AM_LDFLAGS = $(xineplug_ldflags) -EXTRA_DIST = vdpau_h264.c - if HAVE_VDPAU vdpau_h264_module = xineplug_decode_vdpau_h264.la +VDPAU_CFLAGS = -D_ISOC99_SOURCE endif -xineplug_LTLIBRARIES = $(vdpau_h264_module) \ - xineplug_decode_vdpau_h264.la \ +xineplug_LTLIBRARIES = $(vdpau_h264_module) -xineplug_decode_image_la_SOURCES = nal_parser.c vdpau_h264.c -xineplug_decode_image_la_CFLAGS = $(AM_CFLAGS) $(WAND_CFLAGS) -xineplug_decode_image_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) $(WAND_LIBS) +xineplug_decode_vdpau_h264_la_SOURCES = nal_parser.c vdpau_h264.c +xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS) +xineplug_decode_vdpau_h264_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index 8b3265337..7422bd118 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -4,6 +4,26 @@ #include "nal_parser.h" +/* default scaling_lists according to Table 7-2 */ +uint8_t default_4x4_intra[16] = + { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42 }; + +uint8_t default_4x4_inter[16] = + { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34}; + +uint8_t default_8x8_intra[64] = + { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 32, + 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, + 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, + 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; + +uint8_t default_8x8_inter[64] = + { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, + 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, + 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, + 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; + + struct buf_reader { uint8_t *buf; uint8_t *cur_pos; @@ -15,6 +35,7 @@ static inline uint32_t read_bits(struct buf_reader *buf, int len); uint32_t read_exp_golomb(struct buf_reader *buf); int32_t read_exp_golomb_s(struct buf_reader *buf); void skip_scaling_list(struct buf_reader *buf, int size); +void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index); int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal); uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps); @@ -105,8 +126,8 @@ static inline uint8_t rbsp_trailing_bits(struct buf_reader *buf) uint8_t rbsp_trailing_bits = 1; - offset = buf->cur_offset; - pos = buf->cur_pos; + last_offset = buf->cur_offset; + last_pos = buf->cur_pos; if(read_bits(buf, 1) == 1) { @@ -116,8 +137,8 @@ static inline uint8_t rbsp_trailing_bits(struct buf_reader *buf) } // revert buffer - buf->cur_offset = offset; - buf->cur_pos = pos; + buf->cur_offset = last_offset; + buf->cur_pos = last_pos; return rbsp_trailing_bits; } @@ -225,8 +246,8 @@ void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int lengt break; } } - scaling_list = (next_scale == 0) ? last_scale : next_scale; - last_scale = scaling_list->scaling_list[i]; + scaling_list[i] = (next_scale == 0) ? last_scale : next_scale; + last_scale = scaling_list[i]; } if(use_default_scaling_matrix_flag) { @@ -234,18 +255,18 @@ void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int lengt case 0: case 1: case 2: - memcpy(scaling_list, length, default_4x4_intra); + memcpy(scaling_list, default_4x4_intra, length); break; case 3: case 4: case 5: - memcpy(scaling_list, length, default_4x4_inter); + memcpy(scaling_list, default_4x4_inter, length); break; case 6: - memcpy(scaling_list, length, default_8x8_intra); + memcpy(scaling_list, default_8x8_intra, length); break; case 7: - memcpy(scaling_list, length, default_8x8_inter); + memcpy(scaling_list, default_8x8_inter, length); break; } } @@ -341,7 +362,7 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) pps->entropy_coding_mode_flag = read_bits(buf, 1); pps->pic_order_present_flag = read_bits(buf, 1); - pps->num_slice_groups_minus1 = read_exp_golomp(buf); + pps->num_slice_groups_minus1 = read_exp_golomb(buf); if(pps->num_slice_groups_minus1 > 0) { pps->slice_group_map_type = read_exp_golomb(buf); if(pps->slice_group_map_type == 0) { @@ -364,7 +385,7 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) int i_group; for(i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { pps->slice_group_id[i_group] = - read_bits(buf, ceil(log2(pps->num_slice_groups_minus1 + 1))); + read_bits(buf, ceil(log(pps->num_slice_groups_minus1 + 1))); } } } @@ -372,7 +393,7 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); pps->weighted_pred_flag = read_bits(buf, 1); - pps->weighted_bipred_flag = read_bits(buf, 2); + pps->weighted_bipred_idc = read_bits(buf, 2); pps->pic_init_qp_minus26 = read_exp_golomb_s(buf); pps->pic_init_qs_minus26 = read_exp_golomb_s(buf); pps->chroma_qp_index_offset = read_exp_golomb_s(buf); @@ -478,7 +499,7 @@ void free_parser(struct nal_parser *parser) } int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, - uint8_t **ret_buf, int *ret_len, int *ret_slice_cnt) + uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) { int next_nal; int parsed_len = 0; diff --git a/src/libvdpau/nal_parser.h b/src/libvdpau/nal_parser.h index 7a3c4726a..fed12ff0d 100644 --- a/src/libvdpau/nal_parser.h +++ b/src/libvdpau/nal_parser.h @@ -22,26 +22,6 @@ enum nal_unit_types { NAL_SPS_EXT }; -/* default scaling_lists according to Table 7-2 */ -uint8_t default_4x4_intra[16] = - { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42 }; - -uint8_t default_4x4_inter[16] = - { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34}; - -uint8_t default_8x8_intra[64] = - { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 32, - 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, - 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, - 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; - -uint8_t default_8x8_inter[64] = - { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, - 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, - 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, - 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; - - struct nal_unit { uint8_t nal_ref_idc; // 0x03 uint8_t nal_unit_type; // 0x1f @@ -64,12 +44,11 @@ struct seq_parameter_set_rbsp { uint8_t seq_scaling_matrix_present_flag; /* if(seq_scaling_matrix_present_flag) */ - { uint8_t seq_scaling_list_present_flag[8]; uint8_t scaling_lists_4x4[6][16]; uint8_t scaling_lists_8x8[2][64]; - } + /* endif */ uint32_t log2_max_frame_num_minus4; uint32_t pic_order_cnt_type; @@ -110,32 +89,22 @@ struct pic_parameter_set_rbsp { uint32_t num_slice_groups_minus1; /* num_slice_groups_minus1 > 0 */ - { - uint32_t slice_group_map_type; + uint32_t slice_group_map_type; /* slice_group_map_type == 1 */ - { uint32_t run_length_minus1[64]; - } /* slice_group_map_type == 2 */ - { uint32_t top_left[64]; uint32_t bottom_right[64]; - } /* slice_group_map_type == 3,4,5 */ - { uint8_t slice_group_change_direction_flag; uint32_t slice_group_change_rate_minus1; - } /* slice_group_map_type == 6 */ - { uint32_t pic_size_in_map_units_minus1; uint8_t slice_group_id[64]; - } - } uint32_t num_ref_idx_l0_active_minus1; uint32_t num_ref_idx_l1_active_minus1; @@ -153,14 +122,12 @@ struct pic_parameter_set_rbsp { uint8_t pic_scaling_matrix_present_flag; /* if(pic_scaling_matrix_present_flag) */ - { uint8_t pic_scaling_list_present_flag[8]; uint8_t scaling_lists_4x4[6][16]; uint8_t scaling_lists_8x8[2][64]; int32_t second_chroma_qp_index_offset; - } }; struct slice_header { @@ -211,6 +178,6 @@ int seek_for_nal(uint8_t *buf, int buf_len); struct nal_parser* init_parser(); void free_parser(struct nal_parser *parser); int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, - uint8_t **ret_buf, int *ret_len); + uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt); #endif diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index afd4561c6..76612168b 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -37,6 +37,7 @@ #include "xineutils.h" #include "bswap.h" #include "accel_vdpau.h" +#include "nal_parser.h" #define VIDEOBUFSIZE 128*1024 @@ -67,11 +68,13 @@ typedef struct vdpau_h264_decoder_s { struct nal_parser *nal_parser; /* h264 nal parser. extracts stream data for vdpau */ + VdpDecoder decoder; + VdpDecoderProfile profile; VdpPictureInfoH264 vdp_picture_info; vdpau_accel_t *vdpau_accel; - xine_t *xine + xine_t *xine; } vdpau_h264_decoder_t; @@ -113,10 +116,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if (!this->decoder_ok) { /* parse the first nal packages to retrieve profile type */ int len = 0; + uint32_t slice_count; while(len < buf->size) { - len += parse_frame(this->parser, buf->content + len, buf->size - len, - &vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes); + len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, + (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); if(this->nal_parser->current_nal->sps != NULL) { printf("SPS PARSED\n"); @@ -151,21 +155,20 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->vdpau_accel = (vdpau_accel_t*)img->accel_data; - VdpBool is_supported; - uint32_t max_level, max_references, max_width, max_height; + /*VdpBool is_supported; + uint32_t max_level, max_references, max_width, max_height;*/ VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, - this->profile, &is_supported, &max_level, &max_references, - &max_width, &max_height); + this->profile, this->width, this->height, &this->decoder); - if(status != OK) + if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%d)\n", status); - if(!is_supported) + /*if(!is_supported) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Profile not supported by VDPAU decoder.\n"); if(max_width < this->width || max_height < this->height) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Image size not supported by VDPAU decoder.\n"); + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Image size not supported by VDPAU decoder.\n");*/ } } @@ -194,9 +197,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->pts = buf->pts; img->bad_frame = 0; - memset(img->base[0], this->current_yuv_byte, + memset(img->base[0], 0, this->width * this->height * 2); - this->current_yuv_byte += 3; img->draw(img, this->stream); img->free(img); @@ -260,7 +262,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t)); /* the videoout must be vdpau-capable to support this decoder */ - if(!stream->video_driver->get_capabilities() & VO_CAP_VDPAU_H264) + if(!stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) return NULL; this->video_decoder.decode_data = vdpau_h264_decode_data; -- cgit v1.2.3 From 8ae1f8fc87c53685251a16f5f535149778096dc9 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 1 Dec 2008 19:51:40 +0000 Subject: Needed for autogen to work. --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 5c876eae8..65d635e40 100644 --- a/configure.ac +++ b/configure.ac @@ -2744,6 +2744,7 @@ src/libmad/Makefile src/libmpeg2/Makefile src/libmusepack/Makefile src/libmusepack/musepack/Makefile +src/libvdpau/Makefile src/libspudec/Makefile src/libspucc/Makefile src/libspucmml/Makefile -- cgit v1.2.3 From e1d660bdadaa9dcf6997dcef931db79bc071ee1f Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 1 Dec 2008 20:22:49 +0000 Subject: Filling almost all information the decoder needs. --- src/libvdpau/vdpau_h264.c | 95 +++++++++++++++++++++++++++++------------------ 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 76612168b..6f0b1315d 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -111,9 +111,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ return; - } + } else { - if (!this->decoder_ok) { /* parse the first nal packages to retrieve profile type */ int len = 0; uint32_t slice_count; @@ -122,8 +121,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); - if(this->nal_parser->current_nal->sps != NULL) { - printf("SPS PARSED\n"); + if(!this->decoder_initialized && + this->nal_parser->current_nal->sps != NULL) { this->width = this->nal_parser->current_nal->sps->pic_width; this->height = this->nal_parser->current_nal->sps->pic_height; @@ -157,12 +156,17 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /*VdpBool is_supported; uint32_t max_level, max_references, max_width, max_height;*/ + xprintf(this->xine, XINE_VERBOSITY_LOG, + "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n", + this->vdpau_accel->vdp_device, this->profile, this->width, this->height); VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, this->profile, this->width, this->height, &this->decoder); if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%d)\n", status); + else + this->decoder_initialized = 1; /*if(!is_supported) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Profile not supported by VDPAU decoder.\n"); @@ -171,41 +175,60 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Image size not supported by VDPAU decoder.\n");*/ } + if(this->nal_parser->current_nal->slc != NULL && + this->nal_parser->current_nal->sps != NULL && + this->nal_parser->current_nal->pps != NULL) { + + struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; + struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; + struct slice_header *slc = this->nal_parser->current_nal->slc; + + /* go and decode a frame */ + VdpPictureInfoH264 pic; + + pic.slice_count = slice_count; + pic.field_order_cnt[0] = 0; // FIXME + pic.is_reference = 1; // FIXME + pic.frame_num = slc->frame_num; + pic.field_pic_flag = slc->field_pic_flag; + pic.bottom_field_flag = slc->bottom_field_flag; + pic.num_ref_frames = sps->num_ref_frames; + pic.mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; + pic.constrained_intra_pred_flag = pps->constrained_intra_pred_flag; + pic.weighted_pred_flag = pps->weighted_pred_flag; + pic.weighted_bipred_idc = pps->weighted_bipred_idc; + pic.frame_mbs_only_flag = sps->frame_mbs_only_flag; + pic.transform_8x8_mode_flag = pps->transform_8x8_mode_flag; + pic.chroma_qp_index_offset = pps->chroma_qp_index_offset; + pic.second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; + pic.pic_init_qp_minus26 = pps->pic_init_qp_minus26; + pic.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1; + pic.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1; + pic.log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; + pic.pic_order_cnt_type = sps->pic_order_cnt_type; + pic.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4; + pic.delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; + pic.direct_8x8_inference_flag = sps->direct_8x8_inference_flag; + pic.entropy_coding_mode_flag = pps->entropy_coding_mode_flag; + pic.pic_order_present_flag = pps->pic_order_present_flag; + pic.deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; + pic.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; + memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); + memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); + + img->duration = this->video_step; + img->pts = buf->pts; + img->bad_frame = 0; + + this->vdpau_accel->vdp_decoder_render(this->vdpau_accel->vdp_device, + this->vdpau_accel->surface, &pic, 1, (VdpPictureInfo*)&vdp_buffer); + + img->draw(img, this->stream); + img->free(img); + } } } - - if (this->decoder_ok) { - - if (this->size + buf->size > this->bufsize) { - this->bufsize = this->size + 2 * buf->size; - this->buf = realloc (this->buf, this->bufsize); - } - - xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); - - this->size += buf->size; - - if (buf->decoder_flags & BUF_FLAG_FRAME_END) { - - img = this->stream->video_out->get_frame (this->stream->video_out, - this->width, this->height, - this->ratio, - XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); - - img->duration = this->video_step; - img->pts = buf->pts; - img->bad_frame = 0; - - memset(img->base[0], 0, - this->width * this->height * 2); - - img->draw(img, this->stream); - img->free(img); - - this->size = 0; - } - } } /* -- cgit v1.2.3 From ba153b5724731308f313e0f5d7231d351a795b98 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 1 Dec 2008 20:30:30 +0000 Subject: Fix VO caps misdetection. --- src/libvdpau/vdpau_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 6f0b1315d..011986312 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -285,7 +285,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t)); /* the videoout must be vdpau-capable to support this decoder */ - if(!stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) + if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) ) return NULL; this->video_decoder.decode_data = vdpau_h264_decode_data; -- cgit v1.2.3 From 833e829c33d3c9a77674e89fb6efacf6b43ad68a Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 1 Dec 2008 20:37:43 +0000 Subject: No segfault any more... --- src/libvdpau/vdpau_h264.c | 129 +++++++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 52 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 011986312..5ca120b04 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -168,6 +168,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, else this->decoder_initialized = 1; + img->free(img); + /*if(!is_supported) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Profile not supported by VDPAU decoder.\n"); @@ -175,56 +177,79 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Image size not supported by VDPAU decoder.\n");*/ } - if(this->nal_parser->current_nal->slc != NULL && - this->nal_parser->current_nal->sps != NULL && - this->nal_parser->current_nal->pps != NULL) { - - struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; - struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; - struct slice_header *slc = this->nal_parser->current_nal->slc; - - /* go and decode a frame */ - VdpPictureInfoH264 pic; - - pic.slice_count = slice_count; - pic.field_order_cnt[0] = 0; // FIXME - pic.is_reference = 1; // FIXME - pic.frame_num = slc->frame_num; - pic.field_pic_flag = slc->field_pic_flag; - pic.bottom_field_flag = slc->bottom_field_flag; - pic.num_ref_frames = sps->num_ref_frames; - pic.mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; - pic.constrained_intra_pred_flag = pps->constrained_intra_pred_flag; - pic.weighted_pred_flag = pps->weighted_pred_flag; - pic.weighted_bipred_idc = pps->weighted_bipred_idc; - pic.frame_mbs_only_flag = sps->frame_mbs_only_flag; - pic.transform_8x8_mode_flag = pps->transform_8x8_mode_flag; - pic.chroma_qp_index_offset = pps->chroma_qp_index_offset; - pic.second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; - pic.pic_init_qp_minus26 = pps->pic_init_qp_minus26; - pic.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1; - pic.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1; - pic.log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; - pic.pic_order_cnt_type = sps->pic_order_cnt_type; - pic.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4; - pic.delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; - pic.direct_8x8_inference_flag = sps->direct_8x8_inference_flag; - pic.entropy_coding_mode_flag = pps->entropy_coding_mode_flag; - pic.pic_order_present_flag = pps->pic_order_present_flag; - pic.deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; - pic.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; - memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); - memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); - - img->duration = this->video_step; - img->pts = buf->pts; - img->bad_frame = 0; - - this->vdpau_accel->vdp_decoder_render(this->vdpau_accel->vdp_device, - this->vdpau_accel->surface, &pic, 1, (VdpPictureInfo*)&vdp_buffer); - - img->draw(img, this->stream); - img->free(img); + if(this->decoder_initialized) { + if(this->nal_parser->current_nal->slc != NULL && + this->nal_parser->current_nal->sps != NULL && + this->nal_parser->current_nal->pps != NULL) { + + img = this->stream->video_out->get_frame (this->stream->video_out, + this->width, this->height, + this->ratio, + XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + this->vdpau_accel = (vdpau_accel_t*)img->accel_data; + + struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; + struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; + struct slice_header *slc = this->nal_parser->current_nal->slc; + + /* go and decode a frame */ + VdpPictureInfoH264 pic; + + pic.slice_count = slice_count; + pic.field_order_cnt[0] = 0; // FIXME + pic.is_reference = 1; // FIXME + pic.frame_num = slc->frame_num; + pic.field_pic_flag = slc->field_pic_flag; + pic.bottom_field_flag = slc->bottom_field_flag; + pic.num_ref_frames = sps->num_ref_frames; + pic.mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; + pic.constrained_intra_pred_flag = pps->constrained_intra_pred_flag; + pic.weighted_pred_flag = pps->weighted_pred_flag; + pic.weighted_bipred_idc = pps->weighted_bipred_idc; + pic.frame_mbs_only_flag = sps->frame_mbs_only_flag; + pic.transform_8x8_mode_flag = pps->transform_8x8_mode_flag; + pic.chroma_qp_index_offset = pps->chroma_qp_index_offset; + pic.second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; + pic.pic_init_qp_minus26 = pps->pic_init_qp_minus26; + pic.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1; + pic.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1; + pic.log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; + pic.pic_order_cnt_type = sps->pic_order_cnt_type; + pic.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4; + pic.delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; + pic.direct_8x8_inference_flag = sps->direct_8x8_inference_flag; + pic.entropy_coding_mode_flag = pps->entropy_coding_mode_flag; + pic.pic_order_present_flag = pps->pic_order_present_flag; + pic.deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; + pic.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; + memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); + memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); + + img->duration = this->video_step; + img->pts = buf->pts; + img->bad_frame = 0; + + /* create surface if needed */ + if(this->vdpau_accel->surface == 0) { + VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, + VDP_YCBCR_FORMAT_YV12, this->width, this->height, + &this->vdpau_accel->surface); + + if(status != VDP_STATUS_OK) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); + else + printf("surface cerated"); + } + + VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, + this->vdpau_accel->surface, &pic, 1, (VdpPictureInfo*)&vdp_buffer); + + if(status != VDP_STATUS_OK) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %d\n", status); + + img->draw(img, this->stream); + img->free(img); + } } } @@ -285,8 +310,8 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t)); /* the videoout must be vdpau-capable to support this decoder */ - if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) ) - return NULL; + /*if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) ) + return NULL;*/ this->video_decoder.decode_data = vdpau_h264_decode_data; this->video_decoder.flush = vdpau_h264_flush; -- cgit v1.2.3 From c81918d927a1bfec86c45fcf293d35f0ef8a3431 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 1 Dec 2008 20:39:58 +0000 Subject: First picture. --- src/libvdpau/vdpau_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 5ca120b04..0559c66d7 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -230,7 +230,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->bad_frame = 0; /* create surface if needed */ - if(this->vdpau_accel->surface == 0) { + if(this->vdpau_accel->surface == VDP_INVALID_HANDLE) { VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, VDP_YCBCR_FORMAT_YV12, this->width, this->height, &this->vdpau_accel->surface); -- cgit v1.2.3 From e7037ea0808a464e87cd3b3446d05ccc8dddab42 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 1 Dec 2008 20:43:16 +0000 Subject: Fix image format. --- src/libvdpau/vdpau_h264.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 0559c66d7..841a94eb1 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -232,13 +232,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /* create surface if needed */ if(this->vdpau_accel->surface == VDP_INVALID_HANDLE) { VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, - VDP_YCBCR_FORMAT_YV12, this->width, this->height, + VDP_CHROMA_TYPE_420, this->width, this->height, &this->vdpau_accel->surface); if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); - else - printf("surface cerated"); } VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, -- cgit v1.2.3 From bd3cfd3d8236c6c8485b1d0b3d9836ba1d1305a5 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 1 Dec 2008 21:06:57 +0000 Subject: Fix vo_cap_vdpau_h264. --- src/video_out/video_out_vdpau.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 5bbbd5784..7d5da96c1 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -911,11 +911,16 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP; ok = 0; - uint32_t dummy; - vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_H264_BASELINE, &ok, &dummy, &dummy, &dummy, &dummy ); - if ( ok ) + uint32_t mw, mh, ml, mr; + st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_H264_MAIN, &ok, &ml, &mr, &mw, &mh ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: getting h264_supported failed! : %s\n", vdp_get_error_string( st ) ); + else if ( !ok ) + printf( "vo_vdpau: no support for h264 ! : no ok\n" ); + else this->capabilities |= VO_CAP_VDPAU_H264; + return &this->vo_driver; } -- cgit v1.2.3 From bea579e29627546d3c09219a5b01d157d3774ba8 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 2 Dec 2008 13:41:36 +0000 Subject: Parser additions. Hopefully all we need now... --- src/libvdpau/nal_parser.c | 189 +++++++++++++++++++++++++++++++++++++++++++--- src/libvdpau/nal_parser.h | 82 +++++++++++++++++++- 2 files changed, 256 insertions(+), 15 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index 7422bd118..ebe9d562f 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -40,7 +40,9 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal); uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps); uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal); - +void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); +void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); +void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_unit *nal); static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) { @@ -433,7 +435,8 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal) return -1; slc->first_mb_in_slice = read_exp_golomb(buf); - slc->slice_type = read_exp_golomb(buf); + /* we do some parsing on the slice type, because the list is doubled */ + slc->slice_type = slice_type(read_exp_golomb(buf)); slc->pic_parameter_set_id = read_exp_golomb(buf); slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); if(!sps->frame_mbs_only_flag) { @@ -459,11 +462,182 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal) if(pps->pic_order_present_flag && !slc->field_pic_flag) slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); } - /* do not need more information for packetizing */ + + if(pps->redundant_pic_cnt_present_flag == 1) { + slc->redundant_pic_cnt = read_exp_golomb(buf); + } + + if(slc->slice_type == SLICE_B) + slc->direct_spatial_mv_pred_flag = read_bits(buf, 1); + + if(slc->slice_type == SLICE_P || + slc->slice_type == SLICE_SP || + slc->slice_type == SLICE_B) { + slc->num_ref_idx_active_override_flag = read_bits(buf, 1); + + if(slc->num_ref_idx_active_override_flag == 1) { + slc->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); + + if(slc->slice_type == SLICE_B) { + slc->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); + } + } + } + + /* --- ref_pic_list_reordering --- */ + parse_ref_pic_list_reordering(buf, nal); + + /* --- pred_weight_table --- */ + if((pps->weighted_pred_flag && + (slc->slice_type == SLICE_P || slc->slice_type == SLICE_SP)) || + (pps->weighted_bipred_idc == 1 && slc->slice_type == SLICE_B)) { + parse_pred_weight_table(buf, nal); + } + + /* --- dec_ref_pic_marking --- */ + if(nal->nal_ref_idc != 0) + parse_dec_ref_pic_marking(buf, nal); return 0; } +void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if(!sps || !pps) + return; + + if(slc->slice_type != SLICE_I && slc->slice_type != SLICE_SI) { + slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 = read_bits(buf, 1); + + if(slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 == 1) { + do { + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc = read_exp_golomb(buf); + + if(slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 || + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { + slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 = read_exp_golomb(buf); + } else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { + slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); + } + } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); + } + } + + if(slc->slice_type == SLICE_B) { + slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 = read_bits(buf, 1); + + if(slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 == 1) { + do { + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc = read_exp_golomb(buf); + + if(slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 || + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { + slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 = read_exp_golomb(buf); + } else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { + slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); + } + } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); + } + } +} + +void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if(!sps || !pps) + return; + + nal->slc->pred_weight_table.luma_log2_weight_denom = read_exp_golomb(buf); + + if(sps->chroma_format_idc != 0) + nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); + + int i; + for(i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) { + uint8_t luma_weight_l0_flag = read_bits(buf, 1); + + if(luma_weight_l0_flag == 1 ) { + nal->slc->pred_weight_table.luma_weight_l0[i] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.luma_offset_l0[i] = read_exp_golomb_s(buf); + } + + if(sps->chroma_format_idc != 0) { + uint8_t chroma_weight_l0_flag = read_bits(buf, 1); + + if(chroma_weight_l0_flag == 1 ) { + int j; + for(j = 0; j < 2 ; j++) { + nal->slc->pred_weight_table.chroma_weight_l0[i][j] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.chroma_offset_l0[i][j] = read_exp_golomb_s(buf); + } + } + } + } + + if(slc->slice_type == SLICE_B) { + for(i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) { + uint8_t luma_weight_l1_flag = read_bits(buf, 1); + + if(luma_weight_l1_flag == 1 ) { + nal->slc->pred_weight_table.luma_weight_l1[i] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.luma_offset_l1[i] = read_exp_golomb_s(buf); + } + + if(sps->chroma_format_idc != 0) { + uint8_t chroma_weight_l1_flag = read_bits(buf, 1); + + if(chroma_weight_l1_flag == 1 ) { + int j; + for(j = 0; j < 2 ; j++) { + nal->slc->pred_weight_table.chroma_weight_l1[i][j] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.chroma_offset_l1[i][j] = read_exp_golomb_s(buf); + } + } + } + } + } +} + +void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if(!sps || !pps) + return; + + if(nal->nal_unit_type == NAL_SLICE_IDR) { + slc->dec_ref_pic_marking.no_output_of_prior_pics_flag = read_bits(buf, 1); + slc->dec_ref_pic_marking.long_term_reference_flag = read_bits(buf, 1); + } else { + slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = read_bits(buf, 1); + + if(slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) { + do { + slc->dec_ref_pic_marking.memory_management_control_operation = read_exp_golomb(buf); + + if(slc->dec_ref_pic_marking.memory_management_control_operation == 1 || + slc->dec_ref_pic_marking.memory_management_control_operation == 3) + slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 = read_exp_golomb(buf); + + if(slc->dec_ref_pic_marking.memory_management_control_operation == 2) + slc->dec_ref_pic_marking.long_term_pic_num = read_exp_golomb(buf); + + if(slc->dec_ref_pic_marking.memory_management_control_operation == 3 || + slc->dec_ref_pic_marking.memory_management_control_operation == 6) + slc->dec_ref_pic_marking.long_term_frame_idx = read_exp_golomb(buf); + + if(slc->dec_ref_pic_marking.memory_management_control_operation == 4) + slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 = read_exp_golomb(buf); + } while(slc->dec_ref_pic_marking.memory_management_control_operation != 0); + } + } +} /* ----------------- NAL parser ----------------- */ @@ -642,15 +816,6 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) if(parser->current_nal->pps == NULL) parser->current_nal->pps = parser->last_nal->pps; - /*if(ret) - parser->slice = 0;*/ - /*if(parser->slice && parser->have_top && parser->field != 0) { - parser->have_frame = 1; - parser->have_top = 0; - parser->slice = 0; - return ret; - }*/ - /* increase the slice_cnt until a new frame is detected */ if(!ret) parser->slice_cnt++; diff --git a/src/libvdpau/nal_parser.h b/src/libvdpau/nal_parser.h index fed12ff0d..609f700a1 100644 --- a/src/libvdpau/nal_parser.h +++ b/src/libvdpau/nal_parser.h @@ -22,6 +22,19 @@ enum nal_unit_types { NAL_SPS_EXT }; +/* slice types repeat from 5-9, we + * need a helper function for comparison + */ +enum slice_types { + SLICE_P = 0, + SLICE_B, + SLICE_I, + SLICE_SP, + SLICE_SI +}; + +static inline uint32_t slice_type(uint32_t slice_type) { return (slice_type < 10 ? slice_type % 5 : slice_type); } + struct nal_unit { uint8_t nal_ref_idc; // 0x03 uint8_t nal_unit_type; // 0x1f @@ -145,10 +158,73 @@ struct slice_header { /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */ int32_t delta_pic_order_cnt[2]; - /* not needed for packetizing */ - /*int32_t redundant_pic_cnt; - uint8_t direct_spatial_mv_pred_flag;*/ + /* pps->redundant_pic_cnt_present_flag == 1 */ + int32_t redundant_pic_cnt; + + /* slice_type == B */ + uint8_t direct_spatial_mv_pred_flag; + + /* slice_type == P, SP, B */ + uint8_t num_ref_idx_active_override_flag; + /* num_ref_idx_active_override_flag == 1 */ + uint32_t num_ref_idx_l0_active_minus1; + /* slice type == B */ + uint32_t num_ref_idx_l1_active_minus1; + + /* ref_pic_list_reordering */ + union { + /* slice_type != I && slice_type != SI */ + uint8_t ref_pic_list_reordering_flag_l0; + + /* slice_type == B */ + uint8_t ref_pic_list_reordering_flag_l1; + + /* ref_pic_list_reordering_flag_l0 == 1 */ + uint32_t reordering_of_pic_nums_idc; + + /* reordering_of_pic_nums_idc == 0, 1 */ + uint32_t abs_diff_pic_num_minus1; + + /* reordering_of_pic_nums_idc == 2) */ + uint32_t long_term_pic_num; + } ref_pic_list_reordering; + + /* pred_weight_table */ + union { + uint32_t luma_log2_weight_denom; + + /* chroma_format_idc != 0 */ + uint32_t chroma_log2_weight_denom; + + int32_t luma_weight_l0[31]; + int32_t luma_offset_l0[31]; + + int32_t chroma_weight_l0[31][2]; + int32_t chroma_offset_l0[31][2]; + + int32_t luma_weight_l1[31]; + int32_t luma_offset_l1[31]; + + int32_t chroma_weight_l1[31][2]; + int32_t chroma_offset_l1[31][2]; + } pred_weight_table; + + /* def_rec_pic_marking */ + union { + + /* nal_unit_type == NAL_SLICE_IDR */ + uint8_t no_output_of_prior_pics_flag; + uint8_t long_term_reference_flag; + + /* else */ + uint8_t adaptive_ref_pic_marking_mode_flag; + uint32_t memory_management_control_operation; + uint32_t difference_of_pic_nums_minus1; + uint32_t long_term_pic_num; + uint32_t long_term_frame_idx; + uint32_t max_long_term_frame_idx_plus1; + } dec_ref_pic_marking; }; -- cgit v1.2.3 From 564fd8cec68835856a2cfe9f313eb64989e6c6f9 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 2 Dec 2008 15:51:18 +0000 Subject: More extensions to the parser, fixes in the decoder. --- src/libvdpau/nal_parser.c | 124 ++++++++++++++++++++++++++++++++++++++++++++-- src/libvdpau/nal_parser.h | 122 +++++++++++++++++++++++++++++++++++++++++---- src/libvdpau/vdpau_h264.c | 12 +++-- 3 files changed, 240 insertions(+), 18 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index ebe9d562f..9835cb1a4 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -34,10 +34,14 @@ struct buf_reader { static inline uint32_t read_bits(struct buf_reader *buf, int len); uint32_t read_exp_golomb(struct buf_reader *buf); int32_t read_exp_golomb_s(struct buf_reader *buf); + +void calculate_pic_order(struct nal_parser *parser); void skip_scaling_list(struct buf_reader *buf, int size); void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index); int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal); uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); +void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); +void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd); uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps); uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal); void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); @@ -223,6 +227,27 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal) return ret; } +void calculate_pic_order(struct nal_parser *parser) +{ + struct nal_unit *nal = parser->current_nal; + + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if(!sps || !pps) + return; + + if(sps->pic_order_cnt_type == 0) { + if(nal->nal_unit_type == NAL_SLICE_IDR) { + parser->prev_pic_order_cnt_lsb = 0; + parser->prev_pic_order_cnt_msb = 0; + } else { + + } + } + +} + void skip_scaling_list(struct buf_reader *buf, int size) { int i; @@ -351,12 +376,99 @@ uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) sps->frame_crop_bottom_offset = read_exp_golomb(buf); } sps->vui_parameters_present_flag = read_bits(buf, 1); - /*if(sps->vui_parameters_present_flag) - printf("ERROR: vui_parameters is not implemented\n");*/ + if(sps->vui_parameters_present_flag) { + parse_vui_parameters(buf, sps); + } return 0; } +void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) +{ + sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.aspect_ration_info_present_flag == 1) { + sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8); + if(sps->vui_parameters.aspect_ratio_idc == ASPECT_RESERVED) { + sps->vui_parameters.sar_width = read_bits(buf, 16); + sps->vui_parameters.sar_height = read_bits(buf, 16); + } + } + + sps->vui_parameters.overscan_info_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.overscan_info_present_flag) { + sps->vui_parameters.overscan_appropriate_flag = read_bits(buf, 1); + } + + sps->vui_parameters.video_signal_type_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.video_signal_type_present_flag) { + sps->vui_parameters.video_format = read_bits(buf, 3); + sps->vui_parameters.video_full_range_flag = read_bits(buf, 1); + sps->vui_parameters.colour_description_present = read_bits(buf, 1); + if(sps->vui_parameters.colour_description_present) { + sps->vui_parameters.colour_primaries = read_bits(buf, 8); + sps->vui_parameters.transfer_characteristics = read_bits(buf, 8); + sps->vui_parameters.matrix_coefficients = read_bits(buf, 8); + } + } + + sps->vui_parameters.chroma_loc_info_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.chroma_loc_info_present_flag) { + sps->vui_parameters.chroma_sample_loc_type_top_field = read_exp_golomb(buf); + sps->vui_parameters.chroma_sample_loc_type_bottom_field = read_exp_golomb(buf); + } + + sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.timing_info_present_flag) { + sps->vui_parameters.num_units_in_tick = read_bits(buf, 32); + sps->vui_parameters.time_scale = read_bits(buf, 32); + sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1); + } + + sps->vui_parameters.nal_hrd_parameters_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.nal_hrd_parameters_present_flag) + parse_hrd_parameters(buf, &sps->vui_parameters.nal_hrd_parameters); + + sps->vui_parameters.vc1_hrd_parameters_present_flag = read_bits(buf, 1); + if(sps->vui_parameters.vc1_hrd_parameters_present_flag) + parse_hrd_parameters(buf, &sps->vui_parameters.vc1_hrd_parameters); + + if(sps->vui_parameters.nal_hrd_parameters_present_flag || + sps->vui_parameters.vc1_hrd_parameters_present_flag) + sps->vui_parameters.low_delay_hrd_flag = read_bits(buf, 1); + + sps->vui_parameters.pic_struct_present_flag = read_bits(buf, 1); + sps->vui_parameters.bitstream_restriction_flag = read_bits(buf, 1); + + if(sps->vui_parameters.bitstream_restriction_flag) { + sps->vui_parameters.motion_vectors_over_pic_boundaries = read_bits(buf, 1); + sps->vui_parameters.max_bytes_per_pic_denom = read_exp_golomb(buf); + sps->vui_parameters.max_bits_per_mb_denom = read_exp_golomb(buf); + sps->vui_parameters.log2_max_mv_length_horizontal = read_exp_golomb(buf); + sps->vui_parameters.log2_max_mv_length_vertical = read_exp_golomb(buf); + sps->vui_parameters.num_reorder_frames = read_exp_golomb(buf); + sps->vui_parameters.max_dec_frame_buffering = read_exp_golomb(buf); + } +} + +void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd) +{ + hrd->cpb_cnt_minus1 = read_exp_golomb(buf); + hrd->bit_rate_scale = read_bits(buf, 4); + hrd->cpb_size_scale = read_bits(buf, 4); + + int i; + for(i = 0; i <= hrd->cpb_cnt_minus1; i++) { + hrd->bit_rate_value_minus1[i] = read_exp_golomb(buf); + hrd->cpb_size_value_minus1[i] = read_exp_golomb(buf); + hrd->cbr_flag[i] = read_bits(buf, 1); + } + + hrd->initial_cpb_removal_delay_length_minus1 = read_bits(buf, 5); + hrd->cpb_removal_delay_length_minus1 = read_bits(buf, 5); + hrd->dpb_output_delay_length_minus1 = read_bits(buf, 5); + hrd->time_offset_length = read_bits(buf, 5); +} + uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) { pps->pic_parameter_set_id = read_exp_golomb(buf); @@ -740,6 +852,8 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) int res = parse_nal_header(&bufr, nal); + calculate_pic_order(parser); + if(res >= NAL_SLICE && res <= NAL_SLICE_IDR) { // now detect if it's a new frame! int ret = 0; @@ -822,14 +936,14 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) return ret; } else if(res == NAL_PPS || res == NAL_SPS) { - return 1; + return 0; } else if (res == NAL_AU_DELIMITER || res == NAL_SEI || (res >= 13 && res <= 18)) { //printf("New Frame\n"); - return 1; + return 0; } - return 0; + return 1; } int seek_for_nal(uint8_t *buf, int buf_len) diff --git a/src/libvdpau/nal_parser.h b/src/libvdpau/nal_parser.h index 609f700a1..792f2e0f2 100644 --- a/src/libvdpau/nal_parser.h +++ b/src/libvdpau/nal_parser.h @@ -33,6 +33,27 @@ enum slice_types { SLICE_SI }; +enum aspect_ratio { + ASPECT_UNSPECIFIED = 0, + ASPECT_1_1, + ASPECT_12_11, + ASPECT_10_11, + ASPECT_16_11, + ASPECT_40_33, + ASPECT_24_11, + ASPECT_20_11, + ASPECT_32_11, + ASPECT_80_33, + ASPECT_18_11, + ASPECT_15_11, + ASPECT_64_33, + ASPECT_160_99, + ASPECT_4_3, + ASPECT_3_2, + ASPECT_2_1, + ASPECT_RESERVED +}; + static inline uint32_t slice_type(uint32_t slice_type) { return (slice_type < 10 ? slice_type % 5 : slice_type); } struct nal_unit { @@ -44,6 +65,21 @@ struct nal_unit { struct slice_header *slc; }; +struct hrd_parameters { + uint32_t cpb_cnt_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + + uint32_t bit_rate_value_minus1[32]; + uint32_t cpb_size_value_minus1[32]; + uint8_t cbr_flag[32]; + + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + uint8_t time_offset_length; +}; + struct seq_parameter_set_rbsp { uint8_t profile_idc; // 0xff uint8_t constraint_setN_flag; // 0x0f @@ -89,7 +125,61 @@ struct seq_parameter_set_rbsp { uint32_t frame_crop_top_offset; uint32_t frame_crop_bottom_offset; uint8_t vui_parameters_present_flag; - // TODO: add vui_parameters, rtbsp_trailing_bits + + /* vui_parameters */ + union { + uint8_t aspect_ration_info_present_flag; + + /* aspect_ration_info_present_flag == 1 */ + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + + uint8_t overscan_info_present_flag; + /* overscan_info_present_flag == 1 */ + uint8_t overscan_appropriate_flag; + + uint8_t video_signal_type_present_flag; + /* video_signal_type_present_flag == 1 */ + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present; + /* colour_description_present == 1 */ + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint8_t chroma_loc_info_present_flag; + /* chroma_loc_info_present_flag == 1 */ + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + + uint8_t timing_info_present_flag; + /* timing_info_present_flag == 1 */ + uint32_t num_units_in_tick; + uint32_t time_scale; + uint8_t fixed_frame_rate_flag; + + uint8_t nal_hrd_parameters_present_flag; + struct hrd_parameters nal_hrd_parameters; + + uint8_t vc1_hrd_parameters_present_flag; + struct hrd_parameters vc1_hrd_parameters; + + uint8_t low_delay_hrd_flag; + + uint8_t pic_struct_present_flag; + uint8_t bitstream_restriction_flag; + + /* bitstream_restriction_flag == 1 */ + uint8_t motion_vectors_over_pic_boundaries; + uint32_t max_bytes_per_pic_denom; + uint32_t max_bits_per_mb_denom; + uint32_t log2_max_mv_length_horizontal; + uint32_t log2_max_mv_length_vertical; + uint32_t num_reorder_frames; + uint32_t max_dec_frame_buffering; + } vui_parameters; }; @@ -196,17 +286,17 @@ struct slice_header { /* chroma_format_idc != 0 */ uint32_t chroma_log2_weight_denom; - int32_t luma_weight_l0[31]; - int32_t luma_offset_l0[31]; + int32_t luma_weight_l0[32]; + int32_t luma_offset_l0[32]; - int32_t chroma_weight_l0[31][2]; - int32_t chroma_offset_l0[31][2]; + int32_t chroma_weight_l0[32][2]; + int32_t chroma_offset_l0[32][2]; - int32_t luma_weight_l1[31]; - int32_t luma_offset_l1[31]; + int32_t luma_weight_l1[32]; + int32_t luma_offset_l1[32]; - int32_t chroma_weight_l1[31][2]; - int32_t chroma_offset_l1[31][2]; + int32_t chroma_weight_l1[32][2]; + int32_t chroma_offset_l1[32][2]; } pred_weight_table; /* def_rec_pic_marking */ @@ -236,15 +326,29 @@ struct nal_parser { int found_sps; int found_pps; int last_nal_res; + int field; /* 0=top, 1=bottom, -1=both */ int slice; int slice_cnt; int have_top; int have_frame; + struct nal_unit *nal0; struct nal_unit *nal1; struct nal_unit *current_nal; struct nal_unit *last_nal; + + /* pic_order_cnt */ + int32_t top_field_order_cnt; + int32_t bottom_field_oder_cnt; + int32_t prev_pic_order_cnt_msb; + int32_t prev_pic_order_cnt_lsb; +}; + +/* Decoded Picture Buffer */ +struct dpb { + uint32_t max_frame_number; + }; int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 841a94eb1..10577bc59 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -178,7 +178,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } if(this->decoder_initialized) { - if(this->nal_parser->current_nal->slc != NULL && + if(vdp_buffer.bitstream_bytes > 0 && + this->nal_parser->current_nal->slc != NULL && this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { @@ -197,7 +198,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, pic.slice_count = slice_count; pic.field_order_cnt[0] = 0; // FIXME - pic.is_reference = 1; // FIXME + pic.is_reference = + (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; pic.frame_num = slc->frame_num; pic.field_pic_flag = slc->field_pic_flag; pic.bottom_field_flag = slc->bottom_field_flag; @@ -229,6 +231,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->pts = buf->pts; img->bad_frame = 0; + printf("Decode pts: %lld, %d\n", img->pts, vdp_buffer.bitstream_bytes); /* create surface if needed */ if(this->vdpau_accel->surface == VDP_INVALID_HANDLE) { VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, @@ -240,17 +243,18 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, - this->vdpau_accel->surface, &pic, 1, (VdpPictureInfo*)&vdp_buffer); + this->vdpau_accel->surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %d\n", status); + else + printf("DECODING SUCCESS\n"); img->draw(img, this->stream); img->free(img); } } } - } } -- cgit v1.2.3 From 3fe63194a6531eadc2d27126b8b04ce34ffbf522 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 2 Dec 2008 20:08:22 +0000 Subject: Start DPB work. --- src/libvdpau/nal_parser.c | 37 +++++++++++++++++++++++++++++++++-- src/libvdpau/nal_parser.h | 22 ++++++++++++++++----- src/libvdpau/vdpau_h264.c | 49 +++++++++++++++++++---------------------------- 3 files changed, 72 insertions(+), 36 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index 9835cb1a4..ef380db36 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -229,7 +229,11 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal) void calculate_pic_order(struct nal_parser *parser) { + return; + + struct nal_unit *nal = parser->current_nal; + struct dpb *dpb = parser->dpb; struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; @@ -237,6 +241,34 @@ void calculate_pic_order(struct nal_parser *parser) if(!sps || !pps) return; + uint32_t max_frame_num = pow(2, sps->log2_max_frame_num_minus4+4); + if(dpb->max_frame_num == 0) + dpb->max_frame_num = max_frame_num; + + if(dpb->max_frame_num != max_frame_num && dpb->max_frame_num != 0) + printf("ERROR, FIXME, max_frame_num changed"); + + /* calculate frame_num based stuff */ + if(nal->nal_unit_type == NAL_SLICE_IDR) { + dpb->prev_ref_frame_number = 0; + } else { + // FIXME: understand p92 in h264 spec + } + + if(slc->frame_num != dpb->prev_ref_frame_number) { + memset(dpb->non_existing_pictures, 0, 32); + int i = 0; + dpb->unused_short_term_frame_num = (dpb->prev_ref_frame_number + 1) % dpb->max_frame_num; + dpb->non_existing_pictures[i] = dpb->unused_short_term_frame_num; + i++; + + while(dpb->unused_short_term_frame_num != slc->frame_num) { + dpb->unused_short_term_frame_num = (dpb->unused_short_term_frame_num + 1) % dpb->max_frame_num; + dpb->non_existing_pictures[i] = dpb->unused_short_term_frame_num; + i++; + } + } + if(sps->pic_order_cnt_type == 0) { if(nal->nal_unit_type == NAL_SLICE_IDR) { parser->prev_pic_order_cnt_lsb = 0; @@ -809,6 +841,9 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, if((parser->last_nal_res = parse_nal(inbuf+4, inbuf_len-parsed_len, parser)) == 1 && parser->buf_len>0) { // parse_nal returned 1 --> detected a frame_boundary + // do the extended parsing stuff... + calculate_pic_order(parser); + *ret_buf = malloc(parser->buf_len); xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); *ret_len = parser->buf_len; @@ -852,8 +887,6 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) int res = parse_nal_header(&bufr, nal); - calculate_pic_order(parser); - if(res >= NAL_SLICE && res <= NAL_SLICE_IDR) { // now detect if it's a new frame! int ret = 0; diff --git a/src/libvdpau/nal_parser.h b/src/libvdpau/nal_parser.h index 792f2e0f2..d8195c987 100644 --- a/src/libvdpau/nal_parser.h +++ b/src/libvdpau/nal_parser.h @@ -318,6 +318,22 @@ struct slice_header { }; +struct decoded_picture { + //VdpReferenceFrameH264 surface; + struct nal_unit *nal; +}; + +/* Decoded Picture Buffer */ +struct dpb { + uint32_t max_frame_num; + + uint32_t prev_ref_frame_number; + uint32_t unused_short_term_frame_num; + uint32_t non_existing_pictures[32]; + + struct decoded_picture *pictures; +}; + #define MAX_FRAME_SIZE 1024*1024 struct nal_parser { @@ -343,12 +359,8 @@ struct nal_parser { int32_t bottom_field_oder_cnt; int32_t prev_pic_order_cnt_msb; int32_t prev_pic_order_cnt_lsb; -}; - -/* Decoded Picture Buffer */ -struct dpb { - uint32_t max_frame_number; + struct dpb *dpb; }; int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 10577bc59..961e8da81 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -53,7 +53,7 @@ typedef struct vdpau_h264_decoder_s { /* these are traditional variables in a video decoder object */ uint64_t video_step; /* frame duration in pts units */ - int decoder_ok; /* current decoder status */ + int decoder_started; /* current decoder status */ int decoder_initialized; /* vdpau init state */ int skipframes; @@ -74,6 +74,9 @@ typedef struct vdpau_h264_decoder_s { VdpPictureInfoH264 vdp_picture_info; vdpau_accel_t *vdpau_accel; + VdpReferenceFrameH264 reference_frames[16]; + int reference_frames_used; + xine_t *xine; } vdpau_h264_decoder_t; @@ -169,12 +172,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->decoder_initialized = 1; img->free(img); - - /*if(!is_supported) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Profile not supported by VDPAU decoder.\n"); - - if(max_width < this->width || max_height < this->height) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: Image size not supported by VDPAU decoder.\n");*/ } if(this->decoder_initialized) { @@ -183,12 +180,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { - img = this->stream->video_out->get_frame (this->stream->video_out, - this->width, this->height, - this->ratio, - XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); - this->vdpau_accel = (vdpau_accel_t*)img->accel_data; - struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; struct slice_header *slc = this->nal_parser->current_nal->slc; @@ -231,27 +222,24 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->pts = buf->pts; img->bad_frame = 0; - printf("Decode pts: %lld, %d\n", img->pts, vdp_buffer.bitstream_bytes); - /* create surface if needed */ - if(this->vdpau_accel->surface == VDP_INVALID_HANDLE) { - VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, - VDP_CHROMA_TYPE_420, this->width, this->height, - &this->vdpau_accel->surface); - if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); - } + VdpVideoSurface surface; + VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, + VDP_CHROMA_TYPE_420, this->width, this->height, + &surface); - VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, - this->vdpau_accel->surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); + if(status != VDP_STATUS_OK) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); + + status = this->vdpau_accel->vdp_decoder_render(this->decoder, + surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %d\n", status); else printf("DECODING SUCCESS\n"); - img->draw(img, this->stream); - img->free(img); + this->vdpau_accel->vdp_video_surface_destroy(surface); } } } @@ -293,8 +281,8 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { this->buf = NULL; } - if (this->decoder_ok) { - this->decoder_ok = 0; + if (this->decoder_initialized) { + this->decoder_initialized = 0; this->stream->video_out->close(this->stream->video_out, this->stream); } @@ -326,11 +314,14 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->xine = stream->xine; this->class = (vdpau_h264_class_t *) class_gen; - this->decoder_ok = 0; + this->decoder_started = 0; this->decoder_initialized = 0; this->nal_parser = init_parser(); this->buf = NULL; + memset(this->reference_frames, 0x00, sizeof(this->reference_frames)); + this->reference_frames_used = 0; + return &this->video_decoder; } -- cgit v1.2.3 From f41edff45fcdb0f59c581b3e50618bf68da40dd4 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 2 Dec 2008 20:20:52 +0000 Subject: Cleanup. --- src/libvdpau/nal_parser.c | 1 - src/libvdpau/vdpau_h264.c | 37 ++++++++++++++++++++----------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index ef380db36..3288387ee 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -394,7 +394,6 @@ uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) sps->pic_height = (2-sps->frame_mbs_only_flag) * sps->pic_height; if(sps->pic_height == 1088) sps->pic_height = 1080; - //printf("res: %dx%d\n", sps->pic_width, sps->pic_height); if(!sps->frame_mbs_only_flag) sps->mb_adaptive_frame_field_flag = read_bits(buf, 1); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 961e8da81..93d7ce087 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -189,6 +189,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, pic.slice_count = slice_count; pic.field_order_cnt[0] = 0; // FIXME + pic.field_order_cnt[0] = 0; pic.is_reference = (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; pic.frame_num = slc->frame_num; @@ -217,29 +218,31 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, pic.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); + memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames)); - img->duration = this->video_step; - img->pts = buf->pts; - img->bad_frame = 0; + if(this->decoder_started || pic.is_reference) { + if(!this->decoder_started) + this->decoder_started = 1; + VdpVideoSurface surface; + VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, + VDP_CHROMA_TYPE_420, this->width, this->height, + &surface); - VdpVideoSurface surface; - VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, - VDP_CHROMA_TYPE_420, this->width, this->height, - &surface); + if(status != VDP_STATUS_OK) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); - if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); + printf("Decode: NUM: %d, REF: %d\n", pic.frame_num, pic.is_reference); + status = this->vdpau_accel->vdp_decoder_render(this->decoder, + surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); - status = this->vdpau_accel->vdp_decoder_render(this->decoder, - surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); + if(status != VDP_STATUS_OK) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %d\n", status); + else + printf("DECODING SUCCESS\n"); - if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %d\n", status); - else - printf("DECODING SUCCESS\n"); - - this->vdpau_accel->vdp_video_surface_destroy(surface); + this->vdpau_accel->vdp_video_surface_destroy(surface); + } } } } -- cgit v1.2.3 From 5a19f1e70d16c67e389e32a261d9a139d3c75ff1 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 2 Dec 2008 20:43:33 +0000 Subject: Debug printfs... --- src/libvdpau/nal_parser.c | 10 ++++++++++ src/libvdpau/vdpau_h264.c | 8 ++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index 3288387ee..f69a6df7a 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -902,49 +902,59 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) parser->slice = 1; if(nal->slc == NULL || last_nal->slc == NULL) { + printf("A\n"); ret = 1; } if(nal->slc && last_nal->slc && (nal->slc->frame_num != last_nal->slc->frame_num)) { + printf("B\n"); ret = 1; } if(nal->slc && last_nal->slc && (nal->slc->pic_parameter_set_id != last_nal->slc->pic_parameter_set_id)) { + printf("C\n"); ret = 1; } if(nal->slc && last_nal->slc && (nal->slc->field_pic_flag != last_nal->slc->field_pic_flag)) { + printf("D\n"); ret = 1; } if(nal->slc && last_nal->slc && (nal->slc->bottom_field_flag != -1 && last_nal->slc->bottom_field_flag != -1 && nal->slc->bottom_field_flag != last_nal->slc->bottom_field_flag)) { + printf("E\n"); ret = 1; } if(nal->nal_ref_idc != last_nal->nal_ref_idc && (nal->nal_ref_idc == 0 || last_nal->nal_ref_idc == 0)) { + printf("F\n"); ret = 1; } if(nal->sps && nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 0 && last_nal->sps->pic_order_cnt_type == 0 && (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb || nal->slc->delta_pic_order_cnt_bottom != last_nal->slc->delta_pic_order_cnt_bottom))) { + printf("G\n"); ret = 1; } if(nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 1 && last_nal->sps->pic_order_cnt_type == 1 && (nal->slc->delta_pic_order_cnt[0] != last_nal->slc->delta_pic_order_cnt[0] || nal->slc->delta_pic_order_cnt[1] != last_nal->slc->delta_pic_order_cnt[1]))) { + printf("H\n"); ret = 1; } if(nal->nal_unit_type != last_nal->nal_unit_type && (nal->nal_unit_type == 5 || last_nal->nal_unit_type == 5)) { + printf("I\n"); ret = 1; } if(nal->slc && last_nal->slc && (nal->nal_unit_type == 5 && last_nal->nal_unit_type == 5 && nal->slc->idr_pic_id != last_nal->slc->idr_pic_id)) { + printf("J\n"); ret = 1; } diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 93d7ce087..ca27cd4f8 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -180,9 +180,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { - struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; - struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; - struct slice_header *slc = this->nal_parser->current_nal->slc; + struct pic_parameter_set_rbsp *pps = this->nal_parser->last_nal->pps; + struct seq_parameter_set_rbsp *sps = this->nal_parser->last_nal->sps; + struct slice_header *slc = this->nal_parser->last_nal->slc; /* go and decode a frame */ VdpPictureInfoH264 pic; @@ -232,7 +232,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); - printf("Decode: NUM: %d, REF: %d\n", pic.frame_num, pic.is_reference); + printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); -- cgit v1.2.3 From d7f27cc26932ea2a82176c2bd2cbed41e20c4788 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Wed, 3 Dec 2008 09:12:49 +0000 Subject: Decodes one picture, but does not display it. --- src/libvdpau/nal_parser.c | 4 ++++ src/libvdpau/nal_parser.h | 1 + src/libvdpau/vdpau_h264.c | 22 +++++++++++++++++++--- src/video_out/video_out_vdpau.c | 2 +- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index f69a6df7a..9bedae71d 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -800,6 +800,7 @@ struct nal_parser* init_parser() parser->last_nal = parser->nal1; parser->last_nal_res = 0; + parser->is_idr = 0; parser->slice = 0; parser->slice_cnt = 0; parser->field = -1; @@ -885,6 +886,9 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) struct nal_unit *last_nal = parser->last_nal; int res = parse_nal_header(&bufr, nal); + printf("type: %d\n", res); + if(res == NAL_SLICE_IDR) + parser->is_idr = 1; if(res >= NAL_SLICE && res <= NAL_SLICE_IDR) { // now detect if it's a new frame! diff --git a/src/libvdpau/nal_parser.h b/src/libvdpau/nal_parser.h index d8195c987..31d55d3ca 100644 --- a/src/libvdpau/nal_parser.h +++ b/src/libvdpau/nal_parser.h @@ -343,6 +343,7 @@ struct nal_parser { int found_pps; int last_nal_res; + int is_idr; int field; /* 0=top, 1=bottom, -1=both */ int slice; int slice_cnt; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ca27cd4f8..56f4d992d 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -221,6 +221,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames)); if(this->decoder_started || pic.is_reference) { + this->nal_parser->is_idr = 0; if(!this->decoder_started) this->decoder_started = 1; @@ -238,8 +239,23 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %d\n", status); - else + else { printf("DECODING SUCCESS\n"); + img = this->stream->video_out->get_frame (this->stream->video_out, + this->width, this->height, + this->ratio, + XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + + this->vdpau_accel = (vdpau_accel_t*)img->accel_data; + this->vdpau_accel->surface = surface; + + img->duration = this->video_step; + img->pts = buf->pts; + img->bad_frame = 0; + + img->draw(img, this->stream); + img->free(img); + } this->vdpau_accel->vdp_video_surface_destroy(surface); } @@ -322,7 +338,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->nal_parser = init_parser(); this->buf = NULL; - memset(this->reference_frames, 0x00, sizeof(this->reference_frames)); + memset(this->reference_frames, VDP_INVALID_HANDLE, sizeof(this->reference_frames)); this->reference_frames_used = 0; return &this->video_decoder; @@ -391,7 +407,7 @@ static const uint32_t video_types[] = { */ static const decoder_info_t dec_info_video = { video_types, /* supported types */ - 5 /* priority */ + 7 /* priority */ }; /* diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 7d5da96c1..210c804f3 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -478,7 +478,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) /*printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 );*/ st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, - 0, 0, surface, 0, 0, &vid_source, this->output_surface, &out_dest, &vid_dest, 0, 0 ); + 0, VDP_INVALID_HANDLE, surface, 0, VDP_INVALID_HANDLE, &vid_source, this->output_surface, &out_dest, &vid_dest, 0, 0 ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); -- cgit v1.2.3 From 52a828deb79eca60cfc074a3869cb0dc7c8ba1d3 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 3 Dec 2008 09:20:04 +0000 Subject: Overlay stuff. --- src/video_out/video_out_vdpau.c | 435 +++++++++++++++++++++++++--------------- 1 file changed, 269 insertions(+), 166 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 210c804f3..3197307a7 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -51,6 +51,15 @@ #include "accel_vdpau.h" +VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE , + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO, + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA, + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, + VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD }; + + VdpDevice vdp_device; VdpPresentationQueue vdp_queue; @@ -69,6 +78,8 @@ VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_putbits_ycbcr; VdpOutputSurfaceCreate *vdp_output_surface_create; VdpOutputSurfaceDestroy *vdp_output_surface_destroy; +VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface; +VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits; VdpVideoMixerCreate *vdp_video_mixer_create; VdpVideoMixerDestroy *vdp_video_mixer_destroy; @@ -79,14 +90,28 @@ VdpPresentationQueueTargetDestroy *vdp_queue_target_destroy; VdpPresentationQueueCreate *vdp_queue_create; VdpPresentationQueueDestroy *vdp_queue_destroy; VdpPresentationQueueDisplay *vdp_queue_display; +VdpPresentationQueueBlockUntilSurfaceIdle *vdp_queue_block; VdpPresentationQueueSetBackgroundColor *vdp_queue_set_backgroung_color; +VdpBitmapSurfacePutBitsNative *vdp_bitmap_put_bits; +VdpBitmapSurfaceCreate *vdp_bitmap_create; +VdpBitmapSurfaceDestroy *vdp_bitmap_destroy; + VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; VdpDecoderCreate *vdp_decoder_create; VdpDecoderDestroy *vdp_decoder_destroy; VdpDecoderRender *vdp_decoder_render; + +typedef struct { + VdpBitmapSurface ovl_bitmap; + uint32_t bitmap_width, bitmap_height; + int ovl_w, ovl_h; /* overlay's width and height */ + int ovl_x, ovl_y; /* overlay's top-left display position */ +} vdpau_overlay_t; + + typedef struct { vo_frame_t vo_frame; @@ -109,17 +134,23 @@ typedef struct { config_values_t *config; int ovl_changed; - raw_overlay_t overlay; - yuv2rgb_t *ovl_yuv2rgb; + vdpau_overlay_t overlays[XINE_VORAW_MAX_OVL]; + yuv2rgb_factory_t *yuv2rgb_factory; + yuv2rgb_t *ovl_yuv2rgb; + VdpOutputSurface overlay_output; + uint32_t overlay_output_width; + uint32_t overlay_output_height; VdpVideoSurface soft_surface; uint32_t soft_surface_width; uint32_t soft_surface_height; int soft_surface_format; - VdpOutputSurface output_surface; - uint32_t output_surface_width; - uint32_t output_surface_height; + VdpOutputSurface output_surface[2]; + uint32_t current_output_surface; + uint32_t output_surface_width[2]; + uint32_t output_surface_height[2]; + uint8_t init_queue; VdpVideoMixer video_mixer; VdpChromaType video_mixer_chroma; @@ -159,23 +190,36 @@ static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *over } + static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) { - raw_overlay_t *ovl = &this_gen->overlay; + vdpau_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1]; if ( overlay->width<=0 || overlay->height<=0 ) return 0; - if ( (overlay->width*overlay->height)!=(ovl->ovl_w*ovl->ovl_h) ) - ovl->ovl_rgba = (uint8_t*)realloc( ovl->ovl_rgba, overlay->width*overlay->height*4 ); + if ( (ovl->bitmap_width < overlay->width ) || (ovl->bitmap_height < overlay->height) || (ovl->ovl_bitmap == VDP_INVALID_HANDLE) ) { + if (ovl->ovl_bitmap != VDP_INVALID_HANDLE) { + vdp_bitmap_destroy( ovl->ovl_bitmap ); + } + VdpStatus st = vdp_bitmap_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, overlay->width, overlay->height, 0, &ovl->ovl_bitmap ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_process_ovl: vdp_bitmap_create failed : %s\n", vdp_get_error_string(st) ); + } + ovl->bitmap_width = overlay->width; + ovl->bitmap_height = overlay->height; + } ovl->ovl_w = overlay->width; ovl->ovl_h = overlay->height; ovl->ovl_x = overlay->x; ovl->ovl_y = overlay->y; + uint8_t *buf = (uint8_t*)malloc(ovl->ovl_w*ovl->ovl_h*4); + if ( !buf ) + return 0; int num_rle = overlay->num_rle; rle_elem_t *rle = overlay->rle; - uint8_t *rgba = ovl->ovl_rgba; + uint8_t *rgba = buf; clut_t *low_colors = (clut_t*)overlay->color; clut_t *hili_colors = (clut_t*)overlay->hili_color; uint8_t *low_trans = overlay->trans; @@ -191,37 +235,44 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) x = pos%ovl->ovl_w; y = pos/ovl->ovl_w; if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) { - colors = hili_colors; - trans = hili_trans; + colors = hili_colors; + trans = hili_trans; } else { - colors = low_colors; - trans = low_trans; + colors = low_colors; + trans = low_trans; } rlelen = rle->len; clr = rle->color; alpha = trans[clr]; for ( i=0; iovl_w*4; + VdpRect dest = { 0, 0, ovl->ovl_w, ovl->ovl_h }; + VdpStatus st = vdp_bitmap_put_bits( ovl->ovl_bitmap, &buf, &pitch, &dest); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_process_ovl: vdp_bitmap_put_bits failed : %s\n", vdp_get_error_string(st) ); + } + free(buf); return 1; } static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { - /*vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - if ( !changed ) - return; + /*if ( !changed ) + return; ++this->ovl_changed;*/ } @@ -232,7 +283,7 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v /*vdpau_driver_t *this = (vdpau_driver_t *) this_gen; vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; - if ( !this->ovl_changed ) + if ( !this->ovl_changed || this->ovl_changed>XINE_VORAW_MAX_OVL ) return; if (overlay->rle) { @@ -247,12 +298,58 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) { /*vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + int i; + VdpStatus st; if ( !this->ovl_changed ) return; - this->raw_overlay_cb( this->user_data, this->ovl_changed-1, this->overlays ); + this->overlay_output_width = this->overlay_output_height = 0; + for ( i=0; iovl_changed-1; ++i ) { + int w = this->overlays[i].ovl_x+this->overlays[i].ovl_w; + int h = this->overlays[i].ovl_y+this->overlays[i].ovl_h; + if ( w > this->overlay_output_width ) + this->overlay_output_width = w; + if ( h > this->overlay_output_height ) + this->overlay_output_height = h; + } + printf( "vdpau_overlay_end: output_overlay size = %dx%d\n", this->overlay_output_width, this->overlay_output_height ); + if ( this->overlay_output != VDP_INVALID_HANDLE ) { + st = vdp_output_surface_destroy( this->overlay_output ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) ); + } + this->overlay_output = VDP_INVALID_HANDLE; + } + if ( !(this->ovl_changed-1) ) { + this->ovl_changed = 0; + return; + } + + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_output_width, this->overlay_output_height, &this->overlay_output ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + } + + uint32_t *buf = (uint32_t*)malloc(this->overlay_output_width*this->overlay_output_height*4); + uint32_t pitch = this->overlay_output_width*4; + VdpRect clear = { 0, 0, this->overlay_output_width, this->overlay_output_height }; + memset( buf, 0, this->overlay_output_width*this->overlay_output_height*4 ); + st = vdp_output_surface_put_bits( this->overlay_output, &buf, &pitch, &clear ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) ); + } + free(buf); + + for ( i=0; iovl_changed-1; ++i ) { + VdpRect dest = { this->overlays[i].ovl_x, this->overlays[i].ovl_y, this->overlays[i].ovl_x+this->overlays[i].ovl_w, this->overlays[i].ovl_y+this->overlays[i].ovl_h }; + VdpRect src = { 0, 0, this->overlays[i].ovl_w, this->overlays[i].ovl_h }; + st = vdp_output_surface_render_bitmap_surface( this->overlay_output, &dest, this->overlays[i].ovl_bitmap, &src, 0, &blend, 0 ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_overlay_end: vdp_output_surface_render_bitmap_surface failed : %s\n", vdp_get_error_string(st) ); + } + } this->ovl_changed = 0;*/ } @@ -461,14 +558,14 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); } - if ( (this->sc.gui_width > this->output_surface_width) || (this->sc.gui_height > this->output_surface_height) ) { + if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { /* recreate output surface to match window size */ printf( "vo_vdpau: output_surface size update\n" ); - this->output_surface_width = this->sc.gui_width; - this->output_surface_height = this->sc.gui_height; + this->output_surface_width[this->current_output_surface] = this->sc.gui_width; + this->output_surface_height[this->current_output_surface] = this->sc.gui_height; - vdp_output_surface_destroy( this->output_surface ); - vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width, this->output_surface_height, &this->output_surface ); + vdp_output_surface_destroy( this->output_surface[this->current_output_surface] ); + vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); } VdpRect vid_source = { this->sc.crop_left, this->sc.crop_top, this->sc.delivered_width-this->sc.crop_right, this->sc.delivered_height-this->sc.crop_bottom }; @@ -477,13 +574,43 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) /*printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 );*/ + XLockDisplay( this->display ); + + if ( this->init_queue ) { + int previous = this->current_output_surface ^ 1; + VdpTime time; + vdp_queue_block( vdp_queue, this->output_surface[previous], &time ); + } + + uint32_t layer_count; + VdpLayer lay, *layer; + VdpRect layersrc; + if ( this->overlay_output_width ) { + printf("vdpau_display_frame: overlay should be visible !\n"); + layer_count = 1; + layersrc.x0 = 0; layersrc.y0 = 0; layersrc.x1 = this->overlay_output_width; layersrc.y1 = this->overlay_output_height; + lay.struct_version = VDP_LAYER_VERSION; lay.source_surface = this->overlay_output; lay.source_rect = &layersrc; lay.destination_rect = &vid_dest; + layer = &lay; + } + else { + layer_count = 0; + layer = 0; + } st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, - 0, VDP_INVALID_HANDLE, surface, 0, VDP_INVALID_HANDLE, &vid_source, this->output_surface, &out_dest, &vid_dest, 0, 0 ); + 0, 0, surface, 0, 0, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - XLockDisplay( this->display ); - vdp_queue_display( vdp_queue, this->output_surface, 0, 0, 0 ) ; + /*if ( this->overlay_output_width ) + vdp_queue_display( vdp_queue, this->overlay_output, 0, 0, 0 ); + else*/ + vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); + + if ( !this->init_queue ) + ++this->init_queue; + + this->current_output_surface ^= 1; + XUnlockDisplay( this->display ); frame->vo_frame.free( &frame->vo_frame ); @@ -493,24 +620,31 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) static int vdpau_get_property (vo_driver_t *this_gen, int property) { + vdpau_driver_t *this = (vdpau_driver_t*)this_gen; + int ret=-1; + switch (property) { - case VO_PROP_ASPECT_RATIO: - return XINE_VO_ASPECT_AUTO; - case VO_PROP_MAX_NUM_FRAMES: - return 15; - case VO_PROP_BRIGHTNESS: - return 0; - case VO_PROP_CONTRAST: - return 128; - case VO_PROP_SATURATION: - return 128; - case VO_PROP_WINDOW_WIDTH: - return 0; - case VO_PROP_WINDOW_HEIGHT: - return 0; - default: - return 0; + case VO_PROP_WINDOW_WIDTH: + ret = this->sc.gui_width; + break; + case VO_PROP_WINDOW_HEIGHT: + ret = this->sc.gui_height; + break; + case VO_PROP_OUTPUT_WIDTH: + ret = this->sc.output_width; + break; + case VO_PROP_OUTPUT_HEIGHT: + ret = this->sc.output_height; + break; + case VO_PROP_OUTPUT_XOFFSET: + ret = this->sc.output_xoffset; + break; + case VO_PROP_OUTPUT_YOFFSET: + ret = this->sc.output_yoffset; + break; } + + return ret; } @@ -555,102 +689,60 @@ static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void * switch (data_type) { #ifndef XINE_DISABLE_DEPRECATED_FEATURES - case XINE_GUI_SEND_COMPLETION_EVENT: - break; + case XINE_GUI_SEND_COMPLETION_EVENT: + break; #endif - case XINE_GUI_SEND_EXPOSE_EVENT: { - /* XExposeEvent * xev = (XExposeEvent *) data; */ - - /*if (this->cur_frame) { - int i; - - LOCK_DISPLAY(this); - - if (this->use_shm) { - XvShmPutImage(this->display, this->xv_port, - this->drawable, this->gc, this->cur_frame->image, - this->sc.displayed_xoffset, this->sc.displayed_yoffset, - this->sc.displayed_width, this->sc.displayed_height, - this->sc.output_xoffset, this->sc.output_yoffset, - this->sc.output_width, this->sc.output_height, True); - } else { - XvPutImage(this->display, this->xv_port, - this->drawable, this->gc, this->cur_frame->image, - this->sc.displayed_xoffset, this->sc.displayed_yoffset, - this->sc.displayed_width, this->sc.displayed_height, - this->sc.output_xoffset, this->sc.output_yoffset, - this->sc.output_width, this->sc.output_height); - } - - XSetForeground (this->display, this->gc, this->black.pixel); - - for( i = 0; i < 4; i++ ) { - if( this->sc.border[i].w && this->sc.border[i].h ) { - XFillRectangle(this->display, this->drawable, this->gc, - this->sc.border[i].x, this->sc.border[i].y, - this->sc.border[i].w, this->sc.border[i].h); - } + case XINE_GUI_SEND_EXPOSE_EVENT: { + if ( this->init_queue ) { + int previous = this->current_output_surface ^ 1; + XLockDisplay( this->display ); + vdp_queue_display( vdp_queue, this->output_surface[previous], 0, 0, 0 ); + XUnlockDisplay( this->display ); } - - if(this->xoverlay) - x11osd_expose(this->xoverlay); - - XSync(this->display, False); - UNLOCK_DISPLAY(this); - }*/ - } - break; - - case XINE_GUI_SEND_DRAWABLE_CHANGED: { - VdpStatus st; - XLockDisplay( this->display ); - this->drawable = (Drawable) data; - vdp_queue_destroy( vdp_queue ); - vdp_queue_target_destroy( vdp_queue_target ); - st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); - if ( st != VDP_STATUS_OK ) { - printf( "vo_vdpau: FATAL !! Can't recreate presentation queue target after drawable change !!\n" ); break; } - st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); - if ( st != VDP_STATUS_OK ) { - printf( "vo_vdpau: FATAL !! Can't recreate presentation queue after drawable change !!\n" ); + + case XINE_GUI_SEND_DRAWABLE_CHANGED: { + VdpStatus st; + XLockDisplay( this->display ); + this->drawable = (Drawable) data; + vdp_queue_destroy( vdp_queue ); + vdp_queue_target_destroy( vdp_queue_target ); + st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); + if ( st != VDP_STATUS_OK ) { + printf( "vo_vdpau: FATAL !! Can't recreate presentation queue target after drawable change !!\n" ); + break; + } + st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); + if ( st != VDP_STATUS_OK ) { + printf( "vo_vdpau: FATAL !! Can't recreate presentation queue after drawable change !!\n" ); + break; + } + VdpColor backColor; + backColor.red = backColor.green = backColor.blue = 0; + backColor.alpha = 1; + vdp_queue_set_backgroung_color( vdp_queue, &backColor ); + XUnlockDisplay( this->display ); + this->sc.force_redraw = 1; break; } - VdpColor backColor; - backColor.red = backColor.green = backColor.blue = 0; - backColor.alpha = 1; - vdp_queue_set_backgroung_color( vdp_queue, &backColor ); - XUnlockDisplay( this->display ); - this->sc.force_redraw = 1; - break; - } - case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: - /*{ + case XINE_GUI_SEND_TRANSLATE_GUI_TO_VIDEO: { int x1, y1, x2, y2; x11_rectangle_t *rect = data; - _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y, - &x1, &y1); - _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h, - &x2, &y2); + _x_vo_scale_translate_gui2video(&this->sc, rect->x, rect->y, &x1, &y1); + _x_vo_scale_translate_gui2video(&this->sc, rect->x + rect->w, rect->y + rect->h, &x2, &y2); rect->x = x1; rect->y = y1; rect->w = x2-x1; rect->h = y2-y1; + break; + } - /* onefield_xv divide by 2 the number of lines */ - /*if (this->deinterlace_enabled - && (this->deinterlace_method == DEINTERLACE_ONEFIELDXV) - && (this->cur_frame->format == XINE_IMGFMT_YV12)) { - rect->y = rect->y * 2; - rect->h = rect->h * 2; - } - - }*/ - break; + default: + return -1; } return 0; @@ -672,7 +764,12 @@ static void vdpau_dispose (vo_driver_t *this_gen) vdpau_driver_t *this = (vdpau_driver_t *) this_gen; int i; - free( this->overlay.ovl_rgba ); + this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); + + for ( i=0; ioverlays[i].ovl_bitmap != VDP_INVALID_HANDLE ) + vdp_bitmap_destroy( this->overlays[i].ovl_bitmap ); + } free (this); } @@ -717,7 +814,6 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->sc.user_data = visual->user_data; this->sc.user_ratio = XINE_VO_ASPECT_AUTO; - this->ovl_changed = 0; this->xine = class->xine; this->config = config; @@ -735,14 +831,18 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->vo_driver.dispose = vdpau_dispose; this->vo_driver.redraw_needed = vdpau_redraw_needed; - this->overlay.ovl_w = this->overlay.ovl_h = 2; - this->overlay.ovl_rgba = (uint8_t*)malloc(2*2*4); - this->overlay.ovl_x = this->overlay.ovl_y = 0; + for ( i=0; ioverlays[i].ovl_w = this->overlays[i].ovl_h = 0; + this->overlays[i].bitmap_width = this->overlays[i].bitmap_height = 0; + this->overlays[i].ovl_bitmap = VDP_INVALID_HANDLE; + this->overlays[i].ovl_x = this->overlays[i].ovl_y = 0; + } + this->overlay_output = VDP_INVALID_HANDLE; + this->ovl_changed = 0; /* overlay converter */ - yuv2rgb_factory_t *factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); - this->ovl_yuv2rgb = factory->create_converter( factory ); - factory->dispose( factory ); + this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); + this->ovl_yuv2rgb = this->yuv2rgb_factory->create_converter( this->yuv2rgb_factory ); VdpStatus st = vdp_device_create_x11( visual->display, visual->screen, &vdp_device, &vdp_get_proc_address ); if ( st != VDP_STATUS_OK ) { @@ -754,29 +854,24 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdpau_dispose( &this->vo_driver ); return NULL; } - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GET_ERROR_STRING , (void*)&vdp_get_error_string ); if ( vdpau_init_error( st, "Can't get GET_ERROR_STRING proc address !!", &this->vo_driver, 0 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GET_API_VERSION , (void*)&vdp_get_api_version ); if ( vdpau_init_error( st, "Can't get GET_API_VERSION proc address !!", &this->vo_driver, 1 ) ) return NULL; uint32_t tmp; vdp_get_api_version( &tmp ); printf( "vo_vdpau: vdpau API version : %d\n", tmp ); - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GET_INFORMATION_STRING , (void*)&vdp_get_information_string ); if ( vdpau_init_error( st, "Can't get GET_INFORMATION_STRING proc address !!", &this->vo_driver, 1 ) ) return NULL; const char *s; st = vdp_get_information_string( &s ); printf( "vo_vdpau: vdpau implementation description : %s\n", s ); - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES , (void*)&vdp_video_surface_query_get_put_bits_ycbcr_capabilities ); if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) return NULL; - VdpBool ok; st = vdp_video_surface_query_get_put_bits_ycbcr_capabilities( vdp_device, VDP_CHROMA_TYPE_422, VDP_YCBCR_FORMAT_YUYV, &ok ); if ( vdpau_init_error( st, "Failed to check vdpau yuy2 capability", &this->vo_driver, 1 ) ) @@ -786,7 +881,6 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdpau_dispose( &this->vo_driver ); return NULL; } - st = vdp_video_surface_query_get_put_bits_ycbcr_capabilities( vdp_device, VDP_CHROMA_TYPE_420, VDP_YCBCR_FORMAT_YV12, &ok ); if ( vdpau_init_error( st, "Failed to check vdpau yv12 capability", &this->vo_driver, 1 ) ) return NULL; @@ -795,87 +889,87 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdpau_dispose( &this->vo_driver ); return NULL; } - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_CREATE , (void*)&vdp_video_surface_create ); if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , (void*)&vdp_video_surface_destroy ); if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , (void*)&vdp_video_surface_putbits_ycbcr ); if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_PUT_BITS_Y_CB_CR proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , (void*)&vdp_output_surface_create ); if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , (void*)&vdp_output_surface_destroy ); if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; - + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE , (void*)&vdp_output_surface_render_bitmap_surface ); + if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_RENDER_BITMAP_SURFACE proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE , (void*)&vdp_output_surface_put_bits ); + if ( vdpau_init_error( st, "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_CREATE , (void*)&vdp_video_mixer_create ); if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_DESTROY , (void*)&vdp_video_mixer_destroy ); if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_RENDER , (void*)&vdp_video_mixer_render ); if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_RENDER proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 , (void*)&vdp_queue_target_create_x11 ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_TARGET_CREATE_X11 proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY , (void*)&vdp_queue_target_destroy ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_TARGET_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE , (void*)&vdp_queue_create ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY , (void*)&vdp_queue_destroy ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY , (void*)&vdp_queue_display ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_DISPLAY proc address !!", &this->vo_driver, 1 ) ) return NULL; - + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE , (void*)&vdp_queue_block ); + if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR , (void*)&vdp_queue_set_backgroung_color ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_SET_BACKGROUND_COLOR proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , (void*)&vdp_decoder_query_capabilities ); if ( vdpau_init_error( st, "Can't get DECODER_QUERY_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_CREATE , (void*)&vdp_decoder_create ); if ( vdpau_init_error( st, "Can't get DECODER_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_DESTROY , (void*)&vdp_decoder_destroy ); if ( vdpau_init_error( st, "Can't get DECODER_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_RENDER , (void*)&vdp_decoder_render ); if ( vdpau_init_error( st, "Can't get DECODER_RENDER proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_CREATE , (void*)&vdp_bitmap_create ); + if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_DESTROY , (void*)&vdp_bitmap_destroy ); + if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE , (void*)&vdp_bitmap_put_bits ); + if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_PUT_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); if ( vdpau_init_error( st, "Can't create presentation queue !!", &this->vo_driver, 1 ) ) return NULL; + VdpColor backColor; backColor.red = backColor.green = backColor.blue = 0; backColor.alpha = 1; @@ -889,11 +983,19 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) return NULL; - this->output_surface_width = 720; - this->output_surface_height = 576; - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width, this->output_surface_height, &this->output_surface ); - if ( vdpau_init_error( st, "Can't create output surface !!", &this->vo_driver, 1 ) ) { + this->output_surface_width[0] = this->output_surface_width[1] = 720; + this->output_surface_height[0] = this->output_surface_height[1] = 576; + this->current_output_surface = 0; + this->init_queue = 0; + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] ); + if ( vdpau_init_error( st, "Can't create first output surface !!", &this->vo_driver, 1 ) ) { + vdp_video_surface_destroy( this->soft_surface ); + return NULL; + } + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[1] ); + if ( vdpau_init_error( st, "Can't create second output surface !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); + vdp_output_surface_destroy( this->output_surface[0] ); return NULL; } @@ -905,7 +1007,8 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); - vdp_output_surface_destroy( this->output_surface ); + vdp_output_surface_destroy( this->output_surface[0] ); + vdp_output_surface_destroy( this->output_surface[1] ); return NULL; } -- cgit v1.2.3 From 9b469905a77cccb45d4bc50c0ee7ae1fd07a88ac Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Wed, 3 Dec 2008 09:50:05 +0000 Subject: Decoding a few frames. --- src/libvdpau/nal_parser.c | 22 ++++++++++++---------- src/libvdpau/vdpau_h264.c | 36 +++++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 25 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index 9bedae71d..d4c3af84d 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -831,14 +831,15 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, *ret_buf = NULL; return parsed_len; } - //if(parser->last_nal_res != 1) { - xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, next_nal+search_offset); - parser->buf_len += next_nal+search_offset; - //} + + xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, next_nal+search_offset); + parser->buf_len += next_nal+search_offset; + inbuf += next_nal+search_offset; parsed_len += next_nal+search_offset; - if((parser->last_nal_res = parse_nal(inbuf+4, inbuf_len-parsed_len, parser)) == 1 + parser->last_nal_res = parse_nal(inbuf+4, inbuf_len-parsed_len, parser); + if(parser->last_nal_res == 1 && parser->buf_len>0) { // parse_nal returned 1 --> detected a frame_boundary // do the extended parsing stuff... @@ -854,6 +855,9 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->last_nal_res = 0; parser->slice_cnt = 0; return parsed_len; + } else if (parser->last_nal_res == 2) { + /* this is a nal_unit != SLICE, cut this out */ + parser->buf_len -= (next_nal+search_offset); } search_offset = 4; @@ -886,7 +890,6 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) struct nal_unit *last_nal = parser->last_nal; int res = parse_nal_header(&bufr, nal); - printf("type: %d\n", res); if(res == NAL_SLICE_IDR) parser->is_idr = 1; @@ -982,11 +985,10 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) return ret; } else if(res == NAL_PPS || res == NAL_SPS) { - return 0; - } else if (res == NAL_AU_DELIMITER || res == NAL_SEI || - (res >= 13 && res <= 18)) { + return 2; + } else if (res >= NAL_SEI) { //printf("New Frame\n"); - return 0; + return 2; } return 1; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 56f4d992d..4586c5afe 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -172,6 +172,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->decoder_initialized = 1; img->free(img); + img = NULL; } if(this->decoder_initialized) { @@ -225,29 +226,33 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(!this->decoder_started) this->decoder_started = 1; - VdpVideoSurface surface; - VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, - VDP_CHROMA_TYPE_420, this->width, this->height, - &surface); + if(img == NULL) { + img = this->stream->video_out->get_frame (this->stream->video_out, + this->width, this->height, + this->ratio, + XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + this->vdpau_accel = (vdpau_accel_t*)img->accel_data; + } - if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); + VdpVideoSurface surface = this->vdpau_accel->surface; + + if(surface == VDP_INVALID_HANDLE) { + VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, + VDP_CHROMA_TYPE_420, this->width, this->height, + &surface); + this->vdpau_accel->surface = surface; + if(status != VDP_STATUS_OK) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); + } printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); - status = this->vdpau_accel->vdp_decoder_render(this->decoder, + VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %d\n", status); else { printf("DECODING SUCCESS\n"); - img = this->stream->video_out->get_frame (this->stream->video_out, - this->width, this->height, - this->ratio, - XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); - - this->vdpau_accel = (vdpau_accel_t*)img->accel_data; - this->vdpau_accel->surface = surface; img->duration = this->video_step; img->pts = buf->pts; @@ -255,9 +260,10 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->draw(img, this->stream); img->free(img); + img = NULL; } - this->vdpau_accel->vdp_video_surface_destroy(surface); + //this->vdpau_accel->vdp_video_surface_destroy(surface); } } } -- cgit v1.2.3 From 0ce90b77d375430b099428bccc9c54e7c2d49e33 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Wed, 3 Dec 2008 14:21:23 +0000 Subject: Almost completely working parser. --- src/libvdpau/nal_parser.c | 93 +++++++++++++++++++++++++++-------------------- src/libvdpau/vdpau_h264.c | 73 +++++++++++++++++++++++++++++++++---- 2 files changed, 119 insertions(+), 47 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index d4c3af84d..c17908618 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -42,7 +42,8 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal); uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd); -uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps); +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, + struct seq_parameter_set_rbsp *sps); uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal); void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); @@ -188,8 +189,8 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal) ibuf.cur_pos = ibuf.buf; if(!nal->sps) nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); - else - memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); + + memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); parse_sps(&ibuf, nal->sps); free(ibuf.buf); @@ -198,10 +199,10 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal) case NAL_PPS: if(!nal->pps) nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); - else - memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); - parse_pps(buf, nal->pps); + memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); + + parse_pps(buf, nal->pps, nal->sps); ret = NAL_PPS; break; case NAL_SLICE: @@ -352,16 +353,19 @@ uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); if(sps->seq_scaling_matrix_present_flag) { int i; - for(i = 0; i < 8; i++) { - sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); - - if(sps->seq_scaling_list_present_flag[i]) { - if(i < 6) - parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); - else - parse_scaling_list(buf, sps->scaling_lists_8x8[i-6], 64, i); - } - } + for(i = 0; i < 8; i++) { + sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); + + if(sps->seq_scaling_list_present_flag[i]) { + if(i < 6) + parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, sps->scaling_lists_8x8[i-6], 64, i); + } + } + } else { + memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); + memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_4x4)); } } @@ -500,7 +504,8 @@ void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd) hrd->time_offset_length = read_bits(buf, 5); } -uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, + struct seq_parameter_set_rbsp *sps) { pps->pic_parameter_set_id = read_exp_golomb(buf); pps->seq_parameter_set_id = read_exp_golomb(buf); @@ -547,23 +552,30 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps) pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); if(!rbsp_trailing_bits(buf)) { - pps->transform_8x8_mode_flag = read_bits(buf, 1); - pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); - if(pps->pic_scaling_matrix_present_flag) { - int i; - for(i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { - pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); - - if(pps->pic_scaling_list_present_flag[i]) { - if(i < 6) - parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); - else - parse_scaling_list(buf, pps->scaling_lists_8x8[i-6], 64, i); - } - } - } + printf("PARSE 8x8\n"); + pps->transform_8x8_mode_flag = read_bits(buf, 1); + pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); + if(pps->pic_scaling_matrix_present_flag) { + int i; + for(i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { + pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); + + if(pps->pic_scaling_list_present_flag[i]) { + if(i < 6) + parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, pps->scaling_lists_8x8[i-6], 64, i); + } + } + } - pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); + pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); + } + + + if(!pps->pic_scaling_matrix_present_flag) { + memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, sizeof(pps->scaling_lists_4x4)); + memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8, sizeof(pps->scaling_lists_8x8)); } return 0; @@ -832,8 +844,11 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, return parsed_len; } - xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, next_nal+search_offset); - parser->buf_len += next_nal+search_offset; + if(parser->last_nal_res != 2) { + /* this is a nal_unit != SLICE, cut this out */ + xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, next_nal+search_offset); + parser->buf_len += next_nal+search_offset; + } inbuf += next_nal+search_offset; parsed_len += next_nal+search_offset; @@ -857,7 +872,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, return parsed_len; } else if (parser->last_nal_res == 2) { /* this is a nal_unit != SLICE, cut this out */ - parser->buf_len -= (next_nal+search_offset); + //parser->buf_len -= (next_nal+search_offset); } search_offset = 4; @@ -865,10 +880,8 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, // no further NAL found, copy the rest of the stream // into the buffer -// if(parser->last_nal_res != 1) { - xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len-parsed_len); - parser->buf_len += inbuf_len-parsed_len; -// } + xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len-parsed_len); + parser->buf_len += inbuf_len-parsed_len; parsed_len += (inbuf_len-parsed_len); *ret_len = 0; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 4586c5afe..b3413f3c4 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -89,6 +89,63 @@ typedef struct vdpau_h264_decoder_s { * xine video plugin functions *************************************************************************/ + +static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) +{ + printf("slice_count: %d\n", pic->slice_count); + printf("field_order_cnt[0]: %d\n", pic->field_order_cnt[0]); + printf("field_order_cnt[1]: %d\n", pic->field_order_cnt[1]); + printf("is_reference: %d\n", pic->is_reference); + printf("frame_num: %d\n", pic->frame_num); + printf("field_pic_flag: %d\n", pic->field_pic_flag); + printf("bottom_field_flag: %d\n", pic->bottom_field_flag); + printf("num_ref_frames: %d\n", pic->num_ref_frames); + printf("mb_adaptive_frame_field_flag: %d\n", pic->mb_adaptive_frame_field_flag); + printf("constrained_intra_pred_flag: %d\n", pic->constrained_intra_pred_flag); + printf("weighted_pred_flag: %d\n", pic->weighted_pred_flag); + printf("weighted_bipred_idc: %d\n", pic->weighted_bipred_idc); + printf("frame_mbs_only_flag: %d\n", pic->frame_mbs_only_flag); + printf("transform_8x8_mode_flag: %d\n", pic->transform_8x8_mode_flag); + printf("chroma_qp_index_offset: %d\n", pic->chroma_qp_index_offset); + printf("second_chroma_qp_index_offset: %d\n", pic->second_chroma_qp_index_offset); + printf("pic_init_qp_minus26: %d\n", pic->pic_init_qp_minus26); + printf("num_ref_idx_l0_active_minus1: %d\n", pic->num_ref_idx_l0_active_minus1); + printf("num_ref_idx_l1_active_minus1: %d\n", pic->num_ref_idx_l1_active_minus1); + printf("log2_max_frame_num_minus4: %d\n", pic->log2_max_frame_num_minus4); + printf("pic_order_cnt_type: %d\n", pic->pic_order_cnt_type); + printf("log2_max_pic_order_cnt_lsb_minus4: %d\n", pic->log2_max_pic_order_cnt_lsb_minus4); + printf("delta_pic_order_always_zero_flag: %d\n", pic->delta_pic_order_always_zero_flag); + printf("direct_8x8_inference_flag: %d\n", pic->direct_8x8_inference_flag); + printf("entropy_coding_mode_flag: %d\n", pic->entropy_coding_mode_flag); + printf("pic_order_present_flag: %d\n", pic->pic_order_present_flag); + printf("deblocking_filter_control_present_flag: %d\n", pic->deblocking_filter_control_present_flag); + printf("redundant_pic_cnt_present_flag: %d\n", pic->redundant_pic_cnt_present_flag); + + int i, j; + for(i = 0; i < 6; i++) { + printf("scalint_list4x4[%d]: ", i); + for(j = 0; j < 16; j++) { + printf("[%d] ", pic->scaling_lists_4x4[i][j]); + if(j%8 == 0) + printf("\n"); + } + printf("\n"); + } + for(i = 0; i < 2; i++) { + printf("scalint_list4x4[%d]: ", i); + for(j = 0; j < 64; j++) { + printf("[%d] ", pic->scaling_lists_4x4[i][j]); + if(j%8 == 0) + printf("\n"); + } + printf("\n"); + } + /*memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); + memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); + memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames));*/ + +} + /* * This function receives a buffer of data from the demuxer layer and * figures out how to handle it based on its header flags. @@ -177,9 +234,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(this->decoder_initialized) { if(vdp_buffer.bitstream_bytes > 0 && - this->nal_parser->current_nal->slc != NULL && - this->nal_parser->current_nal->sps != NULL && - this->nal_parser->current_nal->pps != NULL) { + this->nal_parser->last_nal->slc != NULL && + this->nal_parser->last_nal->sps != NULL && + this->nal_parser->last_nal->pps != NULL) { struct pic_parameter_set_rbsp *pps = this->nal_parser->last_nal->pps; struct seq_parameter_set_rbsp *sps = this->nal_parser->last_nal->sps; @@ -190,7 +247,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, pic.slice_count = slice_count; pic.field_order_cnt[0] = 0; // FIXME - pic.field_order_cnt[0] = 0; + pic.field_order_cnt[1] = 0; pic.is_reference = (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; pic.frame_num = slc->frame_num; @@ -217,15 +274,17 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, pic.pic_order_present_flag = pps->pic_order_present_flag; pic.deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; pic.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; - memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); + memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic.scaling_lists_4x4)); memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); - memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames)); + memcpy(pic.referenceFrames, this->reference_frames, sizeof(pic.scaling_lists_8x8)); if(this->decoder_started || pic.is_reference) { this->nal_parser->is_idr = 0; if(!this->decoder_started) this->decoder_started = 1; + //dump_pictureinfo_h264(&pic); + if(img == NULL) { img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, @@ -245,7 +304,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); } - printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); + //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); -- cgit v1.2.3 From 6d5a3cd061535826de2b18ca75e26a0e9b0affad Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Wed, 3 Dec 2008 14:24:34 +0000 Subject: Fix typo. --- src/libvdpau/vdpau_h264.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index b3413f3c4..93702b26e 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -275,8 +275,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, pic.deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; pic.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic.scaling_lists_4x4)); - memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); - memcpy(pic.referenceFrames, this->reference_frames, sizeof(pic.scaling_lists_8x8)); + memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic.scaling_lists_8x8)); + memcpy(pic.referenceFrames, this->reference_frames, sizeof(pic.referenceFrames)); if(this->decoder_started || pic.is_reference) { this->nal_parser->is_idr = 0; -- cgit v1.2.3 From 8a6ae6a604c8c9766a50e59e9a4937ab5e4be19c Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Wed, 3 Dec 2008 17:24:48 +0000 Subject: Fully working parser. --- src/libvdpau/nal_parser.c | 65 ++++++++++++++++++++++++++++++++--------------- src/libvdpau/nal_parser.h | 3 ++- src/libvdpau/vdpau_h264.c | 18 ++++++------- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index c17908618..314170380 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -38,13 +38,13 @@ int32_t read_exp_golomb_s(struct buf_reader *buf); void calculate_pic_order(struct nal_parser *parser); void skip_scaling_list(struct buf_reader *buf, int size); void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index); -int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal); +int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser); uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd); uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, struct seq_parameter_set_rbsp *sps); -uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal); +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser); void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_unit *nal); @@ -168,12 +168,14 @@ int32_t read_exp_golomb_s(struct buf_reader *buf) return code; } -int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal) +int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) { if(buf->len < 1) return -1; int ret = -1; + struct nal_unit *nal = parser->current_nal; + nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; nal->nal_unit_type = buf->buf[0] & 0x1f; @@ -216,7 +218,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal) else memset(nal->slc, 0x00, sizeof(struct slice_header)); - parse_slice_header(buf, nal); + parse_slice_header(buf, parser); ret = nal->nal_unit_type; } break; @@ -230,26 +232,23 @@ int parse_nal_header(struct buf_reader *buf, struct nal_unit *nal) void calculate_pic_order(struct nal_parser *parser) { - return; - - struct nal_unit *nal = parser->current_nal; struct dpb *dpb = parser->dpb; struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; - if(!sps || !pps) + if(!sps || !pps || !slc) return; - uint32_t max_frame_num = pow(2, sps->log2_max_frame_num_minus4+4); + /*uint32_t max_frame_num = pow(2, sps->log2_max_frame_num_minus4+4); if(dpb->max_frame_num == 0) dpb->max_frame_num = max_frame_num; if(dpb->max_frame_num != max_frame_num && dpb->max_frame_num != 0) printf("ERROR, FIXME, max_frame_num changed"); - /* calculate frame_num based stuff */ + / * calculate frame_num based stuff * / if(nal->nal_unit_type == NAL_SLICE_IDR) { dpb->prev_ref_frame_number = 0; } else { @@ -268,14 +267,32 @@ void calculate_pic_order(struct nal_parser *parser) dpb->non_existing_pictures[i] = dpb->unused_short_term_frame_num; i++; } - } + }*/ if(sps->pic_order_cnt_type == 0) { if(nal->nal_unit_type == NAL_SLICE_IDR) { parser->prev_pic_order_cnt_lsb = 0; parser->prev_pic_order_cnt_msb = 0; } else { + const int max_poc_lsb = 1<<(sps->log2_max_pic_order_cnt_lsb_minus4+4); + + if(slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb && + parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb >= max_poc_lsb/2) + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + max_poc_lsb; + else if(slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb && + parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb < -max_poc_lsb/2) + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - max_poc_lsb; + else + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; + if(!slc->bottom_field_flag) { + parser->top_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; + parser->bottom_field_order_cnt = 0; + } else + parser->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; + + if(parser->field == -1) + parser->bottom_field_order_cnt += slc->delta_pic_order_cnt_bottom; } } @@ -581,8 +598,10 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, return 0; } -uint8_t parse_slice_header(struct buf_reader *buf, struct nal_unit *nal) +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) { + struct nal_unit *nal = parser->current_nal; + struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; @@ -818,6 +837,11 @@ struct nal_parser* init_parser() parser->field = -1; parser->have_top = 0; + /* no idea why we do that. inspired by libavcodec, + * as we couldn't figure in the specs.... + */ + parser->prev_pic_order_cnt_msb = 1<<16; + return parser; } @@ -856,23 +880,24 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->last_nal_res = parse_nal(inbuf+4, inbuf_len-parsed_len, parser); if(parser->last_nal_res == 1 && parser->buf_len>0) { - // parse_nal returned 1 --> detected a frame_boundary - // do the extended parsing stuff... - calculate_pic_order(parser); - *ret_buf = malloc(parser->buf_len); xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); *ret_len = parser->buf_len; *ret_slice_cnt = parser->slice_cnt; + calculate_pic_order(parser); + //memset(parser->buf, 0x00, parser->buf_len); parser->buf_len = 0; parser->last_nal_res = 0; parser->slice_cnt = 0; + + /*if(parser->current_nal->nal_ref_idc) { + if(parser->current_nal->slc != NULL) + parser->prev_pic_order_cnt_lsb = parser->current_nal->slc->pic_order_cnt_lsb; + parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; + }*/ return parsed_len; - } else if (parser->last_nal_res == 2) { - /* this is a nal_unit != SLICE, cut this out */ - //parser->buf_len -= (next_nal+search_offset); } search_offset = 4; @@ -902,7 +927,7 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) struct nal_unit *nal = parser->current_nal; struct nal_unit *last_nal = parser->last_nal; - int res = parse_nal_header(&bufr, nal); + int res = parse_nal_header(&bufr, parser); if(res == NAL_SLICE_IDR) parser->is_idr = 1; diff --git a/src/libvdpau/nal_parser.h b/src/libvdpau/nal_parser.h index 31d55d3ca..f64f62305 100644 --- a/src/libvdpau/nal_parser.h +++ b/src/libvdpau/nal_parser.h @@ -357,7 +357,8 @@ struct nal_parser { /* pic_order_cnt */ int32_t top_field_order_cnt; - int32_t bottom_field_oder_cnt; + int32_t bottom_field_order_cnt; + int32_t pic_order_cnt_msb; int32_t prev_pic_order_cnt_msb; int32_t prev_pic_order_cnt_lsb; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 93702b26e..699c9108c 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -234,20 +234,20 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(this->decoder_initialized) { if(vdp_buffer.bitstream_bytes > 0 && - this->nal_parser->last_nal->slc != NULL && - this->nal_parser->last_nal->sps != NULL && - this->nal_parser->last_nal->pps != NULL) { + this->nal_parser->current_nal->slc != NULL && + this->nal_parser->current_nal->sps != NULL && + this->nal_parser->current_nal->pps != NULL) { - struct pic_parameter_set_rbsp *pps = this->nal_parser->last_nal->pps; - struct seq_parameter_set_rbsp *sps = this->nal_parser->last_nal->sps; - struct slice_header *slc = this->nal_parser->last_nal->slc; + struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; + struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; + struct slice_header *slc = this->nal_parser->current_nal->slc; /* go and decode a frame */ VdpPictureInfoH264 pic; pic.slice_count = slice_count; - pic.field_order_cnt[0] = 0; // FIXME - pic.field_order_cnt[1] = 0; + pic.field_order_cnt[0] = this->nal_parser->top_field_order_cnt; + pic.field_order_cnt[1] = this->nal_parser->bottom_field_order_cnt; pic.is_reference = (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; pic.frame_num = slc->frame_num; @@ -304,7 +304,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); } - //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); + printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); -- cgit v1.2.3 From e7d1ae873db6c9a28e978fd16a7b1fa5b7770567 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Thu, 4 Dec 2008 18:31:08 +0000 Subject: Fix very bad pointer failure... --- src/libvdpau/nal_parser.c | 6 +++--- src/libvdpau/vdpau_h264.c | 15 +++++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index 314170380..be765d408 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -869,8 +869,8 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, } if(parser->last_nal_res != 2) { - /* this is a nal_unit != SLICE, cut this out */ - xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, next_nal+search_offset); + /* this is not nal_unit != SLICE, keep it in the buffer */ + xine_fast_memcpy(parser->buf + parser->buf_len, inbuf, next_nal+search_offset); parser->buf_len += next_nal+search_offset; } @@ -889,7 +889,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, //memset(parser->buf, 0x00, parser->buf_len); parser->buf_len = 0; - parser->last_nal_res = 0; + parser->last_nal_res = 1; parser->slice_cnt = 0; /*if(parser->current_nal->nal_ref_idc) { diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 699c9108c..2e88932d4 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -285,6 +285,21 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, //dump_pictureinfo_h264(&pic); + int i; + printf("Decode data: \n"); + for(i = 0; i < ((vdp_buffer.bitstream_bytes < 20) ? vdp_buffer.bitstream_bytes : 20); i++) { + printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); + if((i+1) % 10 == 0) + printf("\n"); + } + printf("\n...\n"); + for(i = vdp_buffer.bitstream_bytes - 20; i < vdp_buffer.bitstream_bytes; i++) { + printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); + if((i+1) % 10 == 0) + printf("\n"); + } + + if(img == NULL) { img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, -- cgit v1.2.3 From 5992b0ca1c538bf2599f336b5749def7a5a455ad Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 5 Dec 2008 16:52:47 +0000 Subject: Fix several parser errors; clean up parser code format. --- src/libvdpau/nal_parser.c | 1491 +++++++++++++++++++++++---------------------- src/libvdpau/nal_parser.h | 4 +- src/libvdpau/vdpau_h264.c | 4 +- 3 files changed, 770 insertions(+), 729 deletions(-) diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c index be765d408..bf5ad3287 100644 --- a/src/libvdpau/nal_parser.c +++ b/src/libvdpau/nal_parser.c @@ -5,30 +5,28 @@ #include "nal_parser.h" /* default scaling_lists according to Table 7-2 */ -uint8_t default_4x4_intra[16] = - { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, 32, 32, 37, 37, 42 }; - -uint8_t default_4x4_inter[16] = - { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34}; - -uint8_t default_8x8_intra[64] = - { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, 18, 18, 18, 18, 32, - 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, - 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, - 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; - -uint8_t default_8x8_inter[64] = - { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, 19, 19, 19, 19, 21, - 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, 24, 24, - 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, - 27, 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; - - -struct buf_reader { - uint8_t *buf; - uint8_t *cur_pos; - int len; - int cur_offset; +uint8_t default_4x4_intra[16] = { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, + 32, 32, 37, 37, 42 }; + +uint8_t default_4x4_inter[16] = { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, + 27, 27, 30, 30, 34 }; + +uint8_t default_8x8_intra[64] = { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, + 18, 18, 18, 18, 32, 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, + 27, 27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, 31, + 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; + +uint8_t default_8x8_inter[64] = { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, + 19, 19, 19, 19, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, + 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27, + 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; + +struct buf_reader +{ + uint8_t *buf; + uint8_t *cur_pos; + int len; + int cur_offset; }; static inline uint32_t read_bits(struct buf_reader *buf, int len); @@ -37,197 +35,195 @@ int32_t read_exp_golomb_s(struct buf_reader *buf); void calculate_pic_order(struct nal_parser *parser); void skip_scaling_list(struct buf_reader *buf, int size); -void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index); +void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, + int length, int index); int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser); uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); -void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); +void parse_vui_parameters(struct buf_reader *buf, + struct seq_parameter_set_rbsp *sps); void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd); uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, struct seq_parameter_set_rbsp *sps); uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser); -void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); +void + parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_unit *nal); static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) { - uint8_t *end = &buf[buf_len]; - uint8_t *pos = malloc(buf_len); + uint8_t *end = &buf[buf_len]; + uint8_t *pos = malloc(buf_len); - *ret = pos; - while(buf < end) { - if(buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 && - buf[2] == 0x03) { + *ret = pos; + while (buf < end) { + if (buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x03) { - *pos++ = 0x00; - *pos++ = 0x00; + *pos++ = 0x00; + *pos++ = 0x00; - buf += 3; - continue; - } - *pos++ = *buf++; + buf += 3; + continue; } + *pos++ = *buf++; + } - *len_ret = pos - *ret; + *len_ret = pos - *ret; } /*uint32_t read_bits(struct buf_reader *buf, int len) + { + uint32_t bits = 0x00; + int i, j; + for(i=0, j=0; icur_offset >= 8) { + buf->cur_pos++; + buf->cur_offset -= 8; + } + uint8_t bit = (*buf->cur_pos >> (7 - buf->cur_offset)) & 0x01; + bits |= ((uint32_t)bit) << i; + buf->cur_offset++; + } + printf("ret: 0x%08x\n", bits); + return bits; + }*/ + +static inline uint32_t read_bits(struct buf_reader *buf, int len) { - uint32_t bits = 0x00; - int i, j; - for(i=0, j=0; icur_offset >= 8) { - buf->cur_pos++; - buf->cur_offset -= 8; - } - uint8_t bit = (*buf->cur_pos >> (7 - buf->cur_offset)) & 0x01; - bits |= ((uint32_t)bit) << i; - buf->cur_offset++; + static uint32_t i_mask[33] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, + 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, + 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, + 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, + 0x3fffffff, 0x7fffffff, 0xffffffff }; + + int i_shr; + uint32_t bits = 0; + + while (len > 0 && (buf->cur_pos - buf->buf) < buf->len) { + if ((i_shr = buf->cur_offset - len) >= 0) { + bits |= (*buf->cur_pos >> i_shr) & i_mask[len]; + buf->cur_offset -= len; + if (buf->cur_offset == 0) { + buf->cur_pos++; + buf->cur_offset = 8; + } + return bits; } -printf("ret: 0x%08x\n", bits); - return bits; -}*/ - -static inline uint32_t read_bits (struct buf_reader *buf, int len) -{ - static uint32_t i_mask[33] = - { 0x00, - 0x01, 0x03, 0x07, 0x0f, - 0x1f, 0x3f, 0x7f, 0xff, - 0x1ff, 0x3ff, 0x7ff, 0xfff, - 0x1fff, 0x3fff, 0x7fff, 0xffff, - 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, - 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, - 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, - 0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff}; - - int i_shr; - uint32_t bits = 0; - - while(len > 0 && (buf->cur_pos - buf->buf) < buf->len) { - if((i_shr = buf->cur_offset-len) >= 0) { - bits |= (*buf->cur_pos >> i_shr)&i_mask[len]; - buf->cur_offset -= len; - if(buf->cur_offset == 0) { - buf->cur_pos++; - buf->cur_offset = 8; - } - return bits; - } else { - bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; - len -= buf->cur_offset; - buf->cur_pos++; - buf->cur_offset = 8; - } + else { + bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; + len -= buf->cur_offset; + buf->cur_pos++; + buf->cur_offset = 8; } - return bits; + } + return bits; } /* determines if following bits are rtsb_trailing_bits */ static inline uint8_t rbsp_trailing_bits(struct buf_reader *buf) { - // store the offset and pos in buffer - // to revert this afterwards. - int last_offset; - uint8_t *last_pos; + // store the offset and pos in buffer + // to revert this afterwards. + int last_offset; + uint8_t *last_pos; - uint8_t rbsp_trailing_bits = 1; + uint8_t rbsp_trailing_bits = 1; - last_offset = buf->cur_offset; - last_pos = buf->cur_pos; + last_offset = buf->cur_offset; + last_pos = buf->cur_pos; - if(read_bits(buf, 1) == 1) - { - while(buf->cur_offset != 8) - if(read_bits(buf, 1) == 1) - rbsp_trailing_bits = 0; - } + if (read_bits(buf, 1) == 1) { + while (buf->cur_offset != 8) + if (read_bits(buf, 1) == 1) + rbsp_trailing_bits = 0; + } - // revert buffer - buf->cur_offset = last_offset; - buf->cur_pos = last_pos; + // revert buffer + buf->cur_offset = last_offset; + buf->cur_pos = last_pos; - return rbsp_trailing_bits; + return rbsp_trailing_bits; } uint32_t read_exp_golomb(struct buf_reader *buf) { - int leading_zero_bits = 0; + int leading_zero_bits = 0; - while(read_bits(buf, 1) == 0 && leading_zero_bits < 32) - leading_zero_bits++; + while (read_bits(buf, 1) == 0 && leading_zero_bits < 32) + leading_zero_bits++; - uint32_t code = (1<len < 1) - return -1; - int ret = -1; - - struct nal_unit *nal = parser->current_nal; - - nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; - nal->nal_unit_type = buf->buf[0] & 0x1f; - - buf->cur_pos = buf->buf + 1; - //printf("NAL: %d\n", nal->nal_unit_type); - - struct buf_reader ibuf; - ibuf.cur_offset = 8; - - switch(nal->nal_unit_type) { - case NAL_SPS: - decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len-1); - ibuf.cur_pos = ibuf.buf; - if(!nal->sps) - nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); - - memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); - - parse_sps(&ibuf, nal->sps); - free(ibuf.buf); - ret = NAL_SPS; - break; - case NAL_PPS: - if(!nal->pps) - nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); - - memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); - - parse_pps(buf, nal->pps, nal->sps); - ret = NAL_PPS; - break; - case NAL_SLICE: - case NAL_PART_A: - case NAL_PART_B: - case NAL_PART_C: - case NAL_SLICE_IDR: - if(nal->sps && nal->pps) { - if(!nal->slc) - nal->slc = malloc(sizeof(struct slice_header)); - else - memset(nal->slc, 0x00, sizeof(struct slice_header)); - - parse_slice_header(buf, parser); - ret = nal->nal_unit_type; - } - break; - default: - ret = nal->nal_unit_type; - break; - } + if (buf->len < 1) + return -1; + int ret = -1; - return ret; + struct nal_unit *nal = parser->current_nal; + + nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; + nal->nal_unit_type = buf->buf[0] & 0x1f; + + buf->cur_pos = buf->buf + 1; + //printf("NAL: %d\n", nal->nal_unit_type); + + struct buf_reader ibuf; + ibuf.cur_offset = 8; + + switch (nal->nal_unit_type) { + case NAL_SPS: + decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len - 1); + ibuf.cur_pos = ibuf.buf; + if (!nal->sps) + nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + + memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); + + parse_sps(&ibuf, nal->sps); + free(ibuf.buf); + ret = NAL_SPS; + break; + case NAL_PPS: + if (!nal->pps) + nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + + memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); + + parse_pps(buf, nal->pps, nal->sps); + ret = NAL_PPS; + break; + case NAL_SLICE: + case NAL_PART_A: + case NAL_PART_B: + case NAL_PART_C: + case NAL_SLICE_IDR: + if (nal->sps && nal->pps) { + if (!nal->slc) + nal->slc = malloc(sizeof(struct slice_header)); + else + memset(nal->slc, 0x00, sizeof(struct slice_header)); + + parse_slice_header(buf, parser); + ret = nal->nal_unit_type; + } + break; + default: + ret = nal->nal_unit_type; + break; + } + + return ret; } void calculate_pic_order(struct nal_parser *parser) @@ -238,61 +234,69 @@ void calculate_pic_order(struct nal_parser *parser) struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; - if(!sps || !pps || !slc) - return; + if (!sps || !pps || !slc) + return; /*uint32_t max_frame_num = pow(2, sps->log2_max_frame_num_minus4+4); - if(dpb->max_frame_num == 0) - dpb->max_frame_num = max_frame_num; - - if(dpb->max_frame_num != max_frame_num && dpb->max_frame_num != 0) - printf("ERROR, FIXME, max_frame_num changed"); - - / * calculate frame_num based stuff * / - if(nal->nal_unit_type == NAL_SLICE_IDR) { - dpb->prev_ref_frame_number = 0; - } else { - // FIXME: understand p92 in h264 spec - } - - if(slc->frame_num != dpb->prev_ref_frame_number) { - memset(dpb->non_existing_pictures, 0, 32); - int i = 0; - dpb->unused_short_term_frame_num = (dpb->prev_ref_frame_number + 1) % dpb->max_frame_num; - dpb->non_existing_pictures[i] = dpb->unused_short_term_frame_num; - i++; - - while(dpb->unused_short_term_frame_num != slc->frame_num) { - dpb->unused_short_term_frame_num = (dpb->unused_short_term_frame_num + 1) % dpb->max_frame_num; - dpb->non_existing_pictures[i] = dpb->unused_short_term_frame_num; - i++; - } - }*/ - - if(sps->pic_order_cnt_type == 0) { - if(nal->nal_unit_type == NAL_SLICE_IDR) { + if(dpb->max_frame_num == 0) + dpb->max_frame_num = max_frame_num; + + if(dpb->max_frame_num != max_frame_num && dpb->max_frame_num != 0) + printf("ERROR, FIXME, max_frame_num changed"); + + / * calculate frame_num based stuff * / + if(nal->nal_unit_type == NAL_SLICE_IDR) { + dpb->prev_ref_frame_number = 0; + } else { + // FIXME: understand p92 in h264 spec + } + + if(slc->frame_num != dpb->prev_ref_frame_number) { + memset(dpb->non_existing_pictures, 0, 32); + int i = 0; + dpb->unused_short_term_frame_num = (dpb->prev_ref_frame_number + 1) % dpb->max_frame_num; + dpb->non_existing_pictures[i] = dpb->unused_short_term_frame_num; + i++; + + while(dpb->unused_short_term_frame_num != slc->frame_num) { + dpb->unused_short_term_frame_num = (dpb->unused_short_term_frame_num + 1) % dpb->max_frame_num; + dpb->non_existing_pictures[i] = dpb->unused_short_term_frame_num; + i++; + } + }*/ + + if (sps->pic_order_cnt_type == 0) { + if (nal->nal_unit_type == NAL_SLICE_IDR) { parser->prev_pic_order_cnt_lsb = 0; parser->prev_pic_order_cnt_msb = 0; - } else { - const int max_poc_lsb = 1<<(sps->log2_max_pic_order_cnt_lsb_minus4+4); - - if(slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb && - parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb >= max_poc_lsb/2) - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + max_poc_lsb; - else if(slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb && - parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb < -max_poc_lsb/2) - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - max_poc_lsb; - else - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; - - if(!slc->bottom_field_flag) { - parser->top_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; - parser->bottom_field_order_cnt = 0; - } else - parser->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; + } + else { + const int max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + if (slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb + && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb + >= max_poc_lsb / 2) + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + + max_poc_lsb; + else if (slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb + && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb + < -max_poc_lsb / 2) + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + - max_poc_lsb; + else + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; + + if (!slc->bottom_field_flag) { + parser->top_field_order_cnt = parser->pic_order_cnt_msb + + slc->pic_order_cnt_lsb; + parser->bottom_field_order_cnt = 0; + } + else + parser->bottom_field_order_cnt = parser->pic_order_cnt_msb + + slc->pic_order_cnt_lsb; - if(parser->field == -1) - parser->bottom_field_order_cnt += slc->delta_pic_order_cnt_bottom; + if (parser->field == -1) + parser->bottom_field_order_cnt += slc->delta_pic_order_cnt_bottom; } } @@ -300,163 +304,168 @@ void calculate_pic_order(struct nal_parser *parser) void skip_scaling_list(struct buf_reader *buf, int size) { - int i; - for(i = 0; i < size; i++) { - read_exp_golomb_s(buf); - } + int i; + for (i = 0; i < size; i++) { + read_exp_golomb_s(buf); + } } -void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index) +void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, + int length, int index) { - int last_scale = 8; - int next_scale = 8; - int32_t delta_scale; - uint8_t use_default_scaling_matrix_flag = 0; - int i; - - for(i = 0; i < length; i++) { - if(next_scale != 0) { - delta_scale = read_exp_golomb_s(buf); - next_scale = (last_scale + delta_scale + 256) % 256; - if(i == 0 && next_scale == 0) { - use_default_scaling_matrix_flag = 1; - break; - } - } - scaling_list[i] = (next_scale == 0) ? last_scale : next_scale; - last_scale = scaling_list[i]; - } - - if(use_default_scaling_matrix_flag) { - switch(index) { - case 0: - case 1: - case 2: - memcpy(scaling_list, default_4x4_intra, length); - break; - case 3: - case 4: - case 5: - memcpy(scaling_list, default_4x4_inter, length); - break; - case 6: - memcpy(scaling_list, default_8x8_intra, length); - break; - case 7: - memcpy(scaling_list, default_8x8_inter, length); - break; - } - } + int last_scale = 8; + int next_scale = 8; + int32_t delta_scale; + uint8_t use_default_scaling_matrix_flag = 0; + int i; + + for (i = 0; i < length; i++) { + if (next_scale != 0) { + delta_scale = read_exp_golomb_s(buf); + next_scale = (last_scale + delta_scale + 256) % 256; + if (i == 0 && next_scale == 0) { + use_default_scaling_matrix_flag = 1; + break; + } + } + scaling_list[i] = (next_scale == 0) ? last_scale : next_scale; + last_scale = scaling_list[i]; + } + + if (use_default_scaling_matrix_flag) { + switch (index) { + case 0: + case 1: + case 2: + memcpy(scaling_list, default_4x4_intra, length); + break; + case 3: + case 4: + case 5: + memcpy(scaling_list, default_4x4_inter, length); + break; + case 6: + memcpy(scaling_list, default_8x8_intra, length); + break; + case 7: + memcpy(scaling_list, default_8x8_inter, length); + break; + } + } } uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) { - sps->profile_idc = buf->buf[0]; - sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; - sps->level_idc = buf->buf[2]; - - buf->cur_pos = buf->buf+3; - sps->seq_parameter_set_id = read_exp_golomb(buf); - if(sps->profile_idc == 100 || sps->profile_idc == 110 || - sps->profile_idc == 122 || sps->profile_idc == 144) { - sps->chroma_format_idc = read_exp_golomb(buf); - if(sps->chroma_format_idc == 3) { - sps->residual_colour_transform_flag = read_bits(buf, 1); - } + sps->profile_idc = buf->buf[0]; + sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; + sps->level_idc = buf->buf[2]; + + buf->cur_pos = buf->buf + 3; + sps->seq_parameter_set_id = read_exp_golomb(buf); + if (sps->profile_idc == 100 || sps->profile_idc == 110 || + sps->profile_idc == 122 || sps->profile_idc == 144) { + sps->chroma_format_idc = read_exp_golomb(buf); + if (sps->chroma_format_idc == 3) { + sps->residual_colour_transform_flag = read_bits(buf, 1); + } - sps->bit_depth_luma_minus8 = read_exp_golomb(buf); - sps->bit_depth_chroma_minus8 = read_exp_golomb(buf); - sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); - sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); - if(sps->seq_scaling_matrix_present_flag) { - int i; - for(i = 0; i < 8; i++) { - sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); - - if(sps->seq_scaling_list_present_flag[i]) { - if(i < 6) - parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); - else - parse_scaling_list(buf, sps->scaling_lists_8x8[i-6], 64, i); - } - } - } else { - memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); - memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_4x4)); + sps->bit_depth_luma_minus8 = read_exp_golomb(buf); + sps->bit_depth_chroma_minus8 = read_exp_golomb(buf); + sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); + sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); + if (sps->seq_scaling_matrix_present_flag) { + printf("SCALING LIST PRESENT\n"); + int i; + for (i = 0; i < 8; i++) { + sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); + + if (sps->seq_scaling_list_present_flag[i]) { + if (i < 6) + parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, sps->scaling_lists_8x8[i - 6], 64, i); } + } } + } - sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); + if (!sps->seq_scaling_matrix_present_flag) { + memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); + memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_4x4)); + } - sps->pic_order_cnt_type = read_exp_golomb(buf); - if(!sps->pic_order_cnt_type) - sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf); - else { - sps->delta_pic_order_always_zero_flag = read_bits(buf, 1); - sps->offset_for_non_ref_pic = read_exp_golomb_s(buf); - sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf); - sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf); - int i; - for(i=0; inum_ref_frames_in_pic_order_cnt_cycle; i++) { - sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf); - } - } - sps->num_ref_frames = read_exp_golomb(buf); - sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1); - - /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf); - sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/ - sps->pic_width = 16 * (read_exp_golomb(buf) + 1); - sps->pic_height = 16 * (read_exp_golomb(buf) + 1); - - sps->frame_mbs_only_flag = read_bits(buf, 1); - - /* compute the height correctly even for interlaced material */ - sps->pic_height = (2-sps->frame_mbs_only_flag) * sps->pic_height; - if(sps->pic_height == 1088) - sps->pic_height = 1080; - - if(!sps->frame_mbs_only_flag) - sps->mb_adaptive_frame_field_flag = read_bits(buf, 1); - - sps->direct_8x8_inference_flag = read_bits(buf, 1); - sps->frame_cropping_flag = read_bits(buf, 1); - if(sps->frame_cropping_flag) { - sps->frame_crop_left_offset = read_exp_golomb(buf); - sps->frame_crop_right_offset = read_exp_golomb(buf); - sps->frame_crop_top_offset = read_exp_golomb(buf); - sps->frame_crop_bottom_offset = read_exp_golomb(buf); - } - sps->vui_parameters_present_flag = read_bits(buf, 1); - if(sps->vui_parameters_present_flag) { - parse_vui_parameters(buf, sps); + sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); + + sps->pic_order_cnt_type = read_exp_golomb(buf); + if (!sps->pic_order_cnt_type) + sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf); + else { + sps->delta_pic_order_always_zero_flag = read_bits(buf, 1); + sps->offset_for_non_ref_pic = read_exp_golomb_s(buf); + sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf); + sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf); + int i; + for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) { + sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf); } + } + sps->num_ref_frames = read_exp_golomb(buf); + sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1); + + /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf); + sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/ + sps->pic_width = 16 * (read_exp_golomb(buf) + 1); + sps->pic_height = 16 * (read_exp_golomb(buf) + 1); + + sps->frame_mbs_only_flag = read_bits(buf, 1); + + /* compute the height correctly even for interlaced material */ + sps->pic_height = (2 - sps->frame_mbs_only_flag) * sps->pic_height; + if (sps->pic_height == 1088) + sps->pic_height = 1080; + + if (!sps->frame_mbs_only_flag) + sps->mb_adaptive_frame_field_flag = read_bits(buf, 1); + + sps->direct_8x8_inference_flag = read_bits(buf, 1); + sps->frame_cropping_flag = read_bits(buf, 1); + if (sps->frame_cropping_flag) { + sps->frame_crop_left_offset = read_exp_golomb(buf); + sps->frame_crop_right_offset = read_exp_golomb(buf); + sps->frame_crop_top_offset = read_exp_golomb(buf); + sps->frame_crop_bottom_offset = read_exp_golomb(buf); + } + sps->vui_parameters_present_flag = read_bits(buf, 1); + if (sps->vui_parameters_present_flag) { + parse_vui_parameters(buf, sps); + } - return 0; + return 0; } -void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) +void parse_vui_parameters(struct buf_reader *buf, + struct seq_parameter_set_rbsp *sps) { sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1); - if(sps->vui_parameters.aspect_ration_info_present_flag == 1) { + if (sps->vui_parameters.aspect_ration_info_present_flag == 1) { sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8); - if(sps->vui_parameters.aspect_ratio_idc == ASPECT_RESERVED) { + if (sps->vui_parameters.aspect_ratio_idc == ASPECT_RESERVED) { sps->vui_parameters.sar_width = read_bits(buf, 16); sps->vui_parameters.sar_height = read_bits(buf, 16); } } sps->vui_parameters.overscan_info_present_flag = read_bits(buf, 1); - if(sps->vui_parameters.overscan_info_present_flag) { + if (sps->vui_parameters.overscan_info_present_flag) { sps->vui_parameters.overscan_appropriate_flag = read_bits(buf, 1); } sps->vui_parameters.video_signal_type_present_flag = read_bits(buf, 1); - if(sps->vui_parameters.video_signal_type_present_flag) { + if (sps->vui_parameters.video_signal_type_present_flag) { sps->vui_parameters.video_format = read_bits(buf, 3); sps->vui_parameters.video_full_range_flag = read_bits(buf, 1); sps->vui_parameters.colour_description_present = read_bits(buf, 1); - if(sps->vui_parameters.colour_description_present) { + if (sps->vui_parameters.colour_description_present) { sps->vui_parameters.colour_primaries = read_bits(buf, 8); sps->vui_parameters.transfer_characteristics = read_bits(buf, 8); sps->vui_parameters.matrix_coefficients = read_bits(buf, 8); @@ -464,34 +473,35 @@ void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp } sps->vui_parameters.chroma_loc_info_present_flag = read_bits(buf, 1); - if(sps->vui_parameters.chroma_loc_info_present_flag) { + if (sps->vui_parameters.chroma_loc_info_present_flag) { sps->vui_parameters.chroma_sample_loc_type_top_field = read_exp_golomb(buf); - sps->vui_parameters.chroma_sample_loc_type_bottom_field = read_exp_golomb(buf); + sps->vui_parameters.chroma_sample_loc_type_bottom_field = read_exp_golomb( + buf); } sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1); - if(sps->vui_parameters.timing_info_present_flag) { + if (sps->vui_parameters.timing_info_present_flag) { sps->vui_parameters.num_units_in_tick = read_bits(buf, 32); sps->vui_parameters.time_scale = read_bits(buf, 32); sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1); } sps->vui_parameters.nal_hrd_parameters_present_flag = read_bits(buf, 1); - if(sps->vui_parameters.nal_hrd_parameters_present_flag) + if (sps->vui_parameters.nal_hrd_parameters_present_flag) parse_hrd_parameters(buf, &sps->vui_parameters.nal_hrd_parameters); sps->vui_parameters.vc1_hrd_parameters_present_flag = read_bits(buf, 1); - if(sps->vui_parameters.vc1_hrd_parameters_present_flag) + if (sps->vui_parameters.vc1_hrd_parameters_present_flag) parse_hrd_parameters(buf, &sps->vui_parameters.vc1_hrd_parameters); - if(sps->vui_parameters.nal_hrd_parameters_present_flag || - sps->vui_parameters.vc1_hrd_parameters_present_flag) + if (sps->vui_parameters.nal_hrd_parameters_present_flag + || sps->vui_parameters.vc1_hrd_parameters_present_flag) sps->vui_parameters.low_delay_hrd_flag = read_bits(buf, 1); sps->vui_parameters.pic_struct_present_flag = read_bits(buf, 1); sps->vui_parameters.bitstream_restriction_flag = read_bits(buf, 1); - if(sps->vui_parameters.bitstream_restriction_flag) { + if (sps->vui_parameters.bitstream_restriction_flag) { sps->vui_parameters.motion_vectors_over_pic_boundaries = read_bits(buf, 1); sps->vui_parameters.max_bytes_per_pic_denom = read_exp_golomb(buf); sps->vui_parameters.max_bits_per_mb_denom = read_exp_golomb(buf); @@ -509,7 +519,7 @@ void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd) hrd->cpb_size_scale = read_bits(buf, 4); int i; - for(i = 0; i <= hrd->cpb_cnt_minus1; i++) { + for (i = 0; i <= hrd->cpb_cnt_minus1; i++) { hrd->bit_rate_value_minus1[i] = read_exp_golomb(buf); hrd->cpb_size_value_minus1[i] = read_exp_golomb(buf); hrd->cbr_flag[i] = read_bits(buf, 1); @@ -524,155 +534,163 @@ void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd) uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, struct seq_parameter_set_rbsp *sps) { - pps->pic_parameter_set_id = read_exp_golomb(buf); - pps->seq_parameter_set_id = read_exp_golomb(buf); - pps->entropy_coding_mode_flag = read_bits(buf, 1); - pps->pic_order_present_flag = read_bits(buf, 1); - - pps->num_slice_groups_minus1 = read_exp_golomb(buf); - if(pps->num_slice_groups_minus1 > 0) { - pps->slice_group_map_type = read_exp_golomb(buf); - if(pps->slice_group_map_type == 0) { - int i_group; - for(i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { - if(i_group < 64) - pps->run_length_minus1[i_group] = read_exp_golomb(buf); - else { // FIXME: skips if more than 64 groups exist - fprintf(stderr, "Error: Only 64 slice_groups are supported\n"); - read_exp_golomb(buf); - } - } - } else if(pps->slice_group_map_type == 3 || - pps->slice_group_map_type == 4 || - pps->slice_group_map_type == 5) { - pps->slice_group_change_direction_flag = read_bits(buf, 1); - pps->slice_group_change_rate_minus1 = read_exp_golomb(buf); - } else if(pps->slice_group_map_type == 6) { - pps->pic_size_in_map_units_minus1 = read_exp_golomb(buf); - int i_group; - for(i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { - pps->slice_group_id[i_group] = - read_bits(buf, ceil(log(pps->num_slice_groups_minus1 + 1))); - } - } + pps->pic_parameter_set_id = read_exp_golomb(buf); + pps->seq_parameter_set_id = read_exp_golomb(buf); + pps->entropy_coding_mode_flag = read_bits(buf, 1); + pps->pic_order_present_flag = read_bits(buf, 1); + + pps->num_slice_groups_minus1 = read_exp_golomb(buf); + if (pps->num_slice_groups_minus1 > 0) { + pps->slice_group_map_type = read_exp_golomb(buf); + if (pps->slice_group_map_type == 0) { + int i_group; + for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { + if (i_group < 64) + pps->run_length_minus1[i_group] = read_exp_golomb(buf); + else { // FIXME: skips if more than 64 groups exist + fprintf(stderr, "Error: Only 64 slice_groups are supported\n"); + read_exp_golomb(buf); + } + } + } + else if (pps->slice_group_map_type == 3 || pps->slice_group_map_type == 4 + || pps->slice_group_map_type == 5) { + pps->slice_group_change_direction_flag = read_bits(buf, 1); + pps->slice_group_change_rate_minus1 = read_exp_golomb(buf); } + else if (pps->slice_group_map_type == 6) { + pps->pic_size_in_map_units_minus1 = read_exp_golomb(buf); + int i_group; + for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { + pps->slice_group_id[i_group] = read_bits(buf, ceil(log( + pps->num_slice_groups_minus1 + 1))); + } + } + } - pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); - pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); - pps->weighted_pred_flag = read_bits(buf, 1); - pps->weighted_bipred_idc = read_bits(buf, 2); - pps->pic_init_qp_minus26 = read_exp_golomb_s(buf); - pps->pic_init_qs_minus26 = read_exp_golomb_s(buf); - pps->chroma_qp_index_offset = read_exp_golomb_s(buf); - pps->deblocking_filter_control_present_flag = read_bits(buf, 1); - pps->constrained_intra_pred_flag = read_bits(buf, 1); - pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); - - if(!rbsp_trailing_bits(buf)) { - printf("PARSE 8x8\n"); - pps->transform_8x8_mode_flag = read_bits(buf, 1); - pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); - if(pps->pic_scaling_matrix_present_flag) { - int i; - for(i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { - pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); - - if(pps->pic_scaling_list_present_flag[i]) { - if(i < 6) - parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); - else - parse_scaling_list(buf, pps->scaling_lists_8x8[i-6], 64, i); - } + pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); + pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); + pps->weighted_pred_flag = read_bits(buf, 1); + pps->weighted_bipred_idc = read_bits(buf, 2); + pps->pic_init_qp_minus26 = read_exp_golomb_s(buf); + pps->pic_init_qs_minus26 = read_exp_golomb_s(buf); + pps->chroma_qp_index_offset = read_exp_golomb_s(buf); + pps->deblocking_filter_control_present_flag = read_bits(buf, 1); + pps->constrained_intra_pred_flag = read_bits(buf, 1); + pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); + + if (!rbsp_trailing_bits(buf)) { + printf("PARSE 8x8\n"); + pps->transform_8x8_mode_flag = read_bits(buf, 1); + pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); + if (pps->pic_scaling_matrix_present_flag) { + int i; + for (i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { + pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); + + if (pps->pic_scaling_list_present_flag[i]) { + if (i < 6) + parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, pps->scaling_lists_8x8[i - 6], 64, i); } } - - pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); } + pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); + } - if(!pps->pic_scaling_matrix_present_flag) { - memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, sizeof(pps->scaling_lists_4x4)); - memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8, sizeof(pps->scaling_lists_8x8)); - } + if (!pps->pic_scaling_matrix_present_flag && sps != NULL) { + printf("MEMCPY SCALING LIST\n"); + memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, + sizeof(pps->scaling_lists_4x4)); + memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8, + sizeof(pps->scaling_lists_8x8)); + } + else if (sps == NULL) { + printf("sPS MISSING\n"); + } - return 0; + return 0; } uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) { - struct nal_unit *nal = parser->current_nal; - - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; - struct slice_header *slc = nal->slc; - if(!sps || !pps) - return -1; - - slc->first_mb_in_slice = read_exp_golomb(buf); - /* we do some parsing on the slice type, because the list is doubled */ - slc->slice_type = slice_type(read_exp_golomb(buf)); - slc->pic_parameter_set_id = read_exp_golomb(buf); - slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); - if(!sps->frame_mbs_only_flag) { - slc->field_pic_flag = read_bits(buf, 1); - if(slc->field_pic_flag) - slc->bottom_field_flag = read_bits(buf, 1); - else - slc->bottom_field_flag = -1; - } else { - slc->field_pic_flag = 0; - slc->bottom_field_flag = -1; - } + struct nal_unit *nal = parser->current_nal; - if(nal->nal_unit_type == NAL_SLICE_IDR) - slc->idr_pic_id = read_exp_golomb(buf); - - if(!sps->pic_order_cnt_type) { - slc->pic_order_cnt_lsb = read_bits(buf, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - if(pps->pic_order_present_flag && !slc->field_pic_flag) - slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf); - } else if (sps->pic_order_cnt_type == 1) { - slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf); - if(pps->pic_order_present_flag && !slc->field_pic_flag) - slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); - } + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if (!sps || !pps) + return -1; - if(pps->redundant_pic_cnt_present_flag == 1) { - slc->redundant_pic_cnt = read_exp_golomb(buf); - } + slc->first_mb_in_slice = read_exp_golomb(buf); + /* we do some parsing on the slice type, because the list is doubled */ + slc->slice_type = slice_type(read_exp_golomb(buf)); + slc->pic_parameter_set_id = read_exp_golomb(buf); + slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); + if (!sps->frame_mbs_only_flag) { + slc->field_pic_flag = read_bits(buf, 1); + if (slc->field_pic_flag) + slc->bottom_field_flag = read_bits(buf, 1); + else + slc->bottom_field_flag = 0; + } + else { + slc->field_pic_flag = 0; + slc->bottom_field_flag = 0; + } - if(slc->slice_type == SLICE_B) - slc->direct_spatial_mv_pred_flag = read_bits(buf, 1); + if (nal->nal_unit_type == NAL_SLICE_IDR) + slc->idr_pic_id = read_exp_golomb(buf); - if(slc->slice_type == SLICE_P || - slc->slice_type == SLICE_SP || - slc->slice_type == SLICE_B) { - slc->num_ref_idx_active_override_flag = read_bits(buf, 1); + if (!sps->pic_order_cnt_type) { + slc->pic_order_cnt_lsb = read_bits(buf, + sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + if (pps->pic_order_present_flag && !slc->field_pic_flag) + slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf); + } + else if (sps->pic_order_cnt_type == 1) { + slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf); + if (pps->pic_order_present_flag && !slc->field_pic_flag) + slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); + } - if(slc->num_ref_idx_active_override_flag == 1) { - slc->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); + if (pps->redundant_pic_cnt_present_flag == 1) { + slc->redundant_pic_cnt = read_exp_golomb(buf); + } - if(slc->slice_type == SLICE_B) { - slc->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); - } + if (slc->slice_type == SLICE_B) + slc->direct_spatial_mv_pred_flag = read_bits(buf, 1); + + if (slc->slice_type == SLICE_P || slc->slice_type == SLICE_SP + || slc->slice_type == SLICE_B) { + slc->num_ref_idx_active_override_flag = read_bits(buf, 1); + + if (slc->num_ref_idx_active_override_flag == 1) { + slc->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); + + if (slc->slice_type == SLICE_B) { + slc->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); } } + } - /* --- ref_pic_list_reordering --- */ - parse_ref_pic_list_reordering(buf, nal); + /* --- ref_pic_list_reordering --- */ + parse_ref_pic_list_reordering(buf, nal); - /* --- pred_weight_table --- */ - if((pps->weighted_pred_flag && - (slc->slice_type == SLICE_P || slc->slice_type == SLICE_SP)) || - (pps->weighted_bipred_idc == 1 && slc->slice_type == SLICE_B)) { - parse_pred_weight_table(buf, nal); - } + /* --- pred_weight_table --- */ + if ((pps->weighted_pred_flag && (slc->slice_type == SLICE_P + || slc->slice_type == SLICE_SP)) || (pps->weighted_bipred_idc == 1 + && slc->slice_type == SLICE_B)) { + parse_pred_weight_table(buf, nal); + } - /* --- dec_ref_pic_marking --- */ - if(nal->nal_ref_idc != 0) - parse_dec_ref_pic_marking(buf, nal); + /* --- dec_ref_pic_marking --- */ + if (nal->nal_ref_idc != 0) + parse_dec_ref_pic_marking(buf, nal); - return 0; + return 0; } void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal) @@ -680,37 +698,45 @@ void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal) struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; - if(!sps || !pps) - return; + if (!sps || !pps) + return; - if(slc->slice_type != SLICE_I && slc->slice_type != SLICE_SI) { - slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 = read_bits(buf, 1); + if (slc->slice_type != SLICE_I && slc->slice_type != SLICE_SI) { + slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 = read_bits( + buf, 1); - if(slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 == 1) { + if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 == 1) { do { - slc->ref_pic_list_reordering.reordering_of_pic_nums_idc = read_exp_golomb(buf); + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc + = read_exp_golomb(buf); - if(slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 || - slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { - slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 = read_exp_golomb(buf); - } else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { + if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 + || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { + slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 + = read_exp_golomb(buf); + } + else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); } } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); } } - if(slc->slice_type == SLICE_B) { - slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 = read_bits(buf, 1); + if (slc->slice_type == SLICE_B) { + slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 = read_bits( + buf, 1); - if(slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 == 1) { + if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 == 1) { do { - slc->ref_pic_list_reordering.reordering_of_pic_nums_idc = read_exp_golomb(buf); + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc + = read_exp_golomb(buf); - if(slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 || - slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { - slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 = read_exp_golomb(buf); - } else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { + if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 + || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { + slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 + = read_exp_golomb(buf); + } + else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); } } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); @@ -723,53 +749,57 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; - if(!sps || !pps) - return; + if (!sps || !pps) + return; nal->slc->pred_weight_table.luma_log2_weight_denom = read_exp_golomb(buf); - if(sps->chroma_format_idc != 0) + if (sps->chroma_format_idc != 0) nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); int i; - for(i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) { + for (i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) { uint8_t luma_weight_l0_flag = read_bits(buf, 1); - if(luma_weight_l0_flag == 1 ) { + if (luma_weight_l0_flag == 1) { nal->slc->pred_weight_table.luma_weight_l0[i] = read_exp_golomb_s(buf); nal->slc->pred_weight_table.luma_offset_l0[i] = read_exp_golomb_s(buf); } - if(sps->chroma_format_idc != 0) { + if (sps->chroma_format_idc != 0) { uint8_t chroma_weight_l0_flag = read_bits(buf, 1); - if(chroma_weight_l0_flag == 1 ) { + if (chroma_weight_l0_flag == 1) { int j; - for(j = 0; j < 2 ; j++) { - nal->slc->pred_weight_table.chroma_weight_l0[i][j] = read_exp_golomb_s(buf); - nal->slc->pred_weight_table.chroma_offset_l0[i][j] = read_exp_golomb_s(buf); + for (j = 0; j < 2; j++) { + nal->slc->pred_weight_table.chroma_weight_l0[i][j] + = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.chroma_offset_l0[i][j] + = read_exp_golomb_s(buf); } } } } - if(slc->slice_type == SLICE_B) { - for(i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) { + if (slc->slice_type == SLICE_B) { + for (i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) { uint8_t luma_weight_l1_flag = read_bits(buf, 1); - if(luma_weight_l1_flag == 1 ) { + if (luma_weight_l1_flag == 1) { nal->slc->pred_weight_table.luma_weight_l1[i] = read_exp_golomb_s(buf); nal->slc->pred_weight_table.luma_offset_l1[i] = read_exp_golomb_s(buf); } - if(sps->chroma_format_idc != 0) { + if (sps->chroma_format_idc != 0) { uint8_t chroma_weight_l1_flag = read_bits(buf, 1); - if(chroma_weight_l1_flag == 1 ) { + if (chroma_weight_l1_flag == 1) { int j; - for(j = 0; j < 2 ; j++) { - nal->slc->pred_weight_table.chroma_weight_l1[i][j] = read_exp_golomb_s(buf); - nal->slc->pred_weight_table.chroma_offset_l1[i][j] = read_exp_golomb_s(buf); + for (j = 0; j < 2; j++) { + nal->slc->pred_weight_table.chroma_weight_l1[i][j] + = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.chroma_offset_l1[i][j] + = read_exp_golomb_s(buf); } } } @@ -782,266 +812,277 @@ void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_unit *nal) struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; - if(!sps || !pps) - return; + if (!sps || !pps) + return; - if(nal->nal_unit_type == NAL_SLICE_IDR) { + if (nal->nal_unit_type == NAL_SLICE_IDR) { slc->dec_ref_pic_marking.no_output_of_prior_pics_flag = read_bits(buf, 1); slc->dec_ref_pic_marking.long_term_reference_flag = read_bits(buf, 1); - } else { - slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = read_bits(buf, 1); + } + else { + slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = read_bits( + buf, 1); - if(slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) { + if (slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) { do { - slc->dec_ref_pic_marking.memory_management_control_operation = read_exp_golomb(buf); + slc->dec_ref_pic_marking.memory_management_control_operation + = read_exp_golomb(buf); - if(slc->dec_ref_pic_marking.memory_management_control_operation == 1 || - slc->dec_ref_pic_marking.memory_management_control_operation == 3) - slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 = read_exp_golomb(buf); + if (slc->dec_ref_pic_marking.memory_management_control_operation == 1 + || slc->dec_ref_pic_marking.memory_management_control_operation + == 3) + slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + = read_exp_golomb(buf); - if(slc->dec_ref_pic_marking.memory_management_control_operation == 2) + if (slc->dec_ref_pic_marking.memory_management_control_operation == 2) slc->dec_ref_pic_marking.long_term_pic_num = read_exp_golomb(buf); - if(slc->dec_ref_pic_marking.memory_management_control_operation == 3 || - slc->dec_ref_pic_marking.memory_management_control_operation == 6) + if (slc->dec_ref_pic_marking.memory_management_control_operation == 3 + || slc->dec_ref_pic_marking.memory_management_control_operation + == 6) slc->dec_ref_pic_marking.long_term_frame_idx = read_exp_golomb(buf); - if(slc->dec_ref_pic_marking.memory_management_control_operation == 4) - slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 = read_exp_golomb(buf); - } while(slc->dec_ref_pic_marking.memory_management_control_operation != 0); + if (slc->dec_ref_pic_marking.memory_management_control_operation == 4) + slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 + = read_exp_golomb(buf); + } while (slc->dec_ref_pic_marking.memory_management_control_operation + != 0); } } } - /* ----------------- NAL parser ----------------- */ struct nal_parser* init_parser() { - struct nal_parser *parser = malloc(sizeof(struct nal_parser)); - memset(parser->buf, 0x00, MAX_FRAME_SIZE); - parser->buf_len = 0; - parser->found_sps = 0; - parser->found_pps = 0; - parser->nal0 = malloc(sizeof(struct nal_unit)); - memset(parser->nal0, 0x00, sizeof(struct nal_unit)); - parser->nal1 = malloc(sizeof(struct nal_unit)); - memset(parser->nal1, 0x00, sizeof(struct nal_unit)); - parser->current_nal = parser->nal0; - parser->last_nal = parser->nal1; - - parser->last_nal_res = 0; - parser->is_idr = 0; - parser->slice = 0; - parser->slice_cnt = 0; - parser->field = -1; - parser->have_top = 0; - - /* no idea why we do that. inspired by libavcodec, - * as we couldn't figure in the specs.... - */ - parser->prev_pic_order_cnt_msb = 1<<16; - - return parser; + struct nal_parser *parser = malloc(sizeof(struct nal_parser)); + memset(parser->buf, 0x00, MAX_FRAME_SIZE); + parser->buf_len = 0; + parser->found_sps = 0; + parser->found_pps = 0; + parser->nal0 = malloc(sizeof(struct nal_unit)); + memset(parser->nal0, 0x00, sizeof(struct nal_unit)); + parser->nal1 = malloc(sizeof(struct nal_unit)); + memset(parser->nal1, 0x00, sizeof(struct nal_unit)); + parser->current_nal = parser->nal0; + parser->last_nal = parser->nal1; + + parser->last_nal_res = 0; + parser->is_idr = 0; + parser->slice = 0; + parser->slice_cnt = 0; + parser->field = -1; + parser->have_top = 0; + + /* no idea why we do that. inspired by libavcodec, + * as we couldn't figure in the specs.... + */ + parser->prev_pic_order_cnt_msb = 1 << 16; + + return parser; } void free_parser(struct nal_parser *parser) { - free(parser->nal0); - free(parser->nal1); - free(parser); + free(parser->nal0); + free(parser->nal1); + free(parser); } int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, - uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) + uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) { - int next_nal; - int parsed_len = 0; - int search_offset = 0; - - while((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len)) >= 0) { - // save buffer up to the nal-start - if(parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; - } - - if(parser->last_nal_res != 2) { - /* this is not nal_unit != SLICE, keep it in the buffer */ - xine_fast_memcpy(parser->buf + parser->buf_len, inbuf, next_nal+search_offset); - parser->buf_len += next_nal+search_offset; - } + int next_nal; + int parsed_len = 0; + int search_offset = 0; + + while ((next_nal + = seek_for_nal(inbuf + search_offset, inbuf_len - parsed_len)) >= 0) { + // save buffer up to the nal-start + if (parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) { + printf("buf underrun!!\n"); + *ret_len = 0; + *ret_buf = NULL; + return parsed_len; + } - inbuf += next_nal+search_offset; - parsed_len += next_nal+search_offset; - - parser->last_nal_res = parse_nal(inbuf+4, inbuf_len-parsed_len, parser); - if(parser->last_nal_res == 1 - && parser->buf_len>0) { - *ret_buf = malloc(parser->buf_len); - xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); - *ret_len = parser->buf_len; - *ret_slice_cnt = parser->slice_cnt; - - calculate_pic_order(parser); - - //memset(parser->buf, 0x00, parser->buf_len); - parser->buf_len = 0; - parser->last_nal_res = 1; - parser->slice_cnt = 0; - - /*if(parser->current_nal->nal_ref_idc) { - if(parser->current_nal->slc != NULL) - parser->prev_pic_order_cnt_lsb = parser->current_nal->slc->pic_order_cnt_lsb; - parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; - }*/ - return parsed_len; - } + if (parser->last_nal_res != 2) { + /* this is not nal_unit != SLICE, keep it in the buffer */ + xine_fast_memcpy(parser->buf + parser->buf_len, inbuf, next_nal + + search_offset); + parser->buf_len += next_nal + search_offset; + } - search_offset = 4; + inbuf += next_nal + search_offset; + parsed_len += next_nal + search_offset; + + parser->last_nal_res = parse_nal(inbuf + 3, inbuf_len - parsed_len, parser); + if (parser->last_nal_res == 1 && parser->buf_len > 0) { + *ret_buf = malloc(parser->buf_len); + xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); + *ret_len = parser->buf_len; + *ret_slice_cnt = parser->slice_cnt; + + calculate_pic_order(parser); + + //memset(parser->buf, 0x00, parser->buf_len); + parser->buf_len = 0; + parser->last_nal_res = 1; + parser->slice_cnt = 0; + + /*if(parser->current_nal->nal_ref_idc) { + if(parser->current_nal->slc != NULL) + parser->prev_pic_order_cnt_lsb = parser->current_nal->slc->pic_order_cnt_lsb; + parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; + }*/ + return parsed_len; } - // no further NAL found, copy the rest of the stream - // into the buffer - xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len-parsed_len); - parser->buf_len += inbuf_len-parsed_len; + search_offset = 3; + } - parsed_len += (inbuf_len-parsed_len); - *ret_len = 0; - *ret_buf = NULL; + // no further NAL found, copy the rest of the stream + // into the buffer + xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len - parsed_len); + parser->buf_len += inbuf_len - parsed_len; - return parsed_len; + parsed_len += (inbuf_len - parsed_len); + *ret_len = 0; + *ret_buf = NULL; + + return parsed_len; } int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { - struct buf_reader bufr; - - bufr.buf = buf; - bufr.cur_pos = buf; - bufr.cur_offset = 8; - bufr.len = buf_len; - - struct nal_unit *nal = parser->current_nal; - struct nal_unit *last_nal = parser->last_nal; - - int res = parse_nal_header(&bufr, parser); - if(res == NAL_SLICE_IDR) - parser->is_idr = 1; - - if(res >= NAL_SLICE && res <= NAL_SLICE_IDR) { - // now detect if it's a new frame! - int ret = 0; - if(nal->slc->field_pic_flag == 1) - parser->field = nal->slc->bottom_field_flag; - else { - parser->have_top = 1; - parser->field = -1; - } + struct buf_reader bufr; - if(nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0) - parser->have_top = 1; + bufr.buf = buf; + bufr.cur_pos = buf; + bufr.cur_offset = 8; + bufr.len = buf_len; - parser->slice = 1; + struct nal_unit *nal = parser->current_nal; + struct nal_unit *last_nal = parser->last_nal; - if(nal->slc == NULL || last_nal->slc == NULL) { - printf("A\n"); - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->slc->frame_num != last_nal->slc->frame_num)) { - printf("B\n"); - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->slc->pic_parameter_set_id != last_nal->slc->pic_parameter_set_id)) { - printf("C\n"); - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->slc->field_pic_flag != last_nal->slc->field_pic_flag)) { - printf("D\n"); - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->slc->bottom_field_flag != -1 && - last_nal->slc->bottom_field_flag != -1 && - nal->slc->bottom_field_flag != last_nal->slc->bottom_field_flag)) { - printf("E\n"); - ret = 1; - } - if(nal->nal_ref_idc != last_nal->nal_ref_idc && - (nal->nal_ref_idc == 0 || last_nal->nal_ref_idc == 0)) { - printf("F\n"); - ret = 1; - } - if(nal->sps && nal->slc && last_nal->slc && - (nal->sps->pic_order_cnt_type == 0 && last_nal->sps->pic_order_cnt_type == 0 && - (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb || - nal->slc->delta_pic_order_cnt_bottom != last_nal->slc->delta_pic_order_cnt_bottom))) { - printf("G\n"); - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->sps->pic_order_cnt_type == 1 && last_nal->sps->pic_order_cnt_type == 1 && - (nal->slc->delta_pic_order_cnt[0] != last_nal->slc->delta_pic_order_cnt[0] || - nal->slc->delta_pic_order_cnt[1] != last_nal->slc->delta_pic_order_cnt[1]))) { - printf("H\n"); - ret = 1; - } - if(nal->nal_unit_type != last_nal->nal_unit_type && - (nal->nal_unit_type == 5 || last_nal->nal_unit_type == 5)) { - printf("I\n"); - ret = 1; - } - if(nal->slc && last_nal->slc && - (nal->nal_unit_type == 5 && last_nal->nal_unit_type == 5 && - nal->slc->idr_pic_id != last_nal->slc->idr_pic_id)) { - printf("J\n"); - ret = 1; - } + int res = parse_nal_header(&bufr, parser); + if (res == NAL_SLICE_IDR) + parser->is_idr = 1; - if(parser->current_nal == parser->nal0) { - parser->current_nal = parser->nal1; - parser->last_nal = parser->nal0; - } - else { - parser->current_nal = parser->nal0; - parser->last_nal = parser->nal1; - } + if (res >= NAL_SLICE && res <= NAL_SLICE_IDR) { + // now detect if it's a new frame! + int ret = 0; + if (nal->slc->field_pic_flag == 1) + parser->field = nal->slc->bottom_field_flag; + else { + parser->have_top = 1; + parser->field = -1; + } + + if (nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0) + parser->have_top = 1; + + parser->slice = 1; - if(parser->current_nal->sps == NULL) - parser->current_nal->sps = parser->last_nal->sps; - if(parser->current_nal->pps == NULL) - parser->current_nal->pps = parser->last_nal->pps; - - /* increase the slice_cnt until a new frame is detected */ - if(!ret) - parser->slice_cnt++; - - return ret; - } else if(res == NAL_PPS || res == NAL_SPS) { - return 2; - } else if (res >= NAL_SEI) { - //printf("New Frame\n"); - return 2; + if (nal->slc == NULL || last_nal->slc == NULL) { + printf("A\n"); + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->slc->frame_num + != last_nal->slc->frame_num)) { + printf("B\n"); + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->slc->pic_parameter_set_id + != last_nal->slc->pic_parameter_set_id)) { + printf("C\n"); + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->slc->field_pic_flag + != last_nal->slc->field_pic_flag)) { + printf("D\n"); + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->slc->bottom_field_flag != -1 + && last_nal->slc->bottom_field_flag != -1 + && nal->slc->bottom_field_flag != last_nal->slc->bottom_field_flag)) { + printf("E\n"); + ret = 1; + } + if (nal->nal_ref_idc != last_nal->nal_ref_idc && (nal->nal_ref_idc == 0 + || last_nal->nal_ref_idc == 0)) { + printf("F\n"); + ret = 1; + } + if (nal->sps && nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type + == 0 && last_nal->sps->pic_order_cnt_type == 0 + && (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb + || nal->slc->delta_pic_order_cnt_bottom + != last_nal->slc->delta_pic_order_cnt_bottom))) { + printf("G\n"); + ret = 1; } + if (nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 1 + && last_nal->sps->pic_order_cnt_type == 1 + && (nal->slc->delta_pic_order_cnt[0] + != last_nal->slc->delta_pic_order_cnt[0] + || nal->slc->delta_pic_order_cnt[1] + != last_nal->slc->delta_pic_order_cnt[1]))) { + printf("H\n"); + ret = 1; + } + if (nal->nal_unit_type != last_nal->nal_unit_type && (nal->nal_unit_type + == 5 || last_nal->nal_unit_type == 5)) { + printf("I\n"); + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->nal_unit_type == 5 + && last_nal->nal_unit_type == 5 && nal->slc->idr_pic_id + != last_nal->slc->idr_pic_id)) { + printf("J\n"); + ret = 1; + } + + if (parser->current_nal == parser->nal0) { + parser->current_nal = parser->nal1; + parser->last_nal = parser->nal0; + } + else { + parser->current_nal = parser->nal0; + parser->last_nal = parser->nal1; + } + + if (parser->current_nal->sps == NULL) + parser->current_nal->sps = parser->last_nal->sps; + if (parser->current_nal->pps == NULL) + parser->current_nal->pps = parser->last_nal->pps; + + /* increase the slice_cnt until a new frame is detected */ + if (!ret) + parser->slice_cnt++; - return 1; + return ret; + } + else if (res == NAL_PPS || res == NAL_SPS) { + return 2; + } + else if (res >= NAL_SEI) { + //printf("New Frame\n"); + return 2; + } + + return 1; } int seek_for_nal(uint8_t *buf, int buf_len) { - int i; - for(i=0; ipic_order_cnt_type == 0 */ diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 2e88932d4..eb2f61040 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -285,7 +285,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, //dump_pictureinfo_h264(&pic); - int i; + /*int i; printf("Decode data: \n"); for(i = 0; i < ((vdp_buffer.bitstream_bytes < 20) ? vdp_buffer.bitstream_bytes : 20); i++) { printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); @@ -297,7 +297,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); if((i+1) % 10 == 0) printf("\n"); - } + }*/ if(img == NULL) { -- cgit v1.2.3 From 58967e9def83953542cfa57b14d5ddd8fe742031 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 5 Dec 2008 20:39:21 +0000 Subject: Queue bits; use-after-free fix. --- src/video_out/video_out_vdpau.c | 65 ++++++++++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 3197307a7..9b7319819 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -75,6 +75,7 @@ VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_get_put VdpVideoSurfaceCreate *vdp_video_surface_create; VdpVideoSurfaceDestroy *vdp_video_surface_destroy; VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_putbits_ycbcr; +VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_getbits_ycbcr; VdpOutputSurfaceCreate *vdp_output_surface_create; VdpOutputSurfaceDestroy *vdp_output_surface_destroy; @@ -147,7 +148,7 @@ typedef struct { int soft_surface_format; VdpOutputSurface output_surface[2]; - uint32_t current_output_surface; + uint8_t current_output_surface; uint32_t output_surface_width[2]; uint32_t output_surface_height[2]; uint8_t init_queue; @@ -159,6 +160,7 @@ typedef struct { uint32_t capabilities; xine_t *xine; + int gotimage; } vdpau_driver_t; @@ -359,13 +361,6 @@ static void vdpau_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) vdpau_frame_t *frame = (vdpau_frame_t *) vo_img ; vo_img->proc_called = 1; - - if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || - frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) - { - /* TODO: ?!? */ - return; - } } @@ -383,9 +378,9 @@ static void vdpau_frame_dispose (vo_frame_t *vo_img) free (frame->chunk[0]); free (frame->chunk[1]); free (frame->chunk[2]); - free (frame); if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); + free (frame); } @@ -458,6 +453,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) { if ( (frame->width != width) || (frame->height != height) || (frame->format != XINE_IMGFMT_VDPAU) ) { + printf("vo_vdpau: update_frame - destroy surface\n"); vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; } @@ -499,6 +495,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) uint32_t mix_w = this->video_mixer_width; uint32_t mix_h = this->video_mixer_height; + if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) || (frame->ratio != this->sc.delivered_ratio) ) { this->sc.force_redraw = 1; /* trigger re-calc of output size */ } @@ -514,9 +511,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_redraw_needed( this_gen ); if ( (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) ) { + printf( "vo_vdpau: got a yuv image -------------\n" ); surface = this->soft_surface; chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; - if ( (frame->width > this->soft_surface_width) | (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { + if ( (frame->width > this->soft_surface_width) || (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { printf( "vo_vdpau: soft_surface size update\n" ); /* recreate surface and mixer to match frame changes */ mix_w = this->soft_surface_width = frame->width; @@ -540,13 +538,37 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } } else if (frame->format == XINE_IMGFMT_VDPAU) { + printf( "vo_vdpau: got a vdpau image -------------\n" ); surface = frame->vdpau_accel_data.surface; + /*if ( !this->gotimage ) { + printf( "vo_vdpau: mallocing yuv ......\n" ); + uint32_t pitches[] = { 8*((frame->width + 7) / 8), 8*((frame->width + 15) / 16), 8*((frame->width + 15) / 16) }; + uint8_t *mem_y = (uint8_t*)malloc(frame->width*frame->height); + uint8_t *mem_u = (uint8_t*)malloc(frame->width*frame->height); + uint8_t *mem_v = (uint8_t*)malloc(frame->width*frame->height); + uint8_t* planes[] = { mem_y, mem_u, mem_v }; + ++this->gotimage; + st = vdp_video_surface_getbits_ycbcr( surface, VDP_YCBCR_FORMAT_YV12, planes, pitches); + if ( st != VDP_STATUS_OK ) + printf( " vo_vdpau: can't get yv12 bbits !!!!!!!!!!!! : %s\n", vdp_get_error_string( st ) ); + else { + fprintf(stderr,"P5\n%d %d\n255\n",frame->width, frame->height); + int j; + uint8_t red, green, blue; + for ( j=0; j<(frame->width*frame->height); j++ ) { + fprintf(stderr,"%d ", mem_y[j] ); + } + fprintf(stderr, "\n"); + printf( "vo_vdpau: ...........got surface bits\n" ); + } + }*/ mix_w = frame->width; mix_h = frame->height; chroma = VDP_CHROMA_TYPE_420; } else { /* unknown format */ + printf( "vo_vdpau: got an unknown image -------------\n" ); frame->vo_frame.free( &frame->vo_frame ); return; } @@ -576,7 +598,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) XLockDisplay( this->display ); - if ( this->init_queue ) { + if ( this->init_queue>1 ) { int previous = this->current_output_surface ^ 1; VdpTime time; vdp_queue_block( vdp_queue, this->output_surface[previous], &time ); @@ -605,8 +627,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_display( vdp_queue, this->overlay_output, 0, 0, 0 ); else*/ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); + printf( "vo_vdpau: image displayed\n" ); - if ( !this->init_queue ) + if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; @@ -898,6 +921,9 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , (void*)&vdp_video_surface_putbits_ycbcr ); if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_PUT_BITS_Y_CB_CR proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR , (void*)&vdp_video_surface_getbits_ycbcr ); + if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_GET_BITS_Y_CB_CR proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , (void*)&vdp_output_surface_create ); if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -969,22 +995,19 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if ( vdpau_init_error( st, "Can't create presentation queue !!", &this->vo_driver, 1 ) ) return NULL; - - VdpColor backColor; - backColor.red = backColor.green = backColor.blue = 0; - backColor.alpha = 1; + VdpColor backColor = { 0, 0, 0, 1 }; vdp_queue_set_backgroung_color( vdp_queue, &backColor ); - this->soft_surface_width = 720; - this->soft_surface_height = 576; + this->soft_surface_width = 1280; + this->soft_surface_height = 720; this->soft_surface_format = XINE_IMGFMT_YV12; VdpChromaType chroma = VDP_CHROMA_TYPE_420; st = vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) return NULL; - this->output_surface_width[0] = this->output_surface_width[1] = 720; - this->output_surface_height[0] = this->output_surface_height[1] = 576; + this->output_surface_width[0] = this->output_surface_width[1] = 1280; + this->output_surface_height[0] = this->output_surface_height[1] = 720; this->current_output_surface = 0; this->init_queue = 0; st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] ); @@ -1023,7 +1046,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo else this->capabilities |= VO_CAP_VDPAU_H264; - + this->gotimage = 0; return &this->vo_driver; } -- cgit v1.2.3 From 6b73508d4e9a12689c8f0749c30f683ce777fef8 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 7 Dec 2008 21:40:50 +0000 Subject: DPB starts growing. Restructuring of parser. --HG-- rename : src/libvdpau/nal_parser.c => src/libvdpau/h264_parser.c rename : src/libvdpau/nal_parser.h => src/libvdpau/h264_parser.h --- src/libvdpau/Makefile.am | 2 +- src/libvdpau/dpb.c | 222 +++++++++ src/libvdpau/dpb.h | 41 ++ src/libvdpau/h264_parser.c | 1131 ++++++++++++++++++++++++++++++++++++++++++++ src/libvdpau/h264_parser.h | 48 ++ src/libvdpau/nal.c | 46 ++ src/libvdpau/nal.h | 350 ++++++++++++++ src/libvdpau/nal_parser.c | 1088 ------------------------------------------ src/libvdpau/nal_parser.h | 377 --------------- src/libvdpau/vdpau_h264.c | 14 +- 10 files changed, 1850 insertions(+), 1469 deletions(-) create mode 100644 src/libvdpau/dpb.c create mode 100644 src/libvdpau/dpb.h create mode 100644 src/libvdpau/h264_parser.c create mode 100644 src/libvdpau/h264_parser.h create mode 100644 src/libvdpau/nal.c create mode 100644 src/libvdpau/nal.h delete mode 100644 src/libvdpau/nal_parser.c delete mode 100644 src/libvdpau/nal_parser.h diff --git a/src/libvdpau/Makefile.am b/src/libvdpau/Makefile.am index 31afca222..6cbce1016 100644 --- a/src/libvdpau/Makefile.am +++ b/src/libvdpau/Makefile.am @@ -10,6 +10,6 @@ endif xineplug_LTLIBRARIES = $(vdpau_h264_module) -xineplug_decode_vdpau_h264_la_SOURCES = nal_parser.c vdpau_h264.c +xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c h264_parser.c vdpau_h264.c xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS) xineplug_decode_vdpau_h264_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c new file mode 100644 index 000000000..460149ea3 --- /dev/null +++ b/src/libvdpau/dpb.c @@ -0,0 +1,222 @@ +/* + * dpb.c + * + * Created on: 07.12.2008 + * Author: julian + */ + +#include +#include +#include + +#include "dpb.h" + +struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, + VdpVideoSurface surface) +{ + struct decoded_picture *pic = malloc(sizeof(struct decoded_picture)); + pic->nal = init_nal_unit(); + copy_nal_unit(pic->nal, src_nal); + pic->surface = surface; + pic->next = NULL; + + return pic; +} + +void free_decoded_picture(struct decoded_picture *pic) +{ + free_nal_unit(pic->nal); +} + +struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum) +{ + struct decoded_picture *pic = dpb->pictures; + + if (pic != NULL) + do { + if (pic->nal->curr_pic_num == picnum) + return pic; + } while ((pic = pic->next) != NULL); + + return NULL; +} + +struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, + uint32_t longterm_picnum) +{ + struct decoded_picture *pic = dpb->pictures; + + if (pic != NULL) + do { + if (pic->nal->long_term_pic_num == longterm_picnum) + return pic; + } while ((pic = pic->next) != NULL); + + return NULL; +} + +struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, + uint32_t longterm_idx) +{ + struct decoded_picture *pic = dpb->pictures; + + if (pic != NULL) + do { + if (pic->nal->long_term_frame_idx == longterm_idx) + return pic; + } while ((pic = pic->next) != NULL); + + return NULL; +} + +int dpb_remove_picture(struct dpb *dpb, uint32_t picnum) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->nal->curr_pic_num == picnum) { + // FIXME: free the picture.... + + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + + free_decoded_picture(pic); + return 0; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return -1; +} + +int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->nal->long_term_pic_num == longterm_picnum) { + // FIXME: free the picture.... + + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + + free_decoded_picture(pic); + return 0; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return -1; +} + +int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->nal->long_term_frame_idx == longterm_idx) { + // FIXME: free the picture.... + + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + + free_decoded_picture(pic); + return 0; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return -1; +} + +int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->nal->long_term_frame_idx > longterm_max) { + // FIXME: free the picture.... + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + + + free_decoded_picture(pic); + + /* don't increase last_pic to current pic + * in case we delete current pic */ + continue; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return 0; +} + +int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic) +{ + pic->next = dpb->pictures; + dpb->pictures = pic; + + return 0; +} + +int dpb_flush(struct dpb *dpb) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + //FIXME: free the picture + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + dpb->pictures = NULL; + + return 0; +} + +void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + int i = 0; + + if (pic != NULL) + do { + if (pic->nal->nal_ref_idc != 0) { + reflist[i].surface = pic->surface; + reflist[i].is_long_term = pic->nal->used_for_long_term_ref; + reflist[i].top_is_reference = pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; + reflist[i].bottom_is_reference = pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1; + reflist[i].field_order_cnt[0] = pic->nal->top_field_order_cnt; + reflist[i].field_order_cnt[1] = pic->nal->bottom_field_order_cnt; + i++; + } + last_pic = pic; + } while ((pic = pic->next) != NULL && i < 16); +} diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h new file mode 100644 index 000000000..8aa430c26 --- /dev/null +++ b/src/libvdpau/dpb.h @@ -0,0 +1,41 @@ +/* + * dpb.h + * + * Created on: 06.12.2008 + * Author: julian + */ + +#ifndef DPB_H_ +#define DPB_H_ + +#include "nal.h" + +struct decoded_picture { + VdpVideoSurface surface; + struct nal_unit *nal; + + struct decoded_picture *next; +}; + +/* Decoded Picture Buffer */ +struct dpb { + struct decoded_picture *pictures; +}; + +struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, + VdpVideoSurface surface); +void free_decoded_picture(struct decoded_picture *pic); + +struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum); +struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); +struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); +int dpb_remove_picture(struct dpb *dpb, uint32_t picnum); +int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); +int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); +int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max); +int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic); +int dpb_flush(struct dpb *dpb); + +void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist); + +#endif /* DPB_H_ */ diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c new file mode 100644 index 000000000..7ae1cc216 --- /dev/null +++ b/src/libvdpau/h264_parser.c @@ -0,0 +1,1131 @@ +#include +#include +#include + +#include "h264_parser.h" +#include "nal.h" + +/* default scaling_lists according to Table 7-2 */ +uint8_t default_4x4_intra[16] = { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, + 32, 32, 37, 37, 42 }; + +uint8_t default_4x4_inter[16] = { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, + 27, 27, 30, 30, 34 }; + +uint8_t default_8x8_intra[64] = { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, + 18, 18, 18, 18, 32, 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, + 27, 27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, 31, + 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; + +uint8_t default_8x8_inter[64] = { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, + 19, 19, 19, 19, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, + 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27, + 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; + +struct buf_reader +{ + uint8_t *buf; + uint8_t *cur_pos; + int len; + int cur_offset; +}; + +static inline uint32_t read_bits(struct buf_reader *buf, int len); +uint32_t read_exp_golomb(struct buf_reader *buf); +int32_t read_exp_golomb_s(struct buf_reader *buf); + +void calculate_pic_order(struct nal_parser *parser); +void skip_scaling_list(struct buf_reader *buf, int size); +void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, + int length, int index); +int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser); +uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); +void parse_vui_parameters(struct buf_reader *buf, + struct seq_parameter_set_rbsp *sps); +void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd); +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, + struct seq_parameter_set_rbsp *sps); +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser); +void + parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); +void decode_ref_pic_marking(uint32_t memory_management_control_operation, + struct nal_parser *parser); +void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); +void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_parser *parser); + +/* here goes the parser implementation */ + +static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) +{ + uint8_t *end = &buf[buf_len]; + uint8_t *pos = malloc(buf_len); + + *ret = pos; + while (buf < end) { + if (buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x03) { + + *pos++ = 0x00; + *pos++ = 0x00; + + buf += 3; + continue; + } + *pos++ = *buf++; + } + + *len_ret = pos - *ret; +} + +static inline uint32_t read_bits(struct buf_reader *buf, int len) +{ + static uint32_t i_mask[33] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, + 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, + 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, + 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, + 0x3fffffff, 0x7fffffff, 0xffffffff }; + + int i_shr; + uint32_t bits = 0; + + while (len > 0 && (buf->cur_pos - buf->buf) < buf->len) { + if ((i_shr = buf->cur_offset - len) >= 0) { + bits |= (*buf->cur_pos >> i_shr) & i_mask[len]; + buf->cur_offset -= len; + if (buf->cur_offset == 0) { + buf->cur_pos++; + buf->cur_offset = 8; + } + return bits; + } + else { + bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; + len -= buf->cur_offset; + buf->cur_pos++; + buf->cur_offset = 8; + } + } + return bits; +} + +/* determines if following bits are rtsb_trailing_bits */ +static inline uint8_t rbsp_trailing_bits(struct buf_reader *buf) +{ + // store the offset and pos in buffer + // to revert this afterwards. + int last_offset; + uint8_t *last_pos; + + uint8_t rbsp_trailing_bits = 1; + + last_offset = buf->cur_offset; + last_pos = buf->cur_pos; + + if (read_bits(buf, 1) == 1) { + while (buf->cur_offset != 8) + if (read_bits(buf, 1) == 1) + rbsp_trailing_bits = 0; + } + + // revert buffer + buf->cur_offset = last_offset; + buf->cur_pos = last_pos; + + return rbsp_trailing_bits; +} + +uint32_t read_exp_golomb(struct buf_reader *buf) +{ + int leading_zero_bits = 0; + + while (read_bits(buf, 1) == 0 && leading_zero_bits < 32) + leading_zero_bits++; + + uint32_t code = (1 << leading_zero_bits) - 1 + read_bits(buf, + leading_zero_bits); + return code; +} + +int32_t read_exp_golomb_s(struct buf_reader *buf) +{ + uint32_t ue = read_exp_golomb(buf); + int32_t code = ue & 0x01 ? (ue + 1) / 2 : -(ue / 2); + return code; +} + +int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) +{ + if (buf->len < 1) + return -1; + int ret = -1; + + struct nal_unit *nal = parser->current_nal; + + nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; + nal->nal_unit_type = buf->buf[0] & 0x1f; + + buf->cur_pos = buf->buf + 1; + //printf("NAL: %d\n", nal->nal_unit_type); + + struct buf_reader ibuf; + ibuf.cur_offset = 8; + + switch (nal->nal_unit_type) { + case NAL_SPS: + decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len - 1); + ibuf.cur_pos = ibuf.buf; + + memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); + + parse_sps(&ibuf, nal->sps); + free(ibuf.buf); + ret = NAL_SPS; + break; + case NAL_PPS: + memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); + + parse_pps(buf, nal->pps, nal->sps); + ret = NAL_PPS; + break; + case NAL_SLICE: + case NAL_PART_A: + case NAL_PART_B: + case NAL_PART_C: + case NAL_SLICE_IDR: + if (nal->sps && nal->pps) { + memset(nal->slc, 0x00, sizeof(struct slice_header)); + + parse_slice_header(buf, parser); + ret = nal->nal_unit_type; + } + break; + default: + ret = nal->nal_unit_type; + break; + } + + return ret; +} + +void calculate_pic_order(struct nal_parser *parser) +{ + struct nal_unit *nal = parser->current_nal; + + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if (!sps || !pps || !slc) + return; + + if (sps->pic_order_cnt_type == 0) { + if (nal->nal_unit_type == NAL_SLICE_IDR) { + parser->prev_pic_order_cnt_lsb = 0; + parser->prev_pic_order_cnt_msb = 0; + } + else { + const int max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + if (slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb + && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb + >= max_poc_lsb / 2) + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + + max_poc_lsb; + else if (slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb + && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb + < -max_poc_lsb / 2) + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + - max_poc_lsb; + else + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; + + if (!slc->bottom_field_flag) { + nal->top_field_order_cnt = parser->pic_order_cnt_msb + + slc->pic_order_cnt_lsb; + + if (!slc->field_pic_flag) + nal->bottom_field_order_cnt = nal->top_field_order_cnt; + else + nal->bottom_field_order_cnt = 0; + } + else + nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + + slc->pic_order_cnt_lsb; + + if (parser->field == -1) + nal->bottom_field_order_cnt += slc->delta_pic_order_cnt_bottom; + } + } + +} + +void skip_scaling_list(struct buf_reader *buf, int size) +{ + int i; + for (i = 0; i < size; i++) { + read_exp_golomb_s(buf); + } +} + +void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, + int length, int index) +{ + int last_scale = 8; + int next_scale = 8; + int32_t delta_scale; + uint8_t use_default_scaling_matrix_flag = 0; + int i; + + for (i = 0; i < length; i++) { + if (next_scale != 0) { + delta_scale = read_exp_golomb_s(buf); + next_scale = (last_scale + delta_scale + 256) % 256; + if (i == 0 && next_scale == 0) { + use_default_scaling_matrix_flag = 1; + break; + } + } + scaling_list[i] = (next_scale == 0) ? last_scale : next_scale; + last_scale = scaling_list[i]; + } + + if (use_default_scaling_matrix_flag) { + switch (index) { + case 0: + case 1: + case 2: + memcpy(scaling_list, default_4x4_intra, length); + break; + case 3: + case 4: + case 5: + memcpy(scaling_list, default_4x4_inter, length); + break; + case 6: + memcpy(scaling_list, default_8x8_intra, length); + break; + case 7: + memcpy(scaling_list, default_8x8_inter, length); + break; + } + } +} + +uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) +{ + sps->profile_idc = buf->buf[0]; + sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; + sps->level_idc = buf->buf[2]; + + buf->cur_pos = buf->buf + 3; + sps->seq_parameter_set_id = read_exp_golomb(buf); + if (sps->profile_idc == 100 || sps->profile_idc == 110 || sps->profile_idc + == 122 || sps->profile_idc == 144) { + sps->chroma_format_idc = read_exp_golomb(buf); + if (sps->chroma_format_idc == 3) { + sps->residual_colour_transform_flag = read_bits(buf, 1); + } + + sps->bit_depth_luma_minus8 = read_exp_golomb(buf); + sps->bit_depth_chroma_minus8 = read_exp_golomb(buf); + sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); + sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); + if (sps->seq_scaling_matrix_present_flag) { + printf("SCALING LIST PRESENT\n"); + int i; + for (i = 0; i < 8; i++) { + sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); + + if (sps->seq_scaling_list_present_flag[i]) { + if (i < 6) + parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, sps->scaling_lists_8x8[i - 6], 64, i); + } + } + } + } + + if (!sps->seq_scaling_matrix_present_flag) { + memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); + memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_4x4)); + } + + sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); + + sps->pic_order_cnt_type = read_exp_golomb(buf); + if (!sps->pic_order_cnt_type) + sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf); + else { + sps->delta_pic_order_always_zero_flag = read_bits(buf, 1); + sps->offset_for_non_ref_pic = read_exp_golomb_s(buf); + sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf); + sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf); + int i; + for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) { + sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf); + } + } + sps->num_ref_frames = read_exp_golomb(buf); + sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1); + + /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf); + sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/ + sps->pic_width = 16 * (read_exp_golomb(buf) + 1); + sps->pic_height = 16 * (read_exp_golomb(buf) + 1); + + sps->frame_mbs_only_flag = read_bits(buf, 1); + + /* compute the height correctly even for interlaced material */ + sps->pic_height = (2 - sps->frame_mbs_only_flag) * sps->pic_height; + if (sps->pic_height == 1088) + sps->pic_height = 1080; + + if (!sps->frame_mbs_only_flag) + sps->mb_adaptive_frame_field_flag = read_bits(buf, 1); + + sps->direct_8x8_inference_flag = read_bits(buf, 1); + sps->frame_cropping_flag = read_bits(buf, 1); + if (sps->frame_cropping_flag) { + sps->frame_crop_left_offset = read_exp_golomb(buf); + sps->frame_crop_right_offset = read_exp_golomb(buf); + sps->frame_crop_top_offset = read_exp_golomb(buf); + sps->frame_crop_bottom_offset = read_exp_golomb(buf); + } + sps->vui_parameters_present_flag = read_bits(buf, 1); + if (sps->vui_parameters_present_flag) { + parse_vui_parameters(buf, sps); + } + + return 0; +} + +void parse_vui_parameters(struct buf_reader *buf, + struct seq_parameter_set_rbsp *sps) +{ + sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1); + if (sps->vui_parameters.aspect_ration_info_present_flag == 1) { + sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8); + if (sps->vui_parameters.aspect_ratio_idc == ASPECT_RESERVED) { + sps->vui_parameters.sar_width = read_bits(buf, 16); + sps->vui_parameters.sar_height = read_bits(buf, 16); + } + } + + sps->vui_parameters.overscan_info_present_flag = read_bits(buf, 1); + if (sps->vui_parameters.overscan_info_present_flag) { + sps->vui_parameters.overscan_appropriate_flag = read_bits(buf, 1); + } + + sps->vui_parameters.video_signal_type_present_flag = read_bits(buf, 1); + if (sps->vui_parameters.video_signal_type_present_flag) { + sps->vui_parameters.video_format = read_bits(buf, 3); + sps->vui_parameters.video_full_range_flag = read_bits(buf, 1); + sps->vui_parameters.colour_description_present = read_bits(buf, 1); + if (sps->vui_parameters.colour_description_present) { + sps->vui_parameters.colour_primaries = read_bits(buf, 8); + sps->vui_parameters.transfer_characteristics = read_bits(buf, 8); + sps->vui_parameters.matrix_coefficients = read_bits(buf, 8); + } + } + + sps->vui_parameters.chroma_loc_info_present_flag = read_bits(buf, 1); + if (sps->vui_parameters.chroma_loc_info_present_flag) { + sps->vui_parameters.chroma_sample_loc_type_top_field = read_exp_golomb(buf); + sps->vui_parameters.chroma_sample_loc_type_bottom_field = read_exp_golomb( + buf); + } + + sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1); + if (sps->vui_parameters.timing_info_present_flag) { + sps->vui_parameters.num_units_in_tick = read_bits(buf, 32); + sps->vui_parameters.time_scale = read_bits(buf, 32); + sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1); + } + + sps->vui_parameters.nal_hrd_parameters_present_flag = read_bits(buf, 1); + if (sps->vui_parameters.nal_hrd_parameters_present_flag) + parse_hrd_parameters(buf, &sps->vui_parameters.nal_hrd_parameters); + + sps->vui_parameters.vc1_hrd_parameters_present_flag = read_bits(buf, 1); + if (sps->vui_parameters.vc1_hrd_parameters_present_flag) + parse_hrd_parameters(buf, &sps->vui_parameters.vc1_hrd_parameters); + + if (sps->vui_parameters.nal_hrd_parameters_present_flag + || sps->vui_parameters.vc1_hrd_parameters_present_flag) + sps->vui_parameters.low_delay_hrd_flag = read_bits(buf, 1); + + sps->vui_parameters.pic_struct_present_flag = read_bits(buf, 1); + sps->vui_parameters.bitstream_restriction_flag = read_bits(buf, 1); + + if (sps->vui_parameters.bitstream_restriction_flag) { + sps->vui_parameters.motion_vectors_over_pic_boundaries = read_bits(buf, 1); + sps->vui_parameters.max_bytes_per_pic_denom = read_exp_golomb(buf); + sps->vui_parameters.max_bits_per_mb_denom = read_exp_golomb(buf); + sps->vui_parameters.log2_max_mv_length_horizontal = read_exp_golomb(buf); + sps->vui_parameters.log2_max_mv_length_vertical = read_exp_golomb(buf); + sps->vui_parameters.num_reorder_frames = read_exp_golomb(buf); + sps->vui_parameters.max_dec_frame_buffering = read_exp_golomb(buf); + } +} + +void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd) +{ + hrd->cpb_cnt_minus1 = read_exp_golomb(buf); + hrd->bit_rate_scale = read_bits(buf, 4); + hrd->cpb_size_scale = read_bits(buf, 4); + + int i; + for (i = 0; i <= hrd->cpb_cnt_minus1; i++) { + hrd->bit_rate_value_minus1[i] = read_exp_golomb(buf); + hrd->cpb_size_value_minus1[i] = read_exp_golomb(buf); + hrd->cbr_flag[i] = read_bits(buf, 1); + } + + hrd->initial_cpb_removal_delay_length_minus1 = read_bits(buf, 5); + hrd->cpb_removal_delay_length_minus1 = read_bits(buf, 5); + hrd->dpb_output_delay_length_minus1 = read_bits(buf, 5); + hrd->time_offset_length = read_bits(buf, 5); +} + +uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, + struct seq_parameter_set_rbsp *sps) +{ + pps->pic_parameter_set_id = read_exp_golomb(buf); + pps->seq_parameter_set_id = read_exp_golomb(buf); + pps->entropy_coding_mode_flag = read_bits(buf, 1); + pps->pic_order_present_flag = read_bits(buf, 1); + + pps->num_slice_groups_minus1 = read_exp_golomb(buf); + if (pps->num_slice_groups_minus1 > 0) { + pps->slice_group_map_type = read_exp_golomb(buf); + if (pps->slice_group_map_type == 0) { + int i_group; + for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { + if (i_group < 64) + pps->run_length_minus1[i_group] = read_exp_golomb(buf); + else { // FIXME: skips if more than 64 groups exist + fprintf(stderr, "Error: Only 64 slice_groups are supported\n"); + read_exp_golomb(buf); + } + } + } + else if (pps->slice_group_map_type == 3 || pps->slice_group_map_type == 4 + || pps->slice_group_map_type == 5) { + pps->slice_group_change_direction_flag = read_bits(buf, 1); + pps->slice_group_change_rate_minus1 = read_exp_golomb(buf); + } + else if (pps->slice_group_map_type == 6) { + pps->pic_size_in_map_units_minus1 = read_exp_golomb(buf); + int i_group; + for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { + pps->slice_group_id[i_group] = read_bits(buf, ceil(log( + pps->num_slice_groups_minus1 + 1))); + } + } + } + + pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); + pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); + pps->weighted_pred_flag = read_bits(buf, 1); + pps->weighted_bipred_idc = read_bits(buf, 2); + pps->pic_init_qp_minus26 = read_exp_golomb_s(buf); + pps->pic_init_qs_minus26 = read_exp_golomb_s(buf); + pps->chroma_qp_index_offset = read_exp_golomb_s(buf); + pps->deblocking_filter_control_present_flag = read_bits(buf, 1); + pps->constrained_intra_pred_flag = read_bits(buf, 1); + pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); + + if (!rbsp_trailing_bits(buf)) { + printf("PARSE 8x8\n"); + pps->transform_8x8_mode_flag = read_bits(buf, 1); + pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); + if (pps->pic_scaling_matrix_present_flag) { + int i; + for (i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { + pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); + + if (pps->pic_scaling_list_present_flag[i]) { + if (i < 6) + parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); + else + parse_scaling_list(buf, pps->scaling_lists_8x8[i - 6], 64, i); + } + } + } + + pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); + } + + if (!pps->pic_scaling_matrix_present_flag && sps != NULL) { + printf("MEMCPY SCALING LIST\n"); + memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, + sizeof(pps->scaling_lists_4x4)); + memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8, + sizeof(pps->scaling_lists_8x8)); + } + else if (sps == NULL) { + printf("sPS MISSING\n"); + } + + return 0; +} + +uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) +{ + struct nal_unit *nal = parser->current_nal; + + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if (!sps || !pps) + return -1; + + slc->first_mb_in_slice = read_exp_golomb(buf); + /* we do some parsing on the slice type, because the list is doubled */ + slc->slice_type = slice_type(read_exp_golomb(buf)); + slc->pic_parameter_set_id = read_exp_golomb(buf); + slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); + if (!sps->frame_mbs_only_flag) { + slc->field_pic_flag = read_bits(buf, 1); + if (slc->field_pic_flag) + slc->bottom_field_flag = read_bits(buf, 1); + else + slc->bottom_field_flag = 0; + } + else { + slc->field_pic_flag = 0; + slc->bottom_field_flag = 0; + } + + if (slc->field_pic_flag == 0) + nal->curr_pic_num = slc->frame_num; + else + nal->curr_pic_num = 2 * slc->frame_num + 1; + + if (nal->nal_unit_type == NAL_SLICE_IDR) + slc->idr_pic_id = read_exp_golomb(buf); + + if (!sps->pic_order_cnt_type) { + slc->pic_order_cnt_lsb = read_bits(buf, + sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + if (pps->pic_order_present_flag && !slc->field_pic_flag) + slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf); + } + else if (sps->pic_order_cnt_type == 1) { + slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf); + if (pps->pic_order_present_flag && !slc->field_pic_flag) + slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); + } + + if (pps->redundant_pic_cnt_present_flag == 1) { + slc->redundant_pic_cnt = read_exp_golomb(buf); + } + + if (slc->slice_type == SLICE_B) + slc->direct_spatial_mv_pred_flag = read_bits(buf, 1); + + if (slc->slice_type == SLICE_P || slc->slice_type == SLICE_SP + || slc->slice_type == SLICE_B) { + slc->num_ref_idx_active_override_flag = read_bits(buf, 1); + + if (slc->num_ref_idx_active_override_flag == 1) { + slc->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); + + if (slc->slice_type == SLICE_B) { + slc->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); + } + } + } + + /* --- ref_pic_list_reordering --- */ + parse_ref_pic_list_reordering(buf, nal); + + /* --- pred_weight_table --- */ + if ((pps->weighted_pred_flag && (slc->slice_type == SLICE_P + || slc->slice_type == SLICE_SP)) || (pps->weighted_bipred_idc == 1 + && slc->slice_type == SLICE_B)) { + parse_pred_weight_table(buf, nal); + } + + /* --- dec_ref_pic_marking --- */ + if (nal->nal_ref_idc != 0) + parse_dec_ref_pic_marking(buf, parser); + + return 0; +} + +void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if (!sps || !pps) + return; + + if (slc->slice_type != SLICE_I && slc->slice_type != SLICE_SI) { + slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 = read_bits( + buf, 1); + + if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 == 1) { + do { + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc + = read_exp_golomb(buf); + + if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 + || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { + slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 + = read_exp_golomb(buf); + } + else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { + slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); + } + } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); + } + } + + if (slc->slice_type == SLICE_B) { + slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 = read_bits( + buf, 1); + + if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 == 1) { + do { + slc->ref_pic_list_reordering.reordering_of_pic_nums_idc + = read_exp_golomb(buf); + + if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 + || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { + slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 + = read_exp_golomb(buf); + } + else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { + slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); + } + } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); + } + } +} + +void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) +{ + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if (!sps || !pps) + return; + + nal->slc->pred_weight_table.luma_log2_weight_denom = read_exp_golomb(buf); + + if (sps->chroma_format_idc != 0) + nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); + + int i; + for (i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) { + uint8_t luma_weight_l0_flag = read_bits(buf, 1); + + if (luma_weight_l0_flag == 1) { + nal->slc->pred_weight_table.luma_weight_l0[i] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.luma_offset_l0[i] = read_exp_golomb_s(buf); + } + + if (sps->chroma_format_idc != 0) { + uint8_t chroma_weight_l0_flag = read_bits(buf, 1); + + if (chroma_weight_l0_flag == 1) { + int j; + for (j = 0; j < 2; j++) { + nal->slc->pred_weight_table.chroma_weight_l0[i][j] + = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.chroma_offset_l0[i][j] + = read_exp_golomb_s(buf); + } + } + } + } + + if (slc->slice_type == SLICE_B) { + for (i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) { + uint8_t luma_weight_l1_flag = read_bits(buf, 1); + + if (luma_weight_l1_flag == 1) { + nal->slc->pred_weight_table.luma_weight_l1[i] = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.luma_offset_l1[i] = read_exp_golomb_s(buf); + } + + if (sps->chroma_format_idc != 0) { + uint8_t chroma_weight_l1_flag = read_bits(buf, 1); + + if (chroma_weight_l1_flag == 1) { + int j; + for (j = 0; j < 2; j++) { + nal->slc->pred_weight_table.chroma_weight_l1[i][j] + = read_exp_golomb_s(buf); + nal->slc->pred_weight_table.chroma_offset_l1[i][j] + = read_exp_golomb_s(buf); + } + } + } + } + } +} + +void decode_ref_pic_marking(uint32_t memory_management_control_operation, + struct nal_parser *parser) +{ + struct nal_unit *nal = parser->current_nal; + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + struct dpb *dpb = &parser->dpb; + if (!sps || !pps || !slc) + return; + + if (memory_management_control_operation == 1) { + // short-term -> unused for reference + uint32_t pic_num_x = nal->curr_pic_num + - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); + struct decoded_picture* pic = dpb_get_picture(dpb, pic_num_x); + if (pic != NULL) { + if (pic->nal->slc->field_pic_flag == 0) + dpb_remove_picture(dpb, pic_num_x); + else { + dpb_remove_picture(dpb, pic_num_x); + printf("FIXME: We might need do delete more from the DPB...\n"); + // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120 + } + } + } + else if (memory_management_control_operation == 2) { + // long-term -> unused for reference + struct decoded_picture* pic = dpb_get_picture_by_ltpn(dpb, + slc->dec_ref_pic_marking.long_term_pic_num); + if (pic != NULL) { + if (pic->nal->slc->field_pic_flag == 0) + dpb_remove_picture_by_ltpn(dpb, + slc->dec_ref_pic_marking.long_term_pic_num); + else { + dpb_remove_picture_by_ltpn(dpb, + slc->dec_ref_pic_marking.long_term_pic_num); + printf("FIXME: We might need do delete more from the DPB...\n"); + } + } + } + else if (memory_management_control_operation == 3) { + // short-term -> long-term, set long-term frame index + uint32_t pic_num_x = nal->curr_pic_num + - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); + struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, + slc->dec_ref_pic_marking.long_term_pic_num); + if (pic != NULL) + dpb_remove_picture_by_ltidx(dpb, + slc->dec_ref_pic_marking.long_term_frame_idx); + + if (pic->nal->slc->field_pic_flag == 0) { + pic = dpb_get_picture(dpb, pic_num_x); + pic->nal->long_term_frame_idx + = slc->dec_ref_pic_marking.long_term_frame_idx; + } + else + printf("FIXME: B Set frame %d to long-term ref\n", pic_num_x); + } + else if (memory_management_control_operation == 4) { + // set max-long-term frame index, + // mark all long-term pictures with long-term frame idx + // greater max-long-term farme idx as unused for ref + if (slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 == 0) + dpb_remove_ltidx_gt(dpb, 0); + else + dpb_remove_ltidx_gt(dpb, + slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 - 1); + } + else if (memory_management_control_operation == 5) { + // mark all ref pics as unused for reference, + // set max-long-term frame index = no long-term frame idxs + dpb_flush(dpb); + } + else if (memory_management_control_operation == 6) { + // mark current picture as used for long-term ref, + // assing long-term frame idx to it + struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, + slc->dec_ref_pic_marking.long_term_frame_idx); + if (pic != NULL) + dpb_remove_picture_by_ltidx(dpb, + slc->dec_ref_pic_marking.long_term_frame_idx); + + nal->long_term_frame_idx = slc->dec_ref_pic_marking.long_term_frame_idx; + + if (slc->field_pic_flag == 0) { + nal->used_for_long_term_ref = 1; + } + else + printf("FIXME: BY Set frame to long-term ref\n"); + } +} + +void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_parser *parser) +{ + struct nal_unit *nal = parser->current_nal; + struct seq_parameter_set_rbsp *sps = nal->sps; + struct pic_parameter_set_rbsp *pps = nal->pps; + struct slice_header *slc = nal->slc; + if (!sps || !pps) + return; + + if (nal->nal_unit_type == NAL_SLICE_IDR) { + slc->dec_ref_pic_marking.no_output_of_prior_pics_flag = read_bits(buf, 1); + slc->dec_ref_pic_marking.long_term_reference_flag = read_bits(buf, 1); + } + else { + slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = read_bits( + buf, 1); + + if (slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) { + do { + slc->dec_ref_pic_marking.memory_management_control_operation + = read_exp_golomb(buf); + + if (slc->dec_ref_pic_marking.memory_management_control_operation == 1 + || slc->dec_ref_pic_marking.memory_management_control_operation + == 3) + slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + = read_exp_golomb(buf); + + if (slc->dec_ref_pic_marking.memory_management_control_operation == 2) + slc->dec_ref_pic_marking.long_term_pic_num = read_exp_golomb(buf); + + if (slc->dec_ref_pic_marking.memory_management_control_operation == 3 + || slc->dec_ref_pic_marking.memory_management_control_operation + == 6) + slc->dec_ref_pic_marking.long_term_frame_idx = read_exp_golomb(buf); + + if (slc->dec_ref_pic_marking.memory_management_control_operation == 4) + slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 + = read_exp_golomb(buf); + + decode_ref_pic_marking( + slc->dec_ref_pic_marking.memory_management_control_operation, parser); + } while (slc->dec_ref_pic_marking.memory_management_control_operation + != 0); + } + } +} + +/* ----------------- NAL parser ----------------- */ + +struct nal_parser* init_parser() +{ + struct nal_parser *parser = malloc(sizeof(struct nal_parser)); + memset(parser->buf, 0x00, MAX_FRAME_SIZE); + parser->buf_len = 0; + parser->found_sps = 0; + parser->found_pps = 0; + parser->nal0 = init_nal_unit(); + parser->nal1 = init_nal_unit(); + parser->current_nal = parser->nal0; + parser->last_nal = parser->nal1; + + parser->last_nal_res = 0; + parser->is_idr = 0; + parser->slice = 0; + parser->slice_cnt = 0; + parser->field = -1; + parser->have_top = 0; + + /* no idea why we do that. inspired by libavcodec, + * as we couldn't figure in the specs.... + */ + parser->prev_pic_order_cnt_msb = 1 << 16; + + return parser; +} + +void free_parser(struct nal_parser *parser) +{ + free(parser->nal0); + free(parser->nal1); + free(parser); +} + +int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, + uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) +{ + int next_nal; + int parsed_len = 0; + int search_offset = 0; + + while ((next_nal + = seek_for_nal(inbuf + search_offset, inbuf_len - parsed_len)) >= 0) { + // save buffer up to the nal-start + if (parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) { + printf("buf underrun!!\n"); + *ret_len = 0; + *ret_buf = NULL; + return parsed_len; + } + + if (parser->last_nal_res != 2) { + /* this is not nal_unit != SLICE, keep it in the buffer */ + xine_fast_memcpy(parser->buf + parser->buf_len, inbuf, next_nal + + search_offset); + parser->buf_len += next_nal + search_offset; + } + + inbuf += next_nal + search_offset; + parsed_len += next_nal + search_offset; + + parser->last_nal_res = parse_nal(inbuf + 3, inbuf_len - parsed_len, parser); + if (parser->last_nal_res == 1 && parser->buf_len > 0) { + *ret_buf = malloc(parser->buf_len); + xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); + *ret_len = parser->buf_len; + *ret_slice_cnt = parser->slice_cnt; + + calculate_pic_order(parser); + + //memset(parser->buf, 0x00, parser->buf_len); + parser->buf_len = 0; + parser->last_nal_res = 1; + parser->slice_cnt = 0; + + /*if(parser->current_nal->nal_ref_idc) { + if(parser->current_nal->slc != NULL) + parser->prev_pic_order_cnt_lsb = parser->current_nal->slc->pic_order_cnt_lsb; + parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; + }*/ + return parsed_len; + } + + search_offset = 3; + } + + // no further NAL found, copy the rest of the stream + // into the buffer + xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len - parsed_len); + parser->buf_len += inbuf_len - parsed_len; + + parsed_len += (inbuf_len - parsed_len); + *ret_len = 0; + *ret_buf = NULL; + + return parsed_len; +} + +int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) +{ + struct buf_reader bufr; + + bufr.buf = buf; + bufr.cur_pos = buf; + bufr.cur_offset = 8; + bufr.len = buf_len; + + struct nal_unit *nal = parser->current_nal; + struct nal_unit *last_nal = parser->last_nal; + + int res = parse_nal_header(&bufr, parser); + if (res == NAL_SLICE_IDR) + parser->is_idr = 1; + + if (res >= NAL_SLICE && res <= NAL_SLICE_IDR) { + // now detect if it's a new frame! + int ret = 0; + if (nal->slc->field_pic_flag == 1) + parser->field = nal->slc->bottom_field_flag; + else { + parser->have_top = 1; + parser->field = -1; + } + + if (nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0) + parser->have_top = 1; + + parser->slice = 1; + + if (nal->slc == NULL || last_nal->slc == NULL) { + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->slc->frame_num + != last_nal->slc->frame_num)) { + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->slc->pic_parameter_set_id + != last_nal->slc->pic_parameter_set_id)) { + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->slc->field_pic_flag + != last_nal->slc->field_pic_flag)) { + ret = 1; + } + if (nal->slc && last_nal->slc && nal->slc->bottom_field_flag + != last_nal->slc->bottom_field_flag) { + ret = 1; + } + if (nal->nal_ref_idc != last_nal->nal_ref_idc && (nal->nal_ref_idc == 0 + || last_nal->nal_ref_idc == 0)) { + ret = 1; + } + if (nal->sps && nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type + == 0 && last_nal->sps->pic_order_cnt_type == 0 + && (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb + || nal->slc->delta_pic_order_cnt_bottom + != last_nal->slc->delta_pic_order_cnt_bottom))) { + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 1 + && last_nal->sps->pic_order_cnt_type == 1 + && (nal->slc->delta_pic_order_cnt[0] + != last_nal->slc->delta_pic_order_cnt[0] + || nal->slc->delta_pic_order_cnt[1] + != last_nal->slc->delta_pic_order_cnt[1]))) { + ret = 1; + } + if (nal->nal_unit_type != last_nal->nal_unit_type && (nal->nal_unit_type + == 5 || last_nal->nal_unit_type == 5)) { + ret = 1; + } + if (nal->slc && last_nal->slc && (nal->nal_unit_type == 5 + && last_nal->nal_unit_type == 5 && nal->slc->idr_pic_id + != last_nal->slc->idr_pic_id)) { + ret = 1; + } + + if (parser->current_nal == parser->nal0) { + parser->current_nal = parser->nal1; + parser->last_nal = parser->nal0; + } + else { + parser->current_nal = parser->nal0; + parser->last_nal = parser->nal1; + } + + if (parser->current_nal->sps == NULL) + parser->current_nal->sps = parser->last_nal->sps; + if (parser->current_nal->pps == NULL) + parser->current_nal->pps = parser->last_nal->pps; + + /* increase the slice_cnt until a new frame is detected */ + if (!ret) + parser->slice_cnt++; + + return ret; + } + else if (res == NAL_PPS || res == NAL_SPS) { + return 2; + } + else if (res >= NAL_SEI) { + return 2; + } + + return 1; +} + +int seek_for_nal(uint8_t *buf, int buf_len) +{ + int i; + for (i = 0; i < buf_len - 2; i++) { + if (buf[i] == 0x00 && buf[i + 1] == 0x00 && buf[i + 2] == 0x01) { + //printf("found nal at: %d\n", i); + return i; + } + } + + return -1; +} diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h new file mode 100644 index 000000000..e067f9741 --- /dev/null +++ b/src/libvdpau/h264_parser.h @@ -0,0 +1,48 @@ +#ifndef NAL_PARSER_H_ +#define NAL_PARSER_H_ + +#include + +#include "xine_internal.h" +#include "nal.h" +#include "dpb.h" + +#define MAX_FRAME_SIZE 1024*1024 + +struct nal_parser { + uint8_t buf[MAX_FRAME_SIZE]; + int buf_len; + int found_sps; + int found_pps; + int last_nal_res; + + int is_idr; + int field; /* 0=top, 1=bottom, -1=both */ + int slice; + int slice_cnt; + int have_top; + int have_frame; + + struct nal_unit *nal0; + struct nal_unit *nal1; + struct nal_unit *current_nal; + struct nal_unit *last_nal; + + uint32_t pic_order_cnt_lsb; + uint32_t pic_order_cnt_msb; + uint32_t prev_pic_order_cnt_lsb; + uint32_t prev_pic_order_cnt_msb; + + struct dpb dpb; +}; + +int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); + +int seek_for_nal(uint8_t *buf, int buf_len); + +struct nal_parser* init_parser(); +void free_parser(struct nal_parser *parser); +int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, + uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt); + +#endif diff --git a/src/libvdpau/nal.c b/src/libvdpau/nal.c new file mode 100644 index 000000000..a9717d76e --- /dev/null +++ b/src/libvdpau/nal.c @@ -0,0 +1,46 @@ +/* + * nal.c + * + * Created on: 07.12.2008 + * Author: julian + */ + +#include +#include +#include + +#include "nal.h" +#include "xine_internal.h" + +struct nal_unit* init_nal_unit() +{ + struct nal_unit *nal = malloc(sizeof(struct nal_unit)); + memset(nal, 0x00, sizeof(struct nal_unit)); + + nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + nal->slc = malloc(sizeof(struct slice_header)); + + return nal; +} + +void free_nal_unit(struct nal_unit *nal) +{ + free(nal->sps); + free(nal->pps); + free(nal->slc); + free(nal); +} + +void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src) +{ + /* size without pps, sps and slc units: */ + int size = sizeof(struct nal_unit) - sizeof(struct seq_parameter_set_rbsp*) + - sizeof(struct pic_parameter_set_rbsp*) - sizeof(struct slice_header*); + + xine_fast_memcpy(dest, src, size); + + xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp)); + xine_fast_memcpy(dest->pps, src->pps, sizeof(struct pic_parameter_set_rbsp)); + xine_fast_memcpy(dest->slc, src->slc, sizeof(struct slice_header)); +} diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h new file mode 100644 index 000000000..c07c1d9a3 --- /dev/null +++ b/src/libvdpau/nal.h @@ -0,0 +1,350 @@ +/* + * nal.h + * + * Created on: 07.12.2008 + * Author: julian + */ + +#ifndef NAL_H_ +#define NAL_H_ +#include +#include + +enum nal_unit_types +{ + NAL_UNSPECIFIED = 0, + NAL_SLICE, + NAL_PART_A, + NAL_PART_B, + NAL_PART_C, + NAL_SLICE_IDR, + NAL_SEI, + NAL_SPS, + NAL_PPS, + NAL_AU_DELIMITER, + NAL_END_OF_SEQUENCE, + NAL_END_OF_STREAM, + NAL_FILLER_DATA, + NAL_SPS_EXT +}; + +/* slice types repeat from 5-9, we + * need a helper function for comparison + */ +enum slice_types +{ + SLICE_P = 0, SLICE_B, SLICE_I, SLICE_SP, SLICE_SI +}; + +enum aspect_ratio +{ + ASPECT_UNSPECIFIED = 0, + ASPECT_1_1, + ASPECT_12_11, + ASPECT_10_11, + ASPECT_16_11, + ASPECT_40_33, + ASPECT_24_11, + ASPECT_20_11, + ASPECT_32_11, + ASPECT_80_33, + ASPECT_18_11, + ASPECT_15_11, + ASPECT_64_33, + ASPECT_160_99, + ASPECT_4_3, + ASPECT_3_2, + ASPECT_2_1, + ASPECT_RESERVED +}; + +static inline uint32_t slice_type(uint32_t slice_type) +{ + return (slice_type < 10 ? slice_type % 5 : slice_type); +} + +struct nal_unit +{ + uint8_t nal_ref_idc; // 0x03 + uint8_t nal_unit_type; // 0x1f + + uint32_t curr_pic_num; + uint8_t used_for_long_term_ref; + uint32_t long_term_pic_num; + uint32_t long_term_frame_idx; + + uint32_t top_field_order_cnt; + uint32_t bottom_field_order_cnt; + + struct seq_parameter_set_rbsp *sps; + struct pic_parameter_set_rbsp *pps; + struct slice_header *slc; +}; + +struct hrd_parameters +{ + uint32_t cpb_cnt_minus1; + uint8_t bit_rate_scale; + uint8_t cpb_size_scale; + + uint32_t bit_rate_value_minus1[32]; + uint32_t cpb_size_value_minus1[32]; + uint8_t cbr_flag[32]; + + uint8_t initial_cpb_removal_delay_length_minus1; + uint8_t cpb_removal_delay_length_minus1; + uint8_t dpb_output_delay_length_minus1; + uint8_t time_offset_length; +}; + +struct seq_parameter_set_rbsp +{ + uint8_t profile_idc; // 0xff + uint8_t constraint_setN_flag; // 0x0f + uint8_t level_idc; // 0xff + uint32_t seq_parameter_set_id; + uint32_t chroma_format_idc; + uint8_t residual_colour_transform_flag; // 0x01 + uint32_t bit_depth_luma_minus8; + uint32_t bit_depth_chroma_minus8; + uint8_t qpprime_y_zero_transform_bypass_flag; + uint8_t seq_scaling_matrix_present_flag; + + /* if(seq_scaling_matrix_present_flag) */ + uint8_t seq_scaling_list_present_flag[8]; + + uint8_t scaling_lists_4x4[6][16]; + uint8_t scaling_lists_8x8[2][64]; + /* endif */ + + uint32_t log2_max_frame_num_minus4; + uint32_t pic_order_cnt_type; + // if pic_order_cnt_type==0 + uint32_t log2_max_pic_order_cnt_lsb_minus4; + // else + uint8_t delta_pic_order_always_zero_flag; + int32_t offset_for_non_ref_pic; + int32_t offset_for_top_to_bottom_field; + uint8_t num_ref_frames_in_pic_order_cnt_cycle; + int32_t offset_for_ref_frame[256]; + // TODO: some more ignored here + uint32_t num_ref_frames; + uint8_t gaps_in_frame_num_value_allowed_flag; + /*uint32_t pic_width_in_mbs_minus1; + uint32_t pic_height_in_map_units_minus1;*/ + uint32_t pic_width; + uint32_t pic_height; + uint8_t frame_mbs_only_flag; + uint8_t mb_adaptive_frame_field_flag; + uint8_t direct_8x8_inference_flag; + uint8_t frame_cropping_flag; + uint32_t frame_crop_left_offset; + uint32_t frame_crop_right_offset; + uint32_t frame_crop_top_offset; + uint32_t frame_crop_bottom_offset; + uint8_t vui_parameters_present_flag; + + /* vui_parameters */ + union + { + uint8_t aspect_ration_info_present_flag; + + /* aspect_ration_info_present_flag == 1 */ + uint8_t aspect_ratio_idc; + uint16_t sar_width; + uint16_t sar_height; + + uint8_t overscan_info_present_flag; + /* overscan_info_present_flag == 1 */ + uint8_t overscan_appropriate_flag; + + uint8_t video_signal_type_present_flag; + /* video_signal_type_present_flag == 1 */ + uint8_t video_format; + uint8_t video_full_range_flag; + uint8_t colour_description_present; + /* colour_description_present == 1 */ + uint8_t colour_primaries; + uint8_t transfer_characteristics; + uint8_t matrix_coefficients; + + uint8_t chroma_loc_info_present_flag; + /* chroma_loc_info_present_flag == 1 */ + uint8_t chroma_sample_loc_type_top_field; + uint8_t chroma_sample_loc_type_bottom_field; + + uint8_t timing_info_present_flag; + /* timing_info_present_flag == 1 */ + uint32_t num_units_in_tick; + uint32_t time_scale; + uint8_t fixed_frame_rate_flag; + + uint8_t nal_hrd_parameters_present_flag; + struct hrd_parameters nal_hrd_parameters; + + uint8_t vc1_hrd_parameters_present_flag; + struct hrd_parameters vc1_hrd_parameters; + + uint8_t low_delay_hrd_flag; + + uint8_t pic_struct_present_flag; + uint8_t bitstream_restriction_flag; + + /* bitstream_restriction_flag == 1 */ + uint8_t motion_vectors_over_pic_boundaries; + uint32_t max_bytes_per_pic_denom; + uint32_t max_bits_per_mb_denom; + uint32_t log2_max_mv_length_horizontal; + uint32_t log2_max_mv_length_vertical; + uint32_t num_reorder_frames; + uint32_t max_dec_frame_buffering; + } vui_parameters; + +}; + +struct pic_parameter_set_rbsp +{ + uint32_t pic_parameter_set_id; + uint32_t seq_parameter_set_id; + uint8_t entropy_coding_mode_flag; + uint8_t pic_order_present_flag; + + uint32_t num_slice_groups_minus1; + + /* num_slice_groups_minus1 > 0 */ + uint32_t slice_group_map_type; + + /* slice_group_map_type == 1 */ + uint32_t run_length_minus1[64]; + + /* slice_group_map_type == 2 */ + uint32_t top_left[64]; + uint32_t bottom_right[64]; + + /* slice_group_map_type == 3,4,5 */ + uint8_t slice_group_change_direction_flag; + uint32_t slice_group_change_rate_minus1; + + /* slice_group_map_type == 6 */ + uint32_t pic_size_in_map_units_minus1; + uint8_t slice_group_id[64]; + + uint32_t num_ref_idx_l0_active_minus1; + uint32_t num_ref_idx_l1_active_minus1; + uint8_t weighted_pred_flag; + uint8_t weighted_bipred_idc; + int32_t pic_init_qp_minus26; + int32_t pic_init_qs_minus26; + int32_t chroma_qp_index_offset; + uint8_t deblocking_filter_control_present_flag; + uint8_t constrained_intra_pred_flag; + uint8_t redundant_pic_cnt_present_flag; + + /* if(more_rbsp_data) */ + uint8_t transform_8x8_mode_flag; + uint8_t pic_scaling_matrix_present_flag; + + /* if(pic_scaling_matrix_present_flag) */ + uint8_t pic_scaling_list_present_flag[8]; + + uint8_t scaling_lists_4x4[6][16]; + uint8_t scaling_lists_8x8[2][64]; + + int32_t second_chroma_qp_index_offset; +}; + +struct slice_header +{ + uint32_t first_mb_in_slice; + uint32_t slice_type; + uint32_t pic_parameter_set_id; + uint32_t frame_num; + uint8_t field_pic_flag; + uint8_t bottom_field_flag; + uint32_t idr_pic_id; + + /* sps->pic_order_cnt_type == 0 */ + uint32_t pic_order_cnt_lsb; + int32_t delta_pic_order_cnt_bottom; + /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */ + int32_t delta_pic_order_cnt[2]; + + /* pps->redundant_pic_cnt_present_flag == 1 */ + int32_t redundant_pic_cnt; + + /* slice_type == B */ + uint8_t direct_spatial_mv_pred_flag; + + /* slice_type == P, SP, B */ + uint8_t num_ref_idx_active_override_flag; + /* num_ref_idx_active_override_flag == 1 */ + uint32_t num_ref_idx_l0_active_minus1; + /* slice type == B */ + uint32_t num_ref_idx_l1_active_minus1; + + /* ref_pic_list_reordering */ + union + { + /* slice_type != I && slice_type != SI */ + uint8_t ref_pic_list_reordering_flag_l0; + + /* slice_type == B */ + uint8_t ref_pic_list_reordering_flag_l1; + + /* ref_pic_list_reordering_flag_l0 == 1 */ + uint32_t reordering_of_pic_nums_idc; + + /* reordering_of_pic_nums_idc == 0, 1 */ + uint32_t abs_diff_pic_num_minus1; + + /* reordering_of_pic_nums_idc == 2) */ + uint32_t long_term_pic_num; + } ref_pic_list_reordering; + + /* pred_weight_table */ + union + { + uint32_t luma_log2_weight_denom; + + /* chroma_format_idc != 0 */ + uint32_t chroma_log2_weight_denom; + + int32_t luma_weight_l0[32]; + int32_t luma_offset_l0[32]; + + int32_t chroma_weight_l0[32][2]; + int32_t chroma_offset_l0[32][2]; + + int32_t luma_weight_l1[32]; + int32_t luma_offset_l1[32]; + + int32_t chroma_weight_l1[32][2]; + int32_t chroma_offset_l1[32][2]; + } pred_weight_table; + + /* def_rec_pic_marking */ + union + { + + /* nal_unit_type == NAL_SLICE_IDR */ + uint8_t no_output_of_prior_pics_flag; + uint8_t long_term_reference_flag; + + /* else */ + uint8_t adaptive_ref_pic_marking_mode_flag; + uint32_t memory_management_control_operation; + + uint32_t difference_of_pic_nums_minus1; + uint32_t long_term_pic_num; + uint32_t long_term_frame_idx; + uint32_t max_long_term_frame_idx_plus1; + } dec_ref_pic_marking; +}; + + +struct nal_unit* init_nal_unit(); +void free_nal_unit(struct nal_unit *nal); +void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src); + + +#endif /* NAL_H_ */ diff --git a/src/libvdpau/nal_parser.c b/src/libvdpau/nal_parser.c deleted file mode 100644 index bf5ad3287..000000000 --- a/src/libvdpau/nal_parser.c +++ /dev/null @@ -1,1088 +0,0 @@ -#include -#include -#include - -#include "nal_parser.h" - -/* default scaling_lists according to Table 7-2 */ -uint8_t default_4x4_intra[16] = { 6, 13, 13, 20, 20, 20, 28, 28, 28, 28, 32, - 32, 32, 37, 37, 42 }; - -uint8_t default_4x4_inter[16] = { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, - 27, 27, 30, 30, 34 }; - -uint8_t default_8x8_intra[64] = { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, - 18, 18, 18, 18, 32, 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, - 27, 27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, 31, - 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; - -uint8_t default_8x8_inter[64] = { 9, 13, 13, 15, 13, 15, 17, 17, 17, 17, 19, - 19, 19, 19, 19, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 24, 24, - 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27, - 28, 28, 28, 28, 28, 30, 30, 30, 30, 32, 32, 32, 33, 33, 35 }; - -struct buf_reader -{ - uint8_t *buf; - uint8_t *cur_pos; - int len; - int cur_offset; -}; - -static inline uint32_t read_bits(struct buf_reader *buf, int len); -uint32_t read_exp_golomb(struct buf_reader *buf); -int32_t read_exp_golomb_s(struct buf_reader *buf); - -void calculate_pic_order(struct nal_parser *parser); -void skip_scaling_list(struct buf_reader *buf, int size); -void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, - int length, int index); -int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser); -uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); -void parse_vui_parameters(struct buf_reader *buf, - struct seq_parameter_set_rbsp *sps); -void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd); -uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, - struct seq_parameter_set_rbsp *sps); -uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser); -void - parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); -void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); -void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_unit *nal); - -static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) -{ - uint8_t *end = &buf[buf_len]; - uint8_t *pos = malloc(buf_len); - - *ret = pos; - while (buf < end) { - if (buf < end - 3 && buf[0] == 0x00 && buf[1] == 0x00 && buf[2] == 0x03) { - - *pos++ = 0x00; - *pos++ = 0x00; - - buf += 3; - continue; - } - *pos++ = *buf++; - } - - *len_ret = pos - *ret; -} - -/*uint32_t read_bits(struct buf_reader *buf, int len) - { - uint32_t bits = 0x00; - int i, j; - for(i=0, j=0; icur_offset >= 8) { - buf->cur_pos++; - buf->cur_offset -= 8; - } - uint8_t bit = (*buf->cur_pos >> (7 - buf->cur_offset)) & 0x01; - bits |= ((uint32_t)bit) << i; - buf->cur_offset++; - } - printf("ret: 0x%08x\n", bits); - return bits; - }*/ - -static inline uint32_t read_bits(struct buf_reader *buf, int len) -{ - static uint32_t i_mask[33] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, - 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, - 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, - 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, - 0x3fffffff, 0x7fffffff, 0xffffffff }; - - int i_shr; - uint32_t bits = 0; - - while (len > 0 && (buf->cur_pos - buf->buf) < buf->len) { - if ((i_shr = buf->cur_offset - len) >= 0) { - bits |= (*buf->cur_pos >> i_shr) & i_mask[len]; - buf->cur_offset -= len; - if (buf->cur_offset == 0) { - buf->cur_pos++; - buf->cur_offset = 8; - } - return bits; - } - else { - bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; - len -= buf->cur_offset; - buf->cur_pos++; - buf->cur_offset = 8; - } - } - return bits; -} - -/* determines if following bits are rtsb_trailing_bits */ -static inline uint8_t rbsp_trailing_bits(struct buf_reader *buf) -{ - // store the offset and pos in buffer - // to revert this afterwards. - int last_offset; - uint8_t *last_pos; - - uint8_t rbsp_trailing_bits = 1; - - last_offset = buf->cur_offset; - last_pos = buf->cur_pos; - - if (read_bits(buf, 1) == 1) { - while (buf->cur_offset != 8) - if (read_bits(buf, 1) == 1) - rbsp_trailing_bits = 0; - } - - // revert buffer - buf->cur_offset = last_offset; - buf->cur_pos = last_pos; - - return rbsp_trailing_bits; -} - -uint32_t read_exp_golomb(struct buf_reader *buf) -{ - int leading_zero_bits = 0; - - while (read_bits(buf, 1) == 0 && leading_zero_bits < 32) - leading_zero_bits++; - - uint32_t code = (1 << leading_zero_bits) - 1 + read_bits(buf, - leading_zero_bits); - return code; -} - -int32_t read_exp_golomb_s(struct buf_reader *buf) -{ - uint32_t ue = read_exp_golomb(buf); - int32_t code = ue & 0x01 ? (ue + 1) / 2 : -(ue / 2); - return code; -} - -int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) -{ - if (buf->len < 1) - return -1; - int ret = -1; - - struct nal_unit *nal = parser->current_nal; - - nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; - nal->nal_unit_type = buf->buf[0] & 0x1f; - - buf->cur_pos = buf->buf + 1; - //printf("NAL: %d\n", nal->nal_unit_type); - - struct buf_reader ibuf; - ibuf.cur_offset = 8; - - switch (nal->nal_unit_type) { - case NAL_SPS: - decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len - 1); - ibuf.cur_pos = ibuf.buf; - if (!nal->sps) - nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); - - memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); - - parse_sps(&ibuf, nal->sps); - free(ibuf.buf); - ret = NAL_SPS; - break; - case NAL_PPS: - if (!nal->pps) - nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); - - memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); - - parse_pps(buf, nal->pps, nal->sps); - ret = NAL_PPS; - break; - case NAL_SLICE: - case NAL_PART_A: - case NAL_PART_B: - case NAL_PART_C: - case NAL_SLICE_IDR: - if (nal->sps && nal->pps) { - if (!nal->slc) - nal->slc = malloc(sizeof(struct slice_header)); - else - memset(nal->slc, 0x00, sizeof(struct slice_header)); - - parse_slice_header(buf, parser); - ret = nal->nal_unit_type; - } - break; - default: - ret = nal->nal_unit_type; - break; - } - - return ret; -} - -void calculate_pic_order(struct nal_parser *parser) -{ - struct nal_unit *nal = parser->current_nal; - struct dpb *dpb = parser->dpb; - - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; - struct slice_header *slc = nal->slc; - if (!sps || !pps || !slc) - return; - - /*uint32_t max_frame_num = pow(2, sps->log2_max_frame_num_minus4+4); - if(dpb->max_frame_num == 0) - dpb->max_frame_num = max_frame_num; - - if(dpb->max_frame_num != max_frame_num && dpb->max_frame_num != 0) - printf("ERROR, FIXME, max_frame_num changed"); - - / * calculate frame_num based stuff * / - if(nal->nal_unit_type == NAL_SLICE_IDR) { - dpb->prev_ref_frame_number = 0; - } else { - // FIXME: understand p92 in h264 spec - } - - if(slc->frame_num != dpb->prev_ref_frame_number) { - memset(dpb->non_existing_pictures, 0, 32); - int i = 0; - dpb->unused_short_term_frame_num = (dpb->prev_ref_frame_number + 1) % dpb->max_frame_num; - dpb->non_existing_pictures[i] = dpb->unused_short_term_frame_num; - i++; - - while(dpb->unused_short_term_frame_num != slc->frame_num) { - dpb->unused_short_term_frame_num = (dpb->unused_short_term_frame_num + 1) % dpb->max_frame_num; - dpb->non_existing_pictures[i] = dpb->unused_short_term_frame_num; - i++; - } - }*/ - - if (sps->pic_order_cnt_type == 0) { - if (nal->nal_unit_type == NAL_SLICE_IDR) { - parser->prev_pic_order_cnt_lsb = 0; - parser->prev_pic_order_cnt_msb = 0; - } - else { - const int max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - - if (slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb - && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb - >= max_poc_lsb / 2) - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - + max_poc_lsb; - else if (slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb - && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb - < -max_poc_lsb / 2) - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - - max_poc_lsb; - else - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; - - if (!slc->bottom_field_flag) { - parser->top_field_order_cnt = parser->pic_order_cnt_msb - + slc->pic_order_cnt_lsb; - parser->bottom_field_order_cnt = 0; - } - else - parser->bottom_field_order_cnt = parser->pic_order_cnt_msb - + slc->pic_order_cnt_lsb; - - if (parser->field == -1) - parser->bottom_field_order_cnt += slc->delta_pic_order_cnt_bottom; - } - } - -} - -void skip_scaling_list(struct buf_reader *buf, int size) -{ - int i; - for (i = 0; i < size; i++) { - read_exp_golomb_s(buf); - } -} - -void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, - int length, int index) -{ - int last_scale = 8; - int next_scale = 8; - int32_t delta_scale; - uint8_t use_default_scaling_matrix_flag = 0; - int i; - - for (i = 0; i < length; i++) { - if (next_scale != 0) { - delta_scale = read_exp_golomb_s(buf); - next_scale = (last_scale + delta_scale + 256) % 256; - if (i == 0 && next_scale == 0) { - use_default_scaling_matrix_flag = 1; - break; - } - } - scaling_list[i] = (next_scale == 0) ? last_scale : next_scale; - last_scale = scaling_list[i]; - } - - if (use_default_scaling_matrix_flag) { - switch (index) { - case 0: - case 1: - case 2: - memcpy(scaling_list, default_4x4_intra, length); - break; - case 3: - case 4: - case 5: - memcpy(scaling_list, default_4x4_inter, length); - break; - case 6: - memcpy(scaling_list, default_8x8_intra, length); - break; - case 7: - memcpy(scaling_list, default_8x8_inter, length); - break; - } - } -} - -uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) -{ - sps->profile_idc = buf->buf[0]; - sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; - sps->level_idc = buf->buf[2]; - - buf->cur_pos = buf->buf + 3; - sps->seq_parameter_set_id = read_exp_golomb(buf); - if (sps->profile_idc == 100 || sps->profile_idc == 110 || - sps->profile_idc == 122 || sps->profile_idc == 144) { - sps->chroma_format_idc = read_exp_golomb(buf); - if (sps->chroma_format_idc == 3) { - sps->residual_colour_transform_flag = read_bits(buf, 1); - } - - sps->bit_depth_luma_minus8 = read_exp_golomb(buf); - sps->bit_depth_chroma_minus8 = read_exp_golomb(buf); - sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); - sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); - if (sps->seq_scaling_matrix_present_flag) { - printf("SCALING LIST PRESENT\n"); - int i; - for (i = 0; i < 8; i++) { - sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); - - if (sps->seq_scaling_list_present_flag[i]) { - if (i < 6) - parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); - else - parse_scaling_list(buf, sps->scaling_lists_8x8[i - 6], 64, i); - } - } - } - } - - if (!sps->seq_scaling_matrix_present_flag) { - memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); - memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_4x4)); - } - - sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); - - sps->pic_order_cnt_type = read_exp_golomb(buf); - if (!sps->pic_order_cnt_type) - sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf); - else { - sps->delta_pic_order_always_zero_flag = read_bits(buf, 1); - sps->offset_for_non_ref_pic = read_exp_golomb_s(buf); - sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf); - sps->num_ref_frames_in_pic_order_cnt_cycle = read_exp_golomb(buf); - int i; - for (i = 0; i < sps->num_ref_frames_in_pic_order_cnt_cycle; i++) { - sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf); - } - } - sps->num_ref_frames = read_exp_golomb(buf); - sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1); - - /*sps->pic_width_in_mbs_minus1 = read_exp_golomb(buf); - sps->pic_height_in_map_units_minus1 = read_exp_golomb(buf);*/ - sps->pic_width = 16 * (read_exp_golomb(buf) + 1); - sps->pic_height = 16 * (read_exp_golomb(buf) + 1); - - sps->frame_mbs_only_flag = read_bits(buf, 1); - - /* compute the height correctly even for interlaced material */ - sps->pic_height = (2 - sps->frame_mbs_only_flag) * sps->pic_height; - if (sps->pic_height == 1088) - sps->pic_height = 1080; - - if (!sps->frame_mbs_only_flag) - sps->mb_adaptive_frame_field_flag = read_bits(buf, 1); - - sps->direct_8x8_inference_flag = read_bits(buf, 1); - sps->frame_cropping_flag = read_bits(buf, 1); - if (sps->frame_cropping_flag) { - sps->frame_crop_left_offset = read_exp_golomb(buf); - sps->frame_crop_right_offset = read_exp_golomb(buf); - sps->frame_crop_top_offset = read_exp_golomb(buf); - sps->frame_crop_bottom_offset = read_exp_golomb(buf); - } - sps->vui_parameters_present_flag = read_bits(buf, 1); - if (sps->vui_parameters_present_flag) { - parse_vui_parameters(buf, sps); - } - - return 0; -} - -void parse_vui_parameters(struct buf_reader *buf, - struct seq_parameter_set_rbsp *sps) -{ - sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1); - if (sps->vui_parameters.aspect_ration_info_present_flag == 1) { - sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8); - if (sps->vui_parameters.aspect_ratio_idc == ASPECT_RESERVED) { - sps->vui_parameters.sar_width = read_bits(buf, 16); - sps->vui_parameters.sar_height = read_bits(buf, 16); - } - } - - sps->vui_parameters.overscan_info_present_flag = read_bits(buf, 1); - if (sps->vui_parameters.overscan_info_present_flag) { - sps->vui_parameters.overscan_appropriate_flag = read_bits(buf, 1); - } - - sps->vui_parameters.video_signal_type_present_flag = read_bits(buf, 1); - if (sps->vui_parameters.video_signal_type_present_flag) { - sps->vui_parameters.video_format = read_bits(buf, 3); - sps->vui_parameters.video_full_range_flag = read_bits(buf, 1); - sps->vui_parameters.colour_description_present = read_bits(buf, 1); - if (sps->vui_parameters.colour_description_present) { - sps->vui_parameters.colour_primaries = read_bits(buf, 8); - sps->vui_parameters.transfer_characteristics = read_bits(buf, 8); - sps->vui_parameters.matrix_coefficients = read_bits(buf, 8); - } - } - - sps->vui_parameters.chroma_loc_info_present_flag = read_bits(buf, 1); - if (sps->vui_parameters.chroma_loc_info_present_flag) { - sps->vui_parameters.chroma_sample_loc_type_top_field = read_exp_golomb(buf); - sps->vui_parameters.chroma_sample_loc_type_bottom_field = read_exp_golomb( - buf); - } - - sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1); - if (sps->vui_parameters.timing_info_present_flag) { - sps->vui_parameters.num_units_in_tick = read_bits(buf, 32); - sps->vui_parameters.time_scale = read_bits(buf, 32); - sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1); - } - - sps->vui_parameters.nal_hrd_parameters_present_flag = read_bits(buf, 1); - if (sps->vui_parameters.nal_hrd_parameters_present_flag) - parse_hrd_parameters(buf, &sps->vui_parameters.nal_hrd_parameters); - - sps->vui_parameters.vc1_hrd_parameters_present_flag = read_bits(buf, 1); - if (sps->vui_parameters.vc1_hrd_parameters_present_flag) - parse_hrd_parameters(buf, &sps->vui_parameters.vc1_hrd_parameters); - - if (sps->vui_parameters.nal_hrd_parameters_present_flag - || sps->vui_parameters.vc1_hrd_parameters_present_flag) - sps->vui_parameters.low_delay_hrd_flag = read_bits(buf, 1); - - sps->vui_parameters.pic_struct_present_flag = read_bits(buf, 1); - sps->vui_parameters.bitstream_restriction_flag = read_bits(buf, 1); - - if (sps->vui_parameters.bitstream_restriction_flag) { - sps->vui_parameters.motion_vectors_over_pic_boundaries = read_bits(buf, 1); - sps->vui_parameters.max_bytes_per_pic_denom = read_exp_golomb(buf); - sps->vui_parameters.max_bits_per_mb_denom = read_exp_golomb(buf); - sps->vui_parameters.log2_max_mv_length_horizontal = read_exp_golomb(buf); - sps->vui_parameters.log2_max_mv_length_vertical = read_exp_golomb(buf); - sps->vui_parameters.num_reorder_frames = read_exp_golomb(buf); - sps->vui_parameters.max_dec_frame_buffering = read_exp_golomb(buf); - } -} - -void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd) -{ - hrd->cpb_cnt_minus1 = read_exp_golomb(buf); - hrd->bit_rate_scale = read_bits(buf, 4); - hrd->cpb_size_scale = read_bits(buf, 4); - - int i; - for (i = 0; i <= hrd->cpb_cnt_minus1; i++) { - hrd->bit_rate_value_minus1[i] = read_exp_golomb(buf); - hrd->cpb_size_value_minus1[i] = read_exp_golomb(buf); - hrd->cbr_flag[i] = read_bits(buf, 1); - } - - hrd->initial_cpb_removal_delay_length_minus1 = read_bits(buf, 5); - hrd->cpb_removal_delay_length_minus1 = read_bits(buf, 5); - hrd->dpb_output_delay_length_minus1 = read_bits(buf, 5); - hrd->time_offset_length = read_bits(buf, 5); -} - -uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, - struct seq_parameter_set_rbsp *sps) -{ - pps->pic_parameter_set_id = read_exp_golomb(buf); - pps->seq_parameter_set_id = read_exp_golomb(buf); - pps->entropy_coding_mode_flag = read_bits(buf, 1); - pps->pic_order_present_flag = read_bits(buf, 1); - - pps->num_slice_groups_minus1 = read_exp_golomb(buf); - if (pps->num_slice_groups_minus1 > 0) { - pps->slice_group_map_type = read_exp_golomb(buf); - if (pps->slice_group_map_type == 0) { - int i_group; - for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { - if (i_group < 64) - pps->run_length_minus1[i_group] = read_exp_golomb(buf); - else { // FIXME: skips if more than 64 groups exist - fprintf(stderr, "Error: Only 64 slice_groups are supported\n"); - read_exp_golomb(buf); - } - } - } - else if (pps->slice_group_map_type == 3 || pps->slice_group_map_type == 4 - || pps->slice_group_map_type == 5) { - pps->slice_group_change_direction_flag = read_bits(buf, 1); - pps->slice_group_change_rate_minus1 = read_exp_golomb(buf); - } - else if (pps->slice_group_map_type == 6) { - pps->pic_size_in_map_units_minus1 = read_exp_golomb(buf); - int i_group; - for (i_group = 0; i_group <= pps->num_slice_groups_minus1; i_group++) { - pps->slice_group_id[i_group] = read_bits(buf, ceil(log( - pps->num_slice_groups_minus1 + 1))); - } - } - } - - pps->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); - pps->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); - pps->weighted_pred_flag = read_bits(buf, 1); - pps->weighted_bipred_idc = read_bits(buf, 2); - pps->pic_init_qp_minus26 = read_exp_golomb_s(buf); - pps->pic_init_qs_minus26 = read_exp_golomb_s(buf); - pps->chroma_qp_index_offset = read_exp_golomb_s(buf); - pps->deblocking_filter_control_present_flag = read_bits(buf, 1); - pps->constrained_intra_pred_flag = read_bits(buf, 1); - pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); - - if (!rbsp_trailing_bits(buf)) { - printf("PARSE 8x8\n"); - pps->transform_8x8_mode_flag = read_bits(buf, 1); - pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); - if (pps->pic_scaling_matrix_present_flag) { - int i; - for (i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { - pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); - - if (pps->pic_scaling_list_present_flag[i]) { - if (i < 6) - parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); - else - parse_scaling_list(buf, pps->scaling_lists_8x8[i - 6], 64, i); - } - } - } - - pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); - } - - if (!pps->pic_scaling_matrix_present_flag && sps != NULL) { - printf("MEMCPY SCALING LIST\n"); - memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, - sizeof(pps->scaling_lists_4x4)); - memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8, - sizeof(pps->scaling_lists_8x8)); - } - else if (sps == NULL) { - printf("sPS MISSING\n"); - } - - return 0; -} - -uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) -{ - struct nal_unit *nal = parser->current_nal; - - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; - struct slice_header *slc = nal->slc; - if (!sps || !pps) - return -1; - - slc->first_mb_in_slice = read_exp_golomb(buf); - /* we do some parsing on the slice type, because the list is doubled */ - slc->slice_type = slice_type(read_exp_golomb(buf)); - slc->pic_parameter_set_id = read_exp_golomb(buf); - slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); - if (!sps->frame_mbs_only_flag) { - slc->field_pic_flag = read_bits(buf, 1); - if (slc->field_pic_flag) - slc->bottom_field_flag = read_bits(buf, 1); - else - slc->bottom_field_flag = 0; - } - else { - slc->field_pic_flag = 0; - slc->bottom_field_flag = 0; - } - - if (nal->nal_unit_type == NAL_SLICE_IDR) - slc->idr_pic_id = read_exp_golomb(buf); - - if (!sps->pic_order_cnt_type) { - slc->pic_order_cnt_lsb = read_bits(buf, - sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - if (pps->pic_order_present_flag && !slc->field_pic_flag) - slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf); - } - else if (sps->pic_order_cnt_type == 1) { - slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf); - if (pps->pic_order_present_flag && !slc->field_pic_flag) - slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); - } - - if (pps->redundant_pic_cnt_present_flag == 1) { - slc->redundant_pic_cnt = read_exp_golomb(buf); - } - - if (slc->slice_type == SLICE_B) - slc->direct_spatial_mv_pred_flag = read_bits(buf, 1); - - if (slc->slice_type == SLICE_P || slc->slice_type == SLICE_SP - || slc->slice_type == SLICE_B) { - slc->num_ref_idx_active_override_flag = read_bits(buf, 1); - - if (slc->num_ref_idx_active_override_flag == 1) { - slc->num_ref_idx_l0_active_minus1 = read_exp_golomb(buf); - - if (slc->slice_type == SLICE_B) { - slc->num_ref_idx_l1_active_minus1 = read_exp_golomb(buf); - } - } - } - - /* --- ref_pic_list_reordering --- */ - parse_ref_pic_list_reordering(buf, nal); - - /* --- pred_weight_table --- */ - if ((pps->weighted_pred_flag && (slc->slice_type == SLICE_P - || slc->slice_type == SLICE_SP)) || (pps->weighted_bipred_idc == 1 - && slc->slice_type == SLICE_B)) { - parse_pred_weight_table(buf, nal); - } - - /* --- dec_ref_pic_marking --- */ - if (nal->nal_ref_idc != 0) - parse_dec_ref_pic_marking(buf, nal); - - return 0; -} - -void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal) -{ - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; - struct slice_header *slc = nal->slc; - if (!sps || !pps) - return; - - if (slc->slice_type != SLICE_I && slc->slice_type != SLICE_SI) { - slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 = read_bits( - buf, 1); - - if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 == 1) { - do { - slc->ref_pic_list_reordering.reordering_of_pic_nums_idc - = read_exp_golomb(buf); - - if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 - || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { - slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 - = read_exp_golomb(buf); - } - else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { - slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); - } - } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); - } - } - - if (slc->slice_type == SLICE_B) { - slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 = read_bits( - buf, 1); - - if (slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l1 == 1) { - do { - slc->ref_pic_list_reordering.reordering_of_pic_nums_idc - = read_exp_golomb(buf); - - if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 0 - || slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 1) { - slc->ref_pic_list_reordering.abs_diff_pic_num_minus1 - = read_exp_golomb(buf); - } - else if (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc == 2) { - slc->ref_pic_list_reordering.long_term_pic_num = read_exp_golomb(buf); - } - } while (slc->ref_pic_list_reordering.reordering_of_pic_nums_idc != 3); - } - } -} - -void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) -{ - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; - struct slice_header *slc = nal->slc; - if (!sps || !pps) - return; - - nal->slc->pred_weight_table.luma_log2_weight_denom = read_exp_golomb(buf); - - if (sps->chroma_format_idc != 0) - nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); - - int i; - for (i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) { - uint8_t luma_weight_l0_flag = read_bits(buf, 1); - - if (luma_weight_l0_flag == 1) { - nal->slc->pred_weight_table.luma_weight_l0[i] = read_exp_golomb_s(buf); - nal->slc->pred_weight_table.luma_offset_l0[i] = read_exp_golomb_s(buf); - } - - if (sps->chroma_format_idc != 0) { - uint8_t chroma_weight_l0_flag = read_bits(buf, 1); - - if (chroma_weight_l0_flag == 1) { - int j; - for (j = 0; j < 2; j++) { - nal->slc->pred_weight_table.chroma_weight_l0[i][j] - = read_exp_golomb_s(buf); - nal->slc->pred_weight_table.chroma_offset_l0[i][j] - = read_exp_golomb_s(buf); - } - } - } - } - - if (slc->slice_type == SLICE_B) { - for (i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) { - uint8_t luma_weight_l1_flag = read_bits(buf, 1); - - if (luma_weight_l1_flag == 1) { - nal->slc->pred_weight_table.luma_weight_l1[i] = read_exp_golomb_s(buf); - nal->slc->pred_weight_table.luma_offset_l1[i] = read_exp_golomb_s(buf); - } - - if (sps->chroma_format_idc != 0) { - uint8_t chroma_weight_l1_flag = read_bits(buf, 1); - - if (chroma_weight_l1_flag == 1) { - int j; - for (j = 0; j < 2; j++) { - nal->slc->pred_weight_table.chroma_weight_l1[i][j] - = read_exp_golomb_s(buf); - nal->slc->pred_weight_table.chroma_offset_l1[i][j] - = read_exp_golomb_s(buf); - } - } - } - } - } -} - -void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_unit *nal) -{ - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; - struct slice_header *slc = nal->slc; - if (!sps || !pps) - return; - - if (nal->nal_unit_type == NAL_SLICE_IDR) { - slc->dec_ref_pic_marking.no_output_of_prior_pics_flag = read_bits(buf, 1); - slc->dec_ref_pic_marking.long_term_reference_flag = read_bits(buf, 1); - } - else { - slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = read_bits( - buf, 1); - - if (slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) { - do { - slc->dec_ref_pic_marking.memory_management_control_operation - = read_exp_golomb(buf); - - if (slc->dec_ref_pic_marking.memory_management_control_operation == 1 - || slc->dec_ref_pic_marking.memory_management_control_operation - == 3) - slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 - = read_exp_golomb(buf); - - if (slc->dec_ref_pic_marking.memory_management_control_operation == 2) - slc->dec_ref_pic_marking.long_term_pic_num = read_exp_golomb(buf); - - if (slc->dec_ref_pic_marking.memory_management_control_operation == 3 - || slc->dec_ref_pic_marking.memory_management_control_operation - == 6) - slc->dec_ref_pic_marking.long_term_frame_idx = read_exp_golomb(buf); - - if (slc->dec_ref_pic_marking.memory_management_control_operation == 4) - slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 - = read_exp_golomb(buf); - } while (slc->dec_ref_pic_marking.memory_management_control_operation - != 0); - } - } -} - -/* ----------------- NAL parser ----------------- */ - -struct nal_parser* init_parser() -{ - struct nal_parser *parser = malloc(sizeof(struct nal_parser)); - memset(parser->buf, 0x00, MAX_FRAME_SIZE); - parser->buf_len = 0; - parser->found_sps = 0; - parser->found_pps = 0; - parser->nal0 = malloc(sizeof(struct nal_unit)); - memset(parser->nal0, 0x00, sizeof(struct nal_unit)); - parser->nal1 = malloc(sizeof(struct nal_unit)); - memset(parser->nal1, 0x00, sizeof(struct nal_unit)); - parser->current_nal = parser->nal0; - parser->last_nal = parser->nal1; - - parser->last_nal_res = 0; - parser->is_idr = 0; - parser->slice = 0; - parser->slice_cnt = 0; - parser->field = -1; - parser->have_top = 0; - - /* no idea why we do that. inspired by libavcodec, - * as we couldn't figure in the specs.... - */ - parser->prev_pic_order_cnt_msb = 1 << 16; - - return parser; -} - -void free_parser(struct nal_parser *parser) -{ - free(parser->nal0); - free(parser->nal1); - free(parser); -} - -int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, - uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) -{ - int next_nal; - int parsed_len = 0; - int search_offset = 0; - - while ((next_nal - = seek_for_nal(inbuf + search_offset, inbuf_len - parsed_len)) >= 0) { - // save buffer up to the nal-start - if (parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; - } - - if (parser->last_nal_res != 2) { - /* this is not nal_unit != SLICE, keep it in the buffer */ - xine_fast_memcpy(parser->buf + parser->buf_len, inbuf, next_nal - + search_offset); - parser->buf_len += next_nal + search_offset; - } - - inbuf += next_nal + search_offset; - parsed_len += next_nal + search_offset; - - parser->last_nal_res = parse_nal(inbuf + 3, inbuf_len - parsed_len, parser); - if (parser->last_nal_res == 1 && parser->buf_len > 0) { - *ret_buf = malloc(parser->buf_len); - xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); - *ret_len = parser->buf_len; - *ret_slice_cnt = parser->slice_cnt; - - calculate_pic_order(parser); - - //memset(parser->buf, 0x00, parser->buf_len); - parser->buf_len = 0; - parser->last_nal_res = 1; - parser->slice_cnt = 0; - - /*if(parser->current_nal->nal_ref_idc) { - if(parser->current_nal->slc != NULL) - parser->prev_pic_order_cnt_lsb = parser->current_nal->slc->pic_order_cnt_lsb; - parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; - }*/ - return parsed_len; - } - - search_offset = 3; - } - - // no further NAL found, copy the rest of the stream - // into the buffer - xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len - parsed_len); - parser->buf_len += inbuf_len - parsed_len; - - parsed_len += (inbuf_len - parsed_len); - *ret_len = 0; - *ret_buf = NULL; - - return parsed_len; -} - -int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) -{ - struct buf_reader bufr; - - bufr.buf = buf; - bufr.cur_pos = buf; - bufr.cur_offset = 8; - bufr.len = buf_len; - - struct nal_unit *nal = parser->current_nal; - struct nal_unit *last_nal = parser->last_nal; - - int res = parse_nal_header(&bufr, parser); - if (res == NAL_SLICE_IDR) - parser->is_idr = 1; - - if (res >= NAL_SLICE && res <= NAL_SLICE_IDR) { - // now detect if it's a new frame! - int ret = 0; - if (nal->slc->field_pic_flag == 1) - parser->field = nal->slc->bottom_field_flag; - else { - parser->have_top = 1; - parser->field = -1; - } - - if (nal->slc->field_pic_flag == 1 && nal->slc->bottom_field_flag == 0) - parser->have_top = 1; - - parser->slice = 1; - - if (nal->slc == NULL || last_nal->slc == NULL) { - printf("A\n"); - ret = 1; - } - if (nal->slc && last_nal->slc && (nal->slc->frame_num - != last_nal->slc->frame_num)) { - printf("B\n"); - ret = 1; - } - if (nal->slc && last_nal->slc && (nal->slc->pic_parameter_set_id - != last_nal->slc->pic_parameter_set_id)) { - printf("C\n"); - ret = 1; - } - if (nal->slc && last_nal->slc && (nal->slc->field_pic_flag - != last_nal->slc->field_pic_flag)) { - printf("D\n"); - ret = 1; - } - if (nal->slc && last_nal->slc && (nal->slc->bottom_field_flag != -1 - && last_nal->slc->bottom_field_flag != -1 - && nal->slc->bottom_field_flag != last_nal->slc->bottom_field_flag)) { - printf("E\n"); - ret = 1; - } - if (nal->nal_ref_idc != last_nal->nal_ref_idc && (nal->nal_ref_idc == 0 - || last_nal->nal_ref_idc == 0)) { - printf("F\n"); - ret = 1; - } - if (nal->sps && nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type - == 0 && last_nal->sps->pic_order_cnt_type == 0 - && (nal->slc->pic_order_cnt_lsb != last_nal->slc->pic_order_cnt_lsb - || nal->slc->delta_pic_order_cnt_bottom - != last_nal->slc->delta_pic_order_cnt_bottom))) { - printf("G\n"); - ret = 1; - } - if (nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 1 - && last_nal->sps->pic_order_cnt_type == 1 - && (nal->slc->delta_pic_order_cnt[0] - != last_nal->slc->delta_pic_order_cnt[0] - || nal->slc->delta_pic_order_cnt[1] - != last_nal->slc->delta_pic_order_cnt[1]))) { - printf("H\n"); - ret = 1; - } - if (nal->nal_unit_type != last_nal->nal_unit_type && (nal->nal_unit_type - == 5 || last_nal->nal_unit_type == 5)) { - printf("I\n"); - ret = 1; - } - if (nal->slc && last_nal->slc && (nal->nal_unit_type == 5 - && last_nal->nal_unit_type == 5 && nal->slc->idr_pic_id - != last_nal->slc->idr_pic_id)) { - printf("J\n"); - ret = 1; - } - - if (parser->current_nal == parser->nal0) { - parser->current_nal = parser->nal1; - parser->last_nal = parser->nal0; - } - else { - parser->current_nal = parser->nal0; - parser->last_nal = parser->nal1; - } - - if (parser->current_nal->sps == NULL) - parser->current_nal->sps = parser->last_nal->sps; - if (parser->current_nal->pps == NULL) - parser->current_nal->pps = parser->last_nal->pps; - - /* increase the slice_cnt until a new frame is detected */ - if (!ret) - parser->slice_cnt++; - - return ret; - } - else if (res == NAL_PPS || res == NAL_SPS) { - return 2; - } - else if (res >= NAL_SEI) { - //printf("New Frame\n"); - return 2; - } - - return 1; -} - -int seek_for_nal(uint8_t *buf, int buf_len) -{ - int i; - for (i = 0; i < buf_len - 2; i++) { - if (buf[i] == 0x00 && buf[i + 1] == 0x00 && buf[i + 2] == 0x01) { - //printf("found nal at: %d\n", i); - return i; - } - } - - return -1; -} diff --git a/src/libvdpau/nal_parser.h b/src/libvdpau/nal_parser.h deleted file mode 100644 index 7c43070cb..000000000 --- a/src/libvdpau/nal_parser.h +++ /dev/null @@ -1,377 +0,0 @@ -#ifndef NAL_PARSER_H_ -#define NAL_PARSER_H_ - -#include - -#include "xine_internal.h" - -enum nal_unit_types { - NAL_UNSPECIFIED = 0, - NAL_SLICE, - NAL_PART_A, - NAL_PART_B, - NAL_PART_C, - NAL_SLICE_IDR, - NAL_SEI, - NAL_SPS, - NAL_PPS, - NAL_AU_DELIMITER, - NAL_END_OF_SEQUENCE, - NAL_END_OF_STREAM, - NAL_FILLER_DATA, - NAL_SPS_EXT -}; - -/* slice types repeat from 5-9, we - * need a helper function for comparison - */ -enum slice_types { - SLICE_P = 0, - SLICE_B, - SLICE_I, - SLICE_SP, - SLICE_SI -}; - -enum aspect_ratio { - ASPECT_UNSPECIFIED = 0, - ASPECT_1_1, - ASPECT_12_11, - ASPECT_10_11, - ASPECT_16_11, - ASPECT_40_33, - ASPECT_24_11, - ASPECT_20_11, - ASPECT_32_11, - ASPECT_80_33, - ASPECT_18_11, - ASPECT_15_11, - ASPECT_64_33, - ASPECT_160_99, - ASPECT_4_3, - ASPECT_3_2, - ASPECT_2_1, - ASPECT_RESERVED -}; - -static inline uint32_t slice_type(uint32_t slice_type) { return (slice_type < 10 ? slice_type % 5 : slice_type); } - -struct nal_unit { - uint8_t nal_ref_idc; // 0x03 - uint8_t nal_unit_type; // 0x1f - - struct seq_parameter_set_rbsp *sps; - struct pic_parameter_set_rbsp *pps; - struct slice_header *slc; -}; - -struct hrd_parameters { - uint32_t cpb_cnt_minus1; - uint8_t bit_rate_scale; - uint8_t cpb_size_scale; - - uint32_t bit_rate_value_minus1[32]; - uint32_t cpb_size_value_minus1[32]; - uint8_t cbr_flag[32]; - - uint8_t initial_cpb_removal_delay_length_minus1; - uint8_t cpb_removal_delay_length_minus1; - uint8_t dpb_output_delay_length_minus1; - uint8_t time_offset_length; -}; - -struct seq_parameter_set_rbsp { - uint8_t profile_idc; // 0xff - uint8_t constraint_setN_flag; // 0x0f - uint8_t level_idc; // 0xff - uint32_t seq_parameter_set_id; - uint32_t chroma_format_idc; - uint8_t residual_colour_transform_flag; // 0x01 - uint32_t bit_depth_luma_minus8; - uint32_t bit_depth_chroma_minus8; - uint8_t qpprime_y_zero_transform_bypass_flag; - uint8_t seq_scaling_matrix_present_flag; - - /* if(seq_scaling_matrix_present_flag) */ - uint8_t seq_scaling_list_present_flag[8]; - - uint8_t scaling_lists_4x4[6][16]; - uint8_t scaling_lists_8x8[2][64]; - /* endif */ - - uint32_t log2_max_frame_num_minus4; - uint32_t pic_order_cnt_type; - // if pic_order_cnt_type==0 - uint32_t log2_max_pic_order_cnt_lsb_minus4; - // else - uint8_t delta_pic_order_always_zero_flag; - int32_t offset_for_non_ref_pic; - int32_t offset_for_top_to_bottom_field; - uint8_t num_ref_frames_in_pic_order_cnt_cycle; - int32_t offset_for_ref_frame[256]; - // TODO: some more ignored here - uint32_t num_ref_frames; - uint8_t gaps_in_frame_num_value_allowed_flag; - /*uint32_t pic_width_in_mbs_minus1; - uint32_t pic_height_in_map_units_minus1;*/ - uint32_t pic_width; - uint32_t pic_height; - uint8_t frame_mbs_only_flag; - uint8_t mb_adaptive_frame_field_flag; - uint8_t direct_8x8_inference_flag; - uint8_t frame_cropping_flag; - uint32_t frame_crop_left_offset; - uint32_t frame_crop_right_offset; - uint32_t frame_crop_top_offset; - uint32_t frame_crop_bottom_offset; - uint8_t vui_parameters_present_flag; - - /* vui_parameters */ - union { - uint8_t aspect_ration_info_present_flag; - - /* aspect_ration_info_present_flag == 1 */ - uint8_t aspect_ratio_idc; - uint16_t sar_width; - uint16_t sar_height; - - uint8_t overscan_info_present_flag; - /* overscan_info_present_flag == 1 */ - uint8_t overscan_appropriate_flag; - - uint8_t video_signal_type_present_flag; - /* video_signal_type_present_flag == 1 */ - uint8_t video_format; - uint8_t video_full_range_flag; - uint8_t colour_description_present; - /* colour_description_present == 1 */ - uint8_t colour_primaries; - uint8_t transfer_characteristics; - uint8_t matrix_coefficients; - - uint8_t chroma_loc_info_present_flag; - /* chroma_loc_info_present_flag == 1 */ - uint8_t chroma_sample_loc_type_top_field; - uint8_t chroma_sample_loc_type_bottom_field; - - uint8_t timing_info_present_flag; - /* timing_info_present_flag == 1 */ - uint32_t num_units_in_tick; - uint32_t time_scale; - uint8_t fixed_frame_rate_flag; - - uint8_t nal_hrd_parameters_present_flag; - struct hrd_parameters nal_hrd_parameters; - - uint8_t vc1_hrd_parameters_present_flag; - struct hrd_parameters vc1_hrd_parameters; - - uint8_t low_delay_hrd_flag; - - uint8_t pic_struct_present_flag; - uint8_t bitstream_restriction_flag; - - /* bitstream_restriction_flag == 1 */ - uint8_t motion_vectors_over_pic_boundaries; - uint32_t max_bytes_per_pic_denom; - uint32_t max_bits_per_mb_denom; - uint32_t log2_max_mv_length_horizontal; - uint32_t log2_max_mv_length_vertical; - uint32_t num_reorder_frames; - uint32_t max_dec_frame_buffering; - } vui_parameters; - -}; - -struct pic_parameter_set_rbsp { - uint32_t pic_parameter_set_id; - uint32_t seq_parameter_set_id; - uint8_t entropy_coding_mode_flag; - uint8_t pic_order_present_flag; - - uint32_t num_slice_groups_minus1; - - /* num_slice_groups_minus1 > 0 */ - uint32_t slice_group_map_type; - - /* slice_group_map_type == 1 */ - uint32_t run_length_minus1[64]; - - /* slice_group_map_type == 2 */ - uint32_t top_left[64]; - uint32_t bottom_right[64]; - - /* slice_group_map_type == 3,4,5 */ - uint8_t slice_group_change_direction_flag; - uint32_t slice_group_change_rate_minus1; - - /* slice_group_map_type == 6 */ - uint32_t pic_size_in_map_units_minus1; - uint8_t slice_group_id[64]; - - uint32_t num_ref_idx_l0_active_minus1; - uint32_t num_ref_idx_l1_active_minus1; - uint8_t weighted_pred_flag; - uint8_t weighted_bipred_idc; - int32_t pic_init_qp_minus26; - int32_t pic_init_qs_minus26; - int32_t chroma_qp_index_offset; - uint8_t deblocking_filter_control_present_flag; - uint8_t constrained_intra_pred_flag; - uint8_t redundant_pic_cnt_present_flag; - - /* if(more_rbsp_data) */ - uint8_t transform_8x8_mode_flag; - uint8_t pic_scaling_matrix_present_flag; - - /* if(pic_scaling_matrix_present_flag) */ - uint8_t pic_scaling_list_present_flag[8]; - - uint8_t scaling_lists_4x4[6][16]; - uint8_t scaling_lists_8x8[2][64]; - - int32_t second_chroma_qp_index_offset; -}; - -struct slice_header { - uint32_t first_mb_in_slice; - uint32_t slice_type; - uint32_t pic_parameter_set_id; - uint32_t frame_num; - uint8_t field_pic_flag; - uint8_t bottom_field_flag; - uint32_t idr_pic_id; - - /* sps->pic_order_cnt_type == 0 */ - uint32_t pic_order_cnt_lsb; - int32_t delta_pic_order_cnt_bottom; - /* sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag */ - int32_t delta_pic_order_cnt[2]; - - /* pps->redundant_pic_cnt_present_flag == 1 */ - int32_t redundant_pic_cnt; - - /* slice_type == B */ - uint8_t direct_spatial_mv_pred_flag; - - /* slice_type == P, SP, B */ - uint8_t num_ref_idx_active_override_flag; - /* num_ref_idx_active_override_flag == 1 */ - uint32_t num_ref_idx_l0_active_minus1; - /* slice type == B */ - uint32_t num_ref_idx_l1_active_minus1; - - /* ref_pic_list_reordering */ - union { - /* slice_type != I && slice_type != SI */ - uint8_t ref_pic_list_reordering_flag_l0; - - /* slice_type == B */ - uint8_t ref_pic_list_reordering_flag_l1; - - /* ref_pic_list_reordering_flag_l0 == 1 */ - uint32_t reordering_of_pic_nums_idc; - - /* reordering_of_pic_nums_idc == 0, 1 */ - uint32_t abs_diff_pic_num_minus1; - - /* reordering_of_pic_nums_idc == 2) */ - uint32_t long_term_pic_num; - } ref_pic_list_reordering; - - /* pred_weight_table */ - union { - uint32_t luma_log2_weight_denom; - - /* chroma_format_idc != 0 */ - uint32_t chroma_log2_weight_denom; - - int32_t luma_weight_l0[32]; - int32_t luma_offset_l0[32]; - - int32_t chroma_weight_l0[32][2]; - int32_t chroma_offset_l0[32][2]; - - int32_t luma_weight_l1[32]; - int32_t luma_offset_l1[32]; - - int32_t chroma_weight_l1[32][2]; - int32_t chroma_offset_l1[32][2]; - } pred_weight_table; - - /* def_rec_pic_marking */ - union { - - /* nal_unit_type == NAL_SLICE_IDR */ - uint8_t no_output_of_prior_pics_flag; - uint8_t long_term_reference_flag; - - /* else */ - uint8_t adaptive_ref_pic_marking_mode_flag; - uint32_t memory_management_control_operation; - - uint32_t difference_of_pic_nums_minus1; - uint32_t long_term_pic_num; - uint32_t long_term_frame_idx; - uint32_t max_long_term_frame_idx_plus1; - } dec_ref_pic_marking; -}; - - -struct decoded_picture { - //VdpReferenceFrameH264 surface; - struct nal_unit *nal; -}; - -/* Decoded Picture Buffer */ -struct dpb { - uint32_t max_frame_num; - - uint32_t prev_ref_frame_number; - uint32_t unused_short_term_frame_num; - uint32_t non_existing_pictures[32]; - - struct decoded_picture *pictures; -}; - -#define MAX_FRAME_SIZE 1024*1024 - -struct nal_parser { - uint8_t buf[MAX_FRAME_SIZE]; - int buf_len; - int found_sps; - int found_pps; - int last_nal_res; - - int is_idr; - int field; /* 0=top, 1=bottom, -1=both */ - int slice; - int slice_cnt; - int have_top; - int have_frame; - - struct nal_unit *nal0; - struct nal_unit *nal1; - struct nal_unit *current_nal; - struct nal_unit *last_nal; - - /* pic_order_cnt */ - int32_t top_field_order_cnt; - int32_t bottom_field_order_cnt; - int32_t pic_order_cnt_msb; - int32_t prev_pic_order_cnt_msb; - int32_t prev_pic_order_cnt_lsb; - - struct dpb *dpb; -}; - -int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); - -int seek_for_nal(uint8_t *buf, int buf_len); - -struct nal_parser* init_parser(); -void free_parser(struct nal_parser *parser); -int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, - uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt); - -#endif diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index eb2f61040..4da276101 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -37,7 +37,8 @@ #include "xineutils.h" #include "bswap.h" #include "accel_vdpau.h" -#include "nal_parser.h" +#include "h264_parser.h" +#include "dpb.h" #define VIDEOBUFSIZE 128*1024 @@ -246,8 +247,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, VdpPictureInfoH264 pic; pic.slice_count = slice_count; - pic.field_order_cnt[0] = this->nal_parser->top_field_order_cnt; - pic.field_order_cnt[1] = this->nal_parser->bottom_field_order_cnt; + pic.field_order_cnt[0] = this->nal_parser->current_nal->top_field_order_cnt; + pic.field_order_cnt[1] = this->nal_parser->current_nal->bottom_field_order_cnt; pic.is_reference = (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; pic.frame_num = slc->frame_num; @@ -277,6 +278,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic.scaling_lists_4x4)); memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic.scaling_lists_8x8)); memcpy(pic.referenceFrames, this->reference_frames, sizeof(pic.referenceFrames)); + memset(pic.referenceFrames, VDP_INVALID_HANDLE, sizeof(pic.referenceFrames)); + fill_vdpau_reference_list(&(this->nal_parser->dpb), pic.referenceFrames); if(this->decoder_started || pic.is_reference) { this->nal_parser->is_idr = 0; @@ -328,6 +331,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, else { printf("DECODING SUCCESS\n"); + if(pic.is_reference) { + struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface); + dpb_add_picture(&(this->nal_parser->dpb), pic); + } + img->duration = this->video_step; img->pts = buf->pts; img->bad_frame = 0; -- cgit v1.2.3 From 2a0e91697830b8645ce3feeda623ad549b9809aa Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 8 Dec 2008 10:46:30 +0000 Subject: Progress... seeing the first picture (c: --- src/libvdpau/dpb.c | 14 ++++++++++++++ src/libvdpau/h264_parser.c | 36 +++++++++++++++++++++++++----------- src/libvdpau/nal.c | 9 ++++++++- src/libvdpau/vdpau_h264.c | 23 +++++++++++++++++++---- 4 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 460149ea3..a13e758bf 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -219,4 +219,18 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) } last_pic = pic; } while ((pic = pic->next) != NULL && i < 16); + + printf("Used ref-frames: %d\n", i); + + // fill all other frames with invalid handles + while(i < 16) { + reflist[i].bottom_is_reference = VDP_FALSE; + reflist[i].top_is_reference = VDP_FALSE; + reflist[i].frame_idx = VDP_INVALID_HANDLE; + reflist[i].is_long_term = VDP_FALSE; + reflist[i].surface = VDP_INVALID_HANDLE; + reflist[i].field_order_cnt[0] = 0; + reflist[i].field_order_cnt[1] = 0; + i++; + } } diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 7ae1cc216..18456d47a 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -174,6 +174,9 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len - 1); ibuf.cur_pos = ibuf.buf; + if(!nal->sps) + nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); parse_sps(&ibuf, nal->sps); @@ -181,6 +184,8 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) ret = NAL_SPS; break; case NAL_PPS: + if(!nal->pps) + nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); parse_pps(buf, nal->pps, nal->sps); @@ -192,6 +197,9 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) case NAL_PART_C: case NAL_SLICE_IDR: if (nal->sps && nal->pps) { + if(!nal->slc) + nal->slc = malloc(sizeof(struct slice_header)); + memset(nal->slc, 0x00, sizeof(struct slice_header)); parse_slice_header(buf, parser); @@ -818,13 +826,19 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, dpb_remove_picture_by_ltidx(dpb, slc->dec_ref_pic_marking.long_term_frame_idx); - if (pic->nal->slc->field_pic_flag == 0) { - pic = dpb_get_picture(dpb, pic_num_x); - pic->nal->long_term_frame_idx - = slc->dec_ref_pic_marking.long_term_frame_idx; + pic = dpb_get_picture(dpb, pic_num_x); + if(pic) { + if (pic->nal->slc->field_pic_flag == 0) { + pic = dpb_get_picture(dpb, pic_num_x); + pic->nal->long_term_frame_idx + = slc->dec_ref_pic_marking.long_term_frame_idx; + } + else + printf("FIXME: B Set frame %d to long-term ref\n", pic_num_x); + } else { + printf("memory_management_control_operation: 3 failed. No such picture."); } - else - printf("FIXME: B Set frame %d to long-term ref\n", pic_num_x); + } else if (memory_management_control_operation == 4) { // set max-long-term frame index, @@ -985,11 +999,11 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->last_nal_res = 1; parser->slice_cnt = 0; - /*if(parser->current_nal->nal_ref_idc) { - if(parser->current_nal->slc != NULL) - parser->prev_pic_order_cnt_lsb = parser->current_nal->slc->pic_order_cnt_lsb; - parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; - }*/ + if(parser->last_nal->nal_ref_idc) { + if(parser->last_nal->slc != NULL) + parser->prev_pic_order_cnt_lsb = parser->last_nal->slc->pic_order_cnt_lsb; + parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; + } return parsed_len; } diff --git a/src/libvdpau/nal.c b/src/libvdpau/nal.c index a9717d76e..0964c446e 100644 --- a/src/libvdpau/nal.c +++ b/src/libvdpau/nal.c @@ -17,9 +17,12 @@ struct nal_unit* init_nal_unit() struct nal_unit *nal = malloc(sizeof(struct nal_unit)); memset(nal, 0x00, sizeof(struct nal_unit)); - nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + /*nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); nal->slc = malloc(sizeof(struct slice_header)); + memset(nal->slc, 0x00, sizeof(struct slice_header));*/ return nal; } @@ -40,6 +43,10 @@ void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src) xine_fast_memcpy(dest, src, size); + dest->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + dest->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + dest->slc = malloc(sizeof(struct slice_header)); + xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp)); xine_fast_memcpy(dest->pps, src->pps, sizeof(struct pic_parameter_set_rbsp)); xine_fast_memcpy(dest->slc, src->slc, sizeof(struct slice_header)); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 4da276101..ac539c985 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -122,7 +122,7 @@ static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) printf("deblocking_filter_control_present_flag: %d\n", pic->deblocking_filter_control_present_flag); printf("redundant_pic_cnt_present_flag: %d\n", pic->redundant_pic_cnt_present_flag); - int i, j; + /*int i, j; for(i = 0; i < 6; i++) { printf("scalint_list4x4[%d]: ", i); for(j = 0; j < 16; j++) { @@ -141,6 +141,18 @@ static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) } printf("\n"); } + + for(i = 0; i < 16; i++) { + printf("-------------------\n"); + printf("Reference Frame %d:\n", i); + printf("frame_idx: %d\n", pic->referenceFrames[i].frame_idx); + printf("field_order_cnt[0]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); + printf("field_order_cnt[1]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); + printf("is_long_term: %d\n", pic->referenceFrames[i].is_long_term); + printf("top_is_reference: %d\n", pic->referenceFrames[i].top_is_reference); + printf("bottom_is_reference: %d\n", pic->referenceFrames[i].bottom_is_reference); + printf("-------------------\n"); + }*/ /*memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames));*/ @@ -183,7 +195,10 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); if(!this->decoder_initialized && - this->nal_parser->current_nal->sps != NULL) { + this->nal_parser->current_nal != NULL && + this->nal_parser->current_nal->sps != NULL && + this->nal_parser->current_nal->sps->pic_width > 0 && + this->nal_parser->current_nal->sps->pic_height > 0) { this->width = this->nal_parser->current_nal->sps->pic_width; this->height = this->nal_parser->current_nal->sps->pic_height; @@ -277,9 +292,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, pic.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic.scaling_lists_4x4)); memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic.scaling_lists_8x8)); - memcpy(pic.referenceFrames, this->reference_frames, sizeof(pic.referenceFrames)); - memset(pic.referenceFrames, VDP_INVALID_HANDLE, sizeof(pic.referenceFrames)); + fill_vdpau_reference_list(&(this->nal_parser->dpb), pic.referenceFrames); + //memcpy(pic.referenceFrames, this->reference_frames, sizeof(pic.referenceFrames)); if(this->decoder_started || pic.is_reference) { this->nal_parser->is_idr = 0; -- cgit v1.2.3 From 22bac86081c46fc2a95dd4865e31f94f7c2e6f53 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 8 Dec 2008 10:49:45 +0000 Subject: Enable VO_CAP check. --- src/libvdpau/vdpau_h264.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ac539c985..35e45bb0e 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -422,8 +422,8 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t)); /* the videoout must be vdpau-capable to support this decoder */ - /*if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) ) - return NULL;*/ + if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) ) + return NULL; this->video_decoder.decode_data = vdpau_h264_decode_data; this->video_decoder.flush = vdpau_h264_flush; -- cgit v1.2.3 From fcceca2c84e5b1cb24262591ee8de98ccedca1db Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 8 Dec 2008 10:51:07 +0000 Subject: Export vdp_get_error_string; define MPEG12 cap. --- src/video_out/video_out_vdpau.c | 14 ++++++++++++-- src/xine-engine/accel_vdpau.h | 1 + src/xine-engine/video_out.h | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 9b7319819..80bb13b0c 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 the xine project + * Copyright (C) 2008 Christophe Thommeret * * This file is part of xine, a free video player. * @@ -20,7 +20,6 @@ * * video_out_vdpau.c, a video output plugin using VDPAU (Video Decode and Presentation Api for Unix) * - * Christophe Thommeret * */ @@ -390,6 +389,8 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) vdpau_frame_t *frame; vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + printf( "vo_vdpau: vdpau_alloc_frame\n" ); + frame = (vdpau_frame_t *) calloc(1, sizeof(vdpau_frame_t)); if (!frame) @@ -415,6 +416,7 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vdpau_accel_data.vdp_decoder_create = vdp_decoder_create; frame->vdpau_accel_data.vdp_decoder_destroy = vdp_decoder_destroy; frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render; + frame->vdpau_accel_data.vdp_get_error_string = vdp_get_error_string; frame->width = frame->height = 0; @@ -1046,6 +1048,14 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo else this->capabilities |= VO_CAP_VDPAU_H264; + st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, &ok, &ml, &mr, &mw, &mh ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: getting mpeg12_supported failed! : %s\n", vdp_get_error_string( st ) ); + else if ( !ok ) + printf( "vo_vdpau: no support for mpeg1/2 ! : no ok\n" ); + else + this->capabilities |= VO_CAP_VDPAU_MPEG12; + this->gotimage = 0; return &this->vo_driver; } diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h index ef76fe5ee..f5b80e4d4 100644 --- a/src/xine-engine/accel_vdpau.h +++ b/src/xine-engine/accel_vdpau.h @@ -41,6 +41,7 @@ typedef struct { VdpDevice vdp_device; + VdpGetErrorString *vdp_get_error_string; VdpVideoSurfaceCreate *vdp_video_surface_create; VdpVideoSurfaceDestroy *vdp_video_surface_destroy; VdpDecoderCreate *vdp_decoder_create; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 77a7134fc..b3903d4f8 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -281,6 +281,7 @@ struct xine_video_port_s { #define VO_CAP_CROP 0x00000020 /* driver can crop */ #define VO_CAP_XXMC 0x00000040 /* driver can use extended XvMC */ #define VO_CAP_VDPAU_H264 0x00000080 /* driver can use Nvidia VDPAU for H264 */ +#define VO_CAP_VDPAU_MPEG12 0x00000100 /* driver can use Nvidia VDPAU for mpeg1/2 */ /* -- cgit v1.2.3 From 25bdacf7a72c1abae24e7e7e82b53505408dc4a9 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 8 Dec 2008 11:24:37 +0000 Subject: Block surfaces until they are not used as reference frames any more. --- src/libvdpau/dpb.c | 5 ++++- src/libvdpau/dpb.h | 5 ++++- src/libvdpau/vdpau_h264.c | 19 ++++++++++--------- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index a13e758bf..d6a6c25df 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -10,14 +10,16 @@ #include #include "dpb.h" +#include "video_out.h" struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, - VdpVideoSurface surface) + VdpVideoSurface surface, vo_frame_t *img) { struct decoded_picture *pic = malloc(sizeof(struct decoded_picture)); pic->nal = init_nal_unit(); copy_nal_unit(pic->nal, src_nal); pic->surface = surface; + pic->img = img; pic->next = NULL; return pic; @@ -25,6 +27,7 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, void free_decoded_picture(struct decoded_picture *pic) { + pic->img->free(pic->img); free_nal_unit(pic->nal); } diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 8aa430c26..857f2fa5f 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -9,9 +9,12 @@ #define DPB_H_ #include "nal.h" +#include "video_out.h" struct decoded_picture { VdpVideoSurface surface; + vo_frame_t *img; /* this is the image we block, to make sure + * the surface is not double-used */ struct nal_unit *nal; struct decoded_picture *next; @@ -23,7 +26,7 @@ struct dpb { }; struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, - VdpVideoSurface surface); + VdpVideoSurface surface, vo_frame_t *img); void free_decoded_picture(struct decoded_picture *pic); struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 35e45bb0e..b53e77551 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -240,7 +240,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->profile, this->width, this->height, &this->decoder); if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%d)\n", status); + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status)); else this->decoder_initialized = 1; @@ -334,7 +334,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, &surface); this->vdpau_accel->surface = surface; if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed\n"); + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed: %s\n", this->vdpau_accel->vdp_get_error_string(status)); } printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); @@ -342,21 +342,22 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %d\n", status); + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); else { printf("DECODING SUCCESS\n"); - if(pic.is_reference) { - struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface); - dpb_add_picture(&(this->nal_parser->dpb), pic); - } - img->duration = this->video_step; img->pts = buf->pts; img->bad_frame = 0; img->draw(img, this->stream); - img->free(img); + + if(pic.is_reference) { + struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + dpb_add_picture(&(this->nal_parser->dpb), pic); + } else { + img->free(img); + } img = NULL; } -- cgit v1.2.3 From f44ca81abbb39c33072cbabff12bdbb29028faac Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 8 Dec 2008 11:39:45 +0000 Subject: Fix frame alloc. --- src/video_out/video_out_vdpau.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 80bb13b0c..23c10fea8 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -649,6 +649,8 @@ static int vdpau_get_property (vo_driver_t *this_gen, int property) int ret=-1; switch (property) { + case VO_PROP_MAX_NUM_FRAMES: + return 20; case VO_PROP_WINDOW_WIDTH: ret = this->sc.gui_width; break; -- cgit v1.2.3 From dd4a901976e0e83cc8557fc6790d87af6ae669a5 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 8 Dec 2008 12:06:41 +0000 Subject: Plays whole streams (progressive), still with glitches, though. --- src/libvdpau/dpb.c | 28 +++++++++++++++++++++++++--- src/libvdpau/dpb.h | 3 ++- src/libvdpau/vdpau_h264.c | 17 +++++++++++------ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index d6a6c25df..8f79dc064 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -88,6 +88,7 @@ int dpb_remove_picture(struct dpb *dpb, uint32_t picnum) dpb->pictures = pic->next; free_decoded_picture(pic); + dpb->used--; return 0; } @@ -113,6 +114,7 @@ int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum) dpb->pictures = pic->next; free_decoded_picture(pic); + dpb->used--; return 0; } @@ -138,6 +140,7 @@ int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx) dpb->pictures = pic->next; free_decoded_picture(pic); + dpb->used--; return 0; } @@ -163,7 +166,7 @@ int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max) free_decoded_picture(pic); - + dpb->used--; /* don't increase last_pic to current pic * in case we delete current pic */ continue; @@ -175,10 +178,27 @@ int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max) return 0; } -int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic) +int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames) { + int i = 0; + struct decoded_picture *last_pic; + pic->next = dpb->pictures; dpb->pictures = pic; + dpb->used++; + + if(dpb->used > num_ref_frames) { + do { + i++; + if(i>num_ref_frames) { + last_pic->next = pic->next; + free_decoded_picture(pic); + pic = last_pic; + dpb->used--; + } else + last_pic = pic; + } while ((pic = pic->next) != NULL); + } return 0; } @@ -191,11 +211,13 @@ int dpb_flush(struct dpb *dpb) if (pic != NULL) do { //FIXME: free the picture - + free_decoded_picture(last_pic); last_pic = pic; } while ((pic = pic->next) != NULL); + free_decoded_picture(last_pic); dpb->pictures = NULL; + dpb->used = NULL; return 0; } diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 857f2fa5f..ace624e32 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -23,6 +23,7 @@ struct decoded_picture { /* Decoded Picture Buffer */ struct dpb { struct decoded_picture *pictures; + uint32_t used; }; struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, @@ -36,7 +37,7 @@ int dpb_remove_picture(struct dpb *dpb, uint32_t picnum); int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max); -int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic); +int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames); int dpb_flush(struct dpb *dpb); void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index b53e77551..112496168 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -140,19 +140,21 @@ static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) printf("\n"); } printf("\n"); - } + }*/ + int i; for(i = 0; i < 16; i++) { + if(pic->referenceFrames[i].surface != VDP_INVALID_HANDLE) { printf("-------------------\n"); - printf("Reference Frame %d:\n", i); + printf("Reference Frame %d:\n", i); printf("frame_idx: %d\n", pic->referenceFrames[i].frame_idx); printf("field_order_cnt[0]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); printf("field_order_cnt[1]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); printf("is_long_term: %d\n", pic->referenceFrames[i].is_long_term); printf("top_is_reference: %d\n", pic->referenceFrames[i].top_is_reference); printf("bottom_is_reference: %d\n", pic->referenceFrames[i].bottom_is_reference); - printf("-------------------\n"); - }*/ + } + } /*memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames));*/ @@ -301,7 +303,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(!this->decoder_started) this->decoder_started = 1; - //dump_pictureinfo_h264(&pic); + dump_pictureinfo_h264(&pic); /*int i; printf("Decode data: \n"); @@ -319,10 +321,13 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(img == NULL) { + printf("Acquire image: "); + fflush(stdout); img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + printf("OK\n"); this->vdpau_accel = (vdpau_accel_t*)img->accel_data; } @@ -354,7 +359,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(pic.is_reference) { struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); - dpb_add_picture(&(this->nal_parser->dpb), pic); + dpb_add_picture(&(this->nal_parser->dpb), pic, sps->num_ref_frames); } else { img->free(img); } -- cgit v1.2.3 From b8d5e7125ed9b6ef044b22576bab2513f9774035 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 8 Dec 2008 12:10:52 +0000 Subject: Set frame_idx in a more correct manner. --- src/libvdpau/dpb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 8f79dc064..da10bde0e 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -197,6 +197,7 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r dpb->used--; } else last_pic = pic; + last_pic = pic; } while ((pic = pic->next) != NULL); } @@ -234,6 +235,10 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) if (pic->nal->nal_ref_idc != 0) { reflist[i].surface = pic->surface; reflist[i].is_long_term = pic->nal->used_for_long_term_ref; + if(reflist[i].is_long_term) + reflist[i].frame_idx = pic->nal->long_term_frame_idx; + else + reflist[i].frame_idx = pic->nal->curr_pic_num; reflist[i].top_is_reference = pic->nal->slc->field_pic_flag ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; reflist[i].bottom_is_reference = pic->nal->slc->field_pic_flag @@ -251,7 +256,7 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) while(i < 16) { reflist[i].bottom_is_reference = VDP_FALSE; reflist[i].top_is_reference = VDP_FALSE; - reflist[i].frame_idx = VDP_INVALID_HANDLE; + reflist[i].frame_idx = 0; reflist[i].is_long_term = VDP_FALSE; reflist[i].surface = VDP_INVALID_HANDLE; reflist[i].field_order_cnt[0] = 0; -- cgit v1.2.3 From 05dd5c1af21bdaa60b31edc5392e4f0c1bf28301 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 8 Dec 2008 14:05:07 +0000 Subject: Ref-frame fixes. --- src/libvdpau/dpb.c | 22 ++++++++--------- src/libvdpau/h264_parser.c | 59 +++++++++++++++++++++++----------------------- src/libvdpau/h264_parser.h | 3 ++- src/libvdpau/vdpau_h264.c | 10 +++++++- 4 files changed, 51 insertions(+), 43 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index da10bde0e..25d9041f2 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -195,9 +195,8 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r free_decoded_picture(pic); pic = last_pic; dpb->used--; - } else - last_pic = pic; - last_pic = pic; + } + last_pic = pic; } while ((pic = pic->next) != NULL); } @@ -207,18 +206,17 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r int dpb_flush(struct dpb *dpb) { struct decoded_picture *pic = dpb->pictures; - struct decoded_picture *last_pic = NULL; if (pic != NULL) do { - //FIXME: free the picture - free_decoded_picture(last_pic); - last_pic = pic; - } while ((pic = pic->next) != NULL); + dpb->pictures = pic->next; + free_decoded_picture(pic); + pic = dpb->pictures; + dpb->used--; + } while (dpb->pictures != NULL); - free_decoded_picture(last_pic); dpb->pictures = NULL; - dpb->used = NULL; + dpb->used = 0; return 0; } @@ -236,9 +234,9 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) reflist[i].surface = pic->surface; reflist[i].is_long_term = pic->nal->used_for_long_term_ref; if(reflist[i].is_long_term) - reflist[i].frame_idx = pic->nal->long_term_frame_idx; + reflist[i].frame_idx = pic->nal->slc->frame_num; //pic->nal->long_term_frame_idx; else - reflist[i].frame_idx = pic->nal->curr_pic_num; + reflist[i].frame_idx = pic->nal->slc->frame_num; //pic->nal->curr_pic_num; reflist[i].top_is_reference = pic->nal->slc->field_pic_flag ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; reflist[i].bottom_is_reference = pic->nal->slc->field_pic_flag diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 18456d47a..c41cb5cf6 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -226,41 +226,41 @@ void calculate_pic_order(struct nal_parser *parser) if (sps->pic_order_cnt_type == 0) { if (nal->nal_unit_type == NAL_SLICE_IDR) { + printf("IDR SLICE\n"); parser->prev_pic_order_cnt_lsb = 0; parser->prev_pic_order_cnt_msb = 0; } - else { - const int max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); - - if (slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb - && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb - >= max_poc_lsb / 2) - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - + max_poc_lsb; - else if (slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb - && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb - < -max_poc_lsb / 2) - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - - max_poc_lsb; - else - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; - if (!slc->bottom_field_flag) { - nal->top_field_order_cnt = parser->pic_order_cnt_msb - + slc->pic_order_cnt_lsb; + const int max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + if (slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb + && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb + >= max_poc_lsb / 2) + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + + max_poc_lsb; + else if (slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb + && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb + < -max_poc_lsb / 2) + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + - max_poc_lsb; + else + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; - if (!slc->field_pic_flag) - nal->bottom_field_order_cnt = nal->top_field_order_cnt; - else - nal->bottom_field_order_cnt = 0; - } - else - nal->bottom_field_order_cnt = parser->pic_order_cnt_msb - + slc->pic_order_cnt_lsb; + if (!slc->bottom_field_flag) { + nal->top_field_order_cnt = parser->pic_order_cnt_msb + + slc->pic_order_cnt_lsb; - if (parser->field == -1) - nal->bottom_field_order_cnt += slc->delta_pic_order_cnt_bottom; + if (!slc->field_pic_flag) + nal->bottom_field_order_cnt = nal->top_field_order_cnt; + else + nal->bottom_field_order_cnt = 0; } + else + nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + + slc->pic_order_cnt_lsb; + + if (parser->field == -1) + nal->bottom_field_order_cnt += slc->delta_pic_order_cnt_bottom; } } @@ -1035,8 +1035,9 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) struct nal_unit *last_nal = parser->last_nal; int res = parse_nal_header(&bufr, parser); - if (res == NAL_SLICE_IDR) + if (res == NAL_SLICE_IDR) { parser->is_idr = 1; + } if (res >= NAL_SLICE && res <= NAL_SLICE_IDR) { // now detect if it's a new frame! diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index e067f9741..bfd6d3b35 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -16,7 +16,8 @@ struct nal_parser { int found_pps; int last_nal_res; - int is_idr; + uint8_t is_idr; + int field; /* 0=top, 1=bottom, -1=both */ int slice; int slice_cnt; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 112496168..f80396ff5 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -260,6 +260,15 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; struct slice_header *slc = this->nal_parser->current_nal->slc; + /* flush the DPB if this frame was an IDR */ + //printf("is_idr: %d\n", this->nal_parser->is_idr); + if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { + printf("IDR Slice, flush\n"); + dpb_flush(&(this->nal_parser->dpb)); + printf("Emtpy: %s", this->nal_parser->dpb.pictures == NULL ? "Yes" : "No"); + } + this->nal_parser->is_idr = 0; + /* go and decode a frame */ VdpPictureInfoH264 pic; @@ -299,7 +308,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, //memcpy(pic.referenceFrames, this->reference_frames, sizeof(pic.referenceFrames)); if(this->decoder_started || pic.is_reference) { - this->nal_parser->is_idr = 0; if(!this->decoder_started) this->decoder_started = 1; -- cgit v1.2.3 From ab45a7f79778b9bbc3a20877a165eb077fd43ee0 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 8 Dec 2008 17:11:11 +0000 Subject: It grows and grows... --- src/libvdpau/h264_parser.c | 16 ++++++++-- src/libvdpau/vdpau_h264.c | 80 +++++++++++++++++++++------------------------- 2 files changed, 51 insertions(+), 45 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index c41cb5cf6..c888d9e1d 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -976,7 +976,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, } if (parser->last_nal_res != 2) { - /* this is not nal_unit != SLICE, keep it in the buffer */ + /* this is a SLICE, keep it in the buffer */ xine_fast_memcpy(parser->buf + parser->buf_len, inbuf, next_nal + search_offset); parser->buf_len += next_nal + search_offset; @@ -1042,6 +1042,7 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) if (res >= NAL_SLICE && res <= NAL_SLICE_IDR) { // now detect if it's a new frame! int ret = 0; + uint8_t reason = 0; if (nal->slc->field_pic_flag == 1) parser->field = nal->slc->bottom_field_flag; else { @@ -1056,26 +1057,32 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) if (nal->slc == NULL || last_nal->slc == NULL) { ret = 1; + reason++; } if (nal->slc && last_nal->slc && (nal->slc->frame_num != last_nal->slc->frame_num)) { ret = 1; + reason++; } if (nal->slc && last_nal->slc && (nal->slc->pic_parameter_set_id != last_nal->slc->pic_parameter_set_id)) { ret = 1; + reason++; } if (nal->slc && last_nal->slc && (nal->slc->field_pic_flag != last_nal->slc->field_pic_flag)) { ret = 1; + reason++; } if (nal->slc && last_nal->slc && nal->slc->bottom_field_flag != last_nal->slc->bottom_field_flag) { ret = 1; + reason++; } if (nal->nal_ref_idc != last_nal->nal_ref_idc && (nal->nal_ref_idc == 0 || last_nal->nal_ref_idc == 0)) { ret = 1; + reason++; } if (nal->sps && nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 0 && last_nal->sps->pic_order_cnt_type == 0 @@ -1083,6 +1090,8 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) || nal->slc->delta_pic_order_cnt_bottom != last_nal->slc->delta_pic_order_cnt_bottom))) { ret = 1; + reason++; + printf("C: Reason: %d, %d, %d\n", res, nal->slc->pic_order_cnt_lsb, last_nal->slc->pic_order_cnt_lsb); } if (nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 1 && last_nal->sps->pic_order_cnt_type == 1 @@ -1091,15 +1100,18 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) || nal->slc->delta_pic_order_cnt[1] != last_nal->slc->delta_pic_order_cnt[1]))) { ret = 1; + reason++; } if (nal->nal_unit_type != last_nal->nal_unit_type && (nal->nal_unit_type == 5 || last_nal->nal_unit_type == 5)) { ret = 1; + reason++; } if (nal->slc && last_nal->slc && (nal->nal_unit_type == 5 && last_nal->nal_unit_type == 5 && nal->slc->idr_pic_id != last_nal->slc->idr_pic_id)) { ret = 1; + reason++; } if (parser->current_nal == parser->nal0) { @@ -1129,7 +1141,7 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) return 2; } - return 1; + return 0; } int seek_for_nal(uint8_t *buf, int buf_len) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index f80396ff5..1d988eeeb 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -75,9 +75,6 @@ typedef struct vdpau_h264_decoder_s { VdpPictureInfoH264 vdp_picture_info; vdpau_accel_t *vdpau_accel; - VdpReferenceFrameH264 reference_frames[16]; - int reference_frames_used; - xine_t *xine; } vdpau_h264_decoder_t; @@ -93,34 +90,34 @@ typedef struct vdpau_h264_decoder_s { static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) { - printf("slice_count: %d\n", pic->slice_count); - printf("field_order_cnt[0]: %d\n", pic->field_order_cnt[0]); - printf("field_order_cnt[1]: %d\n", pic->field_order_cnt[1]); - printf("is_reference: %d\n", pic->is_reference); - printf("frame_num: %d\n", pic->frame_num); - printf("field_pic_flag: %d\n", pic->field_pic_flag); - printf("bottom_field_flag: %d\n", pic->bottom_field_flag); - printf("num_ref_frames: %d\n", pic->num_ref_frames); - printf("mb_adaptive_frame_field_flag: %d\n", pic->mb_adaptive_frame_field_flag); - printf("constrained_intra_pred_flag: %d\n", pic->constrained_intra_pred_flag); - printf("weighted_pred_flag: %d\n", pic->weighted_pred_flag); - printf("weighted_bipred_idc: %d\n", pic->weighted_bipred_idc); - printf("frame_mbs_only_flag: %d\n", pic->frame_mbs_only_flag); - printf("transform_8x8_mode_flag: %d\n", pic->transform_8x8_mode_flag); - printf("chroma_qp_index_offset: %d\n", pic->chroma_qp_index_offset); - printf("second_chroma_qp_index_offset: %d\n", pic->second_chroma_qp_index_offset); - printf("pic_init_qp_minus26: %d\n", pic->pic_init_qp_minus26); - printf("num_ref_idx_l0_active_minus1: %d\n", pic->num_ref_idx_l0_active_minus1); - printf("num_ref_idx_l1_active_minus1: %d\n", pic->num_ref_idx_l1_active_minus1); - printf("log2_max_frame_num_minus4: %d\n", pic->log2_max_frame_num_minus4); - printf("pic_order_cnt_type: %d\n", pic->pic_order_cnt_type); - printf("log2_max_pic_order_cnt_lsb_minus4: %d\n", pic->log2_max_pic_order_cnt_lsb_minus4); - printf("delta_pic_order_always_zero_flag: %d\n", pic->delta_pic_order_always_zero_flag); - printf("direct_8x8_inference_flag: %d\n", pic->direct_8x8_inference_flag); - printf("entropy_coding_mode_flag: %d\n", pic->entropy_coding_mode_flag); - printf("pic_order_present_flag: %d\n", pic->pic_order_present_flag); - printf("deblocking_filter_control_present_flag: %d\n", pic->deblocking_filter_control_present_flag); - printf("redundant_pic_cnt_present_flag: %d\n", pic->redundant_pic_cnt_present_flag); + printf("C: slice_count: %d\n", pic->slice_count); + printf("C: field_order_cnt[0]: %d\n", pic->field_order_cnt[0]); + printf("C: field_order_cnt[1]: %d\n", pic->field_order_cnt[1]); + printf("C: is_reference: %d\n", pic->is_reference); + printf("C: frame_num: %d\n", pic->frame_num); + printf("C: field_pic_flag: %d\n", pic->field_pic_flag); + printf("C: bottom_field_flag: %d\n", pic->bottom_field_flag); + printf("C: num_ref_frames: %d\n", pic->num_ref_frames); + printf("C: mb_adaptive_frame_field_flag: %d\n", pic->mb_adaptive_frame_field_flag); + printf("C: constrained_intra_pred_flag: %d\n", pic->constrained_intra_pred_flag); + printf("C: weighted_pred_flag: %d\n", pic->weighted_pred_flag); + printf("C: weighted_bipred_idc: %d\n", pic->weighted_bipred_idc); + printf("C: frame_mbs_only_flag: %d\n", pic->frame_mbs_only_flag); + printf("C: transform_8x8_mode_flag: %d\n", pic->transform_8x8_mode_flag); + printf("C: chroma_qp_index_offset: %d\n", pic->chroma_qp_index_offset); + printf("C: second_chroma_qp_index_offset: %d\n", pic->second_chroma_qp_index_offset); + printf("C: pic_init_qp_minus26: %d\n", pic->pic_init_qp_minus26); + printf("C: num_ref_idx_l0_active_minus1: %d\n", pic->num_ref_idx_l0_active_minus1); + printf("C: num_ref_idx_l1_active_minus1: %d\n", pic->num_ref_idx_l1_active_minus1); + printf("C: log2_max_frame_num_minus4: %d\n", pic->log2_max_frame_num_minus4); + printf("C: pic_order_cnt_type: %d\n", pic->pic_order_cnt_type); + printf("C: log2_max_pic_order_cnt_lsb_minus4: %d\n", pic->log2_max_pic_order_cnt_lsb_minus4); + printf("C: delta_pic_order_always_zero_flag: %d\n", pic->delta_pic_order_always_zero_flag); + printf("C: direct_8x8_inference_flag: %d\n", pic->direct_8x8_inference_flag); + printf("C: entropy_coding_mode_flag: %d\n", pic->entropy_coding_mode_flag); + printf("C: pic_order_present_flag: %d\n", pic->pic_order_present_flag); + printf("C: deblocking_filter_control_present_flag: %d\n", pic->deblocking_filter_control_present_flag); + printf("C: redundant_pic_cnt_present_flag: %d\n", pic->redundant_pic_cnt_present_flag); /*int i, j; for(i = 0; i < 6; i++) { @@ -145,16 +142,17 @@ static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) int i; for(i = 0; i < 16; i++) { if(pic->referenceFrames[i].surface != VDP_INVALID_HANDLE) { - printf("-------------------\n"); - printf("Reference Frame %d:\n", i); - printf("frame_idx: %d\n", pic->referenceFrames[i].frame_idx); - printf("field_order_cnt[0]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); - printf("field_order_cnt[1]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); - printf("is_long_term: %d\n", pic->referenceFrames[i].is_long_term); - printf("top_is_reference: %d\n", pic->referenceFrames[i].top_is_reference); - printf("bottom_is_reference: %d\n", pic->referenceFrames[i].bottom_is_reference); + printf("C: -------------------\n"); + printf("C: Reference Frame %d:\n", i); + printf("C: frame_idx: %d\n", pic->referenceFrames[i].frame_idx); + printf("C: field_order_cnt[0]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); + printf("C: field_order_cnt[1]: %d\n", pic->referenceFrames[i].field_order_cnt[0]); + printf("C: is_long_term: %d\n", pic->referenceFrames[i].is_long_term); + printf("C: top_is_reference: %d\n", pic->referenceFrames[i].top_is_reference); + printf("C: bottom_is_reference: %d\n", pic->referenceFrames[i].bottom_is_reference); } } + printf("C: ---------------------------------------------------------------\n"); /*memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, 6*16); memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, 2*64); memcpy(pic.referenceFrames, this->reference_frames, sizeof(this->reference_frames));*/ @@ -305,7 +303,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic.scaling_lists_8x8)); fill_vdpau_reference_list(&(this->nal_parser->dpb), pic.referenceFrames); - //memcpy(pic.referenceFrames, this->reference_frames, sizeof(pic.referenceFrames)); if(this->decoder_started || pic.is_reference) { if(!this->decoder_started) @@ -455,9 +452,6 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->nal_parser = init_parser(); this->buf = NULL; - memset(this->reference_frames, VDP_INVALID_HANDLE, sizeof(this->reference_frames)); - this->reference_frames_used = 0; - return &this->video_decoder; } -- cgit v1.2.3 From adb82413dc9e704d644b237928c4a7d89708fbb7 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 8 Dec 2008 20:35:46 +0000 Subject: NAL WIP. --- src/libvdpau/h264_parser.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index c888d9e1d..555c253b7 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -961,12 +961,13 @@ void free_parser(struct nal_parser *parser) int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) { - int next_nal; + int next_nal, second_next_nal; int parsed_len = 0; int search_offset = 0; while ((next_nal - = seek_for_nal(inbuf + search_offset, inbuf_len - parsed_len)) >= 0) { + = seek_for_nal(inbuf + search_offset, inbuf_len - parsed_len)) >= 0 && + (second_next_nal = seek_for_nal(inbuf + next_nal + 3, inbuf_len - parsed_len - next_nal - 3)) >= 0) { // save buffer up to the nal-start if (parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) { printf("buf underrun!!\n"); -- cgit v1.2.3 From c4727f4f60e417012be20404930291c8a810a9ab Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 9 Dec 2008 10:30:41 +0000 Subject: Add vdpau_mpeg12. --- src/libvdpau/Makefile.am | 9 +- src/libvdpau/vdpau_mpeg12.c | 644 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 652 insertions(+), 1 deletion(-) create mode 100644 src/libvdpau/vdpau_mpeg12.c diff --git a/src/libvdpau/Makefile.am b/src/libvdpau/Makefile.am index 6cbce1016..5c372dabc 100644 --- a/src/libvdpau/Makefile.am +++ b/src/libvdpau/Makefile.am @@ -6,10 +6,17 @@ AM_LDFLAGS = $(xineplug_ldflags) if HAVE_VDPAU vdpau_h264_module = xineplug_decode_vdpau_h264.la VDPAU_CFLAGS = -D_ISOC99_SOURCE + +vdpau_mpeg12_module = xineplug_decode_vdpau_mpeg12.la endif -xineplug_LTLIBRARIES = $(vdpau_h264_module) +xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c h264_parser.c vdpau_h264.c xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS) xineplug_decode_vdpau_h264_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) + +xineplug_decode_vdpau_mpeg12_la_SOURCES = vdpau_mpeg12.c +xineplug_decode_vdpau_mpeg12_la_CFLAGS = $(AM_CFLAGS) +xineplug_decode_vdpau_mpeg12_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) + diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c new file mode 100644 index 000000000..2f62a6f93 --- /dev/null +++ b/src/libvdpau/vdpau_mpeg12.c @@ -0,0 +1,644 @@ +/* + * Copyright (C) 2008 Christophe Thommeret + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * vdpau_mpeg12.c, a mpeg1/2 video stream parser using VDPAU hardware decoder + * + */ + +#include +#include +#include +#include +#include + +#include "xine_internal.h" +#include "video_out.h" +#include "buffer.h" +#include "xineutils.h" +#include "accel_vdpau.h" + +#include + + + +#define sequence_header_code 0xb3 +#define sequence_error_code 0xb4 +#define sequence_end_code 0xb7 +#define group_start_code 0xb8 +#define extension_start_code 0xb5 +#define user_data_start_code 0xb2 +#define picture_start_code 0x00 +#define begin_slice_start_code 0x01 +#define end_slice_start_code 0xaf + +#define I_FRAME 1 +#define P_FRAME 2 +#define B_FRAME 3 + +#define WANT_HEADER 1 +#define WANT_EXT 2 +#define WANT_SLICE 3 + + + +/* default intra quant matrix, in zig-zag order */ +static const uint8_t default_intra_quantizer_matrix[64] = { + 8, + 16, 16, + 19, 16, 19, + 22, 22, 22, 22, + 22, 22, 26, 24, 26, + 27, 27, 27, 26, 26, 26, + 26, 27, 27, 27, 29, 29, 29, + 34, 34, 34, 29, 29, 29, 27, 27, + 29, 29, 32, 32, 34, 34, 37, + 38, 37, 35, 35, 34, 35, + 38, 38, 40, 40, 40, + 48, 48, 46, 46, + 56, 56, 58, + 69, 69, + 83 +}; + + +typedef struct { + VdpPictureInfoMPEG1Or2 vdp_infos; + int slices_count; + uint8_t *slices; + int slices_size; + int slices_pos; + + int64_t pts; + + int state; +} picture_t; + + + +typedef struct { + uint32_t coded_width; + uint32_t coded_height; + uint32_t display_width; + uint32_t display_height; + uint64_t video_step; /* frame duration in pts units */ + double ratio; + + uint8_t intra_quant_matrix[64]; + uint8_t non_intra_quant_matrix[64]; + + int have_header; + + uint8_t *buf; /* accumulate data */ + int bufseek; + uint32_t bufsize; + uint32_t bufpos; + int start; + + picture_t picture; + vo_frame_t *forward_ref; + + int64_t pts; +} sequence_t; + + +typedef struct { + video_decoder_class_t decoder_class; +} vdpau_mpeg12_class_t; + + +typedef struct foovideo_decoder_s { + video_decoder_t video_decoder; /* parent video decoder structure */ + + vdpau_mpeg12_class_t *class; + xine_stream_t *stream; + + sequence_t sequence; + + VdpDecoder decoder; + +} vdpau_mpeg12_decoder_t; + + + +static void reset_picture( picture_t *pic ) +{ + pic->slices_count = 0; + pic->slices_pos = 0; + pic->pts = 0; + pic->state = WANT_HEADER; +} + + + +static void init_picture( picture_t *pic ) +{ + pic->slices_size = 2048; + pic->slices = (uint8_t*)malloc(pic->slices_size); + reset_picture( pic ); +} + + + +static void reset_sequence( sequence_t *sequence ) +{ + sequence->have_header = 0; + sequence->bufpos = 0; + sequence->bufseek = 0; + sequence->start = -1; + xine_fast_memcpy( sequence->intra_quant_matrix, &default_intra_quantizer_matrix, 64 ); + memset( sequence->non_intra_quant_matrix, 16, 64 ); + if ( sequence->forward_ref ) + sequence->forward_ref->free( sequence->forward_ref ); + sequence->forward_ref = 0; +} + + + +static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) +{ + int i, nbytes; + uint32_t ret = 0; + uint8_t *buf; + + buf = b+(offbits/8); + offbits %=8; + nbytes = (offbits+nbits)/8; + if ( ((offbits+nbits)%8)>0 ) + nbytes++; + for ( i=0; i>i)>>((nbytes*8)-nbits-offbits); + + return ret; +} + + + +static void sequence_header( sequence_t *sequence, uint8_t *buf, int len ) +{ + int i, j, off=0; + sequence->coded_width = get_bits( buf,0,12 ); + sequence->coded_height = get_bits( buf,12,12 ); + switch ( get_bits( buf+3,0,4 ) ) { + case 2: sequence->ratio = 4.0/3.0; break; + case 3: sequence->ratio = 16.0/9.0; break; + case 4: sequence->ratio = 2.21; break; + } + //printf( "frame_rate_code: %d\n", get_bits( buf+3,4,4 ) ); + //printf( "bit_rate_value: %d\n", get_bits( buf+4,0,18 ) ); + //printf( "marker_bit: %d\n", get_bits( buf+6,2,1 ) ); + //printf( "vbv_buffer_size_value: %d\n", get_bits( buf+6,3,10 ) ); + //printf( "constrained_parameters_flag: %d\n", get_bits( buf+7,5,1 ) ); + i = get_bits( buf+7,6,1 ); + if ( i ) { + for ( j=0; j<64; ++j ) { + sequence->intra_quant_matrix[j] = get_bits( buf+7+j,7,8 ); + } + off = 64; + } + //printf( "load_intra_quantizer_matrix: %d\n", i ); + i = get_bits( buf+7+off,7,1 ); + //printf( "load_non_intra_quantizer_matrix: %d\n", i ); + if ( i ) { + for ( j=0; j<64; ++j ) { + sequence->non_intra_quant_matrix[j] = get_bits( buf+8+off+j,0,8 ); + } + } + sequence->have_header = 1; +} + + + +static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) +{ + int i = get_bits( buf,10,3 ); + printf( "!!!!!!!!!!!!!!! picture type : %d !!!!!!!!!!!!!!!!!!!!!!!!!!\n", i ); + if ( (i!=I_FRAME && i!=P_FRAME) || sequence->picture.state!=WANT_HEADER ) + return; + reset_picture( &sequence->picture ); + sequence->picture.vdp_infos.picture_coding_type = i; + sequence->picture.vdp_infos.forward_reference = VDP_INVALID_HANDLE; + sequence->picture.vdp_infos.backward_reference = VDP_INVALID_HANDLE; + sequence->picture.vdp_infos.full_pel_forward_vector = 0; + sequence->picture.vdp_infos.full_pel_backward_vector = 0; + sequence->picture.state = WANT_EXT; + //printf( "temporal_reference: %d\n", get_bits( buf,0,10 ) ); + //printf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) ); +} + + + +static void sequence_extension( uint8_t *buf, int len ) +{ + printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); + printf( "profile_and_level_indication: %d\n", get_bits( buf,4,8 ) ); + printf( "progressive_sequence: %d\n", get_bits( buf,12,1 ) ); + printf( "chroma_format: %d\n", get_bits( buf,13,2 ) ); + printf( "horizontal_size_extension: %d\n", get_bits( buf,15,2 ) ); + printf( "vertical_size_extension: %d\n", get_bits( buf,17,2 ) ); + printf( "bit_rate_extension: %d\n", get_bits( buf,19,12 ) ); + printf( "marker_bit: %d\n", get_bits( buf,31,1 ) ); + printf( "vbv_buffer_size_extension: %d\n", get_bits( buf+4,0,8 ) ); + printf( "low_delay: %d\n", get_bits( buf+5,0,1 ) ); + printf( "frame_rate_extension_n: %d\n", get_bits( buf+5,1,2 ) ); + printf( "frame_rate_extension_d: %d\n", get_bits( buf+5,3,5 ) ); +} + + + +static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int len ) +{ + if ( sequence->picture.state!=WANT_EXT ) + return; + sequence->picture.vdp_infos.f_code[0][0] = get_bits( buf,4,4 ); + sequence->picture.vdp_infos.f_code[0][1] = get_bits( buf,8,4 ); + sequence->picture.vdp_infos.f_code[1][0] = get_bits( buf,12,4 ); + sequence->picture.vdp_infos.f_code[1][1] = get_bits( buf,16,4 ); + //printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); + //printf( "f_code_0_0: %d\n", get_bits( buf,4,4 ) ); + //printf( "f_code_0_1: %d\n", get_bits( buf,8,4 ) ); + //printf( "f_code_1_0: %d\n", get_bits( buf,12,4 ) ); + //printf( "f_code_1_1: %d\n", get_bits( buf,16,4 ) ); + sequence->picture.vdp_infos.intra_dc_precision = get_bits( buf,20,2 ); + //printf( "intra_dc_precision: %d\n", get_bits( buf,20,2 ) ); + sequence->picture.vdp_infos.picture_structure = get_bits( buf,22,2 ); + //printf( "picture_structure: %d\n", get_bits( buf,22,2 ) ); + sequence->picture.vdp_infos.top_field_first = get_bits( buf,24,1 ); + //printf( "top_field_first: %d\n", get_bits( buf,24,1 ) ); + sequence->picture.vdp_infos.frame_pred_frame_dct = get_bits( buf,25,1 ); + //printf( "frame_pred_frame_dct: %d\n", get_bits( buf,25,1 ) ); + sequence->picture.vdp_infos.concealment_motion_vectors = get_bits( buf,26,1 ); + //printf( "concealment_motion_vectors: %d\n", get_bits( buf,26,1 ) ); + sequence->picture.vdp_infos.q_scale_type = get_bits( buf,27,1 ); + //printf( "q_scale_type: %d\n", get_bits( buf,27,1 ) ); + sequence->picture.vdp_infos.intra_vlc_format = get_bits( buf,28,1 ); + //printf( "intra_vlc_format: %d\n", get_bits( buf,28,1 ) ); + sequence->picture.vdp_infos.alternate_scan = get_bits( buf,29,1 ); + //printf( "alternate_scan: %d\n", get_bits( buf,29,1 ) ); + //printf( "repeat_first_field: %d\n", get_bits( buf,30,1 ) ); + //printf( "chroma_420_type: %d\n", get_bits( buf,31,1 ) ); + //printf( "progressive_frame: %d\n", get_bits( buf,32,1 ) ); + sequence->picture.state = WANT_SLICE; +} + + + +static void copy_slice( sequence_t *sequence, uint8_t *buf, int len ) +{ + int size = sequence->picture.slices_pos+len; + if ( sequence->picture.slices_size < size ) { + sequence->picture.slices_size = size+1024; + sequence->picture.slices = realloc( sequence->picture.slices, sequence->picture.slices_size ); + } + xine_fast_memcpy( sequence->picture.slices+sequence->picture.slices_pos, buf, len ); + sequence->picture.slices_pos += len; + sequence->picture.slices_count++; +} + + + +static void quant_matrix_extension( uint8_t *buf, int len ) +{ +} + + + +static int parse_code( sequence_t *sequence, uint8_t *buf, int len ) +{ + if ( !sequence->have_header && buf[3]!=sequence_header_code ) + return 0; + + if ( (buf[3] >= begin_slice_start_code) && (buf[3] <= end_slice_start_code) ) { + if ( sequence->picture.state==WANT_SLICE ) + copy_slice( sequence, buf, len ); + return 0; + //printf( " ----------- slice_start_code: %d\n", i+3 ); + } + else if ( sequence->picture.state==WANT_SLICE ) { + /* no more slices, decode */ + return 1; + } + + switch ( buf[3] ) { + case sequence_header_code: + printf( " ----------- sequence_header_code\n" ); + sequence_header( sequence, buf+4, len-4 ); + break; + case extension_start_code: { + switch ( get_bits( buf+4,0,4 ) ) { + case 1: + printf( " ----------- sequence_extension_start_code\n" ); + sequence_extension( buf+4, len-4 ); + break; + case 3: + printf( " ----------- quant_matrix_extension_start_code\n" ); + quant_matrix_extension( buf+4, len-4 ); + break; + case 8: + printf( " ----------- picture_coding_extension_start_code\n" ); + picture_coding_extension( sequence, buf+4, len-4 ); + break; + } + break; + } + case user_data_start_code: + printf( " ----------- user_data_start_code\n" ); + break; + case group_start_code: + printf( " ----------- group_start_code\n" ); + break; + case picture_start_code: + printf( " ----------- picture_start_code\n" ); + //slice_count = 0; + picture_header( sequence, buf+4, len-4 ); + break; + case sequence_error_code: + printf( " ----------- sequence_error_code\n" ); + break; + case sequence_end_code: + printf( " ----------- sequence_end_code\n" ); + break; + } + return 0; +} + + + +static void decode_picture( vdpau_mpeg12_decoder_t *vd ) +{ + sequence_t *seq = (sequence_t*)&vd->sequence; + picture_t *pic = (picture_t*)&seq->picture; + + if ( seq->forward_ref && pic->vdp_infos.picture_coding_type==P_FRAME ) { + vdpau_accel_t *back_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; + pic->vdp_infos.forward_reference = back_accel->surface; + } + pic->vdp_infos.slice_count = pic->slices_count; + xine_fast_memcpy( &pic->vdp_infos.intra_quantizer_matrix, &seq->intra_quant_matrix, 64 ); + xine_fast_memcpy( &pic->vdp_infos.non_intra_quantizer_matrix, &seq->non_intra_quant_matrix, 64 ); + pic->state = WANT_HEADER; + vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, + seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + VdpStatus st; + if ( vd->decoder==VDP_INVALID_HANDLE ) { + st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, seq->coded_width, seq->coded_height, &vd->decoder); + if ( st!=VDP_STATUS_OK ) + printf( "vdpau_mpeg12: failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); + } + if ( accel->surface==VDP_INVALID_HANDLE ) { + st = accel->vdp_video_surface_create( accel->vdp_device, VDP_CHROMA_TYPE_420, seq->coded_width, seq->coded_height, &accel->surface); + if ( st!=VDP_STATUS_OK ) + printf( "vdpau_mpeg12: failed to create surface !! %s\n", accel->vdp_get_error_string( st ) ); + } + VdpBitstreamBuffer vbit; + vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit.bitstream = seq->picture.slices; + vbit.bitstream_bytes = seq->picture.slices_pos; + st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); + if ( st!=VDP_STATUS_OK ) + printf( "vdpau_mpeg12: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); + else + printf( "vdpau_mpeg12: DECODER SUCCESS !! \n" ); + + //img->duration = 3600; + img->pts = seq->pts; + img->bad_frame = 0; + img->draw( img, vd->stream ); + + if ( seq->forward_ref ) + seq->forward_ref->free( seq->forward_ref ); + seq->forward_ref = img; +} + + + +/* + * This function receives a buffer of data from the demuxer layer and + * figures out how to handle it based on its header flags. + */ +static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { + + vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; + sequence_t *seq = (sequence_t*)&this->sequence; + + /* a video decoder does not care about this flag (?) */ + if (buf->decoder_flags & BUF_FLAG_PREVIEW) + return; + + if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { + //this->video_step = buf->decoder_info[0]; + //_x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); + } + + if ( buf->pts ) { + seq->pts = buf->pts; + //printf("vdpau_mpeg12_decode_data: new pts : %lld\n", buf->pts ); + } + + int size = seq->bufpos+buf->size; + if ( seq->bufsize < size ) { + seq->bufsize = size+1024; + seq->buf = realloc( seq->buf, seq->bufsize ); + printf("sequence buffer realloced = %d\n", seq->bufsize ); + } + xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size ); + seq->bufpos += buf->size; + + while ( seq->bufseek < seq->bufpos-4 ) { + uint8_t *buf = seq->buf+seq->bufseek; + if ( buf[0]==0 && buf[1]==0 && buf[2]==1 ) { + if ( seq->start<0 ) { + seq->start = seq->bufseek; + } + else { + if ( parse_code( seq, seq->buf+seq->start, seq->bufseek-seq->start ) ) { + decode_picture( this ); + //seq->pts += 3600; + parse_code( seq, seq->buf+seq->start, seq->bufseek-seq->start ); + } + uint8_t *tmp = (uint8_t*)malloc(seq->bufsize); + xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek ); + seq->bufpos -= seq->bufseek; + seq->start = -1; + seq->bufseek = -1; + free( seq->buf ); + seq->buf = tmp; + } + } + ++seq->bufseek; + } + +} + +/* + * This function is called when xine needs to flush the system. + */ +static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { +} + +/* + * This function resets the video decoder. + */ +static void vdpau_mpeg12_reset (video_decoder_t *this_gen) { + vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; + + //this->size = 0; +} + +/* + * The decoder should forget any stored pts values here. + */ +static void vdpau_mpeg12_discontinuity (video_decoder_t *this_gen) { + vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; + +} + +/* + * This function frees the video decoder instance allocated to the decoder. + */ +static void vdpau_mpeg12_dispose (video_decoder_t *this_gen) { + + vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; + + /*if (this->buf) { + free (this->buf); + this->buf = NULL; + } + + if (this->decoder_ok) { + this->decoder_ok = 0; + this->stream->video_out->close(this->stream->video_out, this->stream); + }*/ + + free( this->sequence.picture.slices ); + free( this->sequence.buf ); + free( this_gen ); +} + +/* + * This function allocates, initializes, and returns a private video + * decoder structure. + */ +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { + + vdpau_mpeg12_decoder_t *this ; + + /* the videoout must be vdpau-capable to support this decoder */ + if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_MPEG12) ) + return NULL; + + this = (vdpau_mpeg12_decoder_t *) calloc(1, sizeof(vdpau_mpeg12_decoder_t)); + + this->video_decoder.decode_data = vdpau_mpeg12_decode_data; + this->video_decoder.flush = vdpau_mpeg12_flush; + this->video_decoder.reset = vdpau_mpeg12_reset; + this->video_decoder.discontinuity = vdpau_mpeg12_discontinuity; + this->video_decoder.dispose = vdpau_mpeg12_dispose; + + this->stream = stream; + this->class = (vdpau_mpeg12_class_t *) class_gen; + + this->sequence.bufsize = 1024; + this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize); + this->sequence.forward_ref = 0; + reset_sequence( &this->sequence ); + + init_picture( &this->sequence.picture ); + + this->decoder = VDP_INVALID_HANDLE; + + return &this->video_decoder; +} + +/* + * This function returns a brief string that describes (usually with the + * decoder's most basic name) the video decoder plugin. + */ +static char *get_identifier (video_decoder_class_t *this) { + return "vdpau_mpeg12"; +} + +/* + * This function returns a slightly longer string describing the video + * decoder plugin. + */ +static char *get_description (video_decoder_class_t *this) { + return "vdpau_mpeg12: mpeg1/2 decoder plugin using VDPAU hardware decoding.\n" + "Must be used along with video_out_vdpau."; +} + +/* + * This function frees the video decoder class and any other memory that was + * allocated. + */ +static void dispose_class (video_decoder_class_t *this) { + free (this); +} + +/* + * This function allocates a private video decoder class and initializes + * the class's member functions. + */ +static void *init_plugin (xine_t *xine, void *data) { + + vdpau_mpeg12_class_t *this; + + this = (vdpau_mpeg12_class_t *) calloc(1, sizeof(vdpau_mpeg12_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; + + return this; +} + +/* + * This is a list of all of the internal xine video buffer types that + * this decoder is able to handle. Check src/xine-engine/buffer.h for a + * list of valid buffer types (and add a new one if the one you need does + * not exist). Terminate the list with a 0. + */ +static const uint32_t video_types[] = { + BUF_VIDEO_MPEG, + 0 +}; + +/* + * This data structure combines the list of supported xine buffer types and + * the priority that the plugin should be given with respect to other + * plugins that handle the same buffer type. A plugin with priority (n+1) + * will be used instead of a plugin with priority (n). + */ +static const decoder_info_t dec_info_video = { + video_types, /* supported types */ + 8 /* priority */ +}; + +/* + * The plugin catalog entry. This is the only information that this plugin + * will export to the public. + */ +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* { type, API, "name", version, special_info, init_function } */ + { PLUGIN_VIDEO_DECODER, 18, "vdpau_mpeg12", XINE_VERSION_CODE, &dec_info_video, init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; -- cgit v1.2.3 From 4f0ed8bccfeec21407f48a23a87fd7d4b704cd45 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 9 Dec 2008 16:55:37 +0000 Subject: Decode I, P and B frames (PTS reordering still missing). --- src/libvdpau/vdpau_mpeg12.c | 78 ++++++++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 25 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 2f62a6f93..ab4312d59 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -112,6 +112,7 @@ typedef struct { picture_t picture; vo_frame_t *forward_ref; + vo_frame_t *backward_ref; int64_t pts; } sequence_t; @@ -122,7 +123,7 @@ typedef struct { } vdpau_mpeg12_class_t; -typedef struct foovideo_decoder_s { +typedef struct vdpau_mpeg12_decoder_s { video_decoder_t video_decoder; /* parent video decoder structure */ vdpau_mpeg12_class_t *class; @@ -166,6 +167,9 @@ static void reset_sequence( sequence_t *sequence ) if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); sequence->forward_ref = 0; + if ( sequence->backward_ref ) + sequence->backward_ref->free( sequence->backward_ref ); + sequence->backward_ref = 0; } @@ -229,8 +233,8 @@ static void sequence_header( sequence_t *sequence, uint8_t *buf, int len ) static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) { int i = get_bits( buf,10,3 ); - printf( "!!!!!!!!!!!!!!! picture type : %d !!!!!!!!!!!!!!!!!!!!!!!!!!\n", i ); - if ( (i!=I_FRAME && i!=P_FRAME) || sequence->picture.state!=WANT_HEADER ) + //printf( "!!!!!!!!!!!!!!! picture type : %d !!!!!!!!!!!!!!!!!!!!!!!!!!\n", i ); + if ( /*i==B_FRAME ||*/ sequence->picture.state!=WANT_HEADER ) return; reset_picture( &sequence->picture ); sequence->picture.vdp_infos.picture_coding_type = i; @@ -247,7 +251,7 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) static void sequence_extension( uint8_t *buf, int len ) { - printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); + /*printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); printf( "profile_and_level_indication: %d\n", get_bits( buf,4,8 ) ); printf( "progressive_sequence: %d\n", get_bits( buf,12,1 ) ); printf( "chroma_format: %d\n", get_bits( buf,13,2 ) ); @@ -258,7 +262,7 @@ static void sequence_extension( uint8_t *buf, int len ) printf( "vbv_buffer_size_extension: %d\n", get_bits( buf+4,0,8 ) ); printf( "low_delay: %d\n", get_bits( buf+5,0,1 ) ); printf( "frame_rate_extension_n: %d\n", get_bits( buf+5,1,2 ) ); - printf( "frame_rate_extension_d: %d\n", get_bits( buf+5,3,5 ) ); + printf( "frame_rate_extension_d: %d\n", get_bits( buf+5,3,5 ) );*/ } @@ -338,42 +342,42 @@ static int parse_code( sequence_t *sequence, uint8_t *buf, int len ) switch ( buf[3] ) { case sequence_header_code: - printf( " ----------- sequence_header_code\n" ); + //printf( " ----------- sequence_header_code\n" ); sequence_header( sequence, buf+4, len-4 ); break; case extension_start_code: { switch ( get_bits( buf+4,0,4 ) ) { case 1: - printf( " ----------- sequence_extension_start_code\n" ); + //printf( " ----------- sequence_extension_start_code\n" ); sequence_extension( buf+4, len-4 ); break; case 3: - printf( " ----------- quant_matrix_extension_start_code\n" ); + //printf( " ----------- quant_matrix_extension_start_code\n" ); quant_matrix_extension( buf+4, len-4 ); break; case 8: - printf( " ----------- picture_coding_extension_start_code\n" ); + //printf( " ----------- picture_coding_extension_start_code\n" ); picture_coding_extension( sequence, buf+4, len-4 ); break; } break; } case user_data_start_code: - printf( " ----------- user_data_start_code\n" ); + //printf( " ----------- user_data_start_code\n" ); break; case group_start_code: - printf( " ----------- group_start_code\n" ); + //printf( " ----------- group_start_code\n" ); break; case picture_start_code: - printf( " ----------- picture_start_code\n" ); + //printf( " ----------- picture_start_code\n" ); //slice_count = 0; picture_header( sequence, buf+4, len-4 ); break; case sequence_error_code: - printf( " ----------- sequence_error_code\n" ); + //printf( " ----------- sequence_error_code\n" ); break; case sequence_end_code: - printf( " ----------- sequence_end_code\n" ); + //printf( " ----------- sequence_end_code\n" ); break; } return 0; @@ -385,11 +389,26 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) { sequence_t *seq = (sequence_t*)&vd->sequence; picture_t *pic = (picture_t*)&seq->picture; - - if ( seq->forward_ref && pic->vdp_infos.picture_coding_type==P_FRAME ) { - vdpau_accel_t *back_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; - pic->vdp_infos.forward_reference = back_accel->surface; + vdpau_accel_t *ref_accel; + + if ( pic->vdp_infos.picture_coding_type==P_FRAME ) { + if ( seq->backward_ref ) + ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; + else + ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; + pic->vdp_infos.forward_reference = ref_accel->surface; } + else if ( pic->vdp_infos.picture_coding_type==B_FRAME ) { + if ( seq->forward_ref ) { + ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; + pic->vdp_infos.forward_reference = ref_accel->surface; + } + if ( seq->backward_ref ) { + ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; + pic->vdp_infos.backward_reference = ref_accel->surface; + } + } + pic->vdp_infos.slice_count = pic->slices_count; xine_fast_memcpy( &pic->vdp_infos.intra_quantizer_matrix, &seq->intra_quant_matrix, 64 ); xine_fast_memcpy( &pic->vdp_infos.non_intra_quantizer_matrix, &seq->non_intra_quant_matrix, 64 ); @@ -416,16 +435,24 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) if ( st!=VDP_STATUS_OK ) printf( "vdpau_mpeg12: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else - printf( "vdpau_mpeg12: DECODER SUCCESS !! \n" ); + printf( "vdpau_mpeg12: DECODER SUCCESS : frame_type:%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.picture_coding_type, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->pts ); + + //printf( "vdpau_meg12: forwref:%d, backref:%d\n", seq->forward_ref, seq->backward_ref ); //img->duration = 3600; img->pts = seq->pts; img->bad_frame = 0; - img->draw( img, vd->stream ); - - if ( seq->forward_ref ) - seq->forward_ref->free( seq->forward_ref ); - seq->forward_ref = img; + //if ( pic->vdp_infos.picture_coding_type==B_FRAME ) + img->draw( img, vd->stream ); + + if ( pic->vdp_infos.picture_coding_type!=B_FRAME ) { + if ( seq->forward_ref ) + seq->forward_ref->free( seq->forward_ref ); + seq->forward_ref = seq->backward_ref; + seq->backward_ref = img; + } + else + img->free( img ); } @@ -457,7 +484,7 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * if ( seq->bufsize < size ) { seq->bufsize = size+1024; seq->buf = realloc( seq->buf, seq->bufsize ); - printf("sequence buffer realloced = %d\n", seq->bufsize ); + //printf("sequence buffer realloced = %d\n", seq->bufsize ); } xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size ); seq->bufpos += buf->size; @@ -559,6 +586,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->sequence.bufsize = 1024; this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize); this->sequence.forward_ref = 0; + this->sequence.backward_ref = 0; reset_sequence( &this->sequence ); init_picture( &this->sequence.picture ); -- cgit v1.2.3 From 7a50f9ae0c9f3c5c7c2872810506fbbe74aaa717 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 9 Dec 2008 18:15:34 +0000 Subject: Fix parsing if a nal header is split across multiple buffers. --- src/libvdpau/h264_parser.c | 152 +++++++++++++++++++++++++++++---------------- src/libvdpau/h264_parser.h | 20 ++++-- 2 files changed, 111 insertions(+), 61 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 555c253b7..4445b5d78 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -51,7 +51,8 @@ void void decode_ref_pic_marking(uint32_t memory_management_control_operation, struct nal_parser *parser); void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); -void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_parser *parser); +void parse_dec_ref_pic_marking(struct buf_reader *buf, + struct nal_parser *parser); /* here goes the parser implementation */ @@ -162,6 +163,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; nal->nal_unit_type = buf->buf[0] & 0x1f; + printf("Unit: %d\n", nal->nal_unit_type); buf->cur_pos = buf->buf + 1; //printf("NAL: %d\n", nal->nal_unit_type); @@ -174,7 +176,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) decode_nal(&ibuf.buf, &ibuf.len, buf->cur_pos, buf->len - 1); ibuf.cur_pos = ibuf.buf; - if(!nal->sps) + if (!nal->sps) nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); @@ -184,7 +186,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) ret = NAL_SPS; break; case NAL_PPS: - if(!nal->pps) + if (!nal->pps) nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); @@ -197,7 +199,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) case NAL_PART_C: case NAL_SLICE_IDR: if (nal->sps && nal->pps) { - if(!nal->slc) + if (!nal->slc) nal->slc = malloc(sizeof(struct slice_header)); memset(nal->slc, 0x00, sizeof(struct slice_header)); @@ -236,13 +238,11 @@ void calculate_pic_order(struct nal_parser *parser) if (slc->pic_order_cnt_lsb < parser->prev_pic_order_cnt_lsb && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb >= max_poc_lsb / 2) - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - + max_poc_lsb; + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb + max_poc_lsb; else if (slc->pic_order_cnt_lsb > parser->prev_pic_order_cnt_lsb && parser->prev_pic_order_cnt_lsb - slc->pic_order_cnt_lsb < -max_poc_lsb / 2) - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - - max_poc_lsb; + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb - max_poc_lsb; else parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; @@ -827,7 +827,7 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, slc->dec_ref_pic_marking.long_term_frame_idx); pic = dpb_get_picture(dpb, pic_num_x); - if(pic) { + if (pic) { if (pic->nal->slc->field_pic_flag == 0) { pic = dpb_get_picture(dpb, pic_num_x); pic->nal->long_term_frame_idx @@ -835,7 +835,8 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, } else printf("FIXME: B Set frame %d to long-term ref\n", pic_num_x); - } else { + } + else { printf("memory_management_control_operation: 3 failed. No such picture."); } @@ -874,7 +875,8 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, } } -void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_parser *parser) +void parse_dec_ref_pic_marking(struct buf_reader *buf, + struct nal_parser *parser) { struct nal_unit *nal = parser->current_nal; struct seq_parameter_set_rbsp *sps = nal->sps; @@ -915,7 +917,8 @@ void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_parser *parser = read_exp_golomb(buf); decode_ref_pic_marking( - slc->dec_ref_pic_marking.memory_management_control_operation, parser); + slc->dec_ref_pic_marking.memory_management_control_operation, + parser); } while (slc->dec_ref_pic_marking.memory_management_control_operation != 0); } @@ -928,7 +931,12 @@ struct nal_parser* init_parser() { struct nal_parser *parser = malloc(sizeof(struct nal_parser)); memset(parser->buf, 0x00, MAX_FRAME_SIZE); + memset(parser->prebuf, 0x00, MAX_FRAME_SIZE); parser->buf_len = 0; + parser->prebuf_len = 0; + parser->incomplete_nal = 0; + parser->next_nal_position = 0; + parser->found_sps = 0; parser->found_pps = 0; parser->nal0 = init_nal_unit(); @@ -961,65 +969,98 @@ void free_parser(struct nal_parser *parser) int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) { - int next_nal, second_next_nal; + int32_t next_nal = 0; int parsed_len = 0; int search_offset = 0; + uint8_t completed_nal = 0; - while ((next_nal - = seek_for_nal(inbuf + search_offset, inbuf_len - parsed_len)) >= 0 && - (second_next_nal = seek_for_nal(inbuf + next_nal + 3, inbuf_len - parsed_len - next_nal - 3)) >= 0) { - // save buffer up to the nal-start - if (parser->buf_len + next_nal + search_offset > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; - } + uint8_t *prebuf = parser->prebuf; + while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset)) >= 0) { + next_nal += search_offset; - if (parser->last_nal_res != 2) { - /* this is a SLICE, keep it in the buffer */ - xine_fast_memcpy(parser->buf + parser->buf_len, inbuf, next_nal - + search_offset); - parser->buf_len += next_nal + search_offset; - } + if(parser->incomplete_nal || completed_nal || next_nal == 0) { - inbuf += next_nal + search_offset; - parsed_len += next_nal + search_offset; + if (parser->prebuf_len + next_nal > MAX_FRAME_SIZE) { + printf("buf underrun!!\n"); + *ret_len = 0; + *ret_buf = NULL; + return parsed_len; + } - parser->last_nal_res = parse_nal(inbuf + 3, inbuf_len - parsed_len, parser); - if (parser->last_nal_res == 1 && parser->buf_len > 0) { - *ret_buf = malloc(parser->buf_len); - xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); - *ret_len = parser->buf_len; - *ret_slice_cnt = parser->slice_cnt; + xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, next_nal); + parser->prebuf_len += next_nal; + parser->incomplete_nal = 0; + + parsed_len += next_nal; + inbuf += next_nal; + + /*int i; + for(i=0; i<5; i++) + printf("0x%02x ", (prebuf+3)[i]); + printf("\n");*/ + parser->last_nal_res = parse_nal(prebuf+3, parser->prebuf_len-3, parser); + if (parser->last_nal_res == 1 && parser->buf_len > 0) { + printf("Frame complete: %d bytes\n", parser->buf_len); + *ret_buf = malloc(parser->buf_len); + xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); + *ret_len = parser->buf_len; + *ret_slice_cnt = parser->slice_cnt; + + calculate_pic_order(parser); + + //memset(parser->buf, 0x00, parser->buf_len); + parser->buf_len = 0; + parser->last_nal_res = 1; + parser->slice_cnt = 1; + + /* this is a SLICE, keep it in the buffer */ + xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); + parser->buf_len += parser->prebuf_len; + parser->prebuf_len = 0; + + if (parser->last_nal->nal_ref_idc) { + if (parser->last_nal->slc != NULL) + parser->prev_pic_order_cnt_lsb + = parser->last_nal->slc->pic_order_cnt_lsb; + parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; + } + return parsed_len; + } - calculate_pic_order(parser); + if (parser->last_nal_res != 2) { + /* this is a SLICE, keep it in the buffer */ + xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); + parser->buf_len += parser->prebuf_len; + } - //memset(parser->buf, 0x00, parser->buf_len); - parser->buf_len = 0; - parser->last_nal_res = 1; - parser->slice_cnt = 0; + parser->prebuf_len = 0; + completed_nal = 1; - if(parser->last_nal->nal_ref_idc) { - if(parser->last_nal->slc != NULL) - parser->prev_pic_order_cnt_lsb = parser->last_nal->slc->pic_order_cnt_lsb; - parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; - } - return parsed_len; + } else { + /* most likely we are at the beginning of the stream here + * which starts not with a nal-boundardy but with some garbage + * -> throw it away + */ + parsed_len += next_nal; + inbuf += next_nal; } + search_offset = 3; } - // no further NAL found, copy the rest of the stream - // into the buffer - xine_fast_memcpy(&parser->buf[parser->buf_len], inbuf, inbuf_len - parsed_len); - parser->buf_len += inbuf_len - parsed_len; + /* if inbuf does not end with the start of a new nal + * copy the left data into prebuf + */ + if(parsed_len < inbuf_len) { + parser->incomplete_nal = 1; + xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len-parsed_len); + parser->prebuf_len += inbuf_len-parsed_len; + parsed_len += inbuf_len-parsed_len; + } - parsed_len += (inbuf_len - parsed_len); *ret_len = 0; *ret_buf = NULL; - return parsed_len; } @@ -1092,7 +1133,8 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) != last_nal->slc->delta_pic_order_cnt_bottom))) { ret = 1; reason++; - printf("C: Reason: %d, %d, %d\n", res, nal->slc->pic_order_cnt_lsb, last_nal->slc->pic_order_cnt_lsb); + printf("C: Reason: %d, %d, %d\n", res, nal->slc->pic_order_cnt_lsb, + last_nal->slc->pic_order_cnt_lsb); } if (nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 1 && last_nal->sps->pic_order_cnt_type == 1 diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index bfd6d3b35..3381cf4c2 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -11,18 +11,26 @@ struct nal_parser { uint8_t buf[MAX_FRAME_SIZE]; - int buf_len; - int found_sps; - int found_pps; - int last_nal_res; + uint32_t buf_len; + + /* prebuf is a ringbuffer */ + uint8_t prebuf[MAX_FRAME_SIZE]; + uint32_t prebuf_len; + uint32_t next_nal_position; + uint8_t incomplete_nal; + + uint8_t found_sps; + uint8_t found_pps; + uint8_t last_nal_res; uint8_t is_idr; int field; /* 0=top, 1=bottom, -1=both */ int slice; int slice_cnt; - int have_top; - int have_frame; + + uint8_t have_top; + uint8_t have_frame; struct nal_unit *nal0; struct nal_unit *nal1; -- cgit v1.2.3 From 1f3c3b344969262aac57cc18b1710c1ec496fd2a Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 10 Dec 2008 11:34:41 +0000 Subject: Header-related bits. --- src/libvdpau/vdpau_mpeg12.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index ab4312d59..a376e4904 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -232,12 +232,12 @@ static void sequence_header( sequence_t *sequence, uint8_t *buf, int len ) static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) { - int i = get_bits( buf,10,3 ); + //int i = get_bits( buf,10,3 ); //printf( "!!!!!!!!!!!!!!! picture type : %d !!!!!!!!!!!!!!!!!!!!!!!!!!\n", i ); if ( /*i==B_FRAME ||*/ sequence->picture.state!=WANT_HEADER ) return; reset_picture( &sequence->picture ); - sequence->picture.vdp_infos.picture_coding_type = i; + sequence->picture.vdp_infos.picture_coding_type = get_bits( buf,10,3 ); sequence->picture.vdp_infos.forward_reference = VDP_INVALID_HANDLE; sequence->picture.vdp_infos.backward_reference = VDP_INVALID_HANDLE; sequence->picture.vdp_infos.full_pel_forward_vector = 0; @@ -392,21 +392,32 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) vdpau_accel_t *ref_accel; if ( pic->vdp_infos.picture_coding_type==P_FRAME ) { - if ( seq->backward_ref ) + if ( seq->backward_ref ) { ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; - else - ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; - pic->vdp_infos.forward_reference = ref_accel->surface; + pic->vdp_infos.forward_reference = ref_accel->surface; + } + else { + pic->state = WANT_HEADER; + return; + } } else if ( pic->vdp_infos.picture_coding_type==B_FRAME ) { if ( seq->forward_ref ) { ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; pic->vdp_infos.forward_reference = ref_accel->surface; } + else { + pic->state = WANT_HEADER; + return; + } if ( seq->backward_ref ) { ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; pic->vdp_infos.backward_reference = ref_accel->surface; } + else { + pic->state = WANT_HEADER; + return; + } } pic->vdp_infos.slice_count = pic->slices_count; @@ -461,8 +472,8 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) * This function receives a buffer of data from the demuxer layer and * figures out how to handle it based on its header flags. */ -static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t *buf) { - +static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t *buf) +{ vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; sequence_t *seq = (sequence_t*)&this->sequence; -- cgit v1.2.3 From 853fa72e8f4c6c4f3a862a2c63d5e21630330be9 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 10 Dec 2008 14:43:44 +0000 Subject: Comment out some printfs. --- src/video_out/video_out_vdpau.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 23c10fea8..7e7026080 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -513,7 +513,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_redraw_needed( this_gen ); if ( (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) ) { - printf( "vo_vdpau: got a yuv image -------------\n" ); + //printf( "vo_vdpau: got a yuv image -------------\n" ); surface = this->soft_surface; chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; if ( (frame->width > this->soft_surface_width) || (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { @@ -540,7 +540,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } } else if (frame->format == XINE_IMGFMT_VDPAU) { - printf( "vo_vdpau: got a vdpau image -------------\n" ); + //printf( "vo_vdpau: got a vdpau image -------------\n" ); surface = frame->vdpau_accel_data.surface; /*if ( !this->gotimage ) { printf( "vo_vdpau: mallocing yuv ......\n" ); @@ -629,7 +629,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_display( vdp_queue, this->overlay_output, 0, 0, 0 ); else*/ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); - printf( "vo_vdpau: image displayed\n" ); + //printf( "vo_vdpau: image displayed\n" ); if ( this->init_queue<2 ) ++this->init_queue; -- cgit v1.2.3 From 208e5119cdaf0bbe4a1d8003c69ff369d7d72de7 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 10 Dec 2008 14:43:52 +0000 Subject: PTS bits. --- src/libvdpau/vdpau_mpeg12.c | 61 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 13 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index a376e4904..493217f6c 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -114,7 +114,9 @@ typedef struct { vo_frame_t *forward_ref; vo_frame_t *backward_ref; - int64_t pts; + int64_t seq_pts; + int64_t cur_pts; + int nframes; } sequence_t; @@ -162,6 +164,10 @@ static void reset_sequence( sequence_t *sequence ) sequence->bufpos = 0; sequence->bufseek = 0; sequence->start = -1; + sequence->seq_pts = sequence->cur_pts = 0; + sequence->nframes = -1; + sequence->ratio = 1.0; + sequence->video_step = 3600; xine_fast_memcpy( sequence->intra_quant_matrix, &default_intra_quantizer_matrix, 64 ); memset( sequence->non_intra_quant_matrix, 16, 64 ); if ( sequence->forward_ref ) @@ -198,6 +204,11 @@ static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) static void sequence_header( sequence_t *sequence, uint8_t *buf, int len ) { int i, j, off=0; + if ( sequence->cur_pts ) { + sequence->seq_pts = sequence->cur_pts; + sequence->nframes = -1; + } + sequence->coded_width = get_bits( buf,0,12 ); sequence->coded_height = get_bits( buf,12,12 ); switch ( get_bits( buf+3,0,4 ) ) { @@ -391,6 +402,8 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) picture_t *pic = (picture_t*)&seq->picture; vdpau_accel_t *ref_accel; + ++seq->nframes; + if ( pic->vdp_infos.picture_coding_type==P_FRAME ) { if ( seq->backward_ref ) { ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; @@ -424,8 +437,12 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) xine_fast_memcpy( &pic->vdp_infos.intra_quantizer_matrix, &seq->intra_quant_matrix, 64 ); xine_fast_memcpy( &pic->vdp_infos.non_intra_quantizer_matrix, &seq->non_intra_quant_matrix, 64 ); pic->state = WANT_HEADER; + + //printf("vdpau_mpeg12: get image ..\n"); vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + //printf("vdpau_mpeg12: .. got image %d\n", img); + vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; VdpStatus st; if ( vd->decoder==VDP_INVALID_HANDLE ) { @@ -445,25 +462,44 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); if ( st!=VDP_STATUS_OK ) printf( "vdpau_mpeg12: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); - else - printf( "vdpau_mpeg12: DECODER SUCCESS : frame_type:%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.picture_coding_type, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->pts ); + //else + //printf( "vdpau_mpeg12: DECODER SUCCESS : frame_type:%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.picture_coding_type, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); //printf( "vdpau_meg12: forwref:%d, backref:%d\n", seq->forward_ref, seq->backward_ref ); - //img->duration = 3600; - img->pts = seq->pts; img->bad_frame = 0; - //if ( pic->vdp_infos.picture_coding_type==B_FRAME ) - img->draw( img, vd->stream ); + img->duration = seq->video_step; if ( pic->vdp_infos.picture_coding_type!=B_FRAME ) { - if ( seq->forward_ref ) + if ( seq->forward_ref ) { + seq->forward_ref->drawn = 0; seq->forward_ref->free( seq->forward_ref ); + //printf("vdpau_mpeg12: freed image %d\n", seq->forward_ref ); + } seq->forward_ref = seq->backward_ref; + if ( seq->forward_ref && !seq->forward_ref->drawn ) { + seq->forward_ref->pts = seq->seq_pts; + seq->forward_ref->draw( seq->forward_ref, vd->stream ); + //printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", seq->forward_ref->pts ); + } seq->backward_ref = img; + + if ( seq->nframes==0 ) { + img->pts = seq->seq_pts; + img->draw( img, vd->stream ); + ++img->drawn; + //printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", img->pts ); + } } - else + else { + img->pts = seq->seq_pts; + img->draw( img, vd->stream ); + //printf( "vdpau_mpeg12: drawn image with pts=%lld\n", img->pts ); img->free( img ); + //printf("vdpau_mpeg12: freed B image %d\n", img ); + } + + seq->seq_pts +=seq->video_step; } @@ -486,10 +522,9 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * //_x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } - if ( buf->pts ) { - seq->pts = buf->pts; - //printf("vdpau_mpeg12_decode_data: new pts : %lld\n", buf->pts ); - } + seq->cur_pts = buf->pts; + //printf("vdpau_mpeg12_decode_data: new pts : %lld\n", buf->pts ); + int size = seq->bufpos+buf->size; if ( seq->bufsize < size ) { -- cgit v1.2.3 From eec6a97f49f113690ad207e9208040fe65bc94d8 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 10 Dec 2008 16:44:32 +0000 Subject: MPEG12 debug. --- src/libvdpau/vdpau_mpeg12.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 493217f6c..312713700 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -484,12 +484,12 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) } seq->backward_ref = img; - if ( seq->nframes==0 ) { + /*if ( seq->nframes==0 ) { img->pts = seq->seq_pts; img->draw( img, vd->stream ); ++img->drawn; //printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", img->pts ); - } + }*/ } else { img->pts = seq->seq_pts; @@ -565,6 +565,7 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * * This function is called when xine needs to flush the system. */ static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { + printf( "vdpau_mpeg12: vdpau_mpeg12_flush\n" ); } /* @@ -573,6 +574,8 @@ static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { static void vdpau_mpeg12_reset (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; + printf( "vdpau_mpeg12: vdpau_mpeg12_reset\n" ); + //this->size = 0; } @@ -582,6 +585,8 @@ static void vdpau_mpeg12_reset (video_decoder_t *this_gen) { static void vdpau_mpeg12_discontinuity (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; + printf( "vdpau_mpeg12: vdpau_mpeg12_discontinuity\n" ); + } /* @@ -591,6 +596,8 @@ static void vdpau_mpeg12_dispose (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; + printf( "vdpau_mpeg12: vdpau_mpeg12_dispose\n" ); + /*if (this->buf) { free (this->buf); this->buf = NULL; -- cgit v1.2.3 From 4890018b8474b2a6c746e9de66da585c6ed016e6 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 12 Dec 2008 06:48:29 +0000 Subject: Format changes etc. --- src/libvdpau/vdpau_mpeg12.c | 215 +++++++++++++++++++++++++++++--------------- 1 file changed, 142 insertions(+), 73 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 312713700..80f59f34d 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -47,10 +47,19 @@ #define begin_slice_start_code 0x01 #define end_slice_start_code 0xaf +#define sequence_ext_sc 1 +#define quant_matrix_ext_sc 3 +#define picture_coding_ext_sc 8 +#define sequence_display_ext_sc 2 + #define I_FRAME 1 #define P_FRAME 2 #define B_FRAME 3 +#define PICTURE_TOP 1 +#define PICTURE_BOTTOM 2 +#define PICTURE_FRAME 3 + #define WANT_HEADER 1 #define WANT_EXT 2 #define WANT_SLICE 3 @@ -78,13 +87,14 @@ static const uint8_t default_intra_quantizer_matrix[64] = { typedef struct { - VdpPictureInfoMPEG1Or2 vdp_infos; + VdpPictureInfoMPEG1Or2 vdp_infos; /* first field, also used for frame */ + VdpPictureInfoMPEG1Or2 vdp_infos2; /* second field */ int slices_count; uint8_t *slices; int slices_size; int slices_pos; - int64_t pts; + int fields; int state; } picture_t; @@ -98,9 +108,7 @@ typedef struct { uint32_t display_height; uint64_t video_step; /* frame duration in pts units */ double ratio; - - uint8_t intra_quant_matrix[64]; - uint8_t non_intra_quant_matrix[64]; + VdpDecoderProfile profile; int have_header; @@ -116,7 +124,9 @@ typedef struct { int64_t seq_pts; int64_t cur_pts; - int nframes; + + vdpau_accel_t *accel_vdpau; + } sequence_t; @@ -133,7 +143,10 @@ typedef struct vdpau_mpeg12_decoder_s { sequence_t sequence; - VdpDecoder decoder; + VdpDecoder decoder; + VdpDecoderProfile decoder_profile; + uint32_t decoder_width; + uint32_t decoder_height; } vdpau_mpeg12_decoder_t; @@ -143,8 +156,11 @@ static void reset_picture( picture_t *pic ) { pic->slices_count = 0; pic->slices_pos = 0; - pic->pts = 0; pic->state = WANT_HEADER; + xine_fast_memcpy( &pic->vdp_infos.intra_quantizer_matrix, &default_intra_quantizer_matrix, 64 ); + memset( &pic->vdp_infos.non_intra_quantizer_matrix, 16, 64 ); + xine_fast_memcpy( &pic->vdp_infos2.intra_quantizer_matrix, &default_intra_quantizer_matrix, 64 ); + memset( &pic->vdp_infos2.non_intra_quantizer_matrix, 16, 64 ); } @@ -165,11 +181,8 @@ static void reset_sequence( sequence_t *sequence ) sequence->bufseek = 0; sequence->start = -1; sequence->seq_pts = sequence->cur_pts = 0; - sequence->nframes = -1; sequence->ratio = 1.0; sequence->video_step = 3600; - xine_fast_memcpy( sequence->intra_quant_matrix, &default_intra_quantizer_matrix, 64 ); - memset( sequence->non_intra_quant_matrix, 16, 64 ); if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); sequence->forward_ref = 0; @@ -201,69 +214,103 @@ static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) -static void sequence_header( sequence_t *sequence, uint8_t *buf, int len ) +static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) { + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + int i, j, off=0; if ( sequence->cur_pts ) { sequence->seq_pts = sequence->cur_pts; - sequence->nframes = -1; } - sequence->coded_width = get_bits( buf,0,12 ); + //printf( "coded_width: %d\n", get_bits( buf,0,12 ) ); sequence->coded_height = get_bits( buf,12,12 ); + //printf( "coded_height: %d\n", get_bits( buf,12,12 ) ); switch ( get_bits( buf+3,0,4 ) ) { + case 1: sequence->ratio = 1.0; break; case 2: sequence->ratio = 4.0/3.0; break; case 3: sequence->ratio = 16.0/9.0; break; case 4: sequence->ratio = 2.21; break; + default: sequence->ratio = (double)sequence->coded_width/(double)sequence->coded_height; } - //printf( "frame_rate_code: %d\n", get_bits( buf+3,4,4 ) ); + //printf( "ratio: %d\n", get_bits( buf+3,0,4 ) ); + switch ( get_bits( buf+3,4,4 ) ) { + case 1: sequence->video_step = 3913; break; /* 23.976.. */ + case 2: sequence->video_step = 3750; break; /* 24 */ + case 3: sequence->video_step = 3600; break; /* 25 */ + case 4: sequence->video_step = 3003; break; /* 29.97.. */ + case 5: sequence->video_step = 3000; break; /* 30 */ + case 6: sequence->video_step = 1800; break; /* 50 */ + case 7: sequence->video_step = 1525; break; /* 59.94.. */ + case 8: sequence->video_step = 1509; break; /* 60 */ + } + //printf( "frame_rate: %d\n", get_bits( buf+3,4,4 ) ); //printf( "bit_rate_value: %d\n", get_bits( buf+4,0,18 ) ); //printf( "marker_bit: %d\n", get_bits( buf+6,2,1 ) ); //printf( "vbv_buffer_size_value: %d\n", get_bits( buf+6,3,10 ) ); //printf( "constrained_parameters_flag: %d\n", get_bits( buf+7,5,1 ) ); i = get_bits( buf+7,6,1 ); + //printf( "load_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->intra_quant_matrix[j] = get_bits( buf+7+j,7,8 ); + sequence->picture.vdp_infos.intra_quantizer_matrix[j] = get_bits( buf+7+j,7,8 ); } off = 64; } - //printf( "load_intra_quantizer_matrix: %d\n", i ); i = get_bits( buf+7+off,7,1 ); - //printf( "load_non_intra_quantizer_matrix: %d\n", i ); + //printf( "load_non_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->non_intra_quant_matrix[j] = get_bits( buf+8+off+j,0,8 ); + sequence->picture.vdp_infos.non_intra_quantizer_matrix[j] = get_bits( buf+8+off+j,0,8 ); } } - sequence->have_header = 1; + if ( !sequence->have_header ) { + sequence->have_header = 1; + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); + _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "MPEG (vdpau)" ); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = this_gen->stream; + event.data = &data; + event.data_length = sizeof(data); + data.width = sequence->coded_width; + data.height = sequence->coded_height; + data.aspect = sequence->ratio; + xine_event_send( this_gen->stream, &event ); + } } static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) { - //int i = get_bits( buf,10,3 ); - //printf( "!!!!!!!!!!!!!!! picture type : %d !!!!!!!!!!!!!!!!!!!!!!!!!!\n", i ); - if ( /*i==B_FRAME ||*/ sequence->picture.state!=WANT_HEADER ) + if ( sequence->picture.state!=WANT_HEADER ) return; reset_picture( &sequence->picture ); + //printf( "temporal_reference: %d\n", get_bits( buf,0,10 ) ); sequence->picture.vdp_infos.picture_coding_type = get_bits( buf,10,3 ); + //printf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) ); sequence->picture.vdp_infos.forward_reference = VDP_INVALID_HANDLE; sequence->picture.vdp_infos.backward_reference = VDP_INVALID_HANDLE; sequence->picture.vdp_infos.full_pel_forward_vector = 0; sequence->picture.vdp_infos.full_pel_backward_vector = 0; sequence->picture.state = WANT_EXT; - //printf( "temporal_reference: %d\n", get_bits( buf,0,10 ) ); - //printf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) ); } -static void sequence_extension( uint8_t *buf, int len ) +static void sequence_extension( sequence_t *sequence, uint8_t *buf, int len ) { - /*printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); - printf( "profile_and_level_indication: %d\n", get_bits( buf,4,8 ) ); + /*printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) );*/ + switch ( get_bits( buf,5,3 ) ) { + case 5: sequence->profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; break; + default: sequence->profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + } + /*printf( "profile_and_level_indication: %d\n", get_bits( buf,4,8 ) ); printf( "progressive_sequence: %d\n", get_bits( buf,12,1 ) ); printf( "chroma_format: %d\n", get_bits( buf,13,2 ) ); printf( "horizontal_size_extension: %d\n", get_bits( buf,15,2 ) ); @@ -335,18 +382,20 @@ static void quant_matrix_extension( uint8_t *buf, int len ) -static int parse_code( sequence_t *sequence, uint8_t *buf, int len ) +static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) { + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + if ( !sequence->have_header && buf[3]!=sequence_header_code ) return 0; if ( (buf[3] >= begin_slice_start_code) && (buf[3] <= end_slice_start_code) ) { + //printf( " ----------- slice_start_code\n" ); if ( sequence->picture.state==WANT_SLICE ) copy_slice( sequence, buf, len ); return 0; - //printf( " ----------- slice_start_code: %d\n", i+3 ); } - else if ( sequence->picture.state==WANT_SLICE ) { + else if ( sequence->picture.state==WANT_SLICE && sequence->picture.slices_count ) { /* no more slices, decode */ return 1; } @@ -354,22 +403,26 @@ static int parse_code( sequence_t *sequence, uint8_t *buf, int len ) switch ( buf[3] ) { case sequence_header_code: //printf( " ----------- sequence_header_code\n" ); - sequence_header( sequence, buf+4, len-4 ); + sequence_header( this_gen, buf+4, len-4 ); break; case extension_start_code: { switch ( get_bits( buf+4,0,4 ) ) { - case 1: + case sequence_ext_sc: //printf( " ----------- sequence_extension_start_code\n" ); - sequence_extension( buf+4, len-4 ); + sequence_extension( sequence, buf+4, len-4 ); break; - case 3: + case quant_matrix_ext_sc: //printf( " ----------- quant_matrix_extension_start_code\n" ); quant_matrix_extension( buf+4, len-4 ); break; - case 8: + case picture_coding_ext_sc: //printf( " ----------- picture_coding_extension_start_code\n" ); picture_coding_extension( sequence, buf+4, len-4 ); break; + case sequence_display_ext_sc: + //printf( " ----------- sequence_display_extension_start_code\n" ); + //sequence_display_extension( sequence, buf+4, len-4 ); + break; } break; } @@ -398,57 +451,63 @@ static int parse_code( sequence_t *sequence, uint8_t *buf, int len ) static void decode_picture( vdpau_mpeg12_decoder_t *vd ) { + //printf("vdpau_mpeg12: decode_picture\n"); sequence_t *seq = (sequence_t*)&vd->sequence; picture_t *pic = (picture_t*)&seq->picture; vdpau_accel_t *ref_accel; - ++seq->nframes; + pic->state = WANT_HEADER; if ( pic->vdp_infos.picture_coding_type==P_FRAME ) { if ( seq->backward_ref ) { ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; pic->vdp_infos.forward_reference = ref_accel->surface; } - else { - pic->state = WANT_HEADER; + else return; - } } else if ( pic->vdp_infos.picture_coding_type==B_FRAME ) { if ( seq->forward_ref ) { ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; pic->vdp_infos.forward_reference = ref_accel->surface; } - else { - pic->state = WANT_HEADER; + else return; - } if ( seq->backward_ref ) { ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; pic->vdp_infos.backward_reference = ref_accel->surface; } - else { - pic->state = WANT_HEADER; + else return; - } } pic->vdp_infos.slice_count = pic->slices_count; - xine_fast_memcpy( &pic->vdp_infos.intra_quantizer_matrix, &seq->intra_quant_matrix, 64 ); - xine_fast_memcpy( &pic->vdp_infos.non_intra_quantizer_matrix, &seq->non_intra_quant_matrix, 64 ); - pic->state = WANT_HEADER; //printf("vdpau_mpeg12: get image ..\n"); vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + + img->drawn = 0; //printf("vdpau_mpeg12: .. got image %d\n", img); vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + if ( !seq->accel_vdpau ) + seq->accel_vdpau = accel; + VdpStatus st; - if ( vd->decoder==VDP_INVALID_HANDLE ) { - st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, seq->coded_width, seq->coded_height, &vd->decoder); + if ( vd->decoder==VDP_INVALID_HANDLE || vd->decoder_profile!=seq->profile || vd->decoder_width!=seq->coded_width || vd->decoder_height!=seq->coded_height ) { + if ( vd->decoder!=VDP_INVALID_HANDLE ) { + accel->vdp_decoder_destroy( vd->decoder ); + vd->decoder = VDP_INVALID_HANDLE; + } + st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, &vd->decoder); if ( st!=VDP_STATUS_OK ) printf( "vdpau_mpeg12: failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); + else { + vd->decoder_profile = seq->profile; + vd->decoder_width = seq->coded_width; + vd->decoder_height = seq->coded_height; + } } if ( accel->surface==VDP_INVALID_HANDLE ) { st = accel->vdp_video_surface_create( accel->vdp_device, VDP_CHROMA_TYPE_420, seq->coded_width, seq->coded_height, &accel->surface); @@ -462,8 +521,9 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); if ( st!=VDP_STATUS_OK ) printf( "vdpau_mpeg12: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); - //else - //printf( "vdpau_mpeg12: DECODER SUCCESS : frame_type:%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.picture_coding_type, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + else + printf( "vdpau_mpeg12: DECODER SUCCESS : frame_type:%d, slices=%d, forwref:%d, backref:%d, pts:%lld\n", + pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); //printf( "vdpau_meg12: forwref:%d, backref:%d\n", seq->forward_ref, seq->backward_ref ); @@ -471,6 +531,11 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) img->duration = seq->video_step; if ( pic->vdp_infos.picture_coding_type!=B_FRAME ) { + if ( pic->vdp_infos.picture_coding_type==I_FRAME && !seq->backward_ref ) { + img->pts = 0; + img->draw( img, vd->stream ); + ++img->drawn; + } if ( seq->forward_ref ) { seq->forward_ref->drawn = 0; seq->forward_ref->free( seq->forward_ref ); @@ -483,13 +548,6 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) //printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", seq->forward_ref->pts ); } seq->backward_ref = img; - - /*if ( seq->nframes==0 ) { - img->pts = seq->seq_pts; - img->draw( img, vd->stream ); - ++img->drawn; - //printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", img->pts ); - }*/ } else { img->pts = seq->seq_pts; @@ -514,18 +572,21 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * sequence_t *seq = (sequence_t*)&this->sequence; /* a video decoder does not care about this flag (?) */ - if (buf->decoder_flags & BUF_FLAG_PREVIEW) + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { return; + } if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { //this->video_step = buf->decoder_info[0]; //_x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } + if ( !buf->size ) + return; + seq->cur_pts = buf->pts; //printf("vdpau_mpeg12_decode_data: new pts : %lld\n", buf->pts ); - int size = seq->bufpos+buf->size; if ( seq->bufsize < size ) { seq->bufsize = size+1024; @@ -542,10 +603,9 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * seq->start = seq->bufseek; } else { - if ( parse_code( seq, seq->buf+seq->start, seq->bufseek-seq->start ) ) { + if ( parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ) ) { decode_picture( this ); - //seq->pts += 3600; - parse_code( seq, seq->buf+seq->start, seq->bufseek-seq->start ); + parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ); } uint8_t *tmp = (uint8_t*)malloc(seq->bufsize); xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek ); @@ -565,7 +625,10 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * * This function is called when xine needs to flush the system. */ static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { + vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; + printf( "vdpau_mpeg12: vdpau_mpeg12_flush\n" ); + //reset_sequence( &this->sequence ); } /* @@ -575,6 +638,7 @@ static void vdpau_mpeg12_reset (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; printf( "vdpau_mpeg12: vdpau_mpeg12_reset\n" ); + reset_sequence( &this->sequence ); //this->size = 0; } @@ -586,6 +650,7 @@ static void vdpau_mpeg12_discontinuity (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; printf( "vdpau_mpeg12: vdpau_mpeg12_discontinuity\n" ); + //reset_sequence( &this->sequence ); } @@ -598,15 +663,14 @@ static void vdpau_mpeg12_dispose (video_decoder_t *this_gen) { printf( "vdpau_mpeg12: vdpau_mpeg12_dispose\n" ); - /*if (this->buf) { - free (this->buf); - this->buf = NULL; - } + if ( this->decoder!=VDP_INVALID_HANDLE && this->sequence.accel_vdpau ) { + this->sequence.accel_vdpau->vdp_decoder_destroy( this->decoder ); + this->decoder = VDP_INVALID_HANDLE; + } + + reset_sequence( &this->sequence ); - if (this->decoder_ok) { - this->decoder_ok = 0; - this->stream->video_out->close(this->stream->video_out, this->stream); - }*/ + this->stream->video_out->close( this->stream->video_out, this->stream ); free( this->sequence.picture.slices ); free( this->sequence.buf ); @@ -625,6 +689,8 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_MPEG12) ) return NULL; + printf( "vdpau_mpeg12: open_plugin\n" ); + this = (vdpau_mpeg12_decoder_t *) calloc(1, sizeof(vdpau_mpeg12_decoder_t)); this->video_decoder.decode_data = vdpau_mpeg12_decode_data; @@ -645,6 +711,9 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre init_picture( &this->sequence.picture ); this->decoder = VDP_INVALID_HANDLE; + this->sequence.accel_vdpau = NULL; + + (stream->video_out->open)(stream->video_out, stream); return &this->video_decoder; } -- cgit v1.2.3 From 65ae9896ac134cad57835d5dcf8ec5594efe7d2c Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 12 Dec 2008 06:49:08 +0000 Subject: Locking fixes. --- src/video_out/video_out_vdpau.c | 5 +++-- src/xine-engine/accel_vdpau.h | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 7e7026080..4f5b7d73e 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -412,7 +412,6 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vdpau_accel_data.vdp_device = vdp_device; frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; frame->vdpau_accel_data.vdp_video_surface_create = vdp_video_surface_create; - frame->vdpau_accel_data.vdp_video_surface_destroy = vdp_video_surface_destroy; frame->vdpau_accel_data.vdp_decoder_create = vdp_decoder_create; frame->vdpau_accel_data.vdp_decoder_destroy = vdp_decoder_destroy; frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render; @@ -722,8 +721,8 @@ static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void * case XINE_GUI_SEND_EXPOSE_EVENT: { if ( this->init_queue ) { - int previous = this->current_output_surface ^ 1; XLockDisplay( this->display ); + int previous = this->current_output_surface ^ 1; vdp_queue_display( vdp_queue, this->output_surface[previous], 0, 0, 0 ); XUnlockDisplay( this->display ); } @@ -739,11 +738,13 @@ static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void * st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); if ( st != VDP_STATUS_OK ) { printf( "vo_vdpau: FATAL !! Can't recreate presentation queue target after drawable change !!\n" ); + XUnlockDisplay( this->display ); break; } st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); if ( st != VDP_STATUS_OK ) { printf( "vo_vdpau: FATAL !! Can't recreate presentation queue after drawable change !!\n" ); + XUnlockDisplay( this->display ); break; } VdpColor backColor; diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h index f5b80e4d4..73965abc2 100644 --- a/src/xine-engine/accel_vdpau.h +++ b/src/xine-engine/accel_vdpau.h @@ -43,7 +43,6 @@ typedef struct { VdpGetErrorString *vdp_get_error_string; VdpVideoSurfaceCreate *vdp_video_surface_create; - VdpVideoSurfaceDestroy *vdp_video_surface_destroy; VdpDecoderCreate *vdp_decoder_create; VdpDecoderDestroy *vdp_decoder_destroy; VdpDecoderRender *vdp_decoder_render; -- cgit v1.2.3 From fc85c220d809a38468704282edd34b9bb00ff911 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 12 Dec 2008 09:15:19 +0000 Subject: Some fixes... --- src/libvdpau/dpb.h | 2 ++ src/libvdpau/h264_parser.c | 6 +++--- src/libvdpau/h264_parser.h | 6 +++++- src/libvdpau/vdpau_h264.c | 6 ++++++ 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index ace624e32..36892b60c 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -17,6 +17,8 @@ struct decoded_picture { * the surface is not double-used */ struct nal_unit *nal; + uint8_t used_for_reference; + struct decoded_picture *next; }; diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 4445b5d78..24a26e86c 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -472,6 +472,7 @@ void parse_vui_parameters(struct buf_reader *buf, sps->vui_parameters.log2_max_mv_length_vertical = read_exp_golomb(buf); sps->vui_parameters.num_reorder_frames = read_exp_golomb(buf); sps->vui_parameters.max_dec_frame_buffering = read_exp_golomb(buf); + printf("Max_dec_frame_buffering: %d\n", sps->vui_parameters.max_dec_frame_buffering); } } @@ -543,7 +544,6 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); if (!rbsp_trailing_bits(buf)) { - printf("PARSE 8x8\n"); pps->transform_8x8_mode_flag = read_bits(buf, 1); pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); if (pps->pic_scaling_matrix_present_flag) { @@ -1133,8 +1133,8 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) != last_nal->slc->delta_pic_order_cnt_bottom))) { ret = 1; reason++; - printf("C: Reason: %d, %d, %d\n", res, nal->slc->pic_order_cnt_lsb, - last_nal->slc->pic_order_cnt_lsb); + /*printf("C: Reason: %d, %d, %d\n", res, nal->slc->pic_order_cnt_lsb, + last_nal->slc->pic_order_cnt_lsb);*/ } if (nal->slc && last_nal->slc && (nal->sps->pic_order_cnt_type == 1 && last_nal->sps->pic_order_cnt_type == 1 diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index 3381cf4c2..99691e950 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -13,7 +13,8 @@ struct nal_parser { uint8_t buf[MAX_FRAME_SIZE]; uint32_t buf_len; - /* prebuf is a ringbuffer */ + /* prebuf is used to store the currently + * processed nal unit */ uint8_t prebuf[MAX_FRAME_SIZE]; uint32_t prebuf_len; uint32_t next_nal_position; @@ -42,6 +43,9 @@ struct nal_parser { uint32_t prev_pic_order_cnt_lsb; uint32_t prev_pic_order_cnt_msb; + /* this is dpb used for reference frame + * heading to vdpau + unordered frames + */ struct dpb dpb; }; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 1d988eeeb..ecf8d21af 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -351,6 +351,12 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); + // FIXME: do we really hit all cases here? + if(((uint8_t*)vdp_buffer.bitstream) != NULL) { + free(vdp_buffer.bitstream); + printf("Freed vdp_buffer.bitstream\n"); + } + if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); else { -- cgit v1.2.3 From 3cb09a6cf6cdc0e6aaa8e63ded14ea81388b5155 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 12 Dec 2008 19:37:02 +0000 Subject: First interlaced support. --- src/libvdpau/dpb.c | 11 +++++++---- src/libvdpau/dpb.h | 2 ++ src/libvdpau/h264_parser.c | 5 ++++- src/libvdpau/vdpau_h264.c | 38 ++++++++++++++++++++++++++------------ 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 25d9041f2..8ea9fd069 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -18,6 +18,9 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, struct decoded_picture *pic = malloc(sizeof(struct decoded_picture)); pic->nal = init_nal_unit(); copy_nal_unit(pic->nal, src_nal); + pic->top_is_reference = pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; + pic->bottom_is_reference = 0; pic->surface = surface; pic->img = img; pic->next = NULL; @@ -237,10 +240,10 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) reflist[i].frame_idx = pic->nal->slc->frame_num; //pic->nal->long_term_frame_idx; else reflist[i].frame_idx = pic->nal->slc->frame_num; //pic->nal->curr_pic_num; - reflist[i].top_is_reference = pic->nal->slc->field_pic_flag - ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; - reflist[i].bottom_is_reference = pic->nal->slc->field_pic_flag - ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1; + reflist[i].top_is_reference = pic->top_is_reference; /*pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1;*/ + reflist[i].bottom_is_reference = pic->bottom_is_reference; /*pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1;*/ reflist[i].field_order_cnt[0] = pic->nal->top_field_order_cnt; reflist[i].field_order_cnt[1] = pic->nal->bottom_field_order_cnt; i++; diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 36892b60c..06f894e44 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -18,6 +18,8 @@ struct decoded_picture { struct nal_unit *nal; uint8_t used_for_reference; + uint8_t top_is_reference; + uint8_t bottom_is_reference; struct decoded_picture *next; }; diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 24a26e86c..65ca7c85b 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -855,6 +855,9 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, // mark all ref pics as unused for reference, // set max-long-term frame index = no long-term frame idxs dpb_flush(dpb); + printf("MMC RESET\n"); + parser->pic_order_cnt_lsb = parser->prev_pic_order_cnt_lsb = 0; + parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb = 0; } else if (memory_management_control_operation == 6) { // mark current picture as used for long-term ref, @@ -954,7 +957,7 @@ struct nal_parser* init_parser() /* no idea why we do that. inspired by libavcodec, * as we couldn't figure in the specs.... */ - parser->prev_pic_order_cnt_msb = 1 << 16; + parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_lsb = 1 << 16; return parser; } diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ecf8d21af..e4faf5969 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -68,6 +68,8 @@ typedef struct vdpau_h264_decoder_s { struct nal_parser *nal_parser; /* h264 nal parser. extracts stream data for vdpau */ + uint8_t wait_for_bottom_field; + struct decoded_picture *last_ref_pic; VdpDecoder decoder; @@ -326,13 +328,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(img == NULL) { - printf("Acquire image: "); fflush(stdout); img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); - printf("OK\n"); this->vdpau_accel = (vdpau_accel_t*)img->accel_data; } @@ -353,28 +353,41 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, // FIXME: do we really hit all cases here? if(((uint8_t*)vdp_buffer.bitstream) != NULL) { - free(vdp_buffer.bitstream); - printf("Freed vdp_buffer.bitstream\n"); } if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); else { - printf("DECODING SUCCESS\n"); img->duration = this->video_step; img->pts = buf->pts; img->bad_frame = 0; - img->draw(img, this->stream); - if(pic.is_reference) { - struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); - dpb_add_picture(&(this->nal_parser->dpb), pic, sps->num_ref_frames); - } else { - img->free(img); + if(!this->wait_for_bottom_field) { + struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + this->last_ref_pic = pic; + dpb_add_picture(&(this->nal_parser->dpb), pic, sps->num_ref_frames); + } else { + if(this->last_ref_pic) { + this->last_ref_pic->bottom_is_reference = 1; + } + } + } + + if(!slc->field_pic_flag || + (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { + img->draw(img, this->stream); + this->wait_for_bottom_field = 0; + + if(!pic.is_reference) + img->free(img); + + img = NULL; + } else if(slc->field_pic_flag && !slc->bottom_field_flag) { + // don't draw yet, second field is missing. + this->wait_for_bottom_field = 1; } - img = NULL; } //this->vdpau_accel->vdp_video_surface_destroy(surface); @@ -457,6 +470,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->decoder_initialized = 0; this->nal_parser = init_parser(); this->buf = NULL; + this->wait_for_bottom_field = 0; return &this->video_decoder; } -- cgit v1.2.3 From f568815dd336855ddb9f5a8d84cee981197304f9 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 13 Dec 2008 11:58:07 +0000 Subject: Fix re-introduced mem-leak & progressive playback. --- src/libvdpau/dpb.c | 3 ++- src/libvdpau/vdpau_h264.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 8ea9fd069..d27611e64 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -20,7 +20,8 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, copy_nal_unit(pic->nal, src_nal); pic->top_is_reference = pic->nal->slc->field_pic_flag ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; - pic->bottom_is_reference = 0; + pic->bottom_is_reference = pic->nal->slc->field_pic_flag + ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1; pic->surface = surface; pic->img = img; pic->next = NULL; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index e4faf5969..7b9299dae 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -353,6 +353,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, // FIXME: do we really hit all cases here? if(((uint8_t*)vdp_buffer.bitstream) != NULL) { + free(vdp_buffer.bitstream); } if(status != VDP_STATUS_OK) @@ -364,11 +365,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->bad_frame = 0; if(pic.is_reference) { - if(!this->wait_for_bottom_field) { + if(!slc->field_pic_flag || !this->wait_for_bottom_field) { struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); this->last_ref_pic = pic; dpb_add_picture(&(this->nal_parser->dpb), pic, sps->num_ref_frames); - } else { + } else if(slc->field_pic_flag && this->wait_for_bottom_field) { if(this->last_ref_pic) { this->last_ref_pic->bottom_is_reference = 1; } -- cgit v1.2.3 From b5c69144556a437103ef363ebb398864e86dd3a0 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 13 Dec 2008 12:24:38 +0000 Subject: Fix possible segfault on buffer underrun. --- src/libvdpau/h264_parser.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 65ca7c85b..f3ee412d7 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1031,6 +1031,14 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, } if (parser->last_nal_res != 2) { + if (parser->buf_len + parser->prebuf_len > MAX_FRAME_SIZE) { + printf("buf underrun!!\n"); + parser->buf_len = 0; + *ret_len = 0; + *ret_buf = NULL; + return parsed_len; + } + /* this is a SLICE, keep it in the buffer */ xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); parser->buf_len += parser->prebuf_len; -- cgit v1.2.3 From 51f37c6723bbfd26c635a4859ec16efe8e0cb32c Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 13 Dec 2008 13:06:06 +0000 Subject: MPEG bits. --- src/libvdpau/vdpau_mpeg12.c | 55 +++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 80f59f34d..1045577bd 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -85,6 +85,26 @@ static const uint8_t default_intra_quantizer_matrix[64] = { 83 }; +uint8_t mpeg2_scan_norm[64] = { + /* Zig-Zag scan pattern */ + 0, 1, 8,16, 9, 2, 3,10, + 17,24,32,25,18,11, 4, 5, + 12,19,26,33,40,48,41,34, + 27,20,13, 6, 7,14,21,28, + 35,42,49,56,57,50,43,36, + 29,22,15,23,30,37,44,51, + 58,59,52,45,38,31,39,46, + 53,60,61,54,47,55,62,63 +}; + +uint8_t mpeg2_scan_alt[64] = { + /* Alternate scan pattern */ + 0,8,16,24,1,9,2,10,17,25,32,40,48,56,57,49, + 41,33,26,18,3,11,4,12,19,27,34,42,50,58,35,43, + 51,59,20,28,5,13,6,14,21,29,36,44,52,60,37,45, + 53,61,22,30,7,15,23,31,38,46,54,62,39,47,55,63 +}; + typedef struct { VdpPictureInfoMPEG1Or2 vdp_infos; /* first field, also used for frame */ @@ -157,10 +177,6 @@ static void reset_picture( picture_t *pic ) pic->slices_count = 0; pic->slices_pos = 0; pic->state = WANT_HEADER; - xine_fast_memcpy( &pic->vdp_infos.intra_quantizer_matrix, &default_intra_quantizer_matrix, 64 ); - memset( &pic->vdp_infos.non_intra_quantizer_matrix, 16, 64 ); - xine_fast_memcpy( &pic->vdp_infos2.intra_quantizer_matrix, &default_intra_quantizer_matrix, 64 ); - memset( &pic->vdp_infos2.non_intra_quantizer_matrix, 16, 64 ); } @@ -185,10 +201,10 @@ static void reset_sequence( sequence_t *sequence ) sequence->video_step = 3600; if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); - sequence->forward_ref = 0; + sequence->forward_ref = NULL; if ( sequence->backward_ref ) sequence->backward_ref->free( sequence->backward_ref ); - sequence->backward_ref = 0; + sequence->backward_ref = NULL; } @@ -253,24 +269,33 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int //printf( "load_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->picture.vdp_infos.intra_quantizer_matrix[j] = get_bits( buf+7+j,7,8 ); + sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+7+j,7,8 ); } off = 64; } + else { + for ( j=0; j<64; ++j ) { + sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = default_intra_quantizer_matrix[j]; + } + } + i = get_bits( buf+7+off,7,1 ); //printf( "load_non_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->picture.vdp_infos.non_intra_quantizer_matrix[j] = get_bits( buf+8+off+j,0,8 ); + sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+8+off+j,0,8 ); } } + else + memset( sequence->picture.vdp_infos.non_intra_quantizer_matrix, 16, 64 ); + if ( !sequence->have_header ) { sequence->have_header = 1; _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); - _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "MPEG (vdpau)" ); + _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "MPEG1/2 (vdpau)" ); xine_event_t event; xine_format_change_data_t data; event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; @@ -341,7 +366,7 @@ static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int le sequence->picture.vdp_infos.intra_dc_precision = get_bits( buf,20,2 ); //printf( "intra_dc_precision: %d\n", get_bits( buf,20,2 ) ); sequence->picture.vdp_infos.picture_structure = get_bits( buf,22,2 ); - //printf( "picture_structure: %d\n", get_bits( buf,22,2 ) ); + printf( "picture_structure: %d\n", get_bits( buf,22,2 ) ); sequence->picture.vdp_infos.top_field_first = get_bits( buf,24,1 ); //printf( "top_field_first: %d\n", get_bits( buf,24,1 ) ); sequence->picture.vdp_infos.frame_pred_frame_dct = get_bits( buf,25,1 ); @@ -353,7 +378,7 @@ static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int le sequence->picture.vdp_infos.intra_vlc_format = get_bits( buf,28,1 ); //printf( "intra_vlc_format: %d\n", get_bits( buf,28,1 ) ); sequence->picture.vdp_infos.alternate_scan = get_bits( buf,29,1 ); - //printf( "alternate_scan: %d\n", get_bits( buf,29,1 ) ); + printf( "alternate_scan: %d\n", get_bits( buf,29,1 ) ); //printf( "repeat_first_field: %d\n", get_bits( buf,30,1 ) ); //printf( "chroma_420_type: %d\n", get_bits( buf,31,1 ) ); //printf( "progressive_frame: %d\n", get_bits( buf,32,1 ) ); @@ -378,6 +403,7 @@ static void copy_slice( sequence_t *sequence, uint8_t *buf, int len ) static void quant_matrix_extension( uint8_t *buf, int len ) { + printf("quant_matrix_extension >>>>>>>>>>>>>>>>>>>>>>>>>\n"); } @@ -500,7 +526,7 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) accel->vdp_decoder_destroy( vd->decoder ); vd->decoder = VDP_INVALID_HANDLE; } - st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, &vd->decoder); + st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder); if ( st!=VDP_STATUS_OK ) printf( "vdpau_mpeg12: failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); else { @@ -514,10 +540,11 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) if ( st!=VDP_STATUS_OK ) printf( "vdpau_mpeg12: failed to create surface !! %s\n", accel->vdp_get_error_string( st ) ); } + VdpBitstreamBuffer vbit; vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; - vbit.bitstream = seq->picture.slices; - vbit.bitstream_bytes = seq->picture.slices_pos; + vbit.bitstream = pic->slices; + vbit.bitstream_bytes = pic->slices_pos; st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); if ( st!=VDP_STATUS_OK ) printf( "vdpau_mpeg12: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); -- cgit v1.2.3 From 3c82138cae76f29d2b5601702e6547551b8782c2 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 13 Dec 2008 17:00:38 +0000 Subject: Add 180.16 support (hardcoded ref-frames to 16, needs change); fix nal-parsing where nal-start sequence was splitted across two ts-packets. --- src/libvdpau/h264_parser.c | 30 ++++++++++++++++++++++++------ src/libvdpau/vdpau_h264.c | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index f3ee412d7..6d376ae44 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -155,15 +155,17 @@ int32_t read_exp_golomb_s(struct buf_reader *buf) int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) { - if (buf->len < 1) + if (buf->len < 1) { + printf("ERROR: Empty buffer passed\n"); return -1; + } int ret = -1; struct nal_unit *nal = parser->current_nal; nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; nal->nal_unit_type = buf->buf[0] & 0x1f; - printf("Unit: %d\n", nal->nal_unit_type); + //printf("Unit: %d\n", nal->nal_unit_type); buf->cur_pos = buf->buf + 1; //printf("NAL: %d\n", nal->nal_unit_type); @@ -969,6 +971,11 @@ void free_parser(struct nal_parser *parser) free(parser); } +void parse_prebuf() +{ + +} + int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) { @@ -997,10 +1004,6 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parsed_len += next_nal; inbuf += next_nal; - /*int i; - for(i=0; i<5; i++) - printf("0x%02x ", (prebuf+3)[i]); - printf("\n");*/ parser->last_nal_res = parse_nal(prebuf+3, parser->prebuf_len-3, parser); if (parser->last_nal_res == 1 && parser->buf_len > 0) { printf("Frame complete: %d bytes\n", parser->buf_len); @@ -1017,9 +1020,11 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->slice_cnt = 1; /* this is a SLICE, keep it in the buffer */ + printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); parser->buf_len += parser->prebuf_len; parser->prebuf_len = 0; + parser->incomplete_nal = 0; if (parser->last_nal->nal_ref_idc) { if (parser->last_nal->slc != NULL) @@ -1039,6 +1044,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, return parsed_len; } + printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); /* this is a SLICE, keep it in the buffer */ xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); parser->buf_len += parser->prebuf_len; @@ -1068,8 +1074,20 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len-parsed_len); parser->prebuf_len += inbuf_len-parsed_len; parsed_len += inbuf_len-parsed_len; + inbuf += inbuf_len-parsed_len; + + /* now check if prebuf contains a second slice header + * this might happen if the nal start sequence is split + * over the buf-boundary - if this is the case we + */ + if((next_nal = seek_for_nal(prebuf+3, parser->prebuf_len)) >= 0) { + inbuf -= parser->prebuf_len-next_nal-3; + parsed_len -= parser->prebuf_len-next_nal-3; + parser->prebuf_len = next_nal+3; + } } + *ret_len = 0; *ret_buf = NULL; return parsed_len; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 7b9299dae..9b66e57c5 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -239,7 +239,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->vdpau_accel->vdp_device, this->profile, this->width, this->height); VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, - this->profile, this->width, this->height, &this->decoder); + this->profile, this->width, this->height, 16, &this->decoder); if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status)); -- cgit v1.2.3 From 7f85cddaec67cf3dd8d30e08cf86057efa626411 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 14 Dec 2008 13:23:48 +0000 Subject: PTS reorder preparations. --- src/libvdpau/dpb.c | 158 ++++++++++++++++++++++++++++++--------------- src/libvdpau/dpb.h | 16 ++++- src/libvdpau/h264_parser.c | 85 ++++++++++++++++++------ src/libvdpau/h264_parser.h | 2 + src/libvdpau/nal.h | 59 +++++++++++------ src/libvdpau/vdpau_h264.c | 36 +++++++++-- 6 files changed, 258 insertions(+), 98 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index d27611e64..0f5970ced 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -18,6 +18,8 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, struct decoded_picture *pic = malloc(sizeof(struct decoded_picture)); pic->nal = init_nal_unit(); copy_nal_unit(pic->nal, src_nal); + pic->used_for_reference = 0; + pic->delayed_output = 0; pic->top_is_reference = pic->nal->slc->field_pic_flag ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; pic->bottom_is_reference = pic->nal->slc->field_pic_flag @@ -35,6 +37,27 @@ void free_decoded_picture(struct decoded_picture *pic) free_nal_unit(pic->nal); } +struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *outpic = pic; + + printf("dpb used: %d\n", dpb->used); + + if(dpb->used < MAX_DPB_SIZE) + return NULL; + + if (pic != NULL) + do { + if (pic->img->pts < outpic->img->pts) + outpic = pic; + } while ((pic = pic->next) != NULL); + + if(outpic) + printf("OUTPUT: %lld\n", outpic->img->pts); + return outpic; +} + struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; @@ -76,75 +99,114 @@ struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, return NULL; } -int dpb_remove_picture(struct dpb *dpb, uint32_t picnum) +int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; - struct decoded_picture *last_pic = NULL; - +printf("UNUSED 1\n"); if (pic != NULL) do { if (pic->nal->curr_pic_num == picnum) { - // FIXME: free the picture.... + pic->used_for_reference = 0; + if(!pic->delayed_output) + dpb_remove_picture(dpb, pic); + return 0; + } + } while ((pic = pic->next) != NULL); - if (last_pic != NULL) - last_pic->next = pic->next; - else - dpb->pictures = pic->next; + return -1; +} - free_decoded_picture(pic); - dpb->used--; +int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum) +{ + struct decoded_picture *pic = dpb->pictures; + printf("UNUSED 2\n"); + if (pic != NULL) + do { + if (pic->nal->long_term_pic_num == longterm_picnum) { + pic->used_for_reference = 0; + if(!pic->delayed_output) + dpb_remove_picture(dpb, pic); return 0; } - - last_pic = pic; } while ((pic = pic->next) != NULL); return -1; } -int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum) +int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx) { struct decoded_picture *pic = dpb->pictures; - struct decoded_picture *last_pic = NULL; + printf("UNUSED 3\n"); + if (pic != NULL) + do { + if (pic->nal->long_term_frame_idx == longterm_idx) { + pic->used_for_reference = 0; + if(!pic->delayed_output) + dpb_remove_picture(dpb, pic); + return 0; + } + } while ((pic = pic->next) != NULL); + + return -1; +} +int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx) +{ + struct decoded_picture *pic = dpb->pictures; + printf("UNUSED 4\n"); if (pic != NULL) do { - if (pic->nal->long_term_pic_num == longterm_picnum) { - // FIXME: free the picture.... + if (pic->nal->long_term_frame_idx >= longterm_idx) { + pic->used_for_reference = 0; + if(!pic->delayed_output) { + struct decoded_picture *next_pic = pic->next; + dpb_remove_picture(dpb, pic); + pic = next_pic; + continue; + } + } + } while ((pic = pic->next) != NULL); - if (last_pic != NULL) - last_pic->next = pic->next; - else - dpb->pictures = pic->next; + return -1; +} - free_decoded_picture(pic); - dpb->used--; + +int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic) +{ + struct decoded_picture *pic = dpb->pictures; +printf("DPB set output pic\n"); + if (pic != NULL) + do { + if (pic == outpic) { + printf("DPB pic num %d output, refuse: %d\n", pic->nal->curr_pic_num, pic->used_for_reference); + pic->delayed_output = 0; + if(!pic->used_for_reference) + dpb_remove_picture(dpb, pic); return 0; } - - last_pic = pic; } while ((pic = pic->next) != NULL); return -1; } -int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx) +int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic) { struct decoded_picture *pic = dpb->pictures; struct decoded_picture *last_pic = NULL; - +printf("DPB remove pic\n"); if (pic != NULL) do { - if (pic->nal->long_term_frame_idx == longterm_idx) { + if (pic == rempic) { + printf("DPB found rempic\n"); // FIXME: free the picture.... if (last_pic != NULL) last_pic->next = pic->next; else dpb->pictures = pic->next; - free_decoded_picture(pic); dpb->used--; + printf("DPB Used: %d\n", dpb->used); return 0; } @@ -154,32 +216,21 @@ int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx) return -1; } -int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max) +int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; struct decoded_picture *last_pic = NULL; if (pic != NULL) do { - if (pic->nal->long_term_frame_idx > longterm_max) { - // FIXME: free the picture.... - if (last_pic != NULL) - last_pic->next = pic->next; - else - dpb->pictures = pic->next; - - - free_decoded_picture(pic); - dpb->used--; - /* don't increase last_pic to current pic - * in case we delete current pic */ - continue; + if (pic->nal->curr_pic_num == picnum) { + dpb_remove_picture(dpb, pic); } last_pic = pic; } while ((pic = pic->next) != NULL); - return 0; + return -1; } int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames) @@ -190,17 +241,20 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r pic->next = dpb->pictures; dpb->pictures = pic; dpb->used++; - +printf("ADD: Used: %d\n", dpb->used); if(dpb->used > num_ref_frames) { do { - i++; - if(i>num_ref_frames) { - last_pic->next = pic->next; - free_decoded_picture(pic); - pic = last_pic; - dpb->used--; + if(pic->used_for_reference) { + i++; + if(i>num_ref_frames) { + printf("DPB REMOVE REF FRAME\n"); + pic->used_for_reference = 0; + if(!pic->delayed_output) + dpb_remove_picture(dpb, pic); + pic = last_pic; + } + last_pic = pic; } - last_pic = pic; } while ((pic = pic->next) != NULL); } @@ -234,7 +288,7 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) if (pic != NULL) do { - if (pic->nal->nal_ref_idc != 0) { + if (pic->used_for_reference) { reflist[i].surface = pic->surface; reflist[i].is_long_term = pic->nal->used_for_long_term_ref; if(reflist[i].is_long_term) diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 06f894e44..c747a38af 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -8,6 +8,8 @@ #ifndef DPB_H_ #define DPB_H_ +#define MAX_DPB_SIZE 10 + #include "nal.h" #include "video_out.h" @@ -21,6 +23,8 @@ struct decoded_picture { uint8_t top_is_reference; uint8_t bottom_is_reference; + uint8_t delayed_output; + struct decoded_picture *next; }; @@ -34,10 +38,20 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, VdpVideoSurface surface, vo_frame_t *img); void free_decoded_picture(struct decoded_picture *pic); +struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb); + struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum); struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); -int dpb_remove_picture(struct dpb *dpb, uint32_t picnum); + +int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum); +int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum); +int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx); + +int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic); + +int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic); +int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum); int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max); diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 6d376ae44..e5206a943 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -39,12 +39,13 @@ void skip_scaling_list(struct buf_reader *buf, int size); void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index); int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser); -uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); +uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser); void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); void parse_hrd_parameters(struct buf_reader *buf, struct hrd_parameters *hrd); uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, struct seq_parameter_set_rbsp *sps); +void parse_sei(struct buf_reader *buf, struct nal_parser *parser); uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser); void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); @@ -165,7 +166,6 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; nal->nal_unit_type = buf->buf[0] & 0x1f; - //printf("Unit: %d\n", nal->nal_unit_type); buf->cur_pos = buf->buf + 1; //printf("NAL: %d\n", nal->nal_unit_type); @@ -183,7 +183,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); - parse_sps(&ibuf, nal->sps); + parse_sps(&ibuf, parser); free(ibuf.buf); ret = NAL_SPS; break; @@ -210,6 +210,10 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) ret = nal->nal_unit_type; } break; + case NAL_SEI: + parse_sei(buf, parser); + ret = nal->nal_unit_type; + break; default: ret = nal->nal_unit_type; break; @@ -230,7 +234,7 @@ void calculate_pic_order(struct nal_parser *parser) if (sps->pic_order_cnt_type == 0) { if (nal->nal_unit_type == NAL_SLICE_IDR) { - printf("IDR SLICE\n"); + //printf("IDR SLICE\n"); parser->prev_pic_order_cnt_lsb = 0; parser->prev_pic_order_cnt_msb = 0; } @@ -319,8 +323,9 @@ void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, } } -uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) +uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) { + struct seq_parameter_set_rbsp *sps = parser->current_nal->sps; sps->profile_idc = buf->buf[0]; sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; sps->level_idc = buf->buf[2]; @@ -339,7 +344,6 @@ uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) sps->qpprime_y_zero_transform_bypass_flag = read_bits(buf, 1); sps->seq_scaling_matrix_present_flag = read_bits(buf, 1); if (sps->seq_scaling_matrix_present_flag) { - printf("SCALING LIST PRESENT\n"); int i; for (i = 0; i < 8; i++) { sps->seq_scaling_list_present_flag[i] = read_bits(buf, 1); @@ -403,11 +407,46 @@ uint8_t parse_sps(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) sps->vui_parameters_present_flag = read_bits(buf, 1); if (sps->vui_parameters_present_flag) { parse_vui_parameters(buf, sps); - } + if(sps->vui_parameters.nal_hrd_parameters_present_flag || + sps->vui_parameters.vc1_hrd_parameters_present_flag) { + parser->cpb_dpb_delays_present_flag = 1; + } else + parser->cpb_dpb_delays_present_flag = 0; + } else + parser->cpb_dpb_delays_present_flag = 0; return 0; } +void parse_sei(struct buf_reader *buf, struct nal_parser *parser) +{ + struct sei_message *sei = &(parser->current_nal->sei); + uint8_t tmp; + + sei->payload_type = 0; + while((tmp = read_bits(buf, 8)) == 0xff) { + sei->payload_type += 255; + } + sei->last_payload_type_byte = tmp; + sei->payload_type += sei->last_payload_type_byte; + + sei->payload_size = 0; + while((tmp = read_bits(buf, 8)) == 0xff) { + sei->payload_size += 255; + } + sei->last_payload_size_byte = tmp; + sei->payload_size += sei->last_payload_size_byte; + + /* pic_timing */ + if(sei->payload_type == 1) { + if(parser->cpb_dpb_delays_present_flag) { + sei->pic_timing.cpb_removal_delay = read_bits(buf, 5); + sei->pic_timing.dpb_output_delay = read_bits(buf, 5); + printf("output delay: %d\n", sei->pic_timing.dpb_output_delay); + } + } +} + void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps) { @@ -566,15 +605,15 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, } if (!pps->pic_scaling_matrix_present_flag && sps != NULL) { - printf("MEMCPY SCALING LIST\n"); + //printf("MEMCPY SCALING LIST\n"); memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, sizeof(pps->scaling_lists_4x4)); memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8, sizeof(pps->scaling_lists_8x8)); } - else if (sps == NULL) { + /*else if (sps == NULL) { printf("sPS MISSING\n"); - } + }*/ return 0; } @@ -789,43 +828,46 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, return; if (memory_management_control_operation == 1) { + printf("MMC 1\n"); // short-term -> unused for reference uint32_t pic_num_x = nal->curr_pic_num - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); struct decoded_picture* pic = dpb_get_picture(dpb, pic_num_x); if (pic != NULL) { if (pic->nal->slc->field_pic_flag == 0) - dpb_remove_picture(dpb, pic_num_x); + dpb_set_unused_ref_picture(dpb, pic_num_x); else { - dpb_remove_picture(dpb, pic_num_x); + dpb_set_unused_ref_picture(dpb, pic_num_x); printf("FIXME: We might need do delete more from the DPB...\n"); // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120 } } } else if (memory_management_control_operation == 2) { + printf("MMC 2\n"); // long-term -> unused for reference struct decoded_picture* pic = dpb_get_picture_by_ltpn(dpb, slc->dec_ref_pic_marking.long_term_pic_num); if (pic != NULL) { if (pic->nal->slc->field_pic_flag == 0) - dpb_remove_picture_by_ltpn(dpb, + dpb_set_unused_ref_picture(dpb, slc->dec_ref_pic_marking.long_term_pic_num); else { - dpb_remove_picture_by_ltpn(dpb, + dpb_set_unused_ref_picture(dpb, slc->dec_ref_pic_marking.long_term_pic_num); printf("FIXME: We might need do delete more from the DPB...\n"); } } } else if (memory_management_control_operation == 3) { + printf("MMC 3\n"); // short-term -> long-term, set long-term frame index uint32_t pic_num_x = nal->curr_pic_num - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, slc->dec_ref_pic_marking.long_term_pic_num); if (pic != NULL) - dpb_remove_picture_by_ltidx(dpb, + dpb_set_unused_ref_picture_bylidx(dpb, slc->dec_ref_pic_marking.long_term_frame_idx); pic = dpb_get_picture(dpb, pic_num_x); @@ -844,16 +886,18 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, } else if (memory_management_control_operation == 4) { + printf("MMC 4\n"); // set max-long-term frame index, // mark all long-term pictures with long-term frame idx // greater max-long-term farme idx as unused for ref if (slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 == 0) - dpb_remove_ltidx_gt(dpb, 0); + dpb_set_unused_ref_picture_lidx_gt(dpb, 0); else - dpb_remove_ltidx_gt(dpb, + dpb_set_unused_ref_picture_lidx_gt(dpb, slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 - 1); } else if (memory_management_control_operation == 5) { + printf("MMC 5\n"); // mark all ref pics as unused for reference, // set max-long-term frame index = no long-term frame idxs dpb_flush(dpb); @@ -862,12 +906,13 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb = 0; } else if (memory_management_control_operation == 6) { + printf("MMC 6\n"); // mark current picture as used for long-term ref, // assing long-term frame idx to it struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, slc->dec_ref_pic_marking.long_term_frame_idx); if (pic != NULL) - dpb_remove_picture_by_ltidx(dpb, + dpb_set_unused_ref_picture_bylidx(dpb, slc->dec_ref_pic_marking.long_term_frame_idx); nal->long_term_frame_idx = slc->dec_ref_pic_marking.long_term_frame_idx; @@ -961,6 +1006,8 @@ struct nal_parser* init_parser() */ parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_lsb = 1 << 16; + parser->cpb_dpb_delays_present_flag = 0; + return parser; } @@ -1044,7 +1091,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, return parsed_len; } - printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); + //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); /* this is a SLICE, keep it in the buffer */ xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); parser->buf_len += parser->prebuf_len; diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index 99691e950..966bf0880 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -38,6 +38,8 @@ struct nal_parser { struct nal_unit *current_nal; struct nal_unit *last_nal; + uint8_t cpb_dpb_delays_present_flag; + uint32_t pic_order_cnt_lsb; uint32_t pic_order_cnt_msb; uint32_t prev_pic_order_cnt_lsb; diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index c07c1d9a3..20c1c32dc 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -63,24 +63,6 @@ static inline uint32_t slice_type(uint32_t slice_type) return (slice_type < 10 ? slice_type % 5 : slice_type); } -struct nal_unit -{ - uint8_t nal_ref_idc; // 0x03 - uint8_t nal_unit_type; // 0x1f - - uint32_t curr_pic_num; - uint8_t used_for_long_term_ref; - uint32_t long_term_pic_num; - uint32_t long_term_frame_idx; - - uint32_t top_field_order_cnt; - uint32_t bottom_field_order_cnt; - - struct seq_parameter_set_rbsp *sps; - struct pic_parameter_set_rbsp *pps; - struct slice_header *slc; -}; - struct hrd_parameters { uint32_t cpb_cnt_minus1; @@ -253,6 +235,27 @@ struct pic_parameter_set_rbsp int32_t second_chroma_qp_index_offset; }; +/* sei contains several additional info, we do + * only care for pic_timing, to handle display + * reordering + */ +struct sei_message +{ + uint32_t payload_type; + uint8_t last_payload_type_byte; + uint32_t payload_size; + uint8_t last_payload_size_byte; + + union + { + /* cpb_dpb_delays_present_flag == 1 */ + uint8_t cpb_removal_delay; + uint8_t dpb_output_delay; + + /* ignore the rest */ + } pic_timing; +}; + struct slice_header { uint32_t first_mb_in_slice; @@ -341,10 +344,28 @@ struct slice_header } dec_ref_pic_marking; }; +struct nal_unit +{ + uint8_t nal_ref_idc; // 0x03 + uint8_t nal_unit_type; // 0x1f + + uint32_t curr_pic_num; + uint8_t used_for_long_term_ref; + uint32_t long_term_pic_num; + uint32_t long_term_frame_idx; + + uint32_t top_field_order_cnt; + uint32_t bottom_field_order_cnt; + + struct sei_message sei; + + struct seq_parameter_set_rbsp *sps; + struct pic_parameter_set_rbsp *pps; + struct slice_header *slc; +}; struct nal_unit* init_nal_unit(); void free_nal_unit(struct nal_unit *nal); void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src); - #endif /* NAL_H_ */ diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 9b66e57c5..fbbdbe205 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -353,7 +353,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, // FIXME: do we really hit all cases here? if(((uint8_t*)vdp_buffer.bitstream) != NULL) { - free(vdp_buffer.bitstream); + free((uint8_t*)vdp_buffer.bitstream); } if(status != VDP_STATUS_OK) @@ -364,13 +364,17 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->pts = buf->pts; img->bad_frame = 0; + struct decoded_picture *decoded_pic = NULL; if(pic.is_reference) { if(!slc->field_pic_flag || !this->wait_for_bottom_field) { - struct decoded_picture *pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); - this->last_ref_pic = pic; - dpb_add_picture(&(this->nal_parser->dpb), pic, sps->num_ref_frames); + decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + this->last_ref_pic = decoded_pic; + printf("Add ref pic: %d\n", decoded_pic->nal->slc->frame_num); + decoded_pic->used_for_reference = 1; + dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); } else if(slc->field_pic_flag && this->wait_for_bottom_field) { if(this->last_ref_pic) { + decoded_pic = this->last_ref_pic; this->last_ref_pic->bottom_is_reference = 1; } } @@ -378,20 +382,38 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(!slc->field_pic_flag || (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { + /*if(!decoded_pic) { + decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + decoded_pic->delayed_output = 1; + dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); + } else + decoded_pic->delayed_output = 1; + + img = NULL; + + / * now retrieve the next output frame * / + decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); + if(decoded_pic) { + printf("DRAW AN IMAGE\n"); + decoded_pic->img->draw(decoded_pic->img, this->stream); + + dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); + } else + printf("NO IMAGE THIS TIME\n"); + + this->wait_for_bottom_field = 0;*/ + img->draw(img, this->stream); this->wait_for_bottom_field = 0; if(!pic.is_reference) img->free(img); - img = NULL; } else if(slc->field_pic_flag && !slc->bottom_field_flag) { // don't draw yet, second field is missing. this->wait_for_bottom_field = 1; } } - - //this->vdpau_accel->vdp_video_surface_destroy(surface); } } } -- cgit v1.2.3 From 6ceda730920bd007cbc38978d06f933c2bdab3e7 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 14 Dec 2008 14:23:48 +0000 Subject: Missed header changes. --- src/libvdpau/dpb.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index c747a38af..d8586cd33 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -47,14 +47,11 @@ struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, uint32_t longt int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum); int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum); int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx); +int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx); int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic); int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic); -int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum); -int dpb_remove_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); -int dpb_remove_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); -int dpb_remove_ltidx_gt(struct dpb *dpb, uint32_t longterm_max); int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames); int dpb_flush(struct dpb *dpb); -- cgit v1.2.3 From 45ca735e7ebd4d520355cd771531aee76684a671 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 14 Dec 2008 14:51:01 +0000 Subject: Remove unneeded debug printfs & add others. --- src/libvdpau/dpb.c | 17 ++--------------- src/libvdpau/h264_parser.c | 16 ++++------------ src/libvdpau/vdpau_h264.c | 4 ++-- 3 files changed, 8 insertions(+), 29 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 0f5970ced..00dd1a580 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -42,8 +42,6 @@ struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) struct decoded_picture *pic = dpb->pictures; struct decoded_picture *outpic = pic; - printf("dpb used: %d\n", dpb->used); - if(dpb->used < MAX_DPB_SIZE) return NULL; @@ -102,7 +100,6 @@ struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; -printf("UNUSED 1\n"); if (pic != NULL) do { if (pic->nal->curr_pic_num == picnum) { @@ -119,7 +116,6 @@ printf("UNUSED 1\n"); int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum) { struct decoded_picture *pic = dpb->pictures; - printf("UNUSED 2\n"); if (pic != NULL) do { if (pic->nal->long_term_pic_num == longterm_picnum) { @@ -136,7 +132,6 @@ int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum) int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx) { struct decoded_picture *pic = dpb->pictures; - printf("UNUSED 3\n"); if (pic != NULL) do { if (pic->nal->long_term_frame_idx == longterm_idx) { @@ -153,7 +148,6 @@ int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx) int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx) { struct decoded_picture *pic = dpb->pictures; - printf("UNUSED 4\n"); if (pic != NULL) do { if (pic->nal->long_term_frame_idx >= longterm_idx) { @@ -174,11 +168,9 @@ int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx) int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic) { struct decoded_picture *pic = dpb->pictures; -printf("DPB set output pic\n"); if (pic != NULL) do { if (pic == outpic) { - printf("DPB pic num %d output, refuse: %d\n", pic->nal->curr_pic_num, pic->used_for_reference); pic->delayed_output = 0; if(!pic->used_for_reference) dpb_remove_picture(dpb, pic); @@ -193,11 +185,10 @@ int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic) { struct decoded_picture *pic = dpb->pictures; struct decoded_picture *last_pic = NULL; -printf("DPB remove pic\n"); + if (pic != NULL) do { if (pic == rempic) { - printf("DPB found rempic\n"); // FIXME: free the picture.... if (last_pic != NULL) @@ -206,7 +197,6 @@ printf("DPB remove pic\n"); dpb->pictures = pic->next; free_decoded_picture(pic); dpb->used--; - printf("DPB Used: %d\n", dpb->used); return 0; } @@ -241,13 +231,12 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r pic->next = dpb->pictures; dpb->pictures = pic; dpb->used++; -printf("ADD: Used: %d\n", dpb->used); + if(dpb->used > num_ref_frames) { do { if(pic->used_for_reference) { i++; if(i>num_ref_frames) { - printf("DPB REMOVE REF FRAME\n"); pic->used_for_reference = 0; if(!pic->delayed_output) dpb_remove_picture(dpb, pic); @@ -306,8 +295,6 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) last_pic = pic; } while ((pic = pic->next) != NULL && i < 16); - printf("Used ref-frames: %d\n", i); - // fill all other frames with invalid handles while(i < 16) { reflist[i].bottom_is_reference = VDP_FALSE; diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index e5206a943..28f9f607f 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -156,10 +156,9 @@ int32_t read_exp_golomb_s(struct buf_reader *buf) int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) { - if (buf->len < 1) { - printf("ERROR: Empty buffer passed\n"); + if (buf->len < 1) return -1; - } + int ret = -1; struct nal_unit *nal = parser->current_nal; @@ -828,7 +827,6 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, return; if (memory_management_control_operation == 1) { - printf("MMC 1\n"); // short-term -> unused for reference uint32_t pic_num_x = nal->curr_pic_num - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); @@ -844,7 +842,6 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, } } else if (memory_management_control_operation == 2) { - printf("MMC 2\n"); // long-term -> unused for reference struct decoded_picture* pic = dpb_get_picture_by_ltpn(dpb, slc->dec_ref_pic_marking.long_term_pic_num); @@ -860,7 +857,6 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, } } else if (memory_management_control_operation == 3) { - printf("MMC 3\n"); // short-term -> long-term, set long-term frame index uint32_t pic_num_x = nal->curr_pic_num - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); @@ -886,7 +882,6 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, } else if (memory_management_control_operation == 4) { - printf("MMC 4\n"); // set max-long-term frame index, // mark all long-term pictures with long-term frame idx // greater max-long-term farme idx as unused for ref @@ -897,16 +892,13 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 - 1); } else if (memory_management_control_operation == 5) { - printf("MMC 5\n"); // mark all ref pics as unused for reference, // set max-long-term frame index = no long-term frame idxs dpb_flush(dpb); - printf("MMC RESET\n"); parser->pic_order_cnt_lsb = parser->prev_pic_order_cnt_lsb = 0; parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb = 0; } else if (memory_management_control_operation == 6) { - printf("MMC 6\n"); // mark current picture as used for long-term ref, // assing long-term frame idx to it struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, @@ -1053,7 +1045,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->last_nal_res = parse_nal(prebuf+3, parser->prebuf_len-3, parser); if (parser->last_nal_res == 1 && parser->buf_len > 0) { - printf("Frame complete: %d bytes\n", parser->buf_len); + //printf("Frame complete: %d bytes\n", parser->buf_len); *ret_buf = malloc(parser->buf_len); xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); *ret_len = parser->buf_len; @@ -1067,7 +1059,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->slice_cnt = 1; /* this is a SLICE, keep it in the buffer */ - printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); + //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); parser->buf_len += parser->prebuf_len; parser->prebuf_len = 0; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index fbbdbe205..a4446d109 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -310,7 +310,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(!this->decoder_started) this->decoder_started = 1; - dump_pictureinfo_h264(&pic); + //dump_pictureinfo_h264(&pic); /*int i; printf("Decode data: \n"); @@ -369,7 +369,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(!slc->field_pic_flag || !this->wait_for_bottom_field) { decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); this->last_ref_pic = decoded_pic; - printf("Add ref pic: %d\n", decoded_pic->nal->slc->frame_num); decoded_pic->used_for_reference = 1; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); } else if(slc->field_pic_flag && this->wait_for_bottom_field) { @@ -403,6 +402,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->wait_for_bottom_field = 0;*/ + printf("pts: %lld\n", buf->pts); img->draw(img, this->stream); this->wait_for_bottom_field = 0; -- cgit v1.2.3 From 45a43cd9761bb5419a8fc0df07ec0e5c10e1b2cc Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 14 Dec 2008 20:35:59 +0000 Subject: Overlay handling. --- src/video_out/video_out_vdpau.c | 50 +++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 4f5b7d73e..2040e72f2 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -214,20 +214,21 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) ovl->ovl_h = overlay->height; ovl->ovl_x = overlay->x; ovl->ovl_y = overlay->y; - uint8_t *buf = (uint8_t*)malloc(ovl->ovl_w*ovl->ovl_h*4); + uint32_t *buf = (uint32_t*)malloc(ovl->ovl_w*ovl->ovl_h*4); if ( !buf ) return 0; int num_rle = overlay->num_rle; rle_elem_t *rle = overlay->rle; - uint8_t *rgba = buf; + uint32_t *rgba = buf; + uint32_t red, green,blue, alpha; clut_t *low_colors = (clut_t*)overlay->color; clut_t *hili_colors = (clut_t*)overlay->hili_color; uint8_t *low_trans = overlay->trans; uint8_t *hili_trans = overlay->hili_trans; clut_t *colors; uint8_t *trans; - uint8_t alpha; + uint8_t src_alpha; int rlelen = 0; uint8_t clr = 0; int i, pos=0, x, y; @@ -245,13 +246,14 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) } rlelen = rle->len; clr = rle->color; - alpha = trans[clr]; + src_alpha = trans[clr]; for ( i=0; iovl_changed;*/ + ++this->ovl_changed; } static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { - /*vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; if ( !this->ovl_changed || this->ovl_changed>XINE_VORAW_MAX_OVL ) @@ -292,13 +294,13 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v vdpau_overlay_clut_yuv2rgb (this, overlay, frame); if ( vdpau_process_ovl( this, overlay ) ) ++this->ovl_changed; - }*/ + } } static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) { - /*vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; int i; VdpStatus st; @@ -351,7 +353,7 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) printf( "vdpau_overlay_end: vdp_output_surface_render_bitmap_surface failed : %s\n", vdp_get_error_string(st) ); } } - this->ovl_changed = 0;*/ + this->ovl_changed = 0; } @@ -595,9 +597,8 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height }; - /*printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 );*/ + //printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 ); - XLockDisplay( this->display ); if ( this->init_queue>1 ) { int previous = this->current_output_surface ^ 1; @@ -606,29 +607,30 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } uint32_t layer_count; - VdpLayer lay, *layer; + VdpLayer layer[1]; VdpRect layersrc; if ( this->overlay_output_width ) { - printf("vdpau_display_frame: overlay should be visible !\n"); + //printf("vdpau_display_frame: overlay should be visible !\n"); layer_count = 1; layersrc.x0 = 0; layersrc.y0 = 0; layersrc.x1 = this->overlay_output_width; layersrc.y1 = this->overlay_output_height; - lay.struct_version = VDP_LAYER_VERSION; lay.source_surface = this->overlay_output; lay.source_rect = &layersrc; lay.destination_rect = &vid_dest; - layer = &lay; + layer[0].struct_version = VDP_LAYER_VERSION; layer[0].source_surface = this->overlay_output; layer[0].source_rect = &layersrc; layer[0].destination_rect = &layersrc;//&vid_dest; + //printf( "layersrc = %d %d %d %d \n", layersrc.x0, layersrc.y0, layersrc.x1, layersrc.y1 ); } else { layer_count = 0; - layer = 0; } st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, - 0, 0, surface, 0, 0, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer ); + 0, 0, surface, 0, 0, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + XLockDisplay( this->display ); /*if ( this->overlay_output_width ) vdp_queue_display( vdp_queue, this->overlay_output, 0, 0, 0 ); else*/ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); - //printf( "vo_vdpau: image displayed\n" ); + //if ( layer_count ) + //printf( "vo_vdpau: overlay count=%d, surface=%d\n", layer_count, layer[0].source_surface ); if ( this->init_queue<2 ) ++this->init_queue; -- cgit v1.2.3 From 87523c94378d136ad0da9e45102bdec3364cb1d4 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 14 Dec 2008 20:36:12 +0000 Subject: Debug printfs (mostly). --- src/libvdpau/vdpau_mpeg12.c | 293 +++++++++++++++++++++++++++----------------- 1 file changed, 178 insertions(+), 115 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 1045577bd..08e7f30a2 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -21,6 +21,10 @@ * */ +//#define LOG +#define LOG_MODULE "vdpau_mpeg12" + + #include #include #include @@ -109,12 +113,10 @@ uint8_t mpeg2_scan_alt[64] = { typedef struct { VdpPictureInfoMPEG1Or2 vdp_infos; /* first field, also used for frame */ VdpPictureInfoMPEG1Or2 vdp_infos2; /* second field */ - int slices_count; + int slices_count, slices_count2; uint8_t *slices; int slices_size; - int slices_pos; - - int fields; + int slices_pos, slices_pos_top; int state; } picture_t; @@ -174,8 +176,11 @@ typedef struct vdpau_mpeg12_decoder_s { static void reset_picture( picture_t *pic ) { + pic->vdp_infos.picture_structure = 0; pic->slices_count = 0; + pic->slices_count2 = 0; pic->slices_pos = 0; + pic->slices_pos_top = 0; pic->state = WANT_HEADER; } @@ -197,7 +202,7 @@ static void reset_sequence( sequence_t *sequence ) sequence->bufseek = 0; sequence->start = -1; sequence->seq_pts = sequence->cur_pts = 0; - sequence->ratio = 1.0; + //sequence->ratio = 1.0; sequence->video_step = 3600; if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); @@ -239,9 +244,9 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int sequence->seq_pts = sequence->cur_pts; } sequence->coded_width = get_bits( buf,0,12 ); - //printf( "coded_width: %d\n", get_bits( buf,0,12 ) ); + lprintf( "coded_width: %d\n", get_bits( buf,0,12 ) ); sequence->coded_height = get_bits( buf,12,12 ); - //printf( "coded_height: %d\n", get_bits( buf,12,12 ) ); + lprintf( "coded_height: %d\n", get_bits( buf,12,12 ) ); switch ( get_bits( buf+3,0,4 ) ) { case 1: sequence->ratio = 1.0; break; case 2: sequence->ratio = 4.0/3.0; break; @@ -249,7 +254,7 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int case 4: sequence->ratio = 2.21; break; default: sequence->ratio = (double)sequence->coded_width/(double)sequence->coded_height; } - //printf( "ratio: %d\n", get_bits( buf+3,0,4 ) ); + lprintf( "ratio: %d\n", get_bits( buf+3,0,4 ) ); switch ( get_bits( buf+3,4,4 ) ) { case 1: sequence->video_step = 3913; break; /* 23.976.. */ case 2: sequence->video_step = 3750; break; /* 24 */ @@ -260,13 +265,13 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int case 7: sequence->video_step = 1525; break; /* 59.94.. */ case 8: sequence->video_step = 1509; break; /* 60 */ } - //printf( "frame_rate: %d\n", get_bits( buf+3,4,4 ) ); - //printf( "bit_rate_value: %d\n", get_bits( buf+4,0,18 ) ); - //printf( "marker_bit: %d\n", get_bits( buf+6,2,1 ) ); - //printf( "vbv_buffer_size_value: %d\n", get_bits( buf+6,3,10 ) ); - //printf( "constrained_parameters_flag: %d\n", get_bits( buf+7,5,1 ) ); + lprintf( "frame_rate: %d\n", get_bits( buf+3,4,4 ) ); + lprintf( "bit_rate_value: %d\n", get_bits( buf+4,0,18 ) ); + lprintf( "marker_bit: %d\n", get_bits( buf+6,2,1 ) ); + lprintf( "vbv_buffer_size_value: %d\n", get_bits( buf+6,3,10 ) ); + lprintf( "constrained_parameters_flag: %d\n", get_bits( buf+7,5,1 ) ); i = get_bits( buf+7,6,1 ); - //printf( "load_intra_quantizer_matrix: %d\n", i ); + lprintf( "load_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+7+j,7,8 ); @@ -280,7 +285,7 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int } i = get_bits( buf+7+off,7,1 ); - //printf( "load_non_intra_quantizer_matrix: %d\n", i ); + lprintf( "load_non_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+8+off+j,0,8 ); @@ -315,14 +320,26 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) { if ( sequence->picture.state!=WANT_HEADER ) return; - reset_picture( &sequence->picture ); - //printf( "temporal_reference: %d\n", get_bits( buf,0,10 ) ); - sequence->picture.vdp_infos.picture_coding_type = get_bits( buf,10,3 ); - //printf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) ); - sequence->picture.vdp_infos.forward_reference = VDP_INVALID_HANDLE; - sequence->picture.vdp_infos.backward_reference = VDP_INVALID_HANDLE; - sequence->picture.vdp_infos.full_pel_forward_vector = 0; - sequence->picture.vdp_infos.full_pel_backward_vector = 0; + + VdpPictureInfoMPEG1Or2 *infos = &sequence->picture.vdp_infos; + + if ( sequence->picture.vdp_infos.picture_structure && sequence->picture.slices_count2 ) + reset_picture( &sequence->picture ); + + if ( sequence->picture.vdp_infos.picture_structure==PICTURE_FRAME ) { + reset_picture( &sequence->picture ); + } + else if ( sequence->picture.vdp_infos.picture_structure ) { + infos = &sequence->picture.vdp_infos2; + } + + lprintf( "temporal_reference: %d\n", get_bits( buf,0,10 ) ); + infos->picture_coding_type = get_bits( buf,10,3 ); + lprintf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) ); + infos->forward_reference = VDP_INVALID_HANDLE; + infos->backward_reference = VDP_INVALID_HANDLE; + infos->full_pel_forward_vector = 0; + infos->full_pel_backward_vector = 0; sequence->picture.state = WANT_EXT; } @@ -330,22 +347,22 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) static void sequence_extension( sequence_t *sequence, uint8_t *buf, int len ) { - /*printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) );*/ + lprintf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); switch ( get_bits( buf,5,3 ) ) { case 5: sequence->profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; break; default: sequence->profile = VDP_DECODER_PROFILE_MPEG2_MAIN; } - /*printf( "profile_and_level_indication: %d\n", get_bits( buf,4,8 ) ); - printf( "progressive_sequence: %d\n", get_bits( buf,12,1 ) ); - printf( "chroma_format: %d\n", get_bits( buf,13,2 ) ); - printf( "horizontal_size_extension: %d\n", get_bits( buf,15,2 ) ); - printf( "vertical_size_extension: %d\n", get_bits( buf,17,2 ) ); - printf( "bit_rate_extension: %d\n", get_bits( buf,19,12 ) ); - printf( "marker_bit: %d\n", get_bits( buf,31,1 ) ); - printf( "vbv_buffer_size_extension: %d\n", get_bits( buf+4,0,8 ) ); - printf( "low_delay: %d\n", get_bits( buf+5,0,1 ) ); - printf( "frame_rate_extension_n: %d\n", get_bits( buf+5,1,2 ) ); - printf( "frame_rate_extension_d: %d\n", get_bits( buf+5,3,5 ) );*/ + lprintf( "profile_and_level_indication: %d\n", get_bits( buf,4,8 ) ); + lprintf( "progressive_sequence: %d\n", get_bits( buf,12,1 ) ); + lprintf( "chroma_format: %d\n", get_bits( buf,13,2 ) ); + lprintf( "horizontal_size_extension: %d\n", get_bits( buf,15,2 ) ); + lprintf( "vertical_size_extension: %d\n", get_bits( buf,17,2 ) ); + lprintf( "bit_rate_extension: %d\n", get_bits( buf,19,12 ) ); + lprintf( "marker_bit: %d\n", get_bits( buf,31,1 ) ); + lprintf( "vbv_buffer_size_extension: %d\n", get_bits( buf+4,0,8 ) ); + lprintf( "low_delay: %d\n", get_bits( buf+5,0,1 ) ); + lprintf( "frame_rate_extension_n: %d\n", get_bits( buf+5,1,2 ) ); + lprintf( "frame_rate_extension_d: %d\n", get_bits( buf+5,3,5 ) ); } @@ -354,34 +371,39 @@ static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int le { if ( sequence->picture.state!=WANT_EXT ) return; - sequence->picture.vdp_infos.f_code[0][0] = get_bits( buf,4,4 ); - sequence->picture.vdp_infos.f_code[0][1] = get_bits( buf,8,4 ); - sequence->picture.vdp_infos.f_code[1][0] = get_bits( buf,12,4 ); - sequence->picture.vdp_infos.f_code[1][1] = get_bits( buf,16,4 ); - //printf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); - //printf( "f_code_0_0: %d\n", get_bits( buf,4,4 ) ); - //printf( "f_code_0_1: %d\n", get_bits( buf,8,4 ) ); - //printf( "f_code_1_0: %d\n", get_bits( buf,12,4 ) ); - //printf( "f_code_1_1: %d\n", get_bits( buf,16,4 ) ); - sequence->picture.vdp_infos.intra_dc_precision = get_bits( buf,20,2 ); - //printf( "intra_dc_precision: %d\n", get_bits( buf,20,2 ) ); - sequence->picture.vdp_infos.picture_structure = get_bits( buf,22,2 ); - printf( "picture_structure: %d\n", get_bits( buf,22,2 ) ); - sequence->picture.vdp_infos.top_field_first = get_bits( buf,24,1 ); - //printf( "top_field_first: %d\n", get_bits( buf,24,1 ) ); - sequence->picture.vdp_infos.frame_pred_frame_dct = get_bits( buf,25,1 ); - //printf( "frame_pred_frame_dct: %d\n", get_bits( buf,25,1 ) ); - sequence->picture.vdp_infos.concealment_motion_vectors = get_bits( buf,26,1 ); - //printf( "concealment_motion_vectors: %d\n", get_bits( buf,26,1 ) ); - sequence->picture.vdp_infos.q_scale_type = get_bits( buf,27,1 ); - //printf( "q_scale_type: %d\n", get_bits( buf,27,1 ) ); - sequence->picture.vdp_infos.intra_vlc_format = get_bits( buf,28,1 ); - //printf( "intra_vlc_format: %d\n", get_bits( buf,28,1 ) ); - sequence->picture.vdp_infos.alternate_scan = get_bits( buf,29,1 ); - printf( "alternate_scan: %d\n", get_bits( buf,29,1 ) ); - //printf( "repeat_first_field: %d\n", get_bits( buf,30,1 ) ); - //printf( "chroma_420_type: %d\n", get_bits( buf,31,1 ) ); - //printf( "progressive_frame: %d\n", get_bits( buf,32,1 ) ); + + VdpPictureInfoMPEG1Or2 *infos = &sequence->picture.vdp_infos; + if ( infos->picture_structure && infos->picture_structure!=PICTURE_FRAME ) + infos = &sequence->picture.vdp_infos2; + + infos->f_code[0][0] = get_bits( buf,4,4 ); + infos->f_code[0][1] = get_bits( buf,8,4 ); + infos->f_code[1][0] = get_bits( buf,12,4 ); + infos->f_code[1][1] = get_bits( buf,16,4 ); + lprintf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); + lprintf( "f_code_0_0: %d\n", get_bits( buf,4,4 ) ); + lprintf( "f_code_0_1: %d\n", get_bits( buf,8,4 ) ); + lprintf( "f_code_1_0: %d\n", get_bits( buf,12,4 ) ); + lprintf( "f_code_1_1: %d\n", get_bits( buf,16,4 ) ); + infos->intra_dc_precision = get_bits( buf,20,2 ); + lprintf( "intra_dc_precision: %d\n", get_bits( buf,20,2 ) ); + infos->picture_structure = get_bits( buf,22,2 ); + lprintf( "picture_structure: %d\n", get_bits( buf,22,2 ) ); + infos->top_field_first = get_bits( buf,24,1 ); + lprintf( "top_field_first: %d\n", get_bits( buf,24,1 ) ); + infos->frame_pred_frame_dct = get_bits( buf,25,1 ); + lprintf( "frame_pred_frame_dct: %d\n", get_bits( buf,25,1 ) ); + infos->concealment_motion_vectors = get_bits( buf,26,1 ); + lprintf( "concealment_motion_vectors: %d\n", get_bits( buf,26,1 ) ); + infos->q_scale_type = get_bits( buf,27,1 ); + lprintf( "q_scale_type: %d\n", get_bits( buf,27,1 ) ); + infos->intra_vlc_format = get_bits( buf,28,1 ); + lprintf( "intra_vlc_format: %d\n", get_bits( buf,28,1 ) ); + infos->alternate_scan = get_bits( buf,29,1 ); + lprintf( "alternate_scan: %d\n", get_bits( buf,29,1 ) ); + lprintf( "repeat_first_field: %d\n", get_bits( buf,30,1 ) ); + lprintf( "chroma_420_type: %d\n", get_bits( buf,31,1 ) ); + lprintf( "progressive_frame: %d\n", get_bits( buf,32,1 ) ); sequence->picture.state = WANT_SLICE; } @@ -396,14 +418,17 @@ static void copy_slice( sequence_t *sequence, uint8_t *buf, int len ) } xine_fast_memcpy( sequence->picture.slices+sequence->picture.slices_pos, buf, len ); sequence->picture.slices_pos += len; - sequence->picture.slices_count++; + if ( sequence->picture.slices_pos_top ) + sequence->picture.slices_count2++; + else + sequence->picture.slices_count++; } static void quant_matrix_extension( uint8_t *buf, int len ) { - printf("quant_matrix_extension >>>>>>>>>>>>>>>>>>>>>>>>>\n"); + lprintf("quant_matrix_extension >>>>>>>>>>>>>>>>>>>>>>>>>\n"); } @@ -416,58 +441,61 @@ static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) return 0; if ( (buf[3] >= begin_slice_start_code) && (buf[3] <= end_slice_start_code) ) { - //printf( " ----------- slice_start_code\n" ); + lprintf( " ----------- slice_start_code\n" ); if ( sequence->picture.state==WANT_SLICE ) copy_slice( sequence, buf, len ); return 0; } else if ( sequence->picture.state==WANT_SLICE && sequence->picture.slices_count ) { + if ( !sequence->picture.slices_count2 ) { + sequence->picture.slices_pos_top = sequence->picture.slices_pos; + } /* no more slices, decode */ return 1; } switch ( buf[3] ) { case sequence_header_code: - //printf( " ----------- sequence_header_code\n" ); + lprintf( " ----------- sequence_header_code\n" ); sequence_header( this_gen, buf+4, len-4 ); break; case extension_start_code: { switch ( get_bits( buf+4,0,4 ) ) { case sequence_ext_sc: - //printf( " ----------- sequence_extension_start_code\n" ); + lprintf( " ----------- sequence_extension_start_code\n" ); sequence_extension( sequence, buf+4, len-4 ); break; case quant_matrix_ext_sc: - //printf( " ----------- quant_matrix_extension_start_code\n" ); + lprintf( " ----------- quant_matrix_extension_start_code\n" ); quant_matrix_extension( buf+4, len-4 ); break; case picture_coding_ext_sc: - //printf( " ----------- picture_coding_extension_start_code\n" ); + lprintf( " ----------- picture_coding_extension_start_code\n" ); picture_coding_extension( sequence, buf+4, len-4 ); break; case sequence_display_ext_sc: - //printf( " ----------- sequence_display_extension_start_code\n" ); + lprintf( " ----------- sequence_display_extension_start_code\n" ); //sequence_display_extension( sequence, buf+4, len-4 ); break; } break; } case user_data_start_code: - //printf( " ----------- user_data_start_code\n" ); + lprintf( " ----------- user_data_start_code\n" ); break; case group_start_code: - //printf( " ----------- group_start_code\n" ); + lprintf( " ----------- group_start_code\n" ); break; case picture_start_code: - //printf( " ----------- picture_start_code\n" ); + lprintf( " ----------- picture_start_code\n" ); //slice_count = 0; picture_header( sequence, buf+4, len-4 ); break; case sequence_error_code: - //printf( " ----------- sequence_error_code\n" ); + lprintf( " ----------- sequence_error_code\n" ); break; case sequence_end_code: - //printf( " ----------- sequence_end_code\n" ); + lprintf( " ----------- sequence_end_code\n" ); break; } return 0; @@ -475,15 +503,85 @@ static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) +static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) +{ + sequence_t *seq = (sequence_t*)&vd->sequence; + picture_t *pic = (picture_t*)&seq->picture; + + pic->vdp_infos.slice_count = pic->slices_count; + pic->vdp_infos2.slice_count = pic->slices_count2; + + VdpStatus st; + if ( vd->decoder==VDP_INVALID_HANDLE || vd->decoder_profile!=seq->profile || vd->decoder_width!=seq->coded_width || vd->decoder_height!=seq->coded_height ) { + if ( vd->decoder!=VDP_INVALID_HANDLE ) { + accel->vdp_decoder_destroy( vd->decoder ); + vd->decoder = VDP_INVALID_HANDLE; + } + st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder); + if ( st!=VDP_STATUS_OK ) + lprintf( "failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); + else { + vd->decoder_profile = seq->profile; + vd->decoder_width = seq->coded_width; + vd->decoder_height = seq->coded_height; + } + } + if ( accel->surface==VDP_INVALID_HANDLE ) { + st = accel->vdp_video_surface_create( accel->vdp_device, VDP_CHROMA_TYPE_420, seq->coded_width, seq->coded_height, &accel->surface); + if ( st!=VDP_STATUS_OK ) + lprintf( "failed to create surface !! %s\n", accel->vdp_get_error_string( st ) ); + } + + if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME && pic->vdp_infos.picture_coding_type==B_FRAME ) + pic->vdp_infos.forward_reference = pic->vdp_infos.backward_reference; + + VdpBitstreamBuffer vbit; + vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit.bitstream = pic->slices; + vbit.bitstream_bytes = (pic->vdp_infos.picture_structure==PICTURE_FRAME)? pic->slices_pos : pic->slices_pos_top; + st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); + if ( st!=VDP_STATUS_OK ) + lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); + else + lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", + pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + + if ( pic->vdp_infos.picture_structure != PICTURE_FRAME ) { + if ( pic->vdp_infos2.picture_coding_type==P_FRAME ) + pic->vdp_infos2.forward_reference = accel->surface; + else if ( pic->vdp_infos2.picture_coding_type==B_FRAME ) + pic->vdp_infos2.forward_reference = pic->vdp_infos.forward_reference; + else + pic->vdp_infos2.forward_reference = VDP_INVALID_HANDLE; + vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit.bitstream = pic->slices+pic->slices_pos_top; + vbit.bitstream_bytes = pic->slices_pos-pic->slices_pos_top; + st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos2, 1, &vbit ); + if ( st!=VDP_STATUS_OK ) + lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); + else + lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", + pic->vdp_infos2.picture_coding_type, pic->vdp_infos2.slice_count, accel->surface, pic->vdp_infos2.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + } + + //printf( "vdpau_meg12: forwref:%d, backref:%d\n", seq->forward_ref, seq->backward_ref ); +} + + + static void decode_picture( vdpau_mpeg12_decoder_t *vd ) { - //printf("vdpau_mpeg12: decode_picture\n"); sequence_t *seq = (sequence_t*)&vd->sequence; picture_t *pic = (picture_t*)&seq->picture; vdpau_accel_t *ref_accel; pic->state = WANT_HEADER; + if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME && !pic->slices_count2 ) { + lprintf("********************* no slices_count2 **********************\n"); + return; + } + if ( pic->vdp_infos.picture_coding_type==P_FRAME ) { if ( seq->backward_ref ) { ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; @@ -507,52 +605,17 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) return; } - pic->vdp_infos.slice_count = pic->slices_count; - //printf("vdpau_mpeg12: get image ..\n"); vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); - - img->drawn = 0; - //printf("vdpau_mpeg12: .. got image %d\n", img); - vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; if ( !seq->accel_vdpau ) seq->accel_vdpau = accel; - VdpStatus st; - if ( vd->decoder==VDP_INVALID_HANDLE || vd->decoder_profile!=seq->profile || vd->decoder_width!=seq->coded_width || vd->decoder_height!=seq->coded_height ) { - if ( vd->decoder!=VDP_INVALID_HANDLE ) { - accel->vdp_decoder_destroy( vd->decoder ); - vd->decoder = VDP_INVALID_HANDLE; - } - st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder); - if ( st!=VDP_STATUS_OK ) - printf( "vdpau_mpeg12: failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); - else { - vd->decoder_profile = seq->profile; - vd->decoder_width = seq->coded_width; - vd->decoder_height = seq->coded_height; - } - } - if ( accel->surface==VDP_INVALID_HANDLE ) { - st = accel->vdp_video_surface_create( accel->vdp_device, VDP_CHROMA_TYPE_420, seq->coded_width, seq->coded_height, &accel->surface); - if ( st!=VDP_STATUS_OK ) - printf( "vdpau_mpeg12: failed to create surface !! %s\n", accel->vdp_get_error_string( st ) ); - } - - VdpBitstreamBuffer vbit; - vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; - vbit.bitstream = pic->slices; - vbit.bitstream_bytes = pic->slices_pos; - st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); - if ( st!=VDP_STATUS_OK ) - printf( "vdpau_mpeg12: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); - else - printf( "vdpau_mpeg12: DECODER SUCCESS : frame_type:%d, slices=%d, forwref:%d, backref:%d, pts:%lld\n", - pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + img->drawn = 0; + //printf("vdpau_mpeg12: .. got image %d\n", img); - //printf( "vdpau_meg12: forwref:%d, backref:%d\n", seq->forward_ref, seq->backward_ref ); + decode_render( vd, accel ); img->bad_frame = 0; img->duration = seq->video_step; -- cgit v1.2.3 From 28ed70dae3b5736d904d704e76b64e039a459f81 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 14 Dec 2008 20:39:57 +0000 Subject: Overlay fixup. --- src/video_out/video_out_vdpau.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 2040e72f2..5966abd0a 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -625,9 +625,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); XLockDisplay( this->display ); - /*if ( this->overlay_output_width ) + if ( this->overlay_output_width ) vdp_queue_display( vdp_queue, this->overlay_output, 0, 0, 0 ); - else*/ + else vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); //if ( layer_count ) //printf( "vo_vdpau: overlay count=%d, surface=%d\n", layer_count, layer[0].source_surface ); -- cgit v1.2.3 From 4ad3c69c9557f7a4385c549556ef3f1bf08740b5 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 08:14:02 +0000 Subject: Testing. --- src/libvdpau/dpb.c | 34 +++++++++++++++++++++++++--------- src/libvdpau/h264_parser.c | 21 +++++++++++++++++++++ src/libvdpau/nal.h | 23 +++++++++++++++++++++++ src/libvdpau/vdpau_h264.c | 4 +++- 4 files changed, 72 insertions(+), 10 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 00dd1a580..bbcfe4a9d 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -47,7 +47,7 @@ struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) if (pic != NULL) do { - if (pic->img->pts < outpic->img->pts) + if (pic->nal->top_field_order_cnt < outpic->nal->top_field_order_cnt) outpic = pic; } while ((pic = pic->next) != NULL); @@ -97,6 +97,22 @@ struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, return NULL; } +int dpb_set_unused_ref_picture_a(struct dpb *dpb, struct decoded_picture *refpic) +{ + struct decoded_picture *pic = dpb->pictures; + if (pic != NULL) + do { + if (pic == refpic) { + pic->used_for_reference = 0; + if(!pic->delayed_output) + dpb_remove_picture(dpb, pic); + return 0; + } + } while ((pic = pic->next) != NULL); + + return -1; +} + int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; @@ -256,14 +272,14 @@ int dpb_flush(struct dpb *dpb) if (pic != NULL) do { - dpb->pictures = pic->next; - free_decoded_picture(pic); - pic = dpb->pictures; - dpb->used--; - } while (dpb->pictures != NULL); - - dpb->pictures = NULL; - dpb->used = 0; + struct decoded_picture *next_pic = pic->next; + dpb_set_unused_ref_picture_a(dpb, pic); + pic = next_pic; + } while (pic != NULL); + + printf("Flushed, used: %d\n", dpb->used); + //dpb->pictures = NULL; + //dpb->used = 0; return 0; } diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 28f9f607f..2e27bd4aa 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -78,6 +78,15 @@ static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) *len_ret = pos - *ret; } +static inline dump_bits(uint32_t bits) +{ + int i; + printf("0b"); + for(i=0; i < 32; i++) + printf("%d", (bits >> 31-i) & 0x01); + printf("\n"); +} + static inline uint32_t read_bits(struct buf_reader *buf, int len) { static uint32_t i_mask[33] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, @@ -97,10 +106,12 @@ static inline uint32_t read_bits(struct buf_reader *buf, int len) buf->cur_pos++; buf->cur_offset = 8; } + //dump_bits(bits); return bits; } else { bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; + //dump_bits(bits); len -= buf->cur_offset; buf->cur_pos++; buf->cur_offset = 8; @@ -452,6 +463,7 @@ void parse_vui_parameters(struct buf_reader *buf, sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1); if (sps->vui_parameters.aspect_ration_info_present_flag == 1) { sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8); + printf("Aspect idc: %d\n", sps->vui_parameters.aspect_ratio_idc); if (sps->vui_parameters.aspect_ratio_idc == ASPECT_RESERVED) { sps->vui_parameters.sar_width = read_bits(buf, 16); sps->vui_parameters.sar_height = read_bits(buf, 16); @@ -485,8 +497,16 @@ void parse_vui_parameters(struct buf_reader *buf, sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1); if (sps->vui_parameters.timing_info_present_flag) { sps->vui_parameters.num_units_in_tick = read_bits(buf, 32); + printf("Framerate\n"); sps->vui_parameters.time_scale = read_bits(buf, 32); + printf("Time scale: %d\n", sps->vui_parameters.time_scale); + printf("Time scale: %d\n", sps->vui_parameters.time_scale); sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1); + printf("Time scale: %d\n", sps->vui_parameters.time_scale); + printf("Framerate fixed: %d\n", sps->vui_parameters.fixed_frame_rate_flag); + printf("Framerate: %d/%d = %f\n", sps->vui_parameters.num_units_in_tick, + sps->vui_parameters.time_scale, + (double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale); } sps->vui_parameters.nal_hrd_parameters_present_flag = read_bits(buf, 1); @@ -630,6 +650,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) slc->first_mb_in_slice = read_exp_golomb(buf); /* we do some parsing on the slice type, because the list is doubled */ slc->slice_type = slice_type(read_exp_golomb(buf)); + print_slice_type(slc->slice_type); slc->pic_parameter_set_id = read_exp_golomb(buf); slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); if (!sps->frame_mbs_only_flag) { diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index 20c1c32dc..30a38bf7c 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -63,6 +63,29 @@ static inline uint32_t slice_type(uint32_t slice_type) return (slice_type < 10 ? slice_type % 5 : slice_type); } +static inline void print_slice_type(uint32_t slice_type) +{ + switch(slice_type) { + case SLICE_P: + printf("SLICE_P\n"); + break; + case SLICE_B: + printf("SLICE_B\n"); + break; + case SLICE_I: + printf("SLICE_I\n"); + break; + case SLICE_SP: + printf("SLICE_SP\n"); + break; + case SLICE_SI: + printf("SLICE_SI\n"); + break; + default: + printf("Unknown SLICE\n"); + } +} + struct hrd_parameters { uint32_t cpb_cnt_minus1; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index a4446d109..5535a48ae 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -79,6 +79,8 @@ typedef struct vdpau_h264_decoder_s { xine_t *xine; + int64_t last_pts; + } vdpau_h264_decoder_t; /************************************************************************** @@ -266,6 +268,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, printf("IDR Slice, flush\n"); dpb_flush(&(this->nal_parser->dpb)); printf("Emtpy: %s", this->nal_parser->dpb.pictures == NULL ? "Yes" : "No"); + this->last_pts = buf->pts; } this->nal_parser->is_idr = 0; @@ -402,7 +405,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->wait_for_bottom_field = 0;*/ - printf("pts: %lld\n", buf->pts); img->draw(img, this->stream); this->wait_for_bottom_field = 0; -- cgit v1.2.3 From ff60558d1695c5c7ffc68b234b92fcde1f781dab Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 09:07:38 +0000 Subject: More testing. --- src/libvdpau/dpb.c | 6 ++++-- src/libvdpau/h264_parser.c | 13 ++++--------- src/libvdpau/vdpau_h264.c | 21 ++++++++++++++------- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index bbcfe4a9d..5afc93fb6 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -40,14 +40,16 @@ void free_decoded_picture(struct decoded_picture *pic) struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) { struct decoded_picture *pic = dpb->pictures; - struct decoded_picture *outpic = pic; + struct decoded_picture *outpic = NULL; if(dpb->used < MAX_DPB_SIZE) return NULL; if (pic != NULL) do { - if (pic->nal->top_field_order_cnt < outpic->nal->top_field_order_cnt) + if (pic->delayed_output && + (outpic == NULL || + pic->nal->top_field_order_cnt < outpic->nal->top_field_order_cnt)) outpic = pic; } while ((pic = pic->next) != NULL); diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 2e27bd4aa..a70f965cd 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -388,6 +388,7 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) sps->offset_for_ref_frame[i] = read_exp_golomb_s(buf); } } + sps->num_ref_frames = read_exp_golomb(buf); sps->gaps_in_frame_num_value_allowed_flag = read_bits(buf, 1); @@ -463,7 +464,6 @@ void parse_vui_parameters(struct buf_reader *buf, sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1); if (sps->vui_parameters.aspect_ration_info_present_flag == 1) { sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8); - printf("Aspect idc: %d\n", sps->vui_parameters.aspect_ratio_idc); if (sps->vui_parameters.aspect_ratio_idc == ASPECT_RESERVED) { sps->vui_parameters.sar_width = read_bits(buf, 16); sps->vui_parameters.sar_height = read_bits(buf, 16); @@ -497,13 +497,8 @@ void parse_vui_parameters(struct buf_reader *buf, sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1); if (sps->vui_parameters.timing_info_present_flag) { sps->vui_parameters.num_units_in_tick = read_bits(buf, 32); - printf("Framerate\n"); sps->vui_parameters.time_scale = read_bits(buf, 32); - printf("Time scale: %d\n", sps->vui_parameters.time_scale); - printf("Time scale: %d\n", sps->vui_parameters.time_scale); sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1); - printf("Time scale: %d\n", sps->vui_parameters.time_scale); - printf("Framerate fixed: %d\n", sps->vui_parameters.fixed_frame_rate_flag); printf("Framerate: %d/%d = %f\n", sps->vui_parameters.num_units_in_tick, sps->vui_parameters.time_scale, (double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale); @@ -650,7 +645,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) slc->first_mb_in_slice = read_exp_golomb(buf); /* we do some parsing on the slice type, because the list is doubled */ slc->slice_type = slice_type(read_exp_golomb(buf)); - print_slice_type(slc->slice_type); + //print_slice_type(slc->slice_type); slc->pic_parameter_set_id = read_exp_golomb(buf); slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); if (!sps->frame_mbs_only_flag) { @@ -1072,8 +1067,6 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, *ret_len = parser->buf_len; *ret_slice_cnt = parser->slice_cnt; - calculate_pic_order(parser); - //memset(parser->buf, 0x00, parser->buf_len); parser->buf_len = 0; parser->last_nal_res = 1; @@ -1170,6 +1163,8 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) parser->is_idr = 1; } + calculate_pic_order(parser); + if (res >= NAL_SLICE && res <= NAL_SLICE_IDR) { // now detect if it's a new frame! int ret = 0; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 5535a48ae..0d20bc89f 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -183,6 +183,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { this->video_step = buf->decoder_info[0]; + printf("Videostep: %lld\n", this->video_step); _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } @@ -258,6 +259,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { + if(this->last_pts = -1) + this->last_pts = buf->pts; + struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; struct slice_header *slc = this->nal_parser->current_nal->slc; @@ -265,6 +269,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /* flush the DPB if this frame was an IDR */ //printf("is_idr: %d\n", this->nal_parser->is_idr); if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { + this->last_pts = buf->pts; printf("IDR Slice, flush\n"); dpb_flush(&(this->nal_parser->dpb)); printf("Emtpy: %s", this->nal_parser->dpb.pictures == NULL ? "Yes" : "No"); @@ -350,7 +355,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed: %s\n", this->vdpau_accel->vdp_get_error_string(status)); } - printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); + printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->last_pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); @@ -364,7 +369,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, else { img->duration = this->video_step; - img->pts = buf->pts; + img->pts = this->last_pts; + this->last_pts += this->video_step; img->bad_frame = 0; struct decoded_picture *decoded_pic = NULL; @@ -384,7 +390,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(!slc->field_pic_flag || (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { - /*if(!decoded_pic) { + if(!decoded_pic) { decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); decoded_pic->delayed_output = 1; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); @@ -393,7 +399,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img = NULL; - / * now retrieve the next output frame * / + /* now retrieve the next output frame */ decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); if(decoded_pic) { printf("DRAW AN IMAGE\n"); @@ -403,14 +409,14 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } else printf("NO IMAGE THIS TIME\n"); - this->wait_for_bottom_field = 0;*/ + this->wait_for_bottom_field = 0; - img->draw(img, this->stream); + /*img->draw(img, this->stream); this->wait_for_bottom_field = 0; if(!pic.is_reference) img->free(img); - img = NULL; + img = NULL;*/ } else if(slc->field_pic_flag && !slc->bottom_field_flag) { // don't draw yet, second field is missing. this->wait_for_bottom_field = 1; @@ -496,6 +502,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->nal_parser = init_parser(); this->buf = NULL; this->wait_for_bottom_field = 0; + this->video_step = 1800; return &this->video_decoder; } -- cgit v1.2.3 From 395b91f715127f3154476b1461622ab065d7bbf2 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 10:51:25 +0000 Subject: Reordering works for progressive. --- src/libvdpau/dpb.c | 9 +++++---- src/libvdpau/dpb.h | 2 +- src/libvdpau/h264_parser.c | 9 ++++----- src/libvdpau/nal.h | 10 +++++----- src/libvdpau/vdpau_h264.c | 30 ++++++++++++++++++++++-------- 5 files changed, 37 insertions(+), 23 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 5afc93fb6..00f5dca0e 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -10,6 +10,7 @@ #include #include "dpb.h" +#include "nal.h" #include "video_out.h" struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, @@ -49,12 +50,11 @@ struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) do { if (pic->delayed_output && (outpic == NULL || - pic->nal->top_field_order_cnt < outpic->nal->top_field_order_cnt)) + pic->nal->top_field_order_cnt < outpic->nal->top_field_order_cnt || + outpic->nal->nal_unit_type == NAL_SLICE_IDR)) outpic = pic; } while ((pic = pic->next) != NULL); - if(outpic) - printf("OUTPUT: %lld\n", outpic->img->pts); return outpic; } @@ -256,8 +256,9 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r i++; if(i>num_ref_frames) { pic->used_for_reference = 0; - if(!pic->delayed_output) + if(!pic->delayed_output) { dpb_remove_picture(dpb, pic); + } pic = last_pic; } last_pic = pic; diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index d8586cd33..d76e47ee0 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -8,7 +8,7 @@ #ifndef DPB_H_ #define DPB_H_ -#define MAX_DPB_SIZE 10 +#define MAX_DPB_SIZE 16 #include "nal.h" #include "video_out.h" diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index a70f965cd..9be736083 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -496,12 +496,11 @@ void parse_vui_parameters(struct buf_reader *buf, sps->vui_parameters.timing_info_present_flag = read_bits(buf, 1); if (sps->vui_parameters.timing_info_present_flag) { - sps->vui_parameters.num_units_in_tick = read_bits(buf, 32); - sps->vui_parameters.time_scale = read_bits(buf, 32); + uint32_t num_units_in_tick = read_bits(buf, 32); + uint32_t time_scale = read_bits(buf, 32); + sps->vui_parameters.num_units_in_tick = num_units_in_tick; + sps->vui_parameters.time_scale = time_scale; sps->vui_parameters.fixed_frame_rate_flag = read_bits(buf, 1); - printf("Framerate: %d/%d = %f\n", sps->vui_parameters.num_units_in_tick, - sps->vui_parameters.time_scale, - (double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale); } sps->vui_parameters.nal_hrd_parameters_present_flag = read_bits(buf, 1); diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index 30a38bf7c..351a3d84f 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -150,7 +150,7 @@ struct seq_parameter_set_rbsp uint8_t vui_parameters_present_flag; /* vui_parameters */ - union + struct { uint8_t aspect_ration_info_present_flag; @@ -269,7 +269,7 @@ struct sei_message uint32_t payload_size; uint8_t last_payload_size_byte; - union + struct { /* cpb_dpb_delays_present_flag == 1 */ uint8_t cpb_removal_delay; @@ -309,7 +309,7 @@ struct slice_header uint32_t num_ref_idx_l1_active_minus1; /* ref_pic_list_reordering */ - union + struct { /* slice_type != I && slice_type != SI */ uint8_t ref_pic_list_reordering_flag_l0; @@ -328,7 +328,7 @@ struct slice_header } ref_pic_list_reordering; /* pred_weight_table */ - union + struct { uint32_t luma_log2_weight_denom; @@ -349,7 +349,7 @@ struct slice_header } pred_weight_table; /* def_rec_pic_marking */ - union + struct { /* nal_unit_type == NAL_SLICE_IDR */ diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 0d20bc89f..bb9d17c62 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -80,6 +80,7 @@ typedef struct vdpau_h264_decoder_s { xine_t *xine; int64_t last_pts; + int64_t last_idr_pts; } vdpau_h264_decoder_t; @@ -259,17 +260,24 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { - if(this->last_pts = -1) + if(this->last_pts == 0) this->last_pts = buf->pts; struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; struct slice_header *slc = this->nal_parser->current_nal->slc; + if(sps->vui_parameters_present_flag && + sps->vui_parameters.timing_info_present_flag && + this->video_step == 0) { + this->video_step = 90000/(1/((double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale)); + printf("Videostep: %d\n", this->video_step); + } + /* flush the DPB if this frame was an IDR */ //printf("is_idr: %d\n", this->nal_parser->is_idr); if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { - this->last_pts = buf->pts; + this->last_idr_pts = buf->pts; printf("IDR Slice, flush\n"); dpb_flush(&(this->nal_parser->dpb)); printf("Emtpy: %s", this->nal_parser->dpb.pictures == NULL ? "Yes" : "No"); @@ -355,7 +363,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed: %s\n", this->vdpau_accel->vdp_get_error_string(status)); } - printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->last_pts); + printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); @@ -368,9 +376,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); else { - img->duration = this->video_step; - img->pts = this->last_pts; - this->last_pts += this->video_step; + img->duration = (!slc->field_pic_flag*2)*this->video_step; + img->pts = 0; img->bad_frame = 0; struct decoded_picture *decoded_pic = NULL; @@ -388,6 +395,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } } + printf("field_pic_flag: %d\n", slc->field_pic_flag); if(!slc->field_pic_flag || (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { if(!decoded_pic) { @@ -402,7 +410,12 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /* now retrieve the next output frame */ decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); if(decoded_pic) { - printf("DRAW AN IMAGE\n"); + if(decoded_pic->nal->nal_unit_type == NAL_SLICE_IDR) + this->last_pts = this->last_idr_pts; + + decoded_pic->img->pts = this->last_pts; + this->last_pts += (this->wait_for_bottom_field*2)*this->video_step; + printf("poc: %d, %d\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); @@ -502,7 +515,8 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->nal_parser = init_parser(); this->buf = NULL; this->wait_for_bottom_field = 0; - this->video_step = 1800; + this->video_step = 0; + this->last_idr_pts = this->last_pts = 0; return &this->video_decoder; } -- cgit v1.2.3 From 3c453ddf665670cbfed6f03bce270835df163df1 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 12:48:43 +0000 Subject: Proper reordering. --- src/libvdpau/dpb.c | 5 ++++- src/libvdpau/vdpau_h264.c | 26 ++++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 00f5dca0e..809bd00fc 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -48,9 +48,12 @@ struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) if (pic != NULL) do { + if(outpic) + printf("select: %d, %d\n", pic->nal->top_field_order_cnt, outpic->nal->top_field_order_cnt); if (pic->delayed_output && (outpic == NULL || - pic->nal->top_field_order_cnt < outpic->nal->top_field_order_cnt || + (pic->nal->top_field_order_cnt <= outpic->nal->top_field_order_cnt && + pic->nal->bottom_field_order_cnt <= outpic->nal->bottom_field_order_cnt)|| outpic->nal->nal_unit_type == NAL_SLICE_IDR)) outpic = pic; } while ((pic = pic->next) != NULL); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index bb9d17c62..ab0891cf7 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -80,7 +80,6 @@ typedef struct vdpau_h264_decoder_s { xine_t *xine; int64_t last_pts; - int64_t last_idr_pts; } vdpau_h264_decoder_t; @@ -184,7 +183,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { this->video_step = buf->decoder_info[0]; - printf("Videostep: %lld\n", this->video_step); + printf("Videostep: %d\n", this->video_step); _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } @@ -270,18 +269,16 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(sps->vui_parameters_present_flag && sps->vui_parameters.timing_info_present_flag && this->video_step == 0) { - this->video_step = 90000/(1/((double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale)); + this->video_step = 2*90000/(1/((double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale)); printf("Videostep: %d\n", this->video_step); } /* flush the DPB if this frame was an IDR */ //printf("is_idr: %d\n", this->nal_parser->is_idr); if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { - this->last_idr_pts = buf->pts; printf("IDR Slice, flush\n"); dpb_flush(&(this->nal_parser->dpb)); printf("Emtpy: %s", this->nal_parser->dpb.pictures == NULL ? "Yes" : "No"); - this->last_pts = buf->pts; } this->nal_parser->is_idr = 0; @@ -376,8 +373,12 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); else { - img->duration = (!slc->field_pic_flag*2)*this->video_step; - img->pts = 0; + img->duration = 0; + if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) + img->pts = buf->pts; + else + img->pts = 0; + img->bad_frame = 0; struct decoded_picture *decoded_pic = NULL; @@ -410,12 +411,13 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /* now retrieve the next output frame */ decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); if(decoded_pic) { - if(decoded_pic->nal->nal_unit_type == NAL_SLICE_IDR) - this->last_pts = this->last_idr_pts; + if(decoded_pic->nal->nal_unit_type == NAL_SLICE_IDR) { + this->last_pts = decoded_pic->img->pts; + } decoded_pic->img->pts = this->last_pts; - this->last_pts += (this->wait_for_bottom_field*2)*this->video_step; - printf("poc: %d, %d\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt); + this->last_pts += (this->wait_for_bottom_field+1)*this->video_step; + printf("poc: %d, %d, pts: %lld\n\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt, decoded_pic->img->pts); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); @@ -516,7 +518,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->buf = NULL; this->wait_for_bottom_field = 0; this->video_step = 0; - this->last_idr_pts = this->last_pts = 0; + this->last_pts = 0; return &this->video_decoder; } -- cgit v1.2.3 From 0ea5575f5b9e5eda279a99c7acbbc63d13a88274 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 14:05:23 +0000 Subject: Fix endless loop. --- src/libvdpau/dpb.c | 2 -- src/libvdpau/h264_parser.c | 4 ++-- src/libvdpau/vdpau_h264.c | 17 +++++++++++------ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 809bd00fc..0c0388e25 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -48,8 +48,6 @@ struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) if (pic != NULL) do { - if(outpic) - printf("select: %d, %d\n", pic->nal->top_field_order_cnt, outpic->nal->top_field_order_cnt); if (pic->delayed_output && (outpic == NULL || (pic->nal->top_field_order_cnt <= outpic->nal->top_field_order_cnt && diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 9be736083..515a1db5e 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1132,14 +1132,14 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, * this might happen if the nal start sequence is split * over the buf-boundary - if this is the case we */ - if((next_nal = seek_for_nal(prebuf+3, parser->prebuf_len)) >= 0) { + if(parsed_len > 2 && + (next_nal = seek_for_nal(prebuf+3, parser->prebuf_len)) >= 0) { inbuf -= parser->prebuf_len-next_nal-3; parsed_len -= parser->prebuf_len-next_nal-3; parser->prebuf_len = next_nal+3; } } - *ret_len = 0; *ret_buf = NULL; return parsed_len; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ab0891cf7..48746bc40 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -80,6 +80,7 @@ typedef struct vdpau_h264_decoder_s { xine_t *xine; int64_t last_pts; + int64_t tmp_pts; } vdpau_h264_decoder_t; @@ -342,11 +343,13 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(img == NULL) { fflush(stdout); + //printf("Acquire Image\n"); img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); this->vdpau_accel = (vdpau_accel_t*)img->accel_data; + //printf("OK\n"); } VdpVideoSurface surface = this->vdpau_accel->surface; @@ -360,7 +363,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed: %s\n", this->vdpau_accel->vdp_get_error_string(status)); } - printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); + //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); @@ -396,7 +399,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } } - printf("field_pic_flag: %d\n", slc->field_pic_flag); if(!slc->field_pic_flag || (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { if(!decoded_pic) { @@ -411,15 +413,17 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /* now retrieve the next output frame */ decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); if(decoded_pic) { - if(decoded_pic->nal->nal_unit_type == NAL_SLICE_IDR) { + if(decoded_pic->nal->nal_unit_type == NAL_SLICE_IDR && + decoded_pic->img->pts != 0) { this->last_pts = decoded_pic->img->pts; } + printf("pts diff: %d\n", this->last_pts - this->tmp_pts); decoded_pic->img->pts = this->last_pts; - this->last_pts += (this->wait_for_bottom_field+1)*this->video_step; - printf("poc: %d, %d, pts: %lld\n\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt, decoded_pic->img->pts); + this->tmp_pts = decoded_pic->img->pts; + this->last_pts += this->video_step; + printf("poc: %d, %d, pts: %lld\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt, decoded_pic->img->pts); decoded_pic->img->draw(decoded_pic->img, this->stream); - dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); } else printf("NO IMAGE THIS TIME\n"); @@ -519,6 +523,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->wait_for_bottom_field = 0; this->video_step = 0; this->last_pts = 0; + this->tmp_pts = 0; return &this->video_decoder; } -- cgit v1.2.3 From b08385e8109ffc196aa13b9cc6dc608e98184587 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 14:11:56 +0000 Subject: Set img->duration. --- src/libvdpau/vdpau_h264.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 48746bc40..ebf838772 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -376,7 +376,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); else { - img->duration = 0; + img->duration = this->video_step; if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) img->pts = buf->pts; else -- cgit v1.2.3 From 5b2f970099040357993e37a59bcf63ef8ad24366 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 14:43:31 +0000 Subject: Testing interlacing. --- src/libvdpau/vdpau_h264.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ebf838772..d3c4cd5df 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -343,13 +343,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(img == NULL) { fflush(stdout); - //printf("Acquire Image\n"); img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); this->vdpau_accel = (vdpau_accel_t*)img->accel_data; - //printf("OK\n"); } VdpVideoSurface surface = this->vdpau_accel->surface; @@ -376,11 +374,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); else { - img->duration = this->video_step; - if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) + img->duration = 0; //this->video_step; + //if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) img->pts = buf->pts; - else - img->pts = 0; + //else + // img->pts = 0; img->bad_frame = 0; @@ -419,7 +417,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } printf("pts diff: %d\n", this->last_pts - this->tmp_pts); - decoded_pic->img->pts = this->last_pts; + //decoded_pic->img->pts = this->last_pts; this->tmp_pts = decoded_pic->img->pts; this->last_pts += this->video_step; printf("poc: %d, %d, pts: %lld\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt, decoded_pic->img->pts); -- cgit v1.2.3 From c3c01b015a95a367b2bc975132f97038e5e1b71c Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 14:58:52 +0000 Subject: Fix interlacing (partly). --- src/libvdpau/vdpau_h264.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index d3c4cd5df..313790e11 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -324,7 +324,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(!this->decoder_started) this->decoder_started = 1; - //dump_pictureinfo_h264(&pic); + dump_pictureinfo_h264(&pic); /*int i; printf("Decode data: \n"); @@ -374,11 +374,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); else { - img->duration = 0; //this->video_step; - //if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) + img->duration = this->video_step; + if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) img->pts = buf->pts; - //else - // img->pts = 0; + else + img->pts = 0; img->bad_frame = 0; @@ -392,6 +392,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } else if(slc->field_pic_flag && this->wait_for_bottom_field) { if(this->last_ref_pic) { decoded_pic = this->last_ref_pic; + free_nal_unit(decoded_pic->nal); + decoded_pic->nal = init_nal_unit(); + copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal); this->last_ref_pic->bottom_is_reference = 1; } } @@ -416,8 +419,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->last_pts = decoded_pic->img->pts; } - printf("pts diff: %d\n", this->last_pts - this->tmp_pts); - //decoded_pic->img->pts = this->last_pts; + decoded_pic->img->pts = this->last_pts; this->tmp_pts = decoded_pic->img->pts; this->last_pts += this->video_step; printf("poc: %d, %d, pts: %lld\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt, decoded_pic->img->pts); -- cgit v1.2.3 From dd0712cc351add6f93b07a122e40ce4c842591a2 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 15:03:14 +0000 Subject: Fix reordering. --- src/libvdpau/nal.c | 11 ++++++++--- src/libvdpau/vdpau_h264.c | 8 ++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/libvdpau/nal.c b/src/libvdpau/nal.c index 0964c446e..366aefd4e 100644 --- a/src/libvdpau/nal.c +++ b/src/libvdpau/nal.c @@ -43,9 +43,14 @@ void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src) xine_fast_memcpy(dest, src, size); - dest->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); - dest->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); - dest->slc = malloc(sizeof(struct slice_header)); + if(!dest->sps) + dest->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + + if(!dest->pps) + dest->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + + if(!dest->slc) + dest->slc = malloc(sizeof(struct slice_header)); xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp)); xine_fast_memcpy(dest->pps, src->pps, sizeof(struct pic_parameter_set_rbsp)); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 313790e11..574386b67 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -324,7 +324,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(!this->decoder_started) this->decoder_started = 1; - dump_pictureinfo_h264(&pic); + //dump_pictureinfo_h264(&pic); /*int i; printf("Decode data: \n"); @@ -392,9 +392,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } else if(slc->field_pic_flag && this->wait_for_bottom_field) { if(this->last_ref_pic) { decoded_pic = this->last_ref_pic; - free_nal_unit(decoded_pic->nal); - decoded_pic->nal = init_nal_unit(); - copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal); + //copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal); + decoded_pic->nal->top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt; + decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; this->last_ref_pic->bottom_is_reference = 1; } } -- cgit v1.2.3 From c62e5fb1b42ff6ceaede676e154b22872c0c11a7 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 15:24:54 +0000 Subject: Fix aspect ratio. --- src/libvdpau/h264_parser.c | 2 +- src/libvdpau/nal.h | 3 ++- src/libvdpau/vdpau_h264.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 515a1db5e..ee6fef682 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -464,7 +464,7 @@ void parse_vui_parameters(struct buf_reader *buf, sps->vui_parameters.aspect_ration_info_present_flag = read_bits(buf, 1); if (sps->vui_parameters.aspect_ration_info_present_flag == 1) { sps->vui_parameters.aspect_ratio_idc = read_bits(buf, 8); - if (sps->vui_parameters.aspect_ratio_idc == ASPECT_RESERVED) { + if (sps->vui_parameters.aspect_ratio_idc == ASPECT_EXTENDED_SAR) { sps->vui_parameters.sar_width = read_bits(buf, 16); sps->vui_parameters.sar_height = read_bits(buf, 16); } diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index 351a3d84f..17f5604b6 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -55,7 +55,8 @@ enum aspect_ratio ASPECT_4_3, ASPECT_3_2, ASPECT_2_1, - ASPECT_RESERVED + ASPECT_RESERVED, + ASPECT_EXTENDED_SAR=255 }; static inline uint32_t slice_type(uint32_t slice_type) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 574386b67..be42b6210 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -213,6 +213,64 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, * support anamorph codings... */ this->ratio = (double)this->width / (double)this->height; + if(this->nal_parser->current_nal->sps->vui_parameters.aspect_ration_info_present_flag) { + switch(this->nal_parser->current_nal->sps->vui_parameters.aspect_ratio_idc) { + case ASPECT_1_1: + this->ratio = 1 * this->ratio; + break; + case ASPECT_12_11: + this->ratio *= 12.0/11.0; + break; + case ASPECT_10_11: + this->ratio *= 10.0/11.0; + break; + case ASPECT_16_11: + this->ratio *= 16.0/11.0; + break; + case ASPECT_40_33: + this->ratio *= 40.0/33.0; + break; + case ASPECT_24_11: + this->ratio *= 24.0/11.0; + break; + case ASPECT_20_11: + this->ratio *= 20.0/11.0; + break; + case ASPECT_32_11: + this->ratio *= 32.0/11.0; + break; + case ASPECT_80_33: + this->ratio *= 80.0/33.0; + break; + case ASPECT_18_11: + this->ratio *= 18.0/11.0; + break; + case ASPECT_15_11: + this->ratio *= 15.0/11.0; + break; + case ASPECT_64_33: + this->ratio *= 64.0/33.0; + break; + case ASPECT_160_99: + this->ratio *= 160.0/99.0; + break; + case ASPECT_4_3: + this->ratio *= 4.0/3.0; + break; + case ASPECT_3_2: + this->ratio *= 3.0/2.0; + break; + case ASPECT_2_1: + this->ratio *= 2.0/1.0; + break; + case ASPECT_EXTENDED_SAR: + this->ratio *= + (double)this->nal_parser->current_nal->sps->vui_parameters.sar_width/ + (double)this->nal_parser->current_nal->sps->vui_parameters.sar_height; + break; + } + } + switch(this->nal_parser->current_nal->sps->profile_idc) { case 100: -- cgit v1.2.3 From 1f330e0deb67dbda0aa4d03ea623140928f0ec8b Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 15 Dec 2008 17:00:26 +0000 Subject: Fix streams where top/bottom references are not necessarily paired. --- src/libvdpau/h264_parser.c | 19 ++++++++++++++++--- src/libvdpau/vdpau_h264.c | 13 ++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index ee6fef682..d436cf952 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -262,7 +262,7 @@ void calculate_pic_order(struct nal_parser *parser) else parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; - if (!slc->bottom_field_flag) { + /*if (!slc->bottom_field_flag) { nal->top_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; @@ -277,6 +277,19 @@ void calculate_pic_order(struct nal_parser *parser) if (parser->field == -1) nal->bottom_field_order_cnt += slc->delta_pic_order_cnt_bottom; + */ + + if(!slc->field_pic_flag || !slc->bottom_field_flag) + nal->top_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; + + if(!slc->field_pic_flag) + nal->bottom_field_order_cnt = nal->top_field_order_cnt + slc->delta_pic_order_cnt_bottom; + else + nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; + + + } else { + printf("FIXME: Unsupported poc_type\n"); } } @@ -910,8 +923,8 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, // mark all ref pics as unused for reference, // set max-long-term frame index = no long-term frame idxs dpb_flush(dpb); - parser->pic_order_cnt_lsb = parser->prev_pic_order_cnt_lsb = 0; - parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb = 0; + parser->prev_pic_order_cnt_lsb = 0; + parser->prev_pic_order_cnt_msb = 0; } else if (memory_management_control_operation == 6) { // mark current picture as used for long-term ref, diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index be42b6210..f69e07387 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -70,6 +70,7 @@ typedef struct vdpau_h264_decoder_s { struct nal_parser *nal_parser; /* h264 nal parser. extracts stream data for vdpau */ uint8_t wait_for_bottom_field; struct decoded_picture *last_ref_pic; + uint32_t last_top_field_order_cnt; VdpDecoder decoder; @@ -337,7 +338,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { printf("IDR Slice, flush\n"); dpb_flush(&(this->nal_parser->dpb)); - printf("Emtpy: %s", this->nal_parser->dpb.pictures == NULL ? "Yes" : "No"); } this->nal_parser->is_idr = 0; @@ -451,7 +451,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(this->last_ref_pic) { decoded_pic = this->last_ref_pic; //copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal); - decoded_pic->nal->top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt; decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; this->last_ref_pic->bottom_is_reference = 1; } @@ -464,9 +463,13 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); decoded_pic->delayed_output = 1; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); + if(decoded_pic->nal->slc->bottom_field_flag) + decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; } else decoded_pic->delayed_output = 1; + if(this->wait_for_bottom_field && slc->bottom_field_flag) + decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; img = NULL; /* now retrieve the next output frame */ @@ -480,11 +483,10 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, decoded_pic->img->pts = this->last_pts; this->tmp_pts = decoded_pic->img->pts; this->last_pts += this->video_step; - printf("poc: %d, %d, pts: %lld\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt, decoded_pic->img->pts); + //printf("poc: %d, %d, pts: %lld\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt, decoded_pic->img->pts); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); - } else - printf("NO IMAGE THIS TIME\n"); + } this->wait_for_bottom_field = 0; @@ -496,6 +498,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img = NULL;*/ } else if(slc->field_pic_flag && !slc->bottom_field_flag) { // don't draw yet, second field is missing. + this->last_top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt; this->wait_for_bottom_field = 1; } } -- cgit v1.2.3 From afff60c711f215f2d0cd86b82a1742c59cb81e4a Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 16 Dec 2008 09:35:20 +0000 Subject: OSD working. --- src/video_out/video_out_vdpau.c | 207 ++++++++++++++++++++++++++++------------ 1 file changed, 145 insertions(+), 62 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 5966abd0a..3002d16ea 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -49,11 +49,13 @@ #include #include "accel_vdpau.h" +#define NUM_FRAMES_BACK 2 + VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE , - VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ZERO, - VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_SRC_ALPHA, + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD }; @@ -109,6 +111,7 @@ typedef struct { uint32_t bitmap_width, bitmap_height; int ovl_w, ovl_h; /* overlay's width and height */ int ovl_x, ovl_y; /* overlay's top-left display position */ + int unscaled; } vdpau_overlay_t; @@ -140,6 +143,12 @@ typedef struct { VdpOutputSurface overlay_output; uint32_t overlay_output_width; uint32_t overlay_output_height; + int has_overlay; + + VdpOutputSurface overlay_unscaled; + uint32_t overlay_unscaled_width; + uint32_t overlay_unscaled_height; + int has_unscaled; VdpVideoSurface soft_surface; uint32_t soft_surface_width; @@ -157,9 +166,11 @@ typedef struct { uint32_t video_mixer_width; uint32_t video_mixer_height; + vdpau_frame_t *back_frame[ NUM_FRAMES_BACK ]; + uint32_t capabilities; xine_t *xine; - int gotimage; + } vdpau_driver_t; @@ -214,6 +225,7 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) ovl->ovl_h = overlay->height; ovl->ovl_x = overlay->x; ovl->ovl_y = overlay->y; + ovl->unscaled = overlay->unscaled; uint32_t *buf = (uint32_t*)malloc(ovl->ovl_w*ovl->ovl_h*4); if ( !buf ) return 0; @@ -221,7 +233,7 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) int num_rle = overlay->num_rle; rle_elem_t *rle = overlay->rle; uint32_t *rgba = buf; - uint32_t red, green,blue, alpha; + uint32_t red, green, blue, alpha; clut_t *low_colors = (clut_t*)overlay->color; clut_t *hili_colors = (clut_t*)overlay->hili_color; uint8_t *low_trans = overlay->trans; @@ -253,7 +265,7 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) blue = colors[clr].cb; /* blue */ alpha = src_alpha*255/15; *rgba = (alpha<<24) | (red<<16) | (green<<8) | blue; - rgba++;//= 4; + rgba++; ++pos; } ++rle; @@ -298,7 +310,7 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v } -static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) +static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; int i; @@ -307,17 +319,20 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) if ( !this->ovl_changed ) return; - this->overlay_output_width = this->overlay_output_height = 0; + int w=0, h=0; for ( i=0; iovl_changed-1; ++i ) { - int w = this->overlays[i].ovl_x+this->overlays[i].ovl_w; - int h = this->overlays[i].ovl_y+this->overlays[i].ovl_h; - if ( w > this->overlay_output_width ) - this->overlay_output_width = w; - if ( h > this->overlay_output_height ) - this->overlay_output_height = h; + if ( this->overlays[i].unscaled ) + continue; + if ( w < (this->overlays[i].ovl_x+this->overlays[i].ovl_w) ) + w = this->overlays[i].ovl_x+this->overlays[i].ovl_w; + if ( h < (this->overlays[i].ovl_y+this->overlays[i].ovl_h) ) + h = this->overlays[i].ovl_y+this->overlays[i].ovl_h; } - printf( "vdpau_overlay_end: output_overlay size = %dx%d\n", this->overlay_output_width, this->overlay_output_height ); - if ( this->overlay_output != VDP_INVALID_HANDLE ) { + + int out_w = (w>frame->width) ? w : frame->width; + int out_h = (h>frame->height) ? h : frame->height; + + if ( (this->overlay_output_width!=out_w || this->overlay_output_height!=out_h) && this->overlay_output != VDP_INVALID_HANDLE ) { st = vdp_output_surface_destroy( this->overlay_output ); if ( st != VDP_STATUS_OK ) { printf( "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) ); @@ -325,34 +340,77 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) this->overlay_output = VDP_INVALID_HANDLE; } + w = 0; h = 0; + for ( i=0; iovl_changed-1; ++i ) { + if ( !this->overlays[i].unscaled ) + continue; + if ( w < (this->overlays[i].ovl_x+this->overlays[i].ovl_w) ) + w = this->overlays[i].ovl_x+this->overlays[i].ovl_w; + if ( h < (this->overlays[i].ovl_y+this->overlays[i].ovl_h) ) + h = this->overlays[i].ovl_y+this->overlays[i].ovl_h; + } + + if ( (this->overlay_unscaled_width!=w || this->overlay_unscaled_height!=h) && this->overlay_unscaled != VDP_INVALID_HANDLE ) { + st = vdp_output_surface_destroy( this->overlay_unscaled ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) ); + } + this->overlay_unscaled = VDP_INVALID_HANDLE; + } + if ( !(this->ovl_changed-1) ) { this->ovl_changed = 0; + this->has_overlay = 0; return; } - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_output_width, this->overlay_output_height, &this->overlay_output ); - if ( st != VDP_STATUS_OK ) { - printf( "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + this->overlay_unscaled_width = w; + this->overlay_unscaled_height = h; + + if ( this->overlay_unscaled == VDP_INVALID_HANDLE ) { + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_unscaled_width, this->overlay_unscaled_height, &this->overlay_unscaled ); + if ( st != VDP_STATUS_OK ) + printf( "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); } - uint32_t *buf = (uint32_t*)malloc(this->overlay_output_width*this->overlay_output_height*4); - uint32_t pitch = this->overlay_output_width*4; + this->overlay_output_width = out_w; + this->overlay_output_height = out_h; + + if ( this->overlay_output == VDP_INVALID_HANDLE ) { + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_output_width, this->overlay_output_height, &this->overlay_output ); + if ( st != VDP_STATUS_OK ) + printf( "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + } + + w = (this->overlay_unscaled_width>this->overlay_output_width) ? this->overlay_unscaled_width : this->overlay_output_width; + h = (this->overlay_unscaled_height>this->overlay_output_height) ? this->overlay_unscaled_height : this->overlay_output_height; + + uint32_t *buf = (uint32_t*)malloc(w*h*4); + uint32_t pitch = w*4; + memset( buf, 0, w*h*4 ); VdpRect clear = { 0, 0, this->overlay_output_width, this->overlay_output_height }; - memset( buf, 0, this->overlay_output_width*this->overlay_output_height*4 ); st = vdp_output_surface_put_bits( this->overlay_output, &buf, &pitch, &clear ); if ( st != VDP_STATUS_OK ) { printf( "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) ); } + clear.x1 = this->overlay_unscaled_width; clear.y1 = this->overlay_unscaled_height; + st = vdp_output_surface_put_bits( this->overlay_unscaled, &buf, &pitch, &clear ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) ); + } free(buf); + VdpOutputSurface *surface; for ( i=0; iovl_changed-1; ++i ) { VdpRect dest = { this->overlays[i].ovl_x, this->overlays[i].ovl_y, this->overlays[i].ovl_x+this->overlays[i].ovl_w, this->overlays[i].ovl_y+this->overlays[i].ovl_h }; VdpRect src = { 0, 0, this->overlays[i].ovl_w, this->overlays[i].ovl_h }; - st = vdp_output_surface_render_bitmap_surface( this->overlay_output, &dest, this->overlays[i].ovl_bitmap, &src, 0, &blend, 0 ); + surface = (this->overlays[i].unscaled) ? &this->overlay_unscaled : &this->overlay_output; + st = vdp_output_surface_render_bitmap_surface( *surface, &dest, this->overlays[i].ovl_bitmap, &src, 0, &blend, 0 ); if ( st != VDP_STATUS_OK ) { printf( "vdpau_overlay_end: vdp_output_surface_render_bitmap_surface failed : %s\n", vdp_get_error_string(st) ); } } + this->has_overlay = 1; this->ovl_changed = 0; } @@ -488,6 +546,20 @@ static int vdpau_redraw_needed (vo_driver_t *this_gen) +static void vdpau_release_back_frames( vo_driver_t *this_gen ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + int i; + + for ( i=0; iback_frame[ i ]) + this->back_frame[ i ]->vo_frame.free( &this->back_frame[ i ]->vo_frame ); + this->back_frame[ i ] = NULL; + } +} + + + static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -526,7 +598,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_video_surface_destroy( this->soft_surface ); vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); } - /* FIXME: have to swap U and V planes to get correct colors !! nvidia ? */ + /* FIXME: have to swap U and V planes to get correct colors !! */ uint32_t pitches[] = { frame->vo_frame.pitches[0], frame->vo_frame.pitches[2], frame->vo_frame.pitches[1] }; void* data[] = { frame->vo_frame.base[0], frame->vo_frame.base[2], frame->vo_frame.base[1] }; if ( frame->format==XINE_IMGFMT_YV12 ) { @@ -543,28 +615,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) else if (frame->format == XINE_IMGFMT_VDPAU) { //printf( "vo_vdpau: got a vdpau image -------------\n" ); surface = frame->vdpau_accel_data.surface; - /*if ( !this->gotimage ) { - printf( "vo_vdpau: mallocing yuv ......\n" ); - uint32_t pitches[] = { 8*((frame->width + 7) / 8), 8*((frame->width + 15) / 16), 8*((frame->width + 15) / 16) }; - uint8_t *mem_y = (uint8_t*)malloc(frame->width*frame->height); - uint8_t *mem_u = (uint8_t*)malloc(frame->width*frame->height); - uint8_t *mem_v = (uint8_t*)malloc(frame->width*frame->height); - uint8_t* planes[] = { mem_y, mem_u, mem_v }; - ++this->gotimage; - st = vdp_video_surface_getbits_ycbcr( surface, VDP_YCBCR_FORMAT_YV12, planes, pitches); - if ( st != VDP_STATUS_OK ) - printf( " vo_vdpau: can't get yv12 bbits !!!!!!!!!!!! : %s\n", vdp_get_error_string( st ) ); - else { - fprintf(stderr,"P5\n%d %d\n255\n",frame->width, frame->height); - int j; - uint8_t red, green, blue; - for ( j=0; j<(frame->width*frame->height); j++ ) { - fprintf(stderr,"%d ", mem_y[j] ); - } - fprintf(stderr, "\n"); - printf( "vo_vdpau: ...........got surface bits\n" ); - } - }*/ mix_w = frame->width; mix_h = frame->height; chroma = VDP_CHROMA_TYPE_420; @@ -577,10 +627,12 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma) ) { + vdpau_release_back_frames( this_gen ); /* empty past frames array */ vdp_video_mixer_destroy( this->video_mixer ); - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE }; - void const *param_values[] = { &mix_w, &mix_h, &chroma }; - vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; + int num_layers = 2; + void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; + vdp_video_mixer_create( vdp_device, 0, 0, 4, params, param_values, &this->video_mixer ); } if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { @@ -607,27 +659,30 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } uint32_t layer_count; - VdpLayer layer[1]; - VdpRect layersrc; - if ( this->overlay_output_width ) { + VdpLayer layer[2]; + VdpRect layersrc, unscaledsrc; + if ( this->has_overlay ) { //printf("vdpau_display_frame: overlay should be visible !\n"); - layer_count = 1; + layer_count = 2; layersrc.x0 = 0; layersrc.y0 = 0; layersrc.x1 = this->overlay_output_width; layersrc.y1 = this->overlay_output_height; - layer[0].struct_version = VDP_LAYER_VERSION; layer[0].source_surface = this->overlay_output; layer[0].source_rect = &layersrc; layer[0].destination_rect = &layersrc;//&vid_dest; + layer[0].struct_version = VDP_LAYER_VERSION; layer[0].source_surface = this->overlay_output; layer[0].source_rect = &layersrc; layer[0].destination_rect = &vid_dest; + unscaledsrc.x0 = 0; unscaledsrc.y0 = 0; unscaledsrc.x1 = this->overlay_unscaled_width; unscaledsrc.y1 = this->overlay_unscaled_height; + layer[1].struct_version = VDP_LAYER_VERSION; layer[1].source_surface = this->overlay_unscaled; layer[1].source_rect = &unscaledsrc; layer[1].destination_rect = &unscaledsrc; //printf( "layersrc = %d %d %d %d \n", layersrc.x0, layersrc.y0, layersrc.x1, layersrc.y1 ); } else { layer_count = 0; } + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, 0, 0, surface, 0, 0, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); XLockDisplay( this->display ); - if ( this->overlay_output_width ) - vdp_queue_display( vdp_queue, this->overlay_output, 0, 0, 0 ); - else + /*if ( this->overlay_output_width ) + vdp_queue_display( vdp_queue, this->overlay_unscaled, 0, 0, 0 ); + else*/ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); //if ( layer_count ) //printf( "vo_vdpau: overlay count=%d, surface=%d\n", layer_count, layer[0].source_surface ); @@ -639,7 +694,13 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) XUnlockDisplay( this->display ); - frame->vo_frame.free( &frame->vo_frame ); + int i; + if ( this->back_frame[NUM_FRAMES_BACK-1]) { + this->back_frame[NUM_FRAMES_BACK-1]->vo_frame.free (&this->back_frame[NUM_FRAMES_BACK-1]->vo_frame); + } + for ( i=NUM_FRAMES_BACK-1; i>0; i-- ) + this->back_frame[i] = this->back_frame[i-1]; + this->back_frame[0] = frame; } @@ -651,7 +712,7 @@ static int vdpau_get_property (vo_driver_t *this_gen, int property) switch (property) { case VO_PROP_MAX_NUM_FRAMES: - return 20; + return 22; case VO_PROP_WINDOW_WIDTH: ret = this->sc.gui_width; break; @@ -801,6 +862,19 @@ static void vdpau_dispose (vo_driver_t *this_gen) vdp_bitmap_destroy( this->overlays[i].ovl_bitmap ); } + if ( this->overlay_unscaled!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->overlay_unscaled ); + if ( this->overlay_output!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->overlay_output ); + if ( this->output_surface[0]!=VDP_INVALID_HANDLE ) + vdp_video_surface_destroy( this->output_surface[0] ); + if ( this->output_surface[1]!=VDP_INVALID_HANDLE ) + vdp_video_surface_destroy( this->output_surface[1] ); + + for ( i=0; iback_frame[i] ) + this->back_frame[i]->vo_frame.dispose( &this->back_frame[i]->vo_frame ); + free (this); } @@ -868,7 +942,11 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->overlays[i].ovl_x = this->overlays[i].ovl_y = 0; } this->overlay_output = VDP_INVALID_HANDLE; + this->overlay_output_width = this->overlay_output_height = 0; + this->overlay_unscaled = VDP_INVALID_HANDLE; + this->overlay_unscaled_width = this->overlay_unscaled_height = 0; this->ovl_changed = 0; + this->has_overlay = 0; /* overlay converter */ this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); @@ -1032,9 +1110,10 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->video_mixer_chroma = chroma; this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE }; - void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma }; - st = vdp_video_mixer_create( vdp_device, 0, 0, 3, params, param_values, &this->video_mixer ); + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; + int num_layers = 2; + void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; + st = vdp_video_mixer_create( vdp_device, 0, 0, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); vdp_output_surface_destroy( this->output_surface[0] ); @@ -1061,7 +1140,11 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo else this->capabilities |= VO_CAP_VDPAU_MPEG12; - this->gotimage = 0; + this->capabilities |= VO_CAP_UNSCALED_OVERLAY; + + for ( i=0; iback_frame[i] = NULL; + return &this->vo_driver; } -- cgit v1.2.3 From bf39dd0cc7a1cee43d6a2b1bf57d3b406713183c Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 16 Dec 2008 15:33:03 +0000 Subject: Deinterlacing. --- src/video_out/video_out_vdpau.c | 90 ++++++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 3002d16ea..7e4c083ef 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -94,6 +94,7 @@ VdpPresentationQueueDestroy *vdp_queue_destroy; VdpPresentationQueueDisplay *vdp_queue_display; VdpPresentationQueueBlockUntilSurfaceIdle *vdp_queue_block; VdpPresentationQueueSetBackgroundColor *vdp_queue_set_backgroung_color; +VdpPresentationQueueGetTime *vdp_queue_get_time; VdpBitmapSurfacePutBitsNative *vdp_bitmap_put_bits; VdpBitmapSurfaceCreate *vdp_bitmap_create; @@ -319,6 +320,12 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) if ( !this->ovl_changed ) return; + if ( !(this->ovl_changed-1) ) { + this->ovl_changed = 0; + this->has_overlay = 0; + return; + } + int w=0, h=0; for ( i=0; iovl_changed-1; ++i ) { if ( this->overlays[i].unscaled ) @@ -340,7 +347,10 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) this->overlay_output = VDP_INVALID_HANDLE; } - w = 0; h = 0; + this->overlay_output_width = out_w; + this->overlay_output_height = out_h; + + w = 64; h = 64; for ( i=0; iovl_changed-1; ++i ) { if ( !this->overlays[i].unscaled ) continue; @@ -358,12 +368,6 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) this->overlay_unscaled = VDP_INVALID_HANDLE; } - if ( !(this->ovl_changed-1) ) { - this->ovl_changed = 0; - this->has_overlay = 0; - return; - } - this->overlay_unscaled_width = w; this->overlay_unscaled_height = h; @@ -373,9 +377,6 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) printf( "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); } - this->overlay_output_width = out_w; - this->overlay_output_height = out_h; - if ( this->overlay_output == VDP_INVALID_HANDLE ) { st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_output_width, this->overlay_output_height, &this->overlay_output ); if ( st != VDP_STATUS_OK ) @@ -629,10 +630,11 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma) ) { vdpau_release_back_frames( this_gen ); /* empty past frames array */ vdp_video_mixer_destroy( this->video_mixer ); + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 2; void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; - vdp_video_mixer_create( vdp_device, 0, 0, 4, params, param_values, &this->video_mixer ); + vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); } if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { @@ -651,12 +653,12 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) //printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 ); + XLockDisplay( this->display ); - if ( this->init_queue>1 ) { - int previous = this->current_output_surface ^ 1; - VdpTime time; - vdp_queue_block( vdp_queue, this->output_surface[previous], &time ); - } + VdpTime time; + + if ( this->init_queue>1 ) + vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface ^ 1], &time ); uint32_t layer_count; VdpLayer layer[2]; @@ -674,23 +676,49 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) layer_count = 0; } - st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, + if ( frame->vo_frame.duration>2000 ) { + VdpTime now = 0; + vdp_queue_get_time( vdp_queue, &now ); + now += frame->vo_frame.duration*100000/9; + VdpVideoSurface past[2]; + VdpVideoSurface future[1]; + past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; + future[0] = surface; + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD, + 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + + vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); + if ( this->init_queue<2 ) ++this->init_queue; + this->current_output_surface ^= 1; + if ( this->init_queue>1 ) + vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface ^ 1], &time ); + + past[0] = surface; + past[1] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; + future[0] = VDP_INVALID_HANDLE; + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD, + 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + + vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, now ); + if ( this->init_queue<2 ) ++this->init_queue; + this->current_output_surface ^= 1; + } + else { + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, 0, 0, surface, 0, 0, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); - if ( st != VDP_STATUS_OK ) - printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - XLockDisplay( this->display ); - /*if ( this->overlay_output_width ) - vdp_queue_display( vdp_queue, this->overlay_unscaled, 0, 0, 0 ); - else*/ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); - //if ( layer_count ) - //printf( "vo_vdpau: overlay count=%d, surface=%d\n", layer_count, layer[0].source_surface ); + if ( this->init_queue<2 ) ++this->init_queue; + this->current_output_surface ^= 1; + } - if ( this->init_queue<2 ) - ++this->init_queue; - this->current_output_surface ^= 1; XUnlockDisplay( this->display ); @@ -1051,6 +1079,9 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR , (void*)&vdp_queue_set_backgroung_color ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_SET_BACKGROUND_COLOR proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME , (void*)&vdp_queue_get_time ); + if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_GET_TIME proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , (void*)&vdp_decoder_query_capabilities ); if ( vdpau_init_error( st, "Can't get DECODER_QUERY_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -1110,10 +1141,11 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->video_mixer_chroma = chroma; this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 2; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; - st = vdp_video_mixer_create( vdp_device, 0, 0, 4, params, param_values, &this->video_mixer ); + st = vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); vdp_output_surface_destroy( this->output_surface[0] ); -- cgit v1.2.3 From 0fc04f0d13c05ab641c10584edb9d3515a7b3fe1 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 16 Dec 2008 16:21:35 +0000 Subject: More deinterlacing. --- src/video_out/video_out_vdpau.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 7e4c083ef..a72054337 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -647,6 +647,16 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); } + if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface^1]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface^1]) ) { + /* recreate output surface to match window size */ + printf( "vo_vdpau: output_surface size update\n" ); + this->output_surface_width[this->current_output_surface^1] = this->sc.gui_width; + this->output_surface_height[this->current_output_surface^1] = this->sc.gui_height; + + vdp_output_surface_destroy( this->output_surface[this->current_output_surface^1] ); + vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface^1], this->output_surface_height[this->current_output_surface^1], &this->output_surface[this->current_output_surface^1] ); + } + VdpRect vid_source = { this->sc.crop_left, this->sc.crop_top, this->sc.delivered_width-this->sc.crop_right, this->sc.delivered_height-this->sc.crop_bottom }; VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height }; @@ -676,10 +686,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) layer_count = 0; } - if ( frame->vo_frame.duration>2000 ) { + if ( frame->vo_frame.duration>2500 && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime now = 0; vdp_queue_get_time( vdp_queue, &now ); - now += frame->vo_frame.duration*100000/9; VdpVideoSurface past[2]; VdpVideoSurface future[1]; past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; @@ -689,7 +698,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); + vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, now ); if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; if ( this->init_queue>1 ) @@ -703,6 +712,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + now += frame->vo_frame.duration*100000/18; vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, now ); if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; -- cgit v1.2.3 From 22d81ff6f76f11119dbb564d9e2d9430461f17b6 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 16 Dec 2008 16:28:22 +0000 Subject: More deinterlacing. --- src/video_out/video_out_vdpau.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index a72054337..af43f5e50 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -706,7 +706,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) past[0] = surface; past[1] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; - future[0] = VDP_INVALID_HANDLE; + future[0] = surface;//VDP_INVALID_HANDLE; st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) -- cgit v1.2.3 From 57bf242b5b3d978e493951246f2ba6295a4cd8f6 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 16 Dec 2008 16:31:57 +0000 Subject: More deinterlacing. --- src/video_out/video_out_vdpau.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index af43f5e50..c3d00149b 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -687,8 +687,8 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } if ( frame->vo_frame.duration>2500 && frame->format==XINE_IMGFMT_VDPAU ) { - VdpTime now = 0; - vdp_queue_get_time( vdp_queue, &now ); + VdpTime current_time = 0; + vdp_queue_get_time( vdp_queue, ¤t_time ); VdpVideoSurface past[2]; VdpVideoSurface future[1]; past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; @@ -698,7 +698,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, now ); + vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; if ( this->init_queue>1 ) @@ -706,14 +706,14 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) past[0] = surface; past[1] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; - future[0] = surface;//VDP_INVALID_HANDLE; + future[0] = VDP_INVALID_HANDLE; st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - now += frame->vo_frame.duration*100000/18; - vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, now ); + current_time += frame->vo_frame.duration*100000/18; + vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; } -- cgit v1.2.3 From a5fc948257b9b423142b836a5a2bade1171f1048 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 16 Dec 2008 17:23:43 +0000 Subject: MPEG1. --- src/libvdpau/vdpau_h264.c | 10 +++++++--- src/libvdpau/vdpau_mpeg12.c | 40 ++++++++++++++++++++++++++++++---------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index f69e07387..3b8e67f2d 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -545,10 +545,12 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { } if (this->decoder_initialized) { + this->vdpau_accel->vdp_decoder_destroy( this->decoder ); this->decoder_initialized = 0; - this->stream->video_out->close(this->stream->video_out, this->stream); } + this->stream->video_out->close( this->stream->video_out, this->stream ); + free (this_gen); } @@ -560,12 +562,12 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre vdpau_h264_decoder_t *this ; - this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t)); - /* the videoout must be vdpau-capable to support this decoder */ if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) ) return NULL; + this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t)); + this->video_decoder.decode_data = vdpau_h264_decode_data; this->video_decoder.flush = vdpau_h264_flush; this->video_decoder.reset = vdpau_h264_reset; @@ -586,6 +588,8 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->last_pts = 0; this->tmp_pts = 0; + (stream->video_out->open)(stream->video_out, stream); + return &this->video_decoder; } diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 08e7f30a2..1d04c851a 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -21,7 +21,7 @@ * */ -//#define LOG +#define LOG #define LOG_MODULE "vdpau_mpeg12" @@ -197,11 +197,13 @@ static void init_picture( picture_t *pic ) static void reset_sequence( sequence_t *sequence ) { + lprintf( "reset_sequence\n" ); sequence->have_header = 0; sequence->bufpos = 0; sequence->bufseek = 0; sequence->start = -1; sequence->seq_pts = sequence->cur_pts = 0; + sequence->profile = VDP_DECODER_PROFILE_MPEG1; //sequence->ratio = 1.0; sequence->video_step = 3600; if ( sequence->forward_ref ) @@ -274,13 +276,13 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int lprintf( "load_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+7+j,7,8 ); + sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+7+j,7,8 ); } off = 64; } else { for ( j=0; j<64; ++j ) { - sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = default_intra_quantizer_matrix[j]; + sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = default_intra_quantizer_matrix[j]; } } @@ -288,11 +290,13 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int lprintf( "load_non_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+8+off+j,0,8 ); + sequence->picture.vdp_infos2.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+8+off+j,0,8 ); } } - else + else { memset( sequence->picture.vdp_infos.non_intra_quantizer_matrix, 16, 64 ); + memset( sequence->picture.vdp_infos2.non_intra_quantizer_matrix, 16, 64 ); + } if ( !sequence->have_header ) { sequence->have_header = 1; @@ -338,9 +342,22 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) lprintf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) ); infos->forward_reference = VDP_INVALID_HANDLE; infos->backward_reference = VDP_INVALID_HANDLE; - infos->full_pel_forward_vector = 0; - infos->full_pel_backward_vector = 0; - sequence->picture.state = WANT_EXT; + if ( infos->picture_coding_type>2 ) { + infos->full_pel_forward_vector = get_bits( buf+2,13,1 ); + infos->f_code[0][0] = infos->f_code[0][1] = get_bits( buf+2,14,3 ); + if ( infos->picture_coding_type==3 ) { + infos->full_pel_forward_vector = get_bits( buf+2,17,1 ); + infos->f_code[1][0] = infos->f_code[1][1] = get_bits( buf+2,18,3 ); + } + } + else { + infos->full_pel_forward_vector = 0; + infos->full_pel_backward_vector = 0; + } + if ( sequence->profile==VDP_DECODER_PROFILE_MPEG1 ) + sequence->picture.state = WANT_SLICE; + else + sequence->picture.state = WANT_EXT; } @@ -543,8 +560,8 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) if ( st!=VDP_STATUS_OK ) lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else - lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", - pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", + pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); if ( pic->vdp_infos.picture_structure != PICTURE_FRAME ) { if ( pic->vdp_infos2.picture_coding_type==P_FRAME ) @@ -577,6 +594,9 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) pic->state = WANT_HEADER; + if ( seq->profile == VDP_DECODER_PROFILE_MPEG1 ) + pic->vdp_infos.picture_structure=PICTURE_FRAME; + if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME && !pic->slices_count2 ) { lprintf("********************* no slices_count2 **********************\n"); return; -- cgit v1.2.3 From 5db1fa9a64ad324315be74e1c93fbd7f430dc12d Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 16 Dec 2008 18:00:32 +0000 Subject: Add license headers. --- src/libvdpau/dpb.c | 21 ++++++++++++++++++--- src/libvdpau/dpb.h | 21 ++++++++++++++++++--- src/libvdpau/h264_parser.c | 22 ++++++++++++++++++++++ src/libvdpau/h264_parser.h | 22 ++++++++++++++++++++++ src/libvdpau/nal.c | 21 ++++++++++++++++++--- src/libvdpau/nal.h | 21 ++++++++++++++++++--- src/libvdpau/vdpau_h264.c | 6 +----- 7 files changed, 117 insertions(+), 17 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 0c0388e25..12167d393 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -1,8 +1,23 @@ /* - * dpb.c + * Copyright (C) 2008 Julian Scheel * - * Created on: 07.12.2008 - * Author: julian + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * dpb.c: Implementing Decoded Picture Buffer */ #include diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index d76e47ee0..b3999f125 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -1,8 +1,23 @@ /* - * dpb.h + * Copyright (C) 2008 Julian Scheel * - * Created on: 06.12.2008 - * Author: julian + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * dpb.h: Decoder Picture Buffer */ #ifndef DPB_H_ diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index d436cf952..531aa6229 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1,3 +1,25 @@ +/* + * Copyright (C) 2008 Julian Scheel + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * h264_parser.c: Almost full-features H264 NAL-Parser + */ + #include #include #include diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index 966bf0880..e40a9b985 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -1,3 +1,25 @@ +/* + * Copyright (C) 2008 Julian Scheel + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * h264_parser.h: Almost full-features H264 NAL-Parser + */ + #ifndef NAL_PARSER_H_ #define NAL_PARSER_H_ diff --git a/src/libvdpau/nal.c b/src/libvdpau/nal.c index 366aefd4e..023357514 100644 --- a/src/libvdpau/nal.c +++ b/src/libvdpau/nal.c @@ -1,8 +1,23 @@ /* - * nal.c + * Copyright (C) 2008 Julian Scheel * - * Created on: 07.12.2008 - * Author: julian + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * nal.c: nal-structure utility functions */ #include diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index 17f5604b6..4ab98b032 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -1,8 +1,23 @@ /* - * nal.h + * Copyright (C) 2008 Julian Scheel * - * Created on: 07.12.2008 - * Author: julian + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * nal.h: H264 NAL structures */ #ifndef NAL_H_ diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 3b8e67f2d..e8b0088e4 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -17,11 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * - * foovideo.c: This is a reference video decoder for the xine multimedia - * player. It really works too! It will output frames of packed YUY2 data - * where each byte in the map is the same value, which is 3 larger than the - * value from the last frame. This creates a slowly rotating solid color - * frame when the frames are played in succession. + * vdpau_h264.c: H264 Video Decoder utilizing nvidia VDPAU engine */ #include -- cgit v1.2.3 From 5a6725e2768eb812b36b5e61caf2153f0e54d0e4 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 16 Dec 2008 21:47:58 +0000 Subject: Link with libm. --- src/libvdpau/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/Makefile.am b/src/libvdpau/Makefile.am index 5c372dabc..dc7ace0a7 100644 --- a/src/libvdpau/Makefile.am +++ b/src/libvdpau/Makefile.am @@ -14,7 +14,7 @@ xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c h264_parser.c vdpau_h264.c xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS) -xineplug_decode_vdpau_h264_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) +xineplug_decode_vdpau_h264_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) -lm xineplug_decode_vdpau_mpeg12_la_SOURCES = vdpau_mpeg12.c xineplug_decode_vdpau_mpeg12_la_CFLAGS = $(AM_CFLAGS) -- cgit v1.2.3 From 31d8688a412222b9c86f9c5ef24933514583a855 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 17 Dec 2008 12:33:01 +0000 Subject: MPEG interlaced fixes. --- src/libvdpau/vdpau_mpeg12.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 1d04c851a..6c65f96f5 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -549,8 +549,8 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) lprintf( "failed to create surface !! %s\n", accel->vdp_get_error_string( st ) ); } - if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME && pic->vdp_infos.picture_coding_type==B_FRAME ) - pic->vdp_infos.forward_reference = pic->vdp_infos.backward_reference; + /*if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME && pic->vdp_infos.picture_coding_type==B_FRAME ) + pic->vdp_infos.forward_reference = pic->vdp_infos.backward_reference;*/ VdpBitstreamBuffer vbit; vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; @@ -564,12 +564,19 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); if ( pic->vdp_infos.picture_structure != PICTURE_FRAME ) { - if ( pic->vdp_infos2.picture_coding_type==P_FRAME ) - pic->vdp_infos2.forward_reference = accel->surface; - else if ( pic->vdp_infos2.picture_coding_type==B_FRAME ) + pic->vdp_infos2.backward_reference = VDP_INVALID_HANDLE; + pic->vdp_infos2.forward_reference = VDP_INVALID_HANDLE; + if ( pic->vdp_infos2.picture_coding_type==P_FRAME ) { + pic->vdp_infos2.backward_reference = VDP_INVALID_HANDLE; + if ( pic->vdp_infos.picture_coding_type==I_FRAME ) + pic->vdp_infos2.forward_reference = accel->surface; + else + pic->vdp_infos2.forward_reference = pic->vdp_infos.forward_reference; + } + else if ( pic->vdp_infos.picture_coding_type==B_FRAME ) { pic->vdp_infos2.forward_reference = pic->vdp_infos.forward_reference; - else - pic->vdp_infos2.forward_reference = VDP_INVALID_HANDLE; + pic->vdp_infos2.backward_reference = pic->vdp_infos.backward_reference; + } vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; vbit.bitstream = pic->slices+pic->slices_pos_top; vbit.bitstream_bytes = pic->slices_pos-pic->slices_pos_top; @@ -578,7 +585,7 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", - pic->vdp_infos2.picture_coding_type, pic->vdp_infos2.slice_count, accel->surface, pic->vdp_infos2.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + pic->vdp_infos2.picture_coding_type, pic->vdp_infos2.slice_count, accel->surface, pic->vdp_infos2.forward_reference, pic->vdp_infos2.backward_reference, seq->seq_pts ); } //printf( "vdpau_meg12: forwref:%d, backref:%d\n", seq->forward_ref, seq->backward_ref ); -- cgit v1.2.3 From 05c78af535294e89a9cf7ae5c2e19ad3b6a56318 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 17 Dec 2008 17:30:19 +0000 Subject: Fix mixer update. --- src/video_out/video_out_vdpau.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index c3d00149b..33ecfea03 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -635,6 +635,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) int num_layers = 2; void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); + this->video_mixer_chroma = chroma; + this->video_mixer_width = mix_w; + this->video_mixer_height = mix_h; } if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { @@ -665,10 +668,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) XLockDisplay( this->display ); - VdpTime time; + VdpTime last_time; if ( this->init_queue>1 ) - vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface ^ 1], &time ); + vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface ^ 1], &last_time ); uint32_t layer_count; VdpLayer layer[2]; @@ -688,7 +691,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( frame->vo_frame.duration>2500 && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; - vdp_queue_get_time( vdp_queue, ¤t_time ); VdpVideoSurface past[2]; VdpVideoSurface future[1]; past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; @@ -698,14 +700,14 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + vdp_queue_get_time( vdp_queue, ¤t_time ); vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; if ( this->init_queue>1 ) - vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface ^ 1], &time ); + vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface ^ 1], &last_time ); past[0] = surface; - past[1] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; future[0] = VDP_INVALID_HANDLE; st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); @@ -728,8 +730,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->current_output_surface ^= 1; } - - XUnlockDisplay( this->display ); int i; @@ -908,6 +908,8 @@ static void vdpau_dispose (vo_driver_t *this_gen) vdp_video_surface_destroy( this->output_surface[0] ); if ( this->output_surface[1]!=VDP_INVALID_HANDLE ) vdp_video_surface_destroy( this->output_surface[1] ); + vdp_queue_destroy( vdp_queue ); + vdp_queue_target_destroy( vdp_queue_target ); for ( i=0; iback_frame[i] ) -- cgit v1.2.3 From 1ba8adfc70a3c060c228151839ba84b41efd8b18 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 18 Dec 2008 11:57:12 +0000 Subject: Property handling. --- src/video_out/video_out_raw.c | 33 +++++--- src/video_out/video_out_vdpau.c | 163 +++++++++++++++++++++++++++++----------- src/video_out/video_out_xv.c | 2 + 3 files changed, 142 insertions(+), 56 deletions(-) diff --git a/src/video_out/video_out_raw.c b/src/video_out/video_out_raw.c index 99e2c0004..f3afb4aaa 100644 --- a/src/video_out/video_out_raw.c +++ b/src/video_out/video_out_raw.c @@ -278,10 +278,14 @@ static void raw_frame_dispose (vo_frame_t *vo_img) frame->yuv2rgb->dispose (frame->yuv2rgb); - free (frame->chunk[0]); - free (frame->chunk[1]); - free (frame->chunk[2]); - free (frame->chunk[3]); + if ( frame->chunk[0] ) + free (frame->chunk[0]); + if ( frame->chunk[1] ) + free (frame->chunk[1]); + if ( frame->chunk[2] ) + free (frame->chunk[2]); + if ( frame->chunk[3] ) + free (frame->chunk[3]); free (frame); } @@ -297,6 +301,9 @@ static vo_frame_t *raw_alloc_frame (vo_driver_t *this_gen) if (!frame) return NULL; + frame->chunk[0] = frame->chunk[1] = frame->chunk[2] = frame->chunk[3] = NULL; + frame->width = frame->height = frame->format = frame->flags = 0; + pthread_mutex_init (&frame->vo_frame.mutex, NULL); /* @@ -330,13 +337,16 @@ static void raw_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ge || (frame->flags != flags)) { /* lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */ - flags &= VO_BOTH_FIELDS; - /* (re-) allocate render space */ - free (frame->chunk[0]); - free (frame->chunk[1]); - free (frame->chunk[2]); - free (frame->chunk[3]); + if ( frame->chunk[0] ) + free (frame->chunk[0]); + if ( frame->chunk[1] ) + free (frame->chunk[1]); + if ( frame->chunk[2] ) + free (frame->chunk[2]); + if ( frame->chunk[3] ) + free (frame->chunk[3]); + frame->chunk[0] = frame->chunk[1] = frame->chunk[2] = frame->chunk[3] = NULL; if (format == XINE_IMGFMT_YV12) { frame->vo_frame.pitches[0] = 8*((width + 7) / 8); @@ -355,7 +365,7 @@ static void raw_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ge (void **) &frame->chunk[3]); /* set up colorspace converter */ - switch (flags) { + switch (flags & VO_BOTH_FIELDS) { case VO_TOP_FIELD: case VO_BOTTOM_FIELD: frame->yuv2rgb->configure (frame->yuv2rgb, @@ -382,6 +392,7 @@ static void raw_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ge frame->width = width; frame->height = height; frame->format = format; + frame->flags = flags; raw_frame_field ((vo_frame_t *)frame, flags); } diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 33ecfea03..b58438169 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -86,6 +86,9 @@ VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits; VdpVideoMixerCreate *vdp_video_mixer_create; VdpVideoMixerDestroy *vdp_video_mixer_destroy; VdpVideoMixerRender *vdp_video_mixer_render; +VdpVideoMixerSetAttributeValues *vdp_video_mixer_set_attribute_values; + +VdpGenerateCSCMatrix *vdp_generate_csc_matrix; VdpPresentationQueueTargetCreateX11 *vdp_queue_target_create_x11; VdpPresentationQueueTargetDestroy *vdp_queue_target_destroy; @@ -172,6 +175,11 @@ typedef struct { uint32_t capabilities; xine_t *xine; + int hue; + int saturation; + int brightness; + int contrast; + } vdpau_driver_t; @@ -435,9 +443,12 @@ static void vdpau_frame_dispose (vo_frame_t *vo_img) { vdpau_frame_t *frame = (vdpau_frame_t *) vo_img ; - free (frame->chunk[0]); - free (frame->chunk[1]); - free (frame->chunk[2]); + if ( frame->chunk[0] ) + free (frame->chunk[0]); + if ( frame->chunk[1] ) + free (frame->chunk[1]); + if ( frame->chunk[2] ) + free (frame->chunk[2]); if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); free (frame); @@ -457,6 +468,9 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) if (!frame) return NULL; + frame->chunk[0] = frame->chunk[1] = frame->chunk[2] = NULL; + frame->width = frame->height = frame->format = frame->flags = 0; + frame->vo_frame.accel_data = &frame->vdpau_accel_data; pthread_mutex_init (&frame->vo_frame.mutex, NULL); @@ -478,8 +492,6 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render; frame->vdpau_accel_data.vdp_get_error_string = vdp_get_error_string; - frame->width = frame->height = 0; - return (vo_frame_t *) frame; } @@ -491,13 +503,17 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; /* Check frame size and format and reallocate if necessary */ - if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->flags != flags)) { + if ( (frame->width != width) || (frame->height != height) || (frame->format != format) ) { /*lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */ /* (re-) allocate render space */ - free (frame->chunk[0]); - free (frame->chunk[1]); - free (frame->chunk[2]); + if ( frame->chunk[0] ) + free (frame->chunk[0]); + if ( frame->chunk[1] ) + free (frame->chunk[1]); + if ( frame->chunk[2] ) + free (frame->chunk[2]); + frame->chunk[0] = frame->chunk[1] = frame->chunk[2] = NULL; if (format == XINE_IMGFMT_YV12) { frame->vo_frame.pitches[0] = 8*((width + 7) / 8); @@ -524,6 +540,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ frame->width = width; frame->height = height; frame->format = format; + frame->flags = flags; vdpau_frame_field ((vo_frame_t *)frame, flags); } @@ -650,16 +667,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); } - if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface^1]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface^1]) ) { - /* recreate output surface to match window size */ - printf( "vo_vdpau: output_surface size update\n" ); - this->output_surface_width[this->current_output_surface^1] = this->sc.gui_width; - this->output_surface_height[this->current_output_surface^1] = this->sc.gui_height; - - vdp_output_surface_destroy( this->output_surface[this->current_output_surface^1] ); - vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface^1], this->output_surface_height[this->current_output_surface^1], &this->output_surface[this->current_output_surface^1] ); - } - VdpRect vid_source = { this->sc.crop_left, this->sc.crop_top, this->sc.delivered_width-this->sc.crop_right, this->sc.delivered_height-this->sc.crop_bottom }; VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height }; @@ -707,6 +714,16 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( this->init_queue>1 ) vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface ^ 1], &last_time ); + if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { + /* recreate output surface to match window size */ + printf( "vo_vdpau: output_surface size update\n" ); + this->output_surface_width[this->current_output_surface] = this->sc.gui_width; + this->output_surface_height[this->current_output_surface] = this->sc.gui_height; + + vdp_output_surface_destroy( this->output_surface[this->current_output_surface] ); + vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); + } + past[0] = surface; future[0] = VDP_INVALID_HANDLE; st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD, @@ -746,32 +763,59 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) static int vdpau_get_property (vo_driver_t *this_gen, int property) { vdpau_driver_t *this = (vdpau_driver_t*)this_gen; - int ret=-1; switch (property) { case VO_PROP_MAX_NUM_FRAMES: return 22; case VO_PROP_WINDOW_WIDTH: - ret = this->sc.gui_width; - break; + return this->sc.gui_width; case VO_PROP_WINDOW_HEIGHT: - ret = this->sc.gui_height; - break; + return this->sc.gui_height; case VO_PROP_OUTPUT_WIDTH: - ret = this->sc.output_width; - break; + return this->sc.output_width; case VO_PROP_OUTPUT_HEIGHT: - ret = this->sc.output_height; - break; + return this->sc.output_height; case VO_PROP_OUTPUT_XOFFSET: - ret = this->sc.output_xoffset; - break; + return this->sc.output_xoffset; case VO_PROP_OUTPUT_YOFFSET: - ret = this->sc.output_yoffset; - break; + return this->sc.output_yoffset; + case VO_PROP_HUE: + return 0; + case VO_PROP_SATURATION: + return 100; + case VO_PROP_CONTRAST: + return 100; + case VO_PROP_BRIGHTNESS: + return 0; } - return ret; + return -1; +} + + + +static void vdpau_update_csc( vdpau_driver_t *this_gen ) +{ + /*float hue = this_gen->hue/100.0; + float saturation = this_gen->saturation/100.0; + float contrast = this_gen->contrast/100.0; + float brightness = this_gen->brightness/100.0; + + printf( "vo_vdpau: vdpau_update_csc: hue=%f, saturation=%f, contrast=%f, brightness=%f\n", hue, saturation, contrast, brightness ); + + VdpCSCMatrix matrix; + VdpProcamp procamp = { VDP_PROCAMP_VERSION, brightness, contrast, saturation, hue }; + + VdpStatus st = vdp_generate_csc_matrix( &procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &matrix ); + if ( st != VDP_STATUS_OK ) { + printf( "vo_vdpau: error, can't generate csc matrix !!\n" ); + return; + } + VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX }; + void* attribute_values[] = { &matrix }; + st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: error, can't set csc matrix !!\n" );*/ } @@ -780,22 +824,28 @@ static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) { vdpau_driver_t *this = (vdpau_driver_t*)this_gen; - /*switch (property) { - case VO_PROP_ZOOM_X: + printf("vdpau_set_property: property=%d, value=%d\n", property, value ); + + switch (property) { + /*case VO_PROP_ZOOM_X: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; _x_vo_scale_compute_ideal_size( &this->sc ); - this->sc.force_redraw = 1; /* trigger re-calc of output size */ - /*} + this->sc.force_redraw = 1; //* trigger re-calc of output size + } break; case VO_PROP_ZOOM_Y: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP; _x_vo_scale_compute_ideal_size( &this->sc ); - this->sc.force_redraw = 1; /* trigger re-calc of output size */ - /*} - break; - }*/ + this->sc.force_redraw = 1; //* trigger re-calc of output size + } + break;*/ + case VO_PROP_HUE: this->hue = value; vdpau_update_csc( this ); break; + case VO_PROP_SATURATION: this->saturation = value; vdpau_update_csc( this ); break; + case VO_PROP_CONTRAST: this->contrast = value; vdpau_update_csc( this ); break; + case VO_PROP_BRIGHTNESS: this->brightness = value; vdpau_update_csc( this ); break; + } return value; } @@ -804,8 +854,18 @@ static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) static void vdpau_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) { - *min = 0; - *max = 0; + switch ( property ) { + case VO_PROP_HUE: + *max = 314; *min = -314; break; + case VO_PROP_SATURATION: + *max = 1000; *min = 0; break; + case VO_PROP_CONTRAST: + *max = 1000; *min = 0; break; + case VO_PROP_BRIGHTNESS: + *max = 100; *min = -100; break; + default: + *max = 0; *min = 0; + } } @@ -905,9 +965,11 @@ static void vdpau_dispose (vo_driver_t *this_gen) if ( this->overlay_output!=VDP_INVALID_HANDLE ) vdp_output_surface_destroy( this->overlay_output ); if ( this->output_surface[0]!=VDP_INVALID_HANDLE ) - vdp_video_surface_destroy( this->output_surface[0] ); + vdp_output_surface_destroy( this->output_surface[0] ); if ( this->output_surface[1]!=VDP_INVALID_HANDLE ) - vdp_video_surface_destroy( this->output_surface[1] ); + vdp_output_surface_destroy( this->output_surface[1] ); + if ( this->soft_surface != VDP_INVALID_HANDLE ) + vdp_video_surface_destroy( this->soft_surface ); vdp_queue_destroy( vdp_queue ); vdp_queue_target_destroy( vdp_queue_target ); @@ -1070,6 +1132,12 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_RENDER , (void*)&vdp_video_mixer_render ); if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_RENDER proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES , (void*)&vdp_video_mixer_set_attribute_values ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_SET_ATTRIBUTE_VALUES proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GENERATE_CSC_MATRIX , (void*)&vdp_generate_csc_matrix ); + if ( vdpau_init_error( st, "Can't get GENERATE_CSC_MATRIX proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 , (void*)&vdp_queue_target_create_x11 ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_TARGET_CREATE_X11 proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -1189,6 +1257,11 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo for ( i=0; iback_frame[i] = NULL; + this->hue = 0; + this->saturation = 100; + this->contrast = 100; + this->brightness = 0; + return &this->vo_driver; } diff --git a/src/video_out/video_out_xv.c b/src/video_out/video_out_xv.c index b71518958..d791e6dc5 100644 --- a/src/video_out/video_out_xv.c +++ b/src/video_out/video_out_xv.c @@ -908,6 +908,8 @@ static int xv_set_property (vo_driver_t *this_gen, int property, int value) { xv_driver_t *this = (xv_driver_t *) this_gen; + printf("xv_set_property: property=%d, value=%d\n", property, value ); + if (this->props[property].atom != None) { /* value is out of bound */ -- cgit v1.2.3 From f47ff39c36f58968e7d8f832313916f5319f3517 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 18 Dec 2008 11:57:26 +0000 Subject: Undefine LOG (MPEG-handling code). --- src/libvdpau/vdpau_mpeg12.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 6c65f96f5..c5aefc7cb 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -21,7 +21,7 @@ * */ -#define LOG +//#define LOG #define LOG_MODULE "vdpau_mpeg12" -- cgit v1.2.3 From 1b395e3b7d070dd81ca466201cb01f3c84065ac5 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 18 Dec 2008 18:28:38 +0000 Subject: Add README-VDPAU. --- README-VDPAU | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 README-VDPAU diff --git a/README-VDPAU b/README-VDPAU new file mode 100644 index 000000000..4606641ac --- /dev/null +++ b/README-VDPAU @@ -0,0 +1,72 @@ +xine-vdpau README: +------------------------------------------------------------------------------ + +So, you want to give it a try, but wonder which steps are required. +Ok, so here it is: + +1) get the sources: +svn co svn://jusst.de/xine-vdpau + +2) compile the sources: +cd xine-vdpau +./autogen.sh +./configure +make +make install (as root) + **(make sure that no other xine-lib installation will conflict with this one) + +3) edit your xine configuration +nano $HOME/.xine/config (if it does not exist, first run "xine --no-logo" then quit. +search for "engine.buffers.video_num_frames" and set it to 22 + +4) running the beast: +xine --no-logo --verbose /path/to/a/working/sample + ** the --no-logo will tell xine to not play its crappy mpv logo (which, atm, doesn't work with vdpau_mpeg12) + ** --verbose will print some usefull things in your console (in case of problems, that are very likely to happen, + the developers will ask you to give this output, at least) + ** You can find working h264 samples at http://hftom.free.fr/video_samples/ + ** MKV or MOV WON'T WORK, at that moment. (we are concentrating on TS streams, but yes, it will work in the future) + ** most mpeg2 should work, if you have a non working one, please provide a sample. + +5) update your svn copy quite often + +6) don't blame us if it crashes, burn you gpu (unlikely:) or anything else. + + +------------------------------------------------------------------------------ + +FAQ: + +Q: + Why my file plays fine with mplayer-vdpau and not with xine-vdpau? +A: + We are not using the nvidia's libavcodec patch. + We are writing decoders from scratch. + So don't expect them to be as mature as ffmpeg ones. Not yet. + +Q: + Why mpeg2 doesn't use less cpu than software decoder? +A: + Because at that moment it does a lot of memcpy. This will be fixed soon, but that's not + a priority. Stability is our focus. + +Q: + Is deinterlacing working? +A: + Yes. It's already quite good (doing 50i->50p), but could even be better in the future. + +Q: + How do i get it working with VDR, Kaffeine, whatever. +A: + Ask VDR, Kaffeine, whatever developers. + (Note: for kaffeine you are lucky, i'm going to tell you the tip. + Build kaffeine like that: ./configure --without-xcb && make && make install) + +Q: + How can i contact you? +A: + IRC: #xine-vdpau on freenode + MAIL: http://lists.kafic.ba/mailman/listinfo/xine-vdpau + Eventually, nvnews. + +---------------------------------------------------------------------------- -- cgit v1.2.3 From 0d8107bfcdb50dbc0f389f4646d6e026133b03b2 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 18 Dec 2008 18:33:59 +0000 Subject: Update README-VDPAU. --- README-VDPAU | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README-VDPAU b/README-VDPAU index 4606641ac..87cb71ea5 100644 --- a/README-VDPAU +++ b/README-VDPAU @@ -4,6 +4,8 @@ xine-vdpau README: So, you want to give it a try, but wonder which steps are required. Ok, so here it is: +0) you need nvidia's driver 180.16 or later. + 1) get the sources: svn co svn://jusst.de/xine-vdpau -- cgit v1.2.3 From 2f42a48d16e7003c778938b3a72842e785f0cd80 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 19 Dec 2008 14:05:04 +0000 Subject: Fix mixer size. --- src/video_out/video_out_vdpau.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index b58438169..4b163ed74 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -605,13 +605,12 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) ) { //printf( "vo_vdpau: got a yuv image -------------\n" ); - surface = this->soft_surface; chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; if ( (frame->width > this->soft_surface_width) || (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { printf( "vo_vdpau: soft_surface size update\n" ); /* recreate surface and mixer to match frame changes */ - mix_w = this->soft_surface_width = frame->width; - mix_h = this->soft_surface_height = frame->height; + this->soft_surface_width = frame->width; + this->soft_surface_height = frame->height; this->soft_surface_format = frame->format; vdp_video_surface_destroy( this->soft_surface ); vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); @@ -629,6 +628,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_surface_putbits_ycbcr YUY2 error : %s\n", vdp_get_error_string( st ) ); } + surface = this->soft_surface; + mix_w = this->soft_surface_width; + mix_h = this->soft_surface_height; } else if (frame->format == XINE_IMGFMT_VDPAU) { //printf( "vo_vdpau: got a vdpau image -------------\n" ); -- cgit v1.2.3 From 7483f01445e287d5817d7aa44caeab406ab88abc Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 19 Dec 2008 14:07:35 +0000 Subject: MPEG1 fixes. --- src/libvdpau/vdpau_mpeg12.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index c5aefc7cb..22a576299 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -177,6 +177,13 @@ typedef struct vdpau_mpeg12_decoder_s { static void reset_picture( picture_t *pic ) { pic->vdp_infos.picture_structure = 0; + pic->vdp_infos2.intra_dc_precision = pic->vdp_infos.intra_dc_precision = 0; + pic->vdp_infos2.frame_pred_frame_dct = pic->vdp_infos.frame_pred_frame_dct = 1; + pic->vdp_infos2.concealment_motion_vectors = pic->vdp_infos.concealment_motion_vectors = 0; + pic->vdp_infos2.intra_vlc_format = pic->vdp_infos.intra_vlc_format = 0; + pic->vdp_infos2.alternate_scan = pic->vdp_infos.alternate_scan = 0; + pic->vdp_infos2.q_scale_type = pic->vdp_infos.q_scale_type = 0; + pic->vdp_infos2.top_field_first = pic->vdp_infos.top_field_first = 0; pic->slices_count = 0; pic->slices_count2 = 0; pic->slices_pos = 0; @@ -325,6 +332,9 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) if ( sequence->picture.state!=WANT_HEADER ) return; + if ( sequence->profile==VDP_DECODER_PROFILE_MPEG1 ) + sequence->picture.vdp_infos.picture_structure = PICTURE_FRAME; + VdpPictureInfoMPEG1Or2 *infos = &sequence->picture.vdp_infos; if ( sequence->picture.vdp_infos.picture_structure && sequence->picture.slices_count2 ) -- cgit v1.2.3 From 9f95af243b2a3845e4e37bafa53f44760a3586df Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 19 Dec 2008 14:08:24 +0000 Subject: Release refframes at reset/dispose. --- src/libvdpau/vdpau_h264.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index e8b0088e4..9d461063b 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -517,7 +517,23 @@ static void vdpau_h264_flush (video_decoder_t *this_gen) { static void vdpau_h264_reset (video_decoder_t *this_gen) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; + printf("vdpau_h264_reset\n"); + this->size = 0; + + dpb_flush( &(this->nal_parser->dpb) ); + + if (this->decoder_initialized) + this->vdpau_accel->vdp_decoder_destroy( this->decoder ); + + this->decoder_started = 0; + this->decoder_initialized = 0; + this->nal_parser = init_parser(); + this->buf = NULL; + this->wait_for_bottom_field = 0; + this->video_step = 0; + this->last_pts = 0; + this->tmp_pts = 0; } /* @@ -540,6 +556,8 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { this->buf = NULL; } + dpb_flush( &(this->nal_parser->dpb) ); + if (this->decoder_initialized) { this->vdpau_accel->vdp_decoder_destroy( this->decoder ); this->decoder_initialized = 0; -- cgit v1.2.3 From e40dc38d6ebc1dae925fac780c099bc4a52cdd69 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 19 Dec 2008 18:16:01 +0000 Subject: MPEG1 fixed. --- src/libvdpau/vdpau_mpeg12.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 22a576299..1ac6e398d 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -176,6 +176,7 @@ typedef struct vdpau_mpeg12_decoder_s { static void reset_picture( picture_t *pic ) { + printf( "reset_picture\n" ); pic->vdp_infos.picture_structure = 0; pic->vdp_infos2.intra_dc_precision = pic->vdp_infos.intra_dc_precision = 0; pic->vdp_infos2.frame_pred_frame_dct = pic->vdp_infos.frame_pred_frame_dct = 1; @@ -352,7 +353,7 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) lprintf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) ); infos->forward_reference = VDP_INVALID_HANDLE; infos->backward_reference = VDP_INVALID_HANDLE; - if ( infos->picture_coding_type>2 ) { + if ( infos->picture_coding_type>1 ) { infos->full_pel_forward_vector = get_bits( buf+2,13,1 ); infos->f_code[0][0] = infos->f_code[0][1] = get_bits( buf+2,14,3 ); if ( infos->picture_coding_type==3 ) { @@ -569,9 +570,12 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); if ( st!=VDP_STATUS_OK ) lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); - else - lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", + else { + printf( "DECODER SUCCESS : frame_type:%d, slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + VdpPictureInfoMPEG1Or2 *info = &pic->vdp_infos; + printf("%d %d %d %d %d %d %d %d %d %d %d %d %d\n", info->intra_dc_precision, info->frame_pred_frame_dct, info->concealment_motion_vectors, info->intra_vlc_format, info->alternate_scan, info->q_scale_type, info->top_field_first, info->full_pel_forward_vector, info->full_pel_backward_vector, info->f_code[0][0], info->f_code[0][1], info->f_code[1][0], info->f_code[1][1] ); + } if ( pic->vdp_infos.picture_structure != PICTURE_FRAME ) { pic->vdp_infos2.backward_reference = VDP_INVALID_HANDLE; -- cgit v1.2.3 From 00fa8c11404ed364edab49ebf7001bd9de4cca3d Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 19 Dec 2008 21:48:06 +0000 Subject: Fix queue_block. --- src/video_out/video_out_vdpau.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 4b163ed74..d868f8d32 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -680,7 +680,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpTime last_time; if ( this->init_queue>1 ) - vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface ^ 1], &last_time ); + vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); uint32_t layer_count; VdpLayer layer[2]; @@ -714,7 +714,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; if ( this->init_queue>1 ) - vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface ^ 1], &last_time ); + vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { /* recreate output surface to match window size */ -- cgit v1.2.3 From 534d98199010e116bdcfd6c27068e93246f43a06 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 20 Dec 2008 17:43:16 +0000 Subject: Reset fixups. --- src/libvdpau/vdpau_h264.c | 4 ++-- src/libvdpau/vdpau_mpeg12.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 9d461063b..008c3630e 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -283,7 +283,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } /* get the vdpau context from vo */ - (this->stream->video_out->open) (this->stream->video_out, this->stream); + //(this->stream->video_out->open) (this->stream->video_out, this->stream); img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, @@ -602,7 +602,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->last_pts = 0; this->tmp_pts = 0; - (stream->video_out->open)(stream->video_out, stream); + (this->stream->video_out->open) (this->stream->video_out, this->stream); return &this->video_decoder; } diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 1ac6e398d..5406bcf5a 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -176,7 +176,7 @@ typedef struct vdpau_mpeg12_decoder_s { static void reset_picture( picture_t *pic ) { - printf( "reset_picture\n" ); + lprintf( "reset_picture\n" ); pic->vdp_infos.picture_structure = 0; pic->vdp_infos2.intra_dc_precision = pic->vdp_infos.intra_dc_precision = 0; pic->vdp_infos2.frame_pred_frame_dct = pic->vdp_infos.frame_pred_frame_dct = 1; @@ -353,11 +353,11 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) lprintf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) ); infos->forward_reference = VDP_INVALID_HANDLE; infos->backward_reference = VDP_INVALID_HANDLE; - if ( infos->picture_coding_type>1 ) { + if ( infos->picture_coding_type > I_FRAME ) { infos->full_pel_forward_vector = get_bits( buf+2,13,1 ); infos->f_code[0][0] = infos->f_code[0][1] = get_bits( buf+2,14,3 ); - if ( infos->picture_coding_type==3 ) { - infos->full_pel_forward_vector = get_bits( buf+2,17,1 ); + if ( infos->picture_coding_type==B_FRAME ) { + infos->full_pel_backward_vector = get_bits( buf+2,17,1 ); infos->f_code[1][0] = infos->f_code[1][1] = get_bits( buf+2,18,3 ); } } @@ -571,10 +571,10 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) if ( st!=VDP_STATUS_OK ) lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else { - printf( "DECODER SUCCESS : frame_type:%d, slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", + lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); VdpPictureInfoMPEG1Or2 *info = &pic->vdp_infos; - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d\n", info->intra_dc_precision, info->frame_pred_frame_dct, info->concealment_motion_vectors, info->intra_vlc_format, info->alternate_scan, info->q_scale_type, info->top_field_first, info->full_pel_forward_vector, info->full_pel_backward_vector, info->f_code[0][0], info->f_code[0][1], info->f_code[1][0], info->f_code[1][1] ); + lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d\n", info->intra_dc_precision, info->frame_pred_frame_dct, info->concealment_motion_vectors, info->intra_vlc_format, info->alternate_scan, info->q_scale_type, info->top_field_first, info->full_pel_forward_vector, info->full_pel_backward_vector, info->f_code[0][0], info->f_code[0][1], info->f_code[1][0], info->f_code[1][1] ); } if ( pic->vdp_infos.picture_structure != PICTURE_FRAME ) { @@ -759,7 +759,7 @@ static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; printf( "vdpau_mpeg12: vdpau_mpeg12_flush\n" ); - //reset_sequence( &this->sequence ); + reset_sequence( &this->sequence ); } /* @@ -781,7 +781,7 @@ static void vdpau_mpeg12_discontinuity (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; printf( "vdpau_mpeg12: vdpau_mpeg12_discontinuity\n" ); - //reset_sequence( &this->sequence ); + reset_sequence( &this->sequence ); } -- cgit v1.2.3 From 223dbfb4fa8cccb43a1efb5ebf9591947f224af0 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 20 Dec 2008 17:43:41 +0000 Subject: Alpha-handling optimisation. --- src/video_out/video_out_vdpau.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index d868f8d32..2ea885d2c 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -249,7 +249,6 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) uint8_t *hili_trans = overlay->hili_trans; clut_t *colors; uint8_t *trans; - uint8_t src_alpha; int rlelen = 0; uint8_t clr = 0; int i, pos=0, x, y; @@ -267,12 +266,11 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) } rlelen = rle->len; clr = rle->color; - src_alpha = trans[clr]; for ( i=0; i Date: Sat, 20 Dec 2008 22:11:48 +0000 Subject: Video format change events. --- src/libvdpau/vdpau_h264.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 008c3630e..77835038d 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -268,6 +268,21 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } } + _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->width ); + _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->height ); + _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*this->ratio) ); + _x_stream_info_set( this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step ); + _x_meta_info_set_utf8( this->stream, XINE_META_INFO_VIDEOCODEC, "H264/AVC (vdpau)" ); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = this->stream; + event.data = &data; + event.data_length = sizeof(data); + data.width = this->width; + data.height = this->height; + data.aspect = this->ratio; + xine_event_send( this->stream, &event ); switch(this->nal_parser->current_nal->sps->profile_idc) { case 100: -- cgit v1.2.3 From 2678d7535d0f261d016a0fd0119822b25b571c9d Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 20 Dec 2008 22:11:48 +0000 Subject: nVidia VDPAU doesn't support BASELINE. --- src/libvdpau/vdpau_h264.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 77835038d..438ba9921 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -293,7 +293,10 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, break; case 66: default: - this->profile = VDP_DECODER_PROFILE_H264_BASELINE; + // nvidia's VDPAU doesn't support BASELINE. But most (every?) streams marked BASELINE do not use BASELINE specifics, + // so, just force MAIN. + //this->profile = VDP_DECODER_PROFILE_H264_BASELINE; + this->profile = VDP_DECODER_PROFILE_H264_MAIN; break; } -- cgit v1.2.3 From 7971f828de6729928e47aebba1891a6adb34a786 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 21 Dec 2008 18:26:02 +0000 Subject: vdpau_h264: release frames at dispose. --- src/libvdpau/dpb.c | 15 +++++++++++++ src/libvdpau/dpb.h | 1 + src/libvdpau/vdpau_h264.c | 8 +++---- src/libvdpau/vdpau_mpeg12.c | 55 +++++++++++++++++++++++++++++++++------------ 4 files changed, 61 insertions(+), 18 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 12167d393..e397449f9 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -303,6 +303,21 @@ int dpb_flush(struct dpb *dpb) return 0; } +void dpb_free_all( struct dpb *dpb ) +{ + struct decoded_picture *pic = dpb->pictures; + + if (pic != NULL) + do { + struct decoded_picture *next_pic = pic->next; + free_decoded_picture(pic); + --dpb->used; + pic = next_pic; + } while (pic != NULL); + + printf("dpb_free_all, used: %d\n", dpb->used); +} + void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) { struct decoded_picture *pic = dpb->pictures; diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index b3999f125..30a0da50b 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -69,6 +69,7 @@ int dpb_set_output_picture(struct dpb *dpb, struct decoded_picture *outpic); int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic); int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames); int dpb_flush(struct dpb *dpb); +void dpb_free_all( struct dpb *dpb ); void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 438ba9921..ba458abb6 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -424,14 +424,14 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, VdpVideoSurface surface = this->vdpau_accel->surface; - if(surface == VDP_INVALID_HANDLE) { + /*if(surface == VDP_INVALID_HANDLE) { VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, VDP_CHROMA_TYPE_420, this->width, this->height, &surface); this->vdpau_accel->surface = surface; if(status != VDP_STATUS_OK) xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed: %s\n", this->vdpau_accel->vdp_get_error_string(status)); - } + }*/ //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, @@ -539,7 +539,7 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->size = 0; - dpb_flush( &(this->nal_parser->dpb) ); + dpb_free_all( &(this->nal_parser->dpb) ); if (this->decoder_initialized) this->vdpau_accel->vdp_decoder_destroy( this->decoder ); @@ -574,7 +574,7 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { this->buf = NULL; } - dpb_flush( &(this->nal_parser->dpb) ); + dpb_free_all( &(this->nal_parser->dpb) ); if (this->decoder_initialized) { this->vdpau_accel->vdp_decoder_destroy( this->decoder ); diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 5406bcf5a..fa20f8579 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -131,6 +131,7 @@ typedef struct { uint64_t video_step; /* frame duration in pts units */ double ratio; VdpDecoderProfile profile; + int chroma; int have_header; @@ -212,6 +213,7 @@ static void reset_sequence( sequence_t *sequence ) sequence->start = -1; sequence->seq_pts = sequence->cur_pts = 0; sequence->profile = VDP_DECODER_PROFILE_MPEG1; + sequence->chroma = 0; //sequence->ratio = 1.0; sequence->video_step = 3600; if ( sequence->forward_ref ) @@ -382,6 +384,8 @@ static void sequence_extension( sequence_t *sequence, uint8_t *buf, int len ) } lprintf( "profile_and_level_indication: %d\n", get_bits( buf,4,8 ) ); lprintf( "progressive_sequence: %d\n", get_bits( buf,12,1 ) ); + if ( get_bits( buf,13,2 )==2 ) + sequence->chroma = VO_CHROMA_422; lprintf( "chroma_format: %d\n", get_bits( buf,13,2 ) ); lprintf( "horizontal_size_extension: %d\n", get_bits( buf,15,2 ) ); lprintf( "vertical_size_extension: %d\n", get_bits( buf,17,2 ) ); @@ -437,6 +441,39 @@ static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int le +static void quant_matrix_extension( sequence_t *sequence, uint8_t *buf, int len ) +{ + int i, j, off; + + i = get_bits( buf,4,1 ); + lprintf( "load_intra_quantizer_matrix: %d\n", i ); + if ( i ) { + for ( j=0; j<64; ++j ) { + sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+j,5,8 ); + } + off = 64; + } + else { + for ( j=0; j<64; ++j ) { + sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = default_intra_quantizer_matrix[j]; + } + } + + i = get_bits( buf+off,5,1 ); + lprintf( "load_non_intra_quantizer_matrix: %d\n", i ); + if ( i ) { + for ( j=0; j<64; ++j ) { + sequence->picture.vdp_infos2.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+off+j,6,8 ); + } + } + else { + memset( sequence->picture.vdp_infos.non_intra_quantizer_matrix, 16, 64 ); + memset( sequence->picture.vdp_infos2.non_intra_quantizer_matrix, 16, 64 ); + } +} + + + static void copy_slice( sequence_t *sequence, uint8_t *buf, int len ) { int size = sequence->picture.slices_pos+len; @@ -454,13 +491,6 @@ static void copy_slice( sequence_t *sequence, uint8_t *buf, int len ) -static void quant_matrix_extension( uint8_t *buf, int len ) -{ - lprintf("quant_matrix_extension >>>>>>>>>>>>>>>>>>>>>>>>>\n"); -} - - - static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) { sequence_t *sequence = (sequence_t*)&this_gen->sequence; @@ -495,7 +525,7 @@ static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) break; case quant_matrix_ext_sc: lprintf( " ----------- quant_matrix_extension_start_code\n" ); - quant_matrix_extension( buf+4, len-4 ); + quant_matrix_extension( sequence, buf+4, len-4 ); break; case picture_coding_ext_sc: lprintf( " ----------- picture_coding_extension_start_code\n" ); @@ -554,14 +584,11 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) vd->decoder_height = seq->coded_height; } } - if ( accel->surface==VDP_INVALID_HANDLE ) { + /*if ( accel->surface==VDP_INVALID_HANDLE ) { st = accel->vdp_video_surface_create( accel->vdp_device, VDP_CHROMA_TYPE_420, seq->coded_width, seq->coded_height, &accel->surface); if ( st!=VDP_STATUS_OK ) lprintf( "failed to create surface !! %s\n", accel->vdp_get_error_string( st ) ); - } - - /*if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME && pic->vdp_infos.picture_coding_type==B_FRAME ) - pic->vdp_infos.forward_reference = pic->vdp_infos.backward_reference;*/ + }*/ VdpBitstreamBuffer vbit; vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; @@ -648,7 +675,7 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) //printf("vdpau_mpeg12: get image ..\n"); vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, - seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS|seq->chroma ); vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; if ( !seq->accel_vdpau ) seq->accel_vdpau = accel; -- cgit v1.2.3 From 32bb0368b6f1c860d20900da9b7a187ecc767502 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 21 Dec 2008 18:26:28 +0000 Subject: Fix chroma_type. --- src/video_out/video_out_vdpau.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 2ea885d2c..3fb4d870f 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -49,7 +49,7 @@ #include #include "accel_vdpau.h" -#define NUM_FRAMES_BACK 2 +#define NUM_FRAMES_BACK 1 VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, @@ -180,6 +180,8 @@ typedef struct { int brightness; int contrast; + int allocated_surfaces; + } vdpau_driver_t; @@ -484,7 +486,7 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vdpau_accel_data.vdp_device = vdp_device; frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; - frame->vdpau_accel_data.vdp_video_surface_create = vdp_video_surface_create; + frame->vdpau_accel_data.chroma = VDP_CHROMA_TYPE_420; frame->vdpau_accel_data.vdp_decoder_create = vdp_decoder_create; frame->vdpau_accel_data.vdp_decoder_destroy = vdp_decoder_destroy; frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render; @@ -498,11 +500,14 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, uint32_t width, uint32_t height, double ratio, int format, int flags) { + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; + VdpChromaType chroma = (flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420; + /* Check frame size and format and reallocate if necessary */ - if ( (frame->width != width) || (frame->height != height) || (frame->format != format) ) { - /*lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */ + if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) ) { + //printf("vo_vdpau: updating frame to %d x %d (ratio=%g, format=%08X)\n", width, height, ratio, format); /* (re-) allocate render space */ if ( frame->chunk[0] ) @@ -528,10 +533,21 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ } if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) { - if ( (frame->width != width) || (frame->height != height) || (frame->format != XINE_IMGFMT_VDPAU) ) { + if ( (frame->width != width) || (frame->height != height) || (format != XINE_IMGFMT_VDPAU) || frame->vdpau_accel_data.chroma != chroma ) { printf("vo_vdpau: update_frame - destroy surface\n"); vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; + --this->allocated_surfaces; + } + } + + if ( (format == XINE_IMGFMT_VDPAU) && (frame->vdpau_accel_data.surface == VDP_INVALID_HANDLE) ) { + VdpStatus st = vdp_video_surface_create( vdp_device, chroma, width, height, &frame->vdpau_accel_data.surface ); + if ( st!=VDP_STATUS_OK ) + printf( "vo_vdpau: failed to create surface !! %s\n", vdp_get_error_string( st ) ); + else { + frame->vdpau_accel_data.chroma = chroma; + ++this->allocated_surfaces; } } @@ -543,6 +559,8 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ vdpau_frame_field ((vo_frame_t *)frame, flags); } + printf("vo_vdpau: allocated_surfaces=%d\n", this->allocated_surfaces ); + frame->ratio = ratio; } @@ -606,7 +624,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; if ( (frame->width > this->soft_surface_width) || (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { printf( "vo_vdpau: soft_surface size update\n" ); - /* recreate surface and mixer to match frame changes */ + /* recreate surface to match frame changes */ this->soft_surface_width = frame->width; this->soft_surface_height = frame->height; this->soft_surface_format = frame->format; @@ -635,7 +653,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) surface = frame->vdpau_accel_data.surface; mix_w = frame->width; mix_h = frame->height; - chroma = VDP_CHROMA_TYPE_420; + chroma = (frame->vo_frame.flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420; } else { /* unknown format */ @@ -646,6 +664,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma) ) { vdpau_release_back_frames( this_gen ); /* empty past frames array */ + printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; @@ -1262,6 +1281,8 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->contrast = 100; this->brightness = 0; + this->allocated_surfaces = 0; + return &this->vo_driver; } -- cgit v1.2.3 From fa9e2c2f46c18cf16a0f6acbc75e671876c29d51 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 21 Dec 2008 18:49:33 +0000 Subject: Chroma type. --- src/xine-engine/accel_vdpau.h | 2 +- src/xine-engine/video_out.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h index 73965abc2..e489408c5 100644 --- a/src/xine-engine/accel_vdpau.h +++ b/src/xine-engine/accel_vdpau.h @@ -42,12 +42,12 @@ typedef struct { VdpDevice vdp_device; VdpGetErrorString *vdp_get_error_string; - VdpVideoSurfaceCreate *vdp_video_surface_create; VdpDecoderCreate *vdp_decoder_create; VdpDecoderDestroy *vdp_decoder_destroy; VdpDecoderRender *vdp_decoder_render; VdpVideoSurface surface; + VdpChromaType chroma; } vdpau_accel_t; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index b3903d4f8..17ddd660b 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -271,6 +271,7 @@ struct xine_video_port_s { #define VO_PAN_SCAN_FLAG 4 #define VO_INTERLACED_FLAG 8 #define VO_NEW_SEQUENCE_FLAG 16 /* set after MPEG2 Sequence Header Code (used by XvMC) */ +#define VO_CHROMA_422 32 /* used by VDPAU, default is chroma_420 */ /* video driver capabilities */ #define VO_CAP_YV12 0x00000001 /* driver can handle YUV 4:2:0 pictures */ @@ -280,8 +281,8 @@ struct xine_video_port_s { #define VO_CAP_UNSCALED_OVERLAY 0x00000010 /* driver can blend overlay at output resolution */ #define VO_CAP_CROP 0x00000020 /* driver can crop */ #define VO_CAP_XXMC 0x00000040 /* driver can use extended XvMC */ -#define VO_CAP_VDPAU_H264 0x00000080 /* driver can use Nvidia VDPAU for H264 */ -#define VO_CAP_VDPAU_MPEG12 0x00000100 /* driver can use Nvidia VDPAU for mpeg1/2 */ +#define VO_CAP_VDPAU_H264 0x00000080 /* driver can use VDPAU for H264 */ +#define VO_CAP_VDPAU_MPEG12 0x00000100 /* driver can use VDPAU for mpeg1/2 */ /* -- cgit v1.2.3 From a2ddf2d655168b7dfffd72b98cc800ffe7ab0965 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 22 Dec 2008 12:28:07 +0000 Subject: Clear PTS on reset; remove a printf. --- src/libvdpau/vdpau_h264.c | 3 +++ src/video_out/video_out_vdpau.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ba458abb6..183ae2712 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -560,6 +560,9 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { static void vdpau_h264_discontinuity (video_decoder_t *this_gen) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; + this->last_pts = 0; + this->tmp_pts = 0; + } /* diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 3fb4d870f..bfd4531c9 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -559,7 +559,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ vdpau_frame_field ((vo_frame_t *)frame, flags); } - printf("vo_vdpau: allocated_surfaces=%d\n", this->allocated_surfaces ); + //printf("vo_vdpau: allocated_surfaces=%d\n", this->allocated_surfaces ); frame->ratio = ratio; } -- cgit v1.2.3 From f06f61d118d95516bb92576c7ba1826e8eaa0d7f Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 22 Dec 2008 13:38:43 +0000 Subject: Fix interlaced playback on generation 3 decoders. --- src/libvdpau/dpb.c | 8 +++++++- src/libvdpau/dpb.h | 4 +++- src/libvdpau/vdpau_h264.c | 4 +++- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index e397449f9..71bc1ce01 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -264,6 +264,7 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r pic->next = dpb->pictures; dpb->pictures = pic; + dpb->num_ref_frames = num_ref_frames; dpb->used++; if(dpb->used > num_ref_frames) { @@ -318,12 +319,13 @@ void dpb_free_all( struct dpb *dpb ) printf("dpb_free_all, used: %d\n", dpb->used); } -void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) +int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) { struct decoded_picture *pic = dpb->pictures; struct decoded_picture *last_pic = NULL; int i = 0; + int used_refframes = 0; if (pic != NULL) do { @@ -345,6 +347,8 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) last_pic = pic; } while ((pic = pic->next) != NULL && i < 16); + used_refframes = i; + // fill all other frames with invalid handles while(i < 16) { reflist[i].bottom_is_reference = VDP_FALSE; @@ -356,4 +360,6 @@ void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) reflist[i].field_order_cnt[1] = 0; i++; } + + return used_refframes; } diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 30a0da50b..3d313177c 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -46,6 +46,8 @@ struct decoded_picture { /* Decoded Picture Buffer */ struct dpb { struct decoded_picture *pictures; + + uint32_t num_ref_frames; uint32_t used; }; @@ -71,6 +73,6 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r int dpb_flush(struct dpb *dpb); void dpb_free_all( struct dpb *dpb ); -void fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist); +int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist); #endif /* DPB_H_ */ diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 183ae2712..7fe570c40 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -390,7 +390,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic.scaling_lists_4x4)); memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic.scaling_lists_8x8)); - fill_vdpau_reference_list(&(this->nal_parser->dpb), pic.referenceFrames); + /* set num_ref_frames to the number of actually available reference frames, + * if this is not set generation 3 decoders will fail. */ + pic.num_ref_frames = fill_vdpau_reference_list(&(this->nal_parser->dpb), pic.referenceFrames); if(this->decoder_started || pic.is_reference) { if(!this->decoder_started) -- cgit v1.2.3 From caf641b1b9f0082413ef4de5372d9c19b0c7e39c Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 23 Dec 2008 17:36:10 +0000 Subject: Fix some more interlaced streams (dpb reference pic removal issues). --- src/libvdpau/h264_parser.c | 11 +++++++---- src/libvdpau/nal.c | 3 +++ src/libvdpau/vdpau_h264.c | 33 ++++++++++----------------------- 3 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 531aa6229..f7d12d322 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -311,7 +311,7 @@ void calculate_pic_order(struct nal_parser *parser) } else { - printf("FIXME: Unsupported poc_type\n"); + printf("FIXME: Unsupported poc_type: %d\n", sps->pic_order_cnt_type); } } @@ -883,10 +883,13 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, struct decoded_picture* pic = dpb_get_picture(dpb, pic_num_x); if (pic != NULL) { if (pic->nal->slc->field_pic_flag == 0) - dpb_set_unused_ref_picture(dpb, pic_num_x); + dpb_set_unused_ref_picture_a(dpb, pic); else { - dpb_set_unused_ref_picture(dpb, pic_num_x); - printf("FIXME: We might need do delete more from the DPB...\n"); + if(!pic->top_is_reference) + dpb_set_unused_ref_picture_a(dpb, pic); + else + pic->top_is_reference = 0; + //printf("FIXME: We might need do delete more from the DPB...\n"); // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120 } } diff --git a/src/libvdpau/nal.c b/src/libvdpau/nal.c index 023357514..608f082c0 100644 --- a/src/libvdpau/nal.c +++ b/src/libvdpau/nal.c @@ -44,6 +44,9 @@ struct nal_unit* init_nal_unit() void free_nal_unit(struct nal_unit *nal) { + if(!nal) + return; + free(nal->sps); free(nal->pps); free(nal->slc); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 7fe570c40..0d55abbc6 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -181,12 +181,14 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { this->video_step = buf->decoder_info[0]; - printf("Videostep: %d\n", this->video_step); _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ - return; + xine_bmiheader *bih = (xine_bmiheader*)buf->content; + this->width = bih->biWidth; + this->height = bih->biHeight; + } else { /* parse the first nal packages to retrieve profile type */ @@ -203,8 +205,10 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->sps->pic_width > 0 && this->nal_parser->current_nal->sps->pic_height > 0) { - this->width = this->nal_parser->current_nal->sps->pic_width; - this->height = this->nal_parser->current_nal->sps->pic_height; + if(this->width == 0) { + this->width = this->nal_parser->current_nal->sps->pic_width; + this->height = this->nal_parser->current_nal->sps->pic_height; + } /* FIXME: ratio should be calculated in some other way to * support anamorph codings... @@ -344,13 +348,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, sps->vui_parameters.timing_info_present_flag && this->video_step == 0) { this->video_step = 2*90000/(1/((double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale)); - printf("Videostep: %d\n", this->video_step); } /* flush the DPB if this frame was an IDR */ //printf("is_idr: %d\n", this->nal_parser->is_idr); if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { - printf("IDR Slice, flush\n"); dpb_flush(&(this->nal_parser->dpb)); } this->nal_parser->is_idr = 0; @@ -366,7 +368,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, pic.frame_num = slc->frame_num; pic.field_pic_flag = slc->field_pic_flag; pic.bottom_field_flag = slc->bottom_field_flag; - pic.num_ref_frames = sps->num_ref_frames; + //pic.num_ref_frames = sps->num_ref_frames; pic.mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; pic.constrained_intra_pred_flag = pps->constrained_intra_pred_flag; pic.weighted_pred_flag = pps->weighted_pred_flag; @@ -416,7 +418,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(img == NULL) { - fflush(stdout); img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, this->ratio, @@ -426,15 +427,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, VdpVideoSurface surface = this->vdpau_accel->surface; - /*if(surface == VDP_INVALID_HANDLE) { - VdpStatus status = this->vdpau_accel->vdp_video_surface_create(this->vdpau_accel->vdp_device, - VDP_CHROMA_TYPE_420, this->width, this->height, - &surface); - this->vdpau_accel->surface = surface; - if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Surface creation failed: %s\n", this->vdpau_accel->vdp_get_error_string(status)); - }*/ - //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); @@ -506,12 +498,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->wait_for_bottom_field = 0; - /*img->draw(img, this->stream); - this->wait_for_bottom_field = 0; - - if(!pic.is_reference) - img->free(img); - img = NULL;*/ } else if(slc->field_pic_flag && !slc->bottom_field_flag) { // don't draw yet, second field is missing. this->last_top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt; @@ -624,6 +610,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->video_step = 0; this->last_pts = 0; this->tmp_pts = 0; + this->width = this->height = 0; (this->stream->video_out->open) (this->stream->video_out, this->stream); -- cgit v1.2.3 From 299eab67f31692aee71a93dc09f9bd2a664bf7a7 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 23 Dec 2008 18:04:00 +0000 Subject: Fix build error & remove a few printfs. --- src/libvdpau/dpb.c | 4 +--- src/libvdpau/dpb.h | 1 + src/libvdpau/h264_parser.c | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 71bc1ce01..7ad87bab7 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -297,9 +297,7 @@ int dpb_flush(struct dpb *dpb) pic = next_pic; } while (pic != NULL); - printf("Flushed, used: %d\n", dpb->used); - //dpb->pictures = NULL; - //dpb->used = 0; + //printf("Flushed, used: %d\n", dpb->used); return 0; } diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 3d313177c..8ecde5d92 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -62,6 +62,7 @@ struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, uint32_t longte struct decoded_picture* dpb_get_picture_by_ltidx(struct dpb *dpb, uint32_t longterm_idx); int dpb_set_unused_ref_picture(struct dpb *dpb, uint32_t picnum); +int dpb_set_unused_ref_picture_a(struct dpb *dpb, struct decoded_picture *refpic); int dpb_set_unused_ref_picture_byltpn(struct dpb *dpb, uint32_t longterm_picnum); int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx); int dpb_set_unused_ref_picture_lidx_gt(struct dpb *dpb, uint32_t longterm_idx); diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index f7d12d322..410732fea 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -488,7 +488,6 @@ void parse_sei(struct buf_reader *buf, struct nal_parser *parser) if(parser->cpb_dpb_delays_present_flag) { sei->pic_timing.cpb_removal_delay = read_bits(buf, 5); sei->pic_timing.dpb_output_delay = read_bits(buf, 5); - printf("output delay: %d\n", sei->pic_timing.dpb_output_delay); } } } -- cgit v1.2.3 From 27a05e59f563e7bb43fa8286646d15448f1670bf Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 23 Dec 2008 18:04:00 +0000 Subject: Enable inverse telecine & noise reduction. --- src/video_out/video_out_vdpau.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index bfd4531c9..11eb0fcb3 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -666,7 +666,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_release_back_frames( this_gen ); /* empty past frames array */ printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 2; void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; @@ -1240,7 +1240,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->video_mixer_chroma = chroma; this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 2; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; -- cgit v1.2.3 From 08b37241e90cddc8d1db6d0aaf6fbb602bd61ae1 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 23 Dec 2008 18:04:00 +0000 Subject: Set H.264 progressive_frame_flag; follow it in video_out_vdpau. (Maybe following the flag is not a good idea for mpeg2...) --- src/libvdpau/vdpau_h264.c | 5 +++++ src/video_out/video_out_vdpau.c | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 0d55abbc6..81932e096 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -448,6 +448,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->bad_frame = 0; + if(!pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag) + img->progressive_frame = 1; + else + img->progressive_frame = 0; + struct decoded_picture *decoded_pic = NULL; if(pic.is_reference) { if(!slc->field_pic_flag || !this->wait_for_bottom_field) { diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 11eb0fcb3..ed68b5c5f 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -715,7 +715,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) layer_count = 0; } - if ( frame->vo_frame.duration>2500 && frame->format==XINE_IMGFMT_VDPAU ) { + if ( frame->vo_frame.duration>2500 && !frame->vo_frame.progressive_frame && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; VdpVideoSurface future[1]; -- cgit v1.2.3 From 3472b11d2a8e131fa297b8e3acf14e69394337ba Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Wed, 24 Dec 2008 10:56:19 +0000 Subject: MMC operations need to be executed _after_ the frame was decoded. This fixes some more streams. --- src/libvdpau/h264_parser.c | 100 ++++++++++++++++++++++++++++----------------- src/libvdpau/nal.h | 3 +- src/libvdpau/vdpau_h264.c | 1 + 3 files changed, 66 insertions(+), 38 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 410732fea..03f906c77 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -71,7 +71,9 @@ void parse_sei(struct buf_reader *buf, struct nal_parser *parser); uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser); void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); -void decode_ref_pic_marking(uint32_t memory_management_control_operation, +void decode_ref_pic_marking(struct nal_unit *nal, + uint32_t memory_management_control_operation, + uint32_t marking_nr, struct nal_parser *parser); void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal); void parse_dec_ref_pic_marking(struct buf_reader *buf, @@ -746,6 +748,8 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) /* --- dec_ref_pic_marking --- */ if (nal->nal_ref_idc != 0) parse_dec_ref_pic_marking(buf, parser); + else + slc->dec_ref_pic_marking_count = 0; return 0; } @@ -864,10 +868,11 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) } } -void decode_ref_pic_marking(uint32_t memory_management_control_operation, +void decode_ref_pic_marking(struct nal_unit *nal, + uint32_t memory_management_control_operation, + uint32_t marking_nr, struct nal_parser *parser) { - struct nal_unit *nal = parser->current_nal; struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; @@ -878,12 +883,13 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, if (memory_management_control_operation == 1) { // short-term -> unused for reference uint32_t pic_num_x = nal->curr_pic_num - - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); + - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1); struct decoded_picture* pic = dpb_get_picture(dpb, pic_num_x); if (pic != NULL) { - if (pic->nal->slc->field_pic_flag == 0) + if (pic->nal->slc->field_pic_flag == 0) { + printf("Set %d as unused for ref\n", pic_num_x); dpb_set_unused_ref_picture_a(dpb, pic); - else { + } else { if(!pic->top_is_reference) dpb_set_unused_ref_picture_a(dpb, pic); else @@ -896,14 +902,14 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, else if (memory_management_control_operation == 2) { // long-term -> unused for reference struct decoded_picture* pic = dpb_get_picture_by_ltpn(dpb, - slc->dec_ref_pic_marking.long_term_pic_num); + slc->dec_ref_pic_marking[marking_nr].long_term_pic_num); if (pic != NULL) { if (pic->nal->slc->field_pic_flag == 0) dpb_set_unused_ref_picture(dpb, - slc->dec_ref_pic_marking.long_term_pic_num); + slc->dec_ref_pic_marking[marking_nr].long_term_pic_num); else { dpb_set_unused_ref_picture(dpb, - slc->dec_ref_pic_marking.long_term_pic_num); + slc->dec_ref_pic_marking[marking_nr].long_term_pic_num); printf("FIXME: We might need do delete more from the DPB...\n"); } } @@ -911,19 +917,19 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, else if (memory_management_control_operation == 3) { // short-term -> long-term, set long-term frame index uint32_t pic_num_x = nal->curr_pic_num - - (slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + 1); + - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1); struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, - slc->dec_ref_pic_marking.long_term_pic_num); + slc->dec_ref_pic_marking[marking_nr].long_term_pic_num); if (pic != NULL) dpb_set_unused_ref_picture_bylidx(dpb, - slc->dec_ref_pic_marking.long_term_frame_idx); + slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx); pic = dpb_get_picture(dpb, pic_num_x); if (pic) { if (pic->nal->slc->field_pic_flag == 0) { pic = dpb_get_picture(dpb, pic_num_x); pic->nal->long_term_frame_idx - = slc->dec_ref_pic_marking.long_term_frame_idx; + = slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx; } else printf("FIXME: B Set frame %d to long-term ref\n", pic_num_x); @@ -937,11 +943,11 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, // set max-long-term frame index, // mark all long-term pictures with long-term frame idx // greater max-long-term farme idx as unused for ref - if (slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 == 0) + if (slc->dec_ref_pic_marking[marking_nr].max_long_term_frame_idx_plus1 == 0) dpb_set_unused_ref_picture_lidx_gt(dpb, 0); else dpb_set_unused_ref_picture_lidx_gt(dpb, - slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 - 1); + slc->dec_ref_pic_marking[marking_nr].max_long_term_frame_idx_plus1 - 1); } else if (memory_management_control_operation == 5) { // mark all ref pics as unused for reference, @@ -954,12 +960,12 @@ void decode_ref_pic_marking(uint32_t memory_management_control_operation, // mark current picture as used for long-term ref, // assing long-term frame idx to it struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, - slc->dec_ref_pic_marking.long_term_frame_idx); + slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx); if (pic != NULL) dpb_set_unused_ref_picture_bylidx(dpb, - slc->dec_ref_pic_marking.long_term_frame_idx); + slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx); - nal->long_term_frame_idx = slc->dec_ref_pic_marking.long_term_frame_idx; + nal->long_term_frame_idx = slc->dec_ref_pic_marking[marking_nr].long_term_frame_idx; if (slc->field_pic_flag == 0) { nal->used_for_long_term_ref = 1; @@ -979,44 +985,51 @@ void parse_dec_ref_pic_marking(struct buf_reader *buf, if (!sps || !pps) return; + slc->dec_ref_pic_marking_count = 0; + int i = slc->dec_ref_pic_marking_count; + if (nal->nal_unit_type == NAL_SLICE_IDR) { - slc->dec_ref_pic_marking.no_output_of_prior_pics_flag = read_bits(buf, 1); - slc->dec_ref_pic_marking.long_term_reference_flag = read_bits(buf, 1); + slc->dec_ref_pic_marking[i].no_output_of_prior_pics_flag = read_bits(buf, 1); + slc->dec_ref_pic_marking[i].long_term_reference_flag = read_bits(buf, 1); } else { - slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag = read_bits( + slc->dec_ref_pic_marking[i].adaptive_ref_pic_marking_mode_flag = read_bits( buf, 1); - if (slc->dec_ref_pic_marking.adaptive_ref_pic_marking_mode_flag) { + if (slc->dec_ref_pic_marking[i].adaptive_ref_pic_marking_mode_flag) { do { - slc->dec_ref_pic_marking.memory_management_control_operation + slc->dec_ref_pic_marking[i].memory_management_control_operation = read_exp_golomb(buf); - if (slc->dec_ref_pic_marking.memory_management_control_operation == 1 - || slc->dec_ref_pic_marking.memory_management_control_operation + if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 1 + || slc->dec_ref_pic_marking[i].memory_management_control_operation == 3) - slc->dec_ref_pic_marking.difference_of_pic_nums_minus1 + slc->dec_ref_pic_marking[i].difference_of_pic_nums_minus1 = read_exp_golomb(buf); - if (slc->dec_ref_pic_marking.memory_management_control_operation == 2) - slc->dec_ref_pic_marking.long_term_pic_num = read_exp_golomb(buf); + if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 2) + slc->dec_ref_pic_marking[i].long_term_pic_num = read_exp_golomb(buf); - if (slc->dec_ref_pic_marking.memory_management_control_operation == 3 - || slc->dec_ref_pic_marking.memory_management_control_operation + if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 3 + || slc->dec_ref_pic_marking[i].memory_management_control_operation == 6) - slc->dec_ref_pic_marking.long_term_frame_idx = read_exp_golomb(buf); + slc->dec_ref_pic_marking[i].long_term_frame_idx = read_exp_golomb(buf); - if (slc->dec_ref_pic_marking.memory_management_control_operation == 4) - slc->dec_ref_pic_marking.max_long_term_frame_idx_plus1 + if (slc->dec_ref_pic_marking[i].memory_management_control_operation == 4) + slc->dec_ref_pic_marking[i].max_long_term_frame_idx_plus1 = read_exp_golomb(buf); - decode_ref_pic_marking( - slc->dec_ref_pic_marking.memory_management_control_operation, - parser); - } while (slc->dec_ref_pic_marking.memory_management_control_operation + i++; + if(i >= 10) { + printf("Error: Not more than 10 MMC operations supported per slice. Dropping some.\n"); + i = 0; + } + } while (slc->dec_ref_pic_marking[i-1].memory_management_control_operation != 0); } } + + slc->dec_ref_pic_marking_count = i; } /* ----------------- NAL parser ----------------- */ @@ -1076,6 +1089,19 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t completed_nal = 0; uint8_t *prebuf = parser->prebuf; + + if(parser->last_nal_res == 1 && parser->current_nal && + parser->current_nal->slc) { + int i; + for(i = 0; i < parser->current_nal->slc->dec_ref_pic_marking_count; i++) { + decode_ref_pic_marking( + parser->current_nal, + parser->current_nal->slc->dec_ref_pic_marking[i].memory_management_control_operation, + i, + parser); + } + } + while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset)) >= 0) { next_nal += search_offset; diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index 4ab98b032..40e463716 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -380,7 +380,8 @@ struct slice_header uint32_t long_term_pic_num; uint32_t long_term_frame_idx; uint32_t max_long_term_frame_idx_plus1; - } dec_ref_pic_marking; + } dec_ref_pic_marking[10]; + uint32_t dec_ref_pic_marking_count; }; struct nal_unit diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 81932e096..f362d457d 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -579,6 +579,7 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { this->stream->video_out->close( this->stream->video_out, this->stream ); + free (this->nal_parser); free (this_gen); } -- cgit v1.2.3 From 8ab46aacc70273916ed362fb712736ec1f2db62d Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Thu, 25 Dec 2008 15:37:45 +0000 Subject: Fix PTS issues if the first incoming buf holds a PTS of 0. --- src/libvdpau/vdpau_h264.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index f362d457d..3cd649cfa 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -337,8 +337,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { - if(this->last_pts == 0) - this->last_pts = buf->pts; + if(this->last_pts == 0 || this->tmp_pts == 0) { + this->tmp_pts = this->last_pts = buf->pts; + } struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; @@ -490,11 +491,10 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(decoded_pic) { if(decoded_pic->nal->nal_unit_type == NAL_SLICE_IDR && decoded_pic->img->pts != 0) { - this->last_pts = decoded_pic->img->pts; + this->last_pts = this->tmp_pts = decoded_pic->img->pts; } decoded_pic->img->pts = this->last_pts; - this->tmp_pts = decoded_pic->img->pts; this->last_pts += this->video_step; //printf("poc: %d, %d, pts: %lld\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt, decoded_pic->img->pts); decoded_pic->img->draw(decoded_pic->img, this->stream); -- cgit v1.2.3 From d05b6585a92b76f4d9cba67e4674b5bfdefc69c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sat, 27 Dec 2008 10:18:47 +0000 Subject: Add still image support. --- src/libvdpau/vdpau_mpeg12.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index fa20f8579..fc7221019 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -754,7 +754,7 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size ); seq->bufpos += buf->size; - while ( seq->bufseek < seq->bufpos-4 ) { + while ( seq->bufseek <= seq->bufpos-4 ) { uint8_t *buf = seq->buf+seq->bufseek; if ( buf[0]==0 && buf[1]==0 && buf[2]==1 ) { if ( seq->start<0 ) { @@ -777,6 +777,14 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * ++seq->bufseek; } + /* still image detection -- don't wait for further data if buffer ends in sequence end code */ + if (seq->start >= 0 && seq->buf[seq->start + 3] == sequence_end_code) { + if (parse_code(this, seq->buf+seq->start, 4)) { + decode_picture(this); + parse_code(this, seq->buf+seq->start, 4); + } + seq->start = -1; + } } /* @@ -786,7 +794,8 @@ static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; printf( "vdpau_mpeg12: vdpau_mpeg12_flush\n" ); - reset_sequence( &this->sequence ); +// incorrect: see libmpeg2, mpeg2_flush() +// reset_sequence( &this->sequence ); } /* -- cgit v1.2.3 From a52f6d552bb02f94de3648d100e6702d73690bf8 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 27 Dec 2008 10:27:28 +0000 Subject: Fix img handling for interlaced streams. --- src/libvdpau/vdpau_h264.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 3cd649cfa..6e5f45eb3 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -79,6 +79,8 @@ typedef struct vdpau_h264_decoder_s { int64_t last_pts; int64_t tmp_pts; + vo_frame_t *last_img; + } vdpau_h264_decoder_t; /************************************************************************** @@ -173,7 +175,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, VdpBitstreamBuffer vdp_buffer; vdp_buffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; - vo_frame_t *img; /* video out frame */ + vo_frame_t *img = this->last_img; /* video out frame */ /* a video decoder does not care about this flag (?) */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) @@ -484,7 +486,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(this->wait_for_bottom_field && slc->bottom_field_flag) decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; - img = NULL; + + this->last_img = img = NULL; /* now retrieve the next output frame */ decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); @@ -507,6 +510,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, // don't draw yet, second field is missing. this->last_top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt; this->wait_for_bottom_field = 1; + this->last_img = img; } } } -- cgit v1.2.3 From ba67f2e81dce751e643ff51a4448a950e27cdc12 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 27 Dec 2008 10:39:35 +0000 Subject: Don't calculate pts for frames where it's contained in buf->pts. --- src/libvdpau/vdpau_h264.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 6e5f45eb3..dfda309eb 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -78,6 +78,7 @@ typedef struct vdpau_h264_decoder_s { int64_t last_pts; int64_t tmp_pts; + int64_t next_pts; vo_frame_t *last_img; @@ -197,6 +198,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, int len = 0; uint32_t slice_count; + if(this->next_pts == 0) + this->next_pts = buf->pts; + while(len < buf->size) { len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); @@ -444,10 +448,12 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, else { img->duration = this->video_step; - if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) + /*if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) img->pts = buf->pts; else - img->pts = 0; + img->pts = 0;*/ + img->pts = this->next_pts; + this->next_pts = buf->pts; img->bad_frame = 0; @@ -492,7 +498,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /* now retrieve the next output frame */ decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); if(decoded_pic) { - if(decoded_pic->nal->nal_unit_type == NAL_SLICE_IDR && + if(//decoded_pic->nal->nal_unit_type == NAL_SLICE_IDR && decoded_pic->img->pts != 0) { this->last_pts = this->tmp_pts = decoded_pic->img->pts; } @@ -620,6 +626,9 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->video_step = 0; this->last_pts = 0; this->tmp_pts = 0; + this->next_pts = 0; + + this->last_img = NULL; this->width = this->height = 0; (this->stream->video_out->open) (this->stream->video_out, this->stream); -- cgit v1.2.3 From f57b7d6e2bfe2d2b759e5389cdd6c9f10acd1f16 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 27 Dec 2008 17:19:57 +0000 Subject: Revert pts changes for now as they cause trouble. --- src/libvdpau/vdpau_h264.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index dfda309eb..d6548b682 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -448,11 +448,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, else { img->duration = this->video_step; - /*if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) + if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) img->pts = buf->pts; else - img->pts = 0;*/ - img->pts = this->next_pts; + img->pts = 0; + //img->pts = this->next_pts; this->next_pts = buf->pts; img->bad_frame = 0; -- cgit v1.2.3 From 92d89235ad1e8a413422947b92b957a5453950ea Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 27 Dec 2008 17:20:17 +0000 Subject: Initial support for ARGB overlay. --- include/xine.h.in | 7 +++++ src/video_out/video_out_vdpau.c | 65 +++++++++++++++++++++++++++++++++++----- src/xine-engine/osd.c | 15 ++++++++++ src/xine-engine/osd.h | 13 ++++++++ src/xine-engine/video_out.h | 2 ++ src/xine-engine/xine_interface.c | 5 ++++ 6 files changed, 100 insertions(+), 7 deletions(-) diff --git a/include/xine.h.in b/include/xine.h.in index ced7a8757..79db9024e 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -2200,6 +2200,13 @@ void xine_osd_get_palette (xine_osd_t *self, uint32_t *color, void xine_osd_set_palette (xine_osd_t *self, const uint32_t *const color, const uint8_t *const trans ) XINE_PROTECTED; + +/* + * set an argb buffer to be blended into video + * this is currently only supported with vdpau + */ +void xine_osd_set_argb_buffer(xine_osd_t *self, uint32_t *argb_buffer) XINE_PROTECTED; + /* * close osd rendering engine * loaded fonts are unloaded diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index ed68b5c5f..190e671b3 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -154,6 +154,11 @@ typedef struct { uint32_t overlay_unscaled_height; int has_unscaled; + VdpOutputSurface argb_overlay; + uint32_t argb_overlay_width; + uint32_t argb_overlay_height; + int has_argb_overlay; + VdpVideoSurface soft_surface; uint32_t soft_surface_width; uint32_t soft_surface_height; @@ -212,7 +217,35 @@ static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *over } } +static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + if(overlay->argb_buffer == NULL) + return 0; + + if ( (this->argb_overlay_width != overlay->width ) || (this->argb_overlay_height != overlay->height) || (this->argb_overlay == VDP_INVALID_HANDLE) ) { + if (this->argb_overlay != VDP_INVALID_HANDLE) { + vdp_output_surface_destroy( this->argb_overlay ); + } + VdpStatus st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, overlay->width, overlay->height, &this->argb_overlay ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + } + this->argb_overlay_width = overlay->width; + this->argb_overlay_height = overlay->height; + } + + uint32_t pitch = this->argb_overlay_width*4; + VdpRect dest = { 0, 0, this->argb_overlay_width, this->argb_overlay_height }; + VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(overlay->argb_buffer), &pitch, &dest ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) ); + } else + this->has_argb_overlay = 1; + return 1; +} static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) { @@ -316,6 +349,9 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v if ( vdpau_process_ovl( this, overlay ) ) ++this->ovl_changed; } + + if(overlay->argb_buffer) + vdpau_process_argb_ovl( this, overlay ); } @@ -667,9 +703,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; - int num_layers = 2; - void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS, VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL }; + int num_layers = 3; + float noise_reduction_level = 1.0; + void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers, &noise_reduction_level }; vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; @@ -700,7 +737,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); uint32_t layer_count; - VdpLayer layer[2]; + VdpLayer layer[3]; VdpRect layersrc, unscaledsrc; if ( this->has_overlay ) { //printf("vdpau_display_frame: overlay should be visible !\n"); @@ -715,6 +752,15 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) layer_count = 0; } + VdpRect argb_rect = {0, 0, this->argb_overlay_width, this->argb_overlay_height }; + if( this->has_argb_overlay ) { + layer_count++; + layer[layer_count-1].destination_rect = &vid_dest; + layer[layer_count-1].source_rect = &argb_rect; + layer[layer_count-1].source_surface = this->argb_overlay; + layer[layer_count-1].struct_version = VDP_LAYER_VERSION; + } + if ( frame->vo_frame.duration>2500 && !frame->vo_frame.progressive_frame && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; @@ -1069,6 +1115,10 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->ovl_changed = 0; this->has_overlay = 0; + this->argb_overlay = VDP_INVALID_HANDLE; + this->argb_overlay_width = this->argb_overlay_height = 0; + this->has_argb_overlay = 0; + /* overlay converter */ this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); this->ovl_yuv2rgb = this->yuv2rgb_factory->create_converter( this->yuv2rgb_factory ); @@ -1241,9 +1291,10 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; - int num_layers = 2; - void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS, VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL }; + int num_layers = 3; + float noise_reduction_level = 1.0; + void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers, &noise_reduction_level }; st = vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 05acd4779..0bc1574ca 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -152,6 +152,8 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width osd->x2 = 0; osd->y2 = 0; + osd->argb_buffer = NULL; + memcpy(osd->color, textpalettes_color[0], sizeof(textpalettes_color[0])); memcpy(osd->trans, textpalettes_trans[0], sizeof(textpalettes_trans[0])); @@ -228,6 +230,9 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { this->event.object.handle = osd->handle; memset( this->event.object.overlay, 0, sizeof(*this->event.object.overlay) ); + + this->event.object.overlay->argb_buffer = osd->argb_buffer; + this->event.object.overlay->unscaled = unscaled; this->event.object.overlay->x = osd->display_x + osd->x1; this->event.object.overlay->y = osd->display_y + osd->y1; @@ -1537,6 +1542,15 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap, } } +static void osd_set_argb_buffer(osd_object_t *osd, uint32_t *argb_buffer) +{ + osd->argb_buffer = argb_buffer; + osd->x2 = osd->width; + osd->x1 = 0; + osd->y2 = osd->height; + osd->y1 = 0; +} + static uint32_t osd_get_capabilities (osd_object_t *osd) { osd_renderer_t *this = osd->renderer; @@ -1612,6 +1626,7 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { this->get_text_size = osd_get_text_size; this->close = osd_renderer_close; this->draw_bitmap = osd_draw_bitmap; + this->set_argb_buffer = osd_set_argb_buffer; this->show_unscaled = osd_show_unscaled; this->get_capabilities = osd_get_capabilities; diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h index 70193a2ea..ed3118a05 100644 --- a/src/xine-engine/osd.h +++ b/src/xine-engine/osd.h @@ -65,6 +65,13 @@ struct osd_object_s { osd_font_t *font; osd_ft2context_t *ft2; + + + /* this holds an optional ARGB overlay, which + * is only be used by supported video_out modules. + * right now this is only vdpau */ + uint32_t *argb_buffer; + }; /* this one is public */ @@ -211,6 +218,12 @@ struct osd_renderer_s { */ uint32_t (*get_capabilities) (osd_object_t *osd); + /* + * set a buffer to an argb buffer + */ + void (*set_argb_buffer) (osd_object_t *osd, uint32_t *argb_buffer); + + /* private stuff */ pthread_mutex_t osd_mutex; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 17ddd660b..7fa34ac8b 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -419,6 +419,8 @@ struct vo_overlay_s { int hili_rgb_clut; /* true if clut was converted to rgb */ int unscaled; /* true if it should be blended unscaled */ + + uint32_t *argb_buffer; }; diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index d1d5a18d9..1f6175a06 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -855,6 +855,11 @@ void xine_osd_draw_bitmap(xine_osd_t *this, uint8_t *bitmap, this->osd.renderer->draw_bitmap(&this->osd, bitmap, x1, y1, width, height, palette_map); } +void xine_osd_set_argb_buffer(xine_osd_t *this, uint32_t *argb_buffer) { + this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer); +} + + const char *const *xine_post_list_inputs(xine_post_t *this_gen) { post_plugin_t *this = (post_plugin_t *)this_gen; return this->input_ids; -- cgit v1.2.3 From 24834b674da33c0c36c71b8dda94254a14562e73 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 27 Dec 2008 20:37:12 +0000 Subject: User aspect ratio. --- src/video_out/video_out_vdpau.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 190e671b3..4daddb2d2 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -906,6 +906,12 @@ static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) this->sc.force_redraw = 1; //* trigger re-calc of output size } break;*/ + case VO_PROP_ASPECT_RATIO: + if ( value>=XINE_VO_ASPECT_NUM_RATIOS ) + value = XINE_VO_ASPECT_AUTO; + this->sc.user_ratio = value; + this->sc.force_redraw = 1; /* trigger re-calc of output size */ + break; case VO_PROP_HUE: this->hue = value; vdpau_update_csc( this ); break; case VO_PROP_SATURATION: this->saturation = value; vdpau_update_csc( this ); break; case VO_PROP_CONTRAST: this->contrast = value; vdpau_update_csc( this ); break; -- cgit v1.2.3 From dd2896d3de4070799cdc8c1ed3600d424780811d Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 27 Dec 2008 23:32:41 +0000 Subject: Progressive frame & background colour bits. --- src/libvdpau/vdpau_h264.c | 5 ++ src/libvdpau/vdpau_mpeg12.c | 4 + src/video_out/video_out_vdpau.c | 167 +++++++++++++++++++++++++++++++++++----- 3 files changed, 158 insertions(+), 18 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index d6548b682..c7ad706e9 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -444,7 +444,12 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } if(status != VDP_STATUS_OK) + { xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); + img->bad_frame = 1; + img->draw(img, this->stream); + this->last_img = 0; + } else { img->duration = this->video_step; diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index fc7221019..66d451c12 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -118,6 +118,7 @@ typedef struct { int slices_size; int slices_pos, slices_pos_top; + int progressive_frame; int state; } picture_t; @@ -435,6 +436,7 @@ static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int le lprintf( "alternate_scan: %d\n", get_bits( buf,29,1 ) ); lprintf( "repeat_first_field: %d\n", get_bits( buf,30,1 ) ); lprintf( "chroma_420_type: %d\n", get_bits( buf,31,1 ) ); + sequence->picture.progressive_frame = get_bits( buf,32,1 ); lprintf( "progressive_frame: %d\n", get_bits( buf,32,1 ) ); sequence->picture.state = WANT_SLICE; } @@ -687,6 +689,8 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) img->bad_frame = 0; img->duration = seq->video_step; + img->top_field_first = pic->vdp_infos.top_field_first; + // progressive_frame is unreliable with most mpeg2 streams //img->progressive_frame = pic->progressive_frame; if ( pic->vdp_infos.picture_coding_type!=B_FRAME ) { if ( pic->vdp_infos.picture_coding_type==I_FRAME && !seq->backward_ref ) { diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 4daddb2d2..f9746a1a4 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -96,7 +96,7 @@ VdpPresentationQueueCreate *vdp_queue_create; VdpPresentationQueueDestroy *vdp_queue_destroy; VdpPresentationQueueDisplay *vdp_queue_display; VdpPresentationQueueBlockUntilSurfaceIdle *vdp_queue_block; -VdpPresentationQueueSetBackgroundColor *vdp_queue_set_backgroung_color; +VdpPresentationQueueSetBackgroundColor *vdp_queue_set_background_color; VdpPresentationQueueGetTime *vdp_queue_get_time; VdpBitmapSurfacePutBitsNative *vdp_bitmap_put_bits; @@ -110,6 +110,62 @@ VdpDecoderRender *vdp_decoder_render; +static VdpVideoSurfaceCreate *orig_vdp_video_surface_create; +static VdpVideoSurfaceDestroy *orig_vdp_video_surface_destroy; + +static VdpDecoderCreate *orig_vdp_decoder_create; +static VdpDecoderDestroy *orig_vdp_decoder_destroy; +static VdpDecoderRender *orig_vdp_decoder_render; + +static Display *guarded_display; + +static VdpStatus guarded_vdp_video_surface_create(VdpDevice device, VdpChromaType chroma_type, uint32_t width, uint32_t height,VdpVideoSurface *surface) +{ + VdpStatus r; + XLockDisplay(guarded_display); + r = orig_vdp_video_surface_create(device, chroma_type, width, height, surface); + XUnlockDisplay(guarded_display); + return r; +} + +static VdpStatus guarded_vdp_video_surface_destroy(VdpVideoSurface surface) +{ + VdpStatus r; +// XLockDisplay(guarded_display); + r = orig_vdp_video_surface_destroy(surface); +// XUnlockDisplay(guarded_display); + return r; +} + +static VdpStatus guarded_vdp_decoder_create(VdpDevice device, VdpDecoderProfile profile, uint32_t width, uint32_t height, uint32_t max_references, VdpDecoder *decoder) +{ + VdpStatus r; + XLockDisplay(guarded_display); + r = orig_vdp_decoder_create(device, profile, width, height, max_references, decoder); + XUnlockDisplay(guarded_display); + return r; +} + +static VdpStatus guarded_vdp_decoder_destroy(VdpDecoder decoder) +{ + VdpStatus r; + XLockDisplay(guarded_display); + r = orig_vdp_decoder_destroy(decoder); + XUnlockDisplay(guarded_display); + return r; +} + +static VdpStatus guarded_vdp_decoder_render(VdpDecoder decoder, VdpVideoSurface target, VdpPictureInfo const *picture_info, uint32_t bitstream_buffer_count, VdpBitstreamBuffer const *bitstream_buffers) +{ + VdpStatus r; + XLockDisplay(guarded_display); + r = orig_vdp_decoder_render(decoder, target, picture_info, bitstream_buffer_count, bitstream_buffers); + XUnlockDisplay(guarded_display); + return r; +} + + + typedef struct { VdpBitmapSurface ovl_bitmap; uint32_t bitmap_width, bitmap_height; @@ -175,6 +231,8 @@ typedef struct { uint32_t video_mixer_width; uint32_t video_mixer_height; + VdpColor back_color; + vdpau_frame_t *back_frame[ NUM_FRAMES_BACK ]; uint32_t capabilities; @@ -217,6 +275,8 @@ static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *over } } + + static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -247,6 +307,8 @@ static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overl return 1; } + + static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) { vdpau_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1]; @@ -514,6 +576,7 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) /* * supply required functions/fields */ + frame->vo_frame.proc_duplicate_frame_data = NULL; frame->vo_frame.proc_slice = vdpau_frame_proc_slice; frame->vo_frame.proc_frame = NULL; frame->vo_frame.field = vdpau_frame_field; @@ -533,6 +596,51 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) +static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original) +{ + vdpau_frame_t *this = (vdpau_frame_t *)this_gen; + vdpau_frame_t *orig = (vdpau_frame_t *)original; + VdpStatus st; + VdpYCbCrFormat format; + + if (orig->vo_frame.format != XINE_IMGFMT_VDPAU) { + fprintf(stderr, "vdpau_duplicate_frame_data: unexpected frame format 0x%08x!\n", orig->vo_frame.format); + return; + } + + if (!(orig->flags & VO_CHROMA_422)) { + this->vo_frame.pitches[0] = 8*((orig->vo_frame.width + 7) / 8); + this->vo_frame.pitches[1] = 8*((orig->vo_frame.width + 15) / 16); + this->vo_frame.pitches[2] = 8*((orig->vo_frame.width + 15) / 16); + this->vo_frame.base[0] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * orig->vo_frame.height, (void **)&this->chunk[0]); + this->vo_frame.base[1] = xine_xmalloc_aligned(16, this->vo_frame.pitches[1] * ((orig->vo_frame.height+1)/2), (void **)&this->chunk[1]); + this->vo_frame.base[2] = xine_xmalloc_aligned(16, this->vo_frame.pitches[2] * ((orig->vo_frame.height+1)/2), (void **)&this->chunk[2]); + format = VDP_YCBCR_FORMAT_YV12; + } else { + this->vo_frame.pitches[0] = 8*((orig->vo_frame.width + 3) / 4); + this->vo_frame.base[0] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * orig->vo_frame.height, (void **)&this->chunk[0]); + format = VDP_YCBCR_FORMAT_YUYV; + } + + st = vdp_video_surface_getbits_ycbcr(orig->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches); + if (st != VDP_STATUS_OK) + printf("vo_vdpau: failed to get surface bits !! %s\n", vdp_get_error_string(st)); + + st = vdp_video_surface_putbits_ycbcr(this->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches); + if (st != VDP_STATUS_OK) + printf("vo_vdpau: failed to put surface bits !! %s\n", vdp_get_error_string(st)); + + if (this->chunk[0]) + free(this->chunk[0]); + if (this->chunk[1]) + free(this->chunk[1]); + if (this->chunk[2]) + free(this->chunk[2]); + this->chunk[0] = this->chunk[1] = this->chunk[2] = NULL; +} + + + static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, uint32_t width, uint32_t height, double ratio, int format, int flags) { @@ -574,6 +682,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; --this->allocated_surfaces; + frame->vo_frame.proc_duplicate_frame_data = NULL; } } @@ -584,6 +693,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ else { frame->vdpau_accel_data.chroma = chroma; ++this->allocated_surfaces; + frame->vo_frame.proc_duplicate_frame_data = vdpau_duplicate_frame_data; } } @@ -639,6 +749,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpChromaType chroma = this->video_mixer_chroma; uint32_t mix_w = this->video_mixer_width; uint32_t mix_h = this->video_mixer_height; + VdpTime stream_speed; if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) || (frame->ratio != this->sc.delivered_ratio) ) { @@ -729,13 +840,23 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) //printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 ); - XLockDisplay( this->display ); + /* prepare field delay calculation to not run into a deadlock while display locked */ + stream_speed = frame->vo_frame.stream ? xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) : 0; + if (stream_speed != 0) { + int vo_bufs_in_fifo = 0; + _x_query_buffer_usage(frame->vo_frame.stream, NULL, NULL, &vo_bufs_in_fifo, NULL); + //fprintf(stderr, "vo_bufs: %d\n", vo_bufs_in_fifo); + if (vo_bufs_in_fifo <= 0) + stream_speed = 0; /* still image -> no delay */ + } VdpTime last_time; if ( this->init_queue>1 ) vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); + XLockDisplay( this->display ); + uint32_t layer_count; VdpLayer layer[3]; VdpRect layersrc, unscaledsrc; @@ -767,7 +888,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpVideoSurface future[1]; past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; future[0] = surface; - st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD, + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, frame->vo_frame.progressive_frame || frame->vo_frame.top_field_first ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); @@ -776,8 +897,11 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; - if ( this->init_queue>1 ) + if ( this->init_queue>1 ) { + XUnlockDisplay(this->display); vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); + XLockDisplay(this->display); + } if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { /* recreate output surface to match window size */ @@ -791,12 +915,17 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) past[0] = surface; future[0] = VDP_INVALID_HANDLE; - st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD, + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, frame->vo_frame.progressive_frame || frame->vo_frame.top_field_first ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - current_time += frame->vo_frame.duration*100000/18; + /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */ + if (stream_speed > 0) + current_time += frame->vo_frame.duration * 100000ull * XINE_FINE_SPEED_NORMAL / (18 * stream_speed); + else + current_time = 0; /* immediately i. e. no delay */ + vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; @@ -979,10 +1108,7 @@ static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void * XUnlockDisplay( this->display ); break; } - VdpColor backColor; - backColor.red = backColor.green = backColor.blue = 0; - backColor.alpha = 1; - vdp_queue_set_backgroung_color( vdp_queue, &backColor ); + vdp_queue_set_background_color( vdp_queue, &this->back_color ); XUnlockDisplay( this->display ); this->sc.force_redraw = 1; break; @@ -1081,6 +1207,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if (!this) return NULL; + guarded_display = visual->display; this->display = visual->display; this->screen = visual->screen; this->drawable = visual->d; @@ -1174,10 +1301,10 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdpau_dispose( &this->vo_driver ); return NULL; } - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_CREATE , (void*)&vdp_video_surface_create ); + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_CREATE , (void*)&orig_vdp_video_surface_create ); vdp_video_surface_create = guarded_vdp_video_surface_create; if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , (void*)&vdp_video_surface_destroy ); + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_DESTROY , (void*)&orig_vdp_video_surface_destroy ); vdp_video_surface_destroy = guarded_vdp_video_surface_destroy; if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR , (void*)&vdp_video_surface_putbits_ycbcr ); @@ -1231,7 +1358,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE , (void*)&vdp_queue_block ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR , (void*)&vdp_queue_set_backgroung_color ); + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR , (void*)&vdp_queue_set_background_color ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_SET_BACKGROUND_COLOR proc address !!", &this->vo_driver, 1 ) ) return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME , (void*)&vdp_queue_get_time ); @@ -1240,13 +1367,13 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , (void*)&vdp_decoder_query_capabilities ); if ( vdpau_init_error( st, "Can't get DECODER_QUERY_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_CREATE , (void*)&vdp_decoder_create ); + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_CREATE , (void*)&orig_vdp_decoder_create ); vdp_decoder_create = guarded_vdp_decoder_create; if ( vdpau_init_error( st, "Can't get DECODER_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_DESTROY , (void*)&vdp_decoder_destroy ); + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_DESTROY , (void*)&orig_vdp_decoder_destroy ); vdp_decoder_destroy = guarded_vdp_decoder_destroy; if ( vdpau_init_error( st, "Can't get DECODER_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_RENDER , (void*)&vdp_decoder_render ); + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_RENDER , (void*)&orig_vdp_decoder_render ); vdp_decoder_render = guarded_vdp_decoder_render; if ( vdpau_init_error( st, "Can't get DECODER_RENDER proc address !!", &this->vo_driver, 1 ) ) return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_CREATE , (void*)&vdp_bitmap_create ); @@ -1266,8 +1393,12 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if ( vdpau_init_error( st, "Can't create presentation queue !!", &this->vo_driver, 1 ) ) return NULL; - VdpColor backColor = { 0, 0, 0, 1 }; - vdp_queue_set_backgroung_color( vdp_queue, &backColor ); + /* choose almost magenta as backcolor for color keying */ + this->back_color.red = 0.98; + this->back_color.green = 0.01; + this->back_color.blue = 0.99; + this->back_color.alpha = 1; + vdp_queue_set_background_color( vdp_queue, &this->back_color ); this->soft_surface_width = 1280; this->soft_surface_height = 720; -- cgit v1.2.3 From 7d4ce517154dc5098284d48b411753054d744963 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 28 Dec 2008 18:44:24 +0000 Subject: ARGB overlay fixups. --- src/video_out/video_out_vdpau.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index f9746a1a4..cbbed7c68 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -284,7 +284,7 @@ static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overl if(overlay->argb_buffer == NULL) return 0; - if ( (this->argb_overlay_width != overlay->width ) || (this->argb_overlay_height != overlay->height) || (this->argb_overlay == VDP_INVALID_HANDLE) ) { + if ( (this->argb_overlay_width < overlay->width ) || (this->argb_overlay_height < overlay->height) || (this->argb_overlay == VDP_INVALID_HANDLE) ) { if (this->argb_overlay != VDP_INVALID_HANDLE) { vdp_output_surface_destroy( this->argb_overlay ); } @@ -297,8 +297,11 @@ static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overl } uint32_t pitch = this->argb_overlay_width*4; - VdpRect dest = { 0, 0, this->argb_overlay_width, this->argb_overlay_height }; - VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(overlay->argb_buffer), &pitch, &dest ); + VdpRect dest = { 0, overlay->y, this->argb_overlay_width, overlay->y + overlay->height }; + printf("Update ARGB: %d, %d - %dx%d\n", dest.x0, dest.y0, dest.x1, dest.y1); + printf("buf offset: %d\n", overlay->y*this->argb_overlay_width); + uint32_t *buffer_start = overlay->argb_buffer + overlay->y*this->argb_overlay_width; + VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(buffer_start), &pitch, &dest ); if ( st != VDP_STATUS_OK ) { printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) ); } else @@ -393,6 +396,7 @@ static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, i if ( !changed ) return; + this->has_argb_overlay = 0; ++this->ovl_changed; } -- cgit v1.2.3 From c233c9834cd68408c5975368268c560c85c095a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 28 Dec 2008 18:45:15 +0000 Subject: Fix pts handling. --- src/libvdpau/vdpau_h264.c | 62 +++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index c7ad706e9..7a9928f90 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -76,8 +76,7 @@ typedef struct vdpau_h264_decoder_s { xine_t *xine; - int64_t last_pts; - int64_t tmp_pts; + int64_t curr_pts; int64_t next_pts; vo_frame_t *last_img; @@ -198,7 +197,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, int len = 0; uint32_t slice_count; - if(this->next_pts == 0) + if(buf->pts != 0) this->next_pts = buf->pts; while(len < buf->size) { @@ -211,6 +210,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->sps->pic_width > 0 && this->nal_parser->current_nal->sps->pic_height > 0) { + this->curr_pts = this->next_pts; + this->next_pts = 0; + if(this->width == 0) { this->width = this->nal_parser->current_nal->sps->pic_width; this->height = this->nal_parser->current_nal->sps->pic_height; @@ -343,10 +345,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { - if(this->last_pts == 0 || this->tmp_pts == 0) { - this->tmp_pts = this->last_pts = buf->pts; - } - struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; struct slice_header *slc = this->nal_parser->current_nal->slc; @@ -430,11 +428,14 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); this->vdpau_accel = (vdpau_accel_t*)img->accel_data; + + img->duration = this->video_step; + img->pts = this->curr_pts; } VdpVideoSurface surface = this->vdpau_accel->surface; - //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, buf->pts); + //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->curr_pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); @@ -443,23 +444,19 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, free((uint8_t*)vdp_buffer.bitstream); } + this->curr_pts = this->next_pts; + this->next_pts = 0; + if(status != VDP_STATUS_OK) { xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); img->bad_frame = 1; + if (img->pts) + fprintf(stderr, "===== img->pts: %lld\n", img->pts); img->draw(img, this->stream); - this->last_img = 0; + this->last_img = NULL; } else { - - img->duration = this->video_step; - if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) - img->pts = buf->pts; - else - img->pts = 0; - //img->pts = this->next_pts; - this->next_pts = buf->pts; - img->bad_frame = 0; if(!pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag) @@ -503,14 +500,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /* now retrieve the next output frame */ decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); if(decoded_pic) { - if(//decoded_pic->nal->nal_unit_type == NAL_SLICE_IDR && - decoded_pic->img->pts != 0) { - this->last_pts = this->tmp_pts = decoded_pic->img->pts; - } - - decoded_pic->img->pts = this->last_pts; - this->last_pts += this->video_step; - //printf("poc: %d, %d, pts: %lld\n", decoded_pic->nal->top_field_order_cnt, decoded_pic->nal->bottom_field_order_cnt, decoded_pic->img->pts); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); } @@ -558,8 +547,13 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->buf = NULL; this->wait_for_bottom_field = 0; this->video_step = 0; - this->last_pts = 0; - this->tmp_pts = 0; + this->curr_pts = 0; + this->next_pts = 0; + + if (this->last_img) { + this->last_img->free(this->last_img); + this->last_img = NULL; + } } /* @@ -568,8 +562,8 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { static void vdpau_h264_discontinuity (video_decoder_t *this_gen) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; - this->last_pts = 0; - this->tmp_pts = 0; + this->curr_pts = 0; + this->next_pts = 0; } @@ -580,6 +574,11 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; + if (this->last_img) { + this->last_img->free(this->last_img); + this->last_img = NULL; + } + if (this->buf) { free (this->buf); this->buf = NULL; @@ -629,8 +628,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->buf = NULL; this->wait_for_bottom_field = 0; this->video_step = 0; - this->last_pts = 0; - this->tmp_pts = 0; + this->curr_pts = 0; this->next_pts = 0; this->last_img = NULL; -- cgit v1.2.3 From 5c9bcbcefee17fdd254bcecd3865cd1a5202134b Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 28 Dec 2008 19:47:18 +0000 Subject: Fix argb overlay; allow partial buffer updates to improve performance. --- include/xine.h.in | 3 ++- src/video_out/video_out_vdpau.c | 2 +- src/xine-engine/osd.c | 15 ++++++++++----- src/xine-engine/osd.h | 3 ++- src/xine-engine/xine_interface.c | 5 +++-- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/include/xine.h.in b/include/xine.h.in index 79db9024e..f66ed0d3e 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -2205,7 +2205,8 @@ void xine_osd_set_palette (xine_osd_t *self, * set an argb buffer to be blended into video * this is currently only supported with vdpau */ -void xine_osd_set_argb_buffer(xine_osd_t *self, uint32_t *argb_buffer) XINE_PROTECTED; +void xine_osd_set_argb_buffer(xine_osd_t *self, uint32_t *argb_buffer, + int x, int y, int width, int height) XINE_PROTECTED; /* * close osd rendering engine diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index cbbed7c68..645ff7301 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -299,8 +299,8 @@ static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overl uint32_t pitch = this->argb_overlay_width*4; VdpRect dest = { 0, overlay->y, this->argb_overlay_width, overlay->y + overlay->height }; printf("Update ARGB: %d, %d - %dx%d\n", dest.x0, dest.y0, dest.x1, dest.y1); - printf("buf offset: %d\n", overlay->y*this->argb_overlay_width); uint32_t *buffer_start = overlay->argb_buffer + overlay->y*this->argb_overlay_width; + printf("buf offset: %d, %p -> %p\n", overlay->y*this->argb_overlay_width, overlay->argb_buffer, buffer_start); VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(buffer_start), &pitch, &dest ); if ( st != VDP_STATUS_OK ) { printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) ); diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 0bc1574ca..4b521e539 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -1542,13 +1542,18 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap, } } -static void osd_set_argb_buffer(osd_object_t *osd, uint32_t *argb_buffer) +static void osd_set_argb_buffer(osd_object_t *osd, uint32_t *argb_buffer, + int x, int y, int width, int height) { osd->argb_buffer = argb_buffer; - osd->x2 = osd->width; - osd->x1 = 0; - osd->y2 = osd->height; - osd->y1 = 0; + if(osd->x1 == 0 || x < osd->x1) + osd->x1 = x; + if(osd->x2 == 0 || (x + width) > osd->x2) + osd->x2 = x + width; + if(osd->y1 == 0 || y < osd->y1) + osd->y1 = y; + if(osd->y2 == 0 || (y + height) > osd->y2) + osd->y2 = y + height; } static uint32_t osd_get_capabilities (osd_object_t *osd) { diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h index ed3118a05..a6acc11ab 100644 --- a/src/xine-engine/osd.h +++ b/src/xine-engine/osd.h @@ -221,7 +221,8 @@ struct osd_renderer_s { /* * set a buffer to an argb buffer */ - void (*set_argb_buffer) (osd_object_t *osd, uint32_t *argb_buffer); + void (*set_argb_buffer) (osd_object_t *osd, uint32_t *argb_buffer, + int x, int y, int width, int height); /* private stuff */ diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 1f6175a06..4f59785a1 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -855,8 +855,9 @@ void xine_osd_draw_bitmap(xine_osd_t *this, uint8_t *bitmap, this->osd.renderer->draw_bitmap(&this->osd, bitmap, x1, y1, width, height, palette_map); } -void xine_osd_set_argb_buffer(xine_osd_t *this, uint32_t *argb_buffer) { - this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer); +void xine_osd_set_argb_buffer(xine_osd_t *this, uint32_t *argb_buffer, + int x, int y, int width, int height) { + this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer, x, y, width, height); } -- cgit v1.2.3 From 862354fcea8351ddf7b6745a1d5bf559e37d2d32 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 29 Dec 2008 01:38:20 +0000 Subject: Add future frame. --- src/libvdpau/vdpau_mpeg12.c | 3 +-- src/video_out/video_out_vdpau.c | 37 ++++++++++++++++++++++++++++--------- src/xine-engine/video_out.c | 7 ++++++- src/xine-engine/video_out.h | 3 +++ 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 66d451c12..763d3ff17 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -127,8 +127,7 @@ typedef struct { typedef struct { uint32_t coded_width; uint32_t coded_height; - uint32_t display_width; - uint32_t display_height; + uint64_t video_step; /* frame duration in pts units */ double ratio; VdpDecoderProfile profile; diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 645ff7301..918af6762 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -49,7 +49,7 @@ #include #include "accel_vdpau.h" -#define NUM_FRAMES_BACK 1 +#define NUM_FRAMES_BACK 2 VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, @@ -712,6 +712,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ //printf("vo_vdpau: allocated_surfaces=%d\n", this->allocated_surfaces ); frame->ratio = ratio; + frame->vo_frame.future_frame = NULL; } @@ -744,6 +745,22 @@ static void vdpau_release_back_frames( vo_driver_t *this_gen ) +static void vdpau_backup_frame( vo_driver_t *this_gen, vo_frame_t *frame_gen ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; + + int i; + if ( this->back_frame[NUM_FRAMES_BACK-1]) { + this->back_frame[NUM_FRAMES_BACK-1]->vo_frame.free (&this->back_frame[NUM_FRAMES_BACK-1]->vo_frame); + } + for ( i=NUM_FRAMES_BACK-1; i>0; i-- ) + this->back_frame[i] = this->back_frame[i-1]; + this->back_frame[0] = frame; +} + + + static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -896,6 +913,8 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + else + printf( "vo_vdpau: vdp_video_mixer_render: top_field, past1=%d, past0=%d, current=%d, future=%d\n", past[1], past[0], surface, future[0] ); vdp_queue_get_time( vdp_queue, ¤t_time ); vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); @@ -918,11 +937,17 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } past[0] = surface; - future[0] = VDP_INVALID_HANDLE; + if ( frame->vo_frame.future_frame!=NULL ) + future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; + else + future[0] = VDP_INVALID_HANDLE; + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, frame->vo_frame.progressive_frame || frame->vo_frame.top_field_first ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + else + printf( "vo_vdpau: vdp_video_mixer_render: bottom_field, past1=%d, past0=%d, current=%d, future=%d\n", past[1], past[0], surface, future[0] ); /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */ if (stream_speed > 0) @@ -947,13 +972,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) XUnlockDisplay( this->display ); - int i; - if ( this->back_frame[NUM_FRAMES_BACK-1]) { - this->back_frame[NUM_FRAMES_BACK-1]->vo_frame.free (&this->back_frame[NUM_FRAMES_BACK-1]->vo_frame); - } - for ( i=NUM_FRAMES_BACK-1; i>0; i-- ) - this->back_frame[i] = this->back_frame[i-1]; - this->back_frame[0] = frame; + vdpau_backup_frame( this_gen, frame_gen ); } diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index be062cc5d..6b0353bee 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -931,7 +931,7 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, /* extra info of the backup is thrown away, because it is not up to date */ _x_extra_info_reset(img->extra_info); } - + img->future_frame = NULL; return img; } else { @@ -989,6 +989,11 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, /* * remove frame from display queue and show it */ + + if ( img->next ) + img->future_frame = img->next; + else + img->future_frame = NULL; img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue, 1, 0, 0, 0, 0, 0); pthread_mutex_unlock(&this->display_img_buf_queue->mutex); diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 7fa34ac8b..76b347a41 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -149,6 +149,9 @@ struct vo_frame_s { /* displacement for overlays */ int overlay_offset_x, overlay_offset_y; + + /* pointer to the next frame in display order, used by some vo deint */ + struct vo_frame_s *future_frame; /* * that part is used only by video_out.c for frame management -- cgit v1.2.3 From 25575a3f4cc3ec3147f0b47ff99f53501cb0e565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Mon, 29 Dec 2008 11:49:50 +0000 Subject: Add top_field_first flag. --- src/libvdpau/vdpau_h264.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 7a9928f90..d69aa0b5c 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -451,8 +451,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, { xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); img->bad_frame = 1; - if (img->pts) - fprintf(stderr, "===== img->pts: %lld\n", img->pts); img->draw(img, this->stream); this->last_img = NULL; } @@ -500,6 +498,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /* now retrieve the next output frame */ decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); if(decoded_pic) { + decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); } -- cgit v1.2.3 From 9628a10ef165e817353e2723c3d320348a4584e9 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 29 Dec 2008 12:00:38 +0000 Subject: Properly calculate the needed ref-frame count. --- src/libvdpau/vdpau_h264.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index d69aa0b5c..cbbe9b009 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -312,6 +312,21 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, break; } + // Level 4.1 limits: + int ref_frames = 0; + if(this->nal_parser->current_nal->sps->num_ref_frames) { + ref_frames = this->nal_parser->current_nal->sps->num_ref_frames; + } else { + uint32_t round_width = (this->width + 15) & ~15; + uint32_t round_height = (this->height + 15) & ~15; + uint32_t surf_size = (round_width * round_height * 3) / 2; + ref_frames = (12 * 1024 * 1024) / surf_size; + } + + if (ref_frames > 16) { + ref_frames = 16; + } + /* get the vdpau context from vo */ //(this->stream->video_out->open) (this->stream->video_out, this->stream); img = this->stream->video_out->get_frame (this->stream->video_out, -- cgit v1.2.3 From 2d6a44ccb38892f3456e389e12428cc7b320e6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Mon, 29 Dec 2008 12:10:30 +0000 Subject: Avoid double free of cached img in combination with dispose. --- src/libvdpau/vdpau_h264.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index cbbe9b009..2fe2591e1 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -80,6 +80,7 @@ typedef struct vdpau_h264_decoder_s { int64_t next_pts; vo_frame_t *last_img; + vo_frame_t *dangling_img; } vdpau_h264_decoder_t; @@ -446,6 +447,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->duration = this->video_step; img->pts = this->curr_pts; + + this->dangling_img = img; } VdpVideoSurface surface = this->vdpau_accel->surface; @@ -468,6 +471,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, img->bad_frame = 1; img->draw(img, this->stream); this->last_img = NULL; + this->dangling_img = NULL; } else { img->bad_frame = 0; @@ -484,6 +488,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->last_ref_pic = decoded_pic; decoded_pic->used_for_reference = 1; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); + this->dangling_img = NULL; } else if(slc->field_pic_flag && this->wait_for_bottom_field) { if(this->last_ref_pic) { decoded_pic = this->last_ref_pic; @@ -500,6 +505,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); decoded_pic->delayed_output = 1; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); + this->dangling_img = NULL; if(decoded_pic->nal->slc->bottom_field_flag) decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; } else @@ -564,9 +570,9 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->curr_pts = 0; this->next_pts = 0; - if (this->last_img) { - this->last_img->free(this->last_img); - this->last_img = NULL; + if (this->dangling_img) { + this->dangling_img->free(this->dangling_img); + this->dangling_img = NULL; } } @@ -588,9 +594,9 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; - if (this->last_img) { - this->last_img->free(this->last_img); - this->last_img = NULL; + if (this->dangling_img) { + this->dangling_img->free(this->dangling_img); + this->dangling_img = NULL; } if (this->buf) { @@ -646,6 +652,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->next_pts = 0; this->last_img = NULL; + this->dangling_img = NULL; this->width = this->height = 0; (this->stream->video_out->open) (this->stream->video_out, this->stream); -- cgit v1.2.3 From b6e460a73b8e741a838d9fb0f9d54b5248ee4407 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 30 Dec 2008 10:07:47 +0000 Subject: Minor cleanups & fixes. --- src/libvdpau/vdpau_mpeg12.c | 20 +++++++------------- src/video_out/video_out_vdpau.c | 36 +++++++++++++++++++++--------------- 2 files changed, 28 insertions(+), 28 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 763d3ff17..7978a7682 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -101,13 +101,6 @@ uint8_t mpeg2_scan_norm[64] = { 53,60,61,54,47,55,62,63 }; -uint8_t mpeg2_scan_alt[64] = { - /* Alternate scan pattern */ - 0,8,16,24,1,9,2,10,17,25,32,40,48,56,57,49, - 41,33,26,18,3,11,4,12,19,27,34,42,50,58,35,43, - 51,59,20,28,5,13,6,14,21,29,36,44,52,60,37,45, - 53,61,22,30,7,15,23,31,38,46,54,62,39,47,55,63 -}; typedef struct { @@ -153,11 +146,13 @@ typedef struct { } sequence_t; + typedef struct { video_decoder_class_t decoder_class; } vdpau_mpeg12_class_t; + typedef struct vdpau_mpeg12_decoder_s { video_decoder_t video_decoder; /* parent video decoder structure */ @@ -585,11 +580,6 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) vd->decoder_height = seq->coded_height; } } - /*if ( accel->surface==VDP_INVALID_HANDLE ) { - st = accel->vdp_video_surface_create( accel->vdp_device, VDP_CHROMA_TYPE_420, seq->coded_width, seq->coded_height, &accel->surface); - if ( st!=VDP_STATUS_OK ) - lprintf( "failed to create surface !! %s\n", accel->vdp_get_error_string( st ) ); - }*/ VdpBitstreamBuffer vbit; vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; @@ -688,7 +678,11 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) img->bad_frame = 0; img->duration = seq->video_step; - img->top_field_first = pic->vdp_infos.top_field_first; + if ( pic->vdp_infos.top_field_first || pic->vdp_infos.picture_structure==PICTURE_FRAME ) + img->top_field_first = 1; + else + img->top_field_first = 0; + // progressive_frame is unreliable with most mpeg2 streams //img->progressive_frame = pic->progressive_frame; if ( pic->vdp_infos.picture_coding_type!=B_FRAME ) { diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 918af6762..b7debc8c7 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -49,7 +49,7 @@ #include #include "accel_vdpau.h" -#define NUM_FRAMES_BACK 2 +#define NUM_FRAMES_BACK 1 VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, @@ -855,11 +855,12 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); } - VdpRect vid_source = { this->sc.crop_left, this->sc.crop_top, this->sc.delivered_width-this->sc.crop_right, this->sc.delivered_height-this->sc.crop_bottom }; + VdpRect vid_source = { this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width+this->sc.displayed_xoffset, this->sc.displayed_height+this->sc.displayed_yoffset }; VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height }; - //printf( "out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 ); + //printf( "vid_src = %d %d %d %d - out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", + //vid_source.x0, vid_source.y0, vid_source.x1, vid_source.y1, out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 ); /* prepare field delay calculation to not run into a deadlock while display locked */ stream_speed = frame->vo_frame.stream ? xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) : 0; @@ -907,14 +908,18 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpTime current_time = 0; VdpVideoSurface past[2]; VdpVideoSurface future[1]; - past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; - future[0] = surface; - st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, frame->vo_frame.progressive_frame || frame->vo_frame.top_field_first ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD, + VdpVideoMixerPictureStructure picture_structure; + + past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; + future[0] = surface; + picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD; + + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - else - printf( "vo_vdpau: vdp_video_mixer_render: top_field, past1=%d, past0=%d, current=%d, future=%d\n", past[1], past[0], surface, future[0] ); + //else + //printf( "vo_vdpau: vdp_video_mixer_render: top_field, past1=%d, past0=%d, current=%d, future=%d\n", past[1], past[0], surface, future[0] ); vdp_queue_get_time( vdp_queue, ¤t_time ); vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); @@ -941,13 +946,14 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; else future[0] = VDP_INVALID_HANDLE; + picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; - st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, frame->vo_frame.progressive_frame || frame->vo_frame.top_field_first ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD, + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - else - printf( "vo_vdpau: vdp_video_mixer_render: bottom_field, past1=%d, past0=%d, current=%d, future=%d\n", past[1], past[0], surface, future[0] ); + //else + //printf( "vo_vdpau: vdp_video_mixer_render: bottom_field, past1=%d, past0=%d, current=%d, future=%d\n", past[1], past[0], surface, future[0] ); /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */ if (stream_speed > 0) @@ -1044,20 +1050,20 @@ static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) printf("vdpau_set_property: property=%d, value=%d\n", property, value ); switch (property) { - /*case VO_PROP_ZOOM_X: + case VO_PROP_ZOOM_X: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; _x_vo_scale_compute_ideal_size( &this->sc ); - this->sc.force_redraw = 1; //* trigger re-calc of output size + this->sc.force_redraw = 1; /* trigger re-calc of output size */ } break; case VO_PROP_ZOOM_Y: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP; _x_vo_scale_compute_ideal_size( &this->sc ); - this->sc.force_redraw = 1; //* trigger re-calc of output size + this->sc.force_redraw = 1; /* trigger re-calc of output size */ } - break;*/ + break; case VO_PROP_ASPECT_RATIO: if ( value>=XINE_VO_ASPECT_NUM_RATIOS ) value = XINE_VO_ASPECT_AUTO; -- cgit v1.2.3 From 36d8e9fb947602066b0b5853d84e97344e7b359d Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 30 Dec 2008 10:09:04 +0000 Subject: Indentation fixes. --- src/video_out/video_out_vdpau.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index b7debc8c7..e80458d19 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -908,11 +908,11 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpTime current_time = 0; VdpVideoSurface past[2]; VdpVideoSurface future[1]; - VdpVideoMixerPictureStructure picture_structure; + VdpVideoMixerPictureStructure picture_structure; - past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; - future[0] = surface; - picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD; + past[1] = past[0] = (this->back_frame[0] && (this->back_frame[0]->format==XINE_IMGFMT_VDPAU)) ? this->back_frame[0]->vdpau_accel_data.surface : VDP_INVALID_HANDLE; + future[0] = surface; + picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD; st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); @@ -946,7 +946,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; else future[0] = VDP_INVALID_HANDLE; - picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; + picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); -- cgit v1.2.3 From b891020134094b26d2e4ad797ecfac87be593847 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 30 Dec 2008 10:33:15 +0000 Subject: Unscaled overlay. --- src/video_out/video_out_vdpau.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index e80458d19..6472e21da 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -215,12 +215,12 @@ typedef struct { uint32_t argb_overlay_height; int has_argb_overlay; - VdpVideoSurface soft_surface; + VdpVideoSurface soft_surface; uint32_t soft_surface_width; uint32_t soft_surface_height; int soft_surface_format; - VdpOutputSurface output_surface[2]; + VdpOutputSurface output_surface[2]; uint8_t current_output_surface; uint32_t output_surface_width[2]; uint32_t output_surface_height[2]; @@ -396,6 +396,7 @@ static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, i if ( !changed ) return; + this->has_overlay = this->has_unscaled = 0; this->has_argb_overlay = 0; ++this->ovl_changed; } @@ -433,6 +434,7 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) if ( !(this->ovl_changed-1) ) { this->ovl_changed = 0; this->has_overlay = 0; + this->has_unscaled = 0; return; } @@ -1276,6 +1278,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->overlay_unscaled_width = this->overlay_unscaled_height = 0; this->ovl_changed = 0; this->has_overlay = 0; + this->has_unscaled = 0; this->argb_overlay = VDP_INVALID_HANDLE; this->argb_overlay_width = this->argb_overlay_height = 0; @@ -1469,7 +1472,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } - this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP; + this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY; ok = 0; uint32_t mw, mh, ml, mr; st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_H264_MAIN, &ok, &ml, &mr, &mw, &mh ); @@ -1488,8 +1491,6 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo else this->capabilities |= VO_CAP_VDPAU_MPEG12; - this->capabilities |= VO_CAP_UNSCALED_OVERLAY; - for ( i=0; iback_frame[i] = NULL; -- cgit v1.2.3 From cf092eb7e4e762d7bbf92f78bf2be9667ed1a1b4 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 30 Dec 2008 10:51:35 +0000 Subject: Future frame fixups. --- src/xine-engine/video_out.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 6b0353bee..f99067ad4 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -930,8 +930,8 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, img->vpts = cur_vpts; /* extra info of the backup is thrown away, because it is not up to date */ _x_extra_info_reset(img->extra_info); + img->future_frame = NULL; } - img->future_frame = NULL; return img; } else { @@ -990,10 +990,12 @@ static vo_frame_t *get_next_frame (vos_t *this, int64_t cur_vpts, * remove frame from display queue and show it */ - if ( img->next ) - img->future_frame = img->next; - else - img->future_frame = NULL; + if ( img ) { + if ( img->next ) + img->future_frame = img->next; + else + img->future_frame = NULL; + } img = vo_remove_from_img_buf_queue_int (this->display_img_buf_queue, 1, 0, 0, 0, 0, 0); pthread_mutex_unlock(&this->display_img_buf_queue->mutex); -- cgit v1.2.3 From e9808b86e7e1b380deb890ca68634a6897f5bba9 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 30 Dec 2008 13:37:49 +0000 Subject: More mixer parameters. --- src/video_out/video_out_vdpau.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 6472e21da..2d5cd3d8a 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -836,11 +836,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_release_back_frames( this_gen ); /* empty past frames array */ printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS, VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL }; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; - float noise_reduction_level = 1.0; - void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers, &noise_reduction_level }; + void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; @@ -1459,11 +1458,10 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->video_mixer_chroma = chroma; this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS, VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL }; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; - float noise_reduction_level = 1.0; - void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers, &noise_reduction_level }; + void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; st = vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); -- cgit v1.2.3 From 2ae69115cf9f38635f4590523b99ffffcbddb950 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 30 Dec 2008 13:40:20 +0000 Subject: Remove some debug printfs. --- src/video_out/video_out_vdpau.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 2d5cd3d8a..33dd0f717 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -298,9 +298,7 @@ static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overl uint32_t pitch = this->argb_overlay_width*4; VdpRect dest = { 0, overlay->y, this->argb_overlay_width, overlay->y + overlay->height }; - printf("Update ARGB: %d, %d - %dx%d\n", dest.x0, dest.y0, dest.x1, dest.y1); uint32_t *buffer_start = overlay->argb_buffer + overlay->y*this->argb_overlay_width; - printf("buf offset: %d, %p -> %p\n", overlay->y*this->argb_overlay_width, overlay->argb_buffer, buffer_start); VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(buffer_start), &pitch, &dest ); if ( st != VDP_STATUS_OK ) { printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) ); -- cgit v1.2.3 From b2795b0844cfab5f5d73f93f90df417a037f73eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Tue, 30 Dec 2008 13:50:01 +0000 Subject: Memory management cleanup; fix freeze after decoder failure. --- src/libvdpau/dpb.c | 7 +++--- src/libvdpau/h264_parser.c | 56 +++++++++++++++++------------------------ src/libvdpau/nal.c | 12 +++------ src/libvdpau/vdpau_h264.c | 26 ++++++------------- src/video_out/video_out_vdpau.c | 3 +++ 5 files changed, 40 insertions(+), 64 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 7ad87bab7..561b1efa7 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -31,18 +31,15 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, VdpVideoSurface surface, vo_frame_t *img) { - struct decoded_picture *pic = malloc(sizeof(struct decoded_picture)); + struct decoded_picture *pic = calloc(1, sizeof(struct decoded_picture)); pic->nal = init_nal_unit(); copy_nal_unit(pic->nal, src_nal); - pic->used_for_reference = 0; - pic->delayed_output = 0; pic->top_is_reference = pic->nal->slc->field_pic_flag ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1; pic->bottom_is_reference = pic->nal->slc->field_pic_flag ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1; pic->surface = surface; pic->img = img; - pic->next = NULL; return pic; } @@ -51,6 +48,7 @@ void free_decoded_picture(struct decoded_picture *pic) { pic->img->free(pic->img); free_nal_unit(pic->nal); + free(pic); } struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) @@ -315,6 +313,7 @@ void dpb_free_all( struct dpb *dpb ) } while (pic != NULL); printf("dpb_free_all, used: %d\n", dpb->used); + dpb->pictures = NULL; } int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 03f906c77..bb2bad31e 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -102,12 +102,12 @@ static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) *len_ret = pos - *ret; } -static inline dump_bits(uint32_t bits) +static inline void dump_bits(uint32_t bits) { int i; printf("0b"); for(i=0; i < 32; i++) - printf("%d", (bits >> 31-i) & 0x01); + printf("%d", (bits >> (31-i)) & 0x01); printf("\n"); } @@ -213,9 +213,9 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) ibuf.cur_pos = ibuf.buf; if (!nal->sps) - nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); - - memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); + nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); + else + memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); parse_sps(&ibuf, parser); free(ibuf.buf); @@ -223,8 +223,9 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) break; case NAL_PPS: if (!nal->pps) - nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); - memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); + nal->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp)); + else + memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); parse_pps(buf, nal->pps, nal->sps); ret = NAL_PPS; @@ -236,9 +237,9 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) case NAL_SLICE_IDR: if (nal->sps && nal->pps) { if (!nal->slc) - nal->slc = malloc(sizeof(struct slice_header)); - - memset(nal->slc, 0x00, sizeof(struct slice_header)); + nal->slc = calloc(1, sizeof(struct slice_header)); + else + memset(nal->slc, 0x00, sizeof(struct slice_header)); parse_slice_header(buf, parser); ret = nal->nal_unit_type; @@ -1036,42 +1037,26 @@ void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_parser* init_parser() { - struct nal_parser *parser = malloc(sizeof(struct nal_parser)); - memset(parser->buf, 0x00, MAX_FRAME_SIZE); - memset(parser->prebuf, 0x00, MAX_FRAME_SIZE); - parser->buf_len = 0; - parser->prebuf_len = 0; - parser->incomplete_nal = 0; - parser->next_nal_position = 0; - - parser->found_sps = 0; - parser->found_pps = 0; + struct nal_parser *parser = calloc(1, sizeof(struct nal_parser)); parser->nal0 = init_nal_unit(); parser->nal1 = init_nal_unit(); parser->current_nal = parser->nal0; parser->last_nal = parser->nal1; - parser->last_nal_res = 0; - parser->is_idr = 0; - parser->slice = 0; - parser->slice_cnt = 0; parser->field = -1; - parser->have_top = 0; /* no idea why we do that. inspired by libavcodec, * as we couldn't figure in the specs.... */ parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_lsb = 1 << 16; - parser->cpb_dpb_delays_present_flag = 0; - return parser; } void free_parser(struct nal_parser *parser) { - free(parser->nal0); - free(parser->nal1); + free_nal_unit(parser->nal0); + free_nal_unit(parser->nal1); free(parser); } @@ -1312,10 +1297,15 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) parser->last_nal = parser->nal1; } - if (parser->current_nal->sps == NULL) - parser->current_nal->sps = parser->last_nal->sps; - if (parser->current_nal->pps == NULL) - parser->current_nal->pps = parser->last_nal->pps; + if(!parser->current_nal->sps && parser->last_nal->sps) { + parser->current_nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + xine_fast_memcpy(parser->current_nal->sps, parser->last_nal->sps, sizeof(struct seq_parameter_set_rbsp)); + } + + if(!parser->current_nal->pps && parser->last_nal->pps) { + parser->current_nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + xine_fast_memcpy(parser->current_nal->pps, parser->last_nal->pps, sizeof(struct pic_parameter_set_rbsp)); + } /* increase the slice_cnt until a new frame is detected */ if (!ret) diff --git a/src/libvdpau/nal.c b/src/libvdpau/nal.c index 608f082c0..eaa32c700 100644 --- a/src/libvdpau/nal.c +++ b/src/libvdpau/nal.c @@ -29,15 +29,11 @@ struct nal_unit* init_nal_unit() { - struct nal_unit *nal = malloc(sizeof(struct nal_unit)); - memset(nal, 0x00, sizeof(struct nal_unit)); + struct nal_unit *nal = calloc(1, sizeof(struct nal_unit)); - /*nal->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); - memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); - nal->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); - memset(nal->pps, 0x00, sizeof(struct pic_parameter_set_rbsp)); - nal->slc = malloc(sizeof(struct slice_header)); - memset(nal->slc, 0x00, sizeof(struct slice_header));*/ + /*nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); + nal->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp)); + nal->slc = calloc(1, sizeof(struct slice_header));*/ return nal; } diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 2fe2591e1..5ba905ade 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -328,6 +328,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, ref_frames = 16; } + printf("Allocate %d reference frames\n", ref_frames); /* get the vdpau context from vo */ //(this->stream->video_out->open) (this->stream->video_out, this->stream); img = this->stream->video_out->get_frame (this->stream->video_out, @@ -468,10 +469,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(status != VDP_STATUS_OK) { xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); - img->bad_frame = 1; - img->draw(img, this->stream); - this->last_img = NULL; - this->dangling_img = NULL; + img->free(img); + img = this->last_img = this->dangling_img = NULL; } else { img->bad_frame = 0; @@ -517,8 +516,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->last_img = img = NULL; /* now retrieve the next output frame */ - decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb)); - if(decoded_pic) { + if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb))) != NULL) { decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); @@ -561,6 +559,8 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { if (this->decoder_initialized) this->vdpau_accel->vdp_decoder_destroy( this->decoder ); + free_parser(this->nal_parser); + this->decoder_started = 0; this->decoder_initialized = 0; this->nal_parser = init_parser(); @@ -613,7 +613,7 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { this->stream->video_out->close( this->stream->video_out, this->stream ); - free (this->nal_parser); + free_parser (this->nal_parser); free (this_gen); } @@ -636,24 +636,12 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->video_decoder.reset = vdpau_h264_reset; this->video_decoder.discontinuity = vdpau_h264_discontinuity; this->video_decoder.dispose = vdpau_h264_dispose; - this->size = 0; this->stream = stream; this->xine = stream->xine; this->class = (vdpau_h264_class_t *) class_gen; - this->decoder_started = 0; - this->decoder_initialized = 0; this->nal_parser = init_parser(); - this->buf = NULL; - this->wait_for_bottom_field = 0; - this->video_step = 0; - this->curr_pts = 0; - this->next_pts = 0; - - this->last_img = NULL; - this->dangling_img = NULL; - this->width = this->height = 0; (this->stream->video_out->open) (this->stream->video_out, this->stream); diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 33dd0f717..4009b08d1 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1178,6 +1178,7 @@ static void vdpau_dispose (vo_driver_t *this_gen) vdpau_driver_t *this = (vdpau_driver_t *) this_gen; int i; + this->ovl_yuv2rgb->dispose(this->ovl_yuv2rgb); this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); for ( i=0; ioverlays[i].ovl_bitmap ); } + if ( this->video_mixer!=VDP_INVALID_HANDLE ) + vdp_video_mixer_destroy( this->video_mixer ); if ( this->overlay_unscaled!=VDP_INVALID_HANDLE ) vdp_output_surface_destroy( this->overlay_unscaled ); if ( this->overlay_output!=VDP_INVALID_HANDLE ) -- cgit v1.2.3 From 5258b2e9b0f12136a5d8fa079f65dfcf495efa9a Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 30 Dec 2008 22:07:07 +0000 Subject: Enable advanced deinterlaced. --- src/video_out/video_out_vdpau.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 4009b08d1..54736c79a 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -87,6 +87,8 @@ VdpVideoMixerCreate *vdp_video_mixer_create; VdpVideoMixerDestroy *vdp_video_mixer_destroy; VdpVideoMixerRender *vdp_video_mixer_render; VdpVideoMixerSetAttributeValues *vdp_video_mixer_set_attribute_values; +VdpVideoMixerSetFeatureEnables *vdp_video_mixer_set_feature_enables; +VdpVideoMixerGetFeatureEnables *vdp_video_mixer_get_feature_enables; VdpGenerateCSCMatrix *vdp_generate_csc_matrix; @@ -835,10 +837,15 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpBool feature_enables[] = { 1, 1 }; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); + vdp_video_mixer_set_feature_enables( this->video_mixer, 2, features, feature_enables ); + printf("vo_vdpau: asked features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); + vdp_video_mixer_get_feature_enables( this->video_mixer, 2, features, feature_enables ); + printf("vo_vdpau: enabled features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; this->video_mixer_height = mix_h; @@ -1369,6 +1376,12 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES , (void*)&vdp_video_mixer_set_attribute_values ); if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_SET_ATTRIBUTE_VALUES proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES , (void*)&vdp_video_mixer_set_feature_enables ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_SET_FEATURE_ENABLES proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES , (void*)&vdp_video_mixer_get_feature_enables ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_GET_FEATURE_ENABLES proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GENERATE_CSC_MATRIX , (void*)&vdp_generate_csc_matrix ); if ( vdpau_init_error( st, "Can't get GENERATE_CSC_MATRIX proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -1470,6 +1483,8 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdp_output_surface_destroy( this->output_surface[1] ); return NULL; } + VdpBool feature_enables[] = { 0, 1 }; + vdp_video_mixer_set_feature_enables( this->video_mixer, 2, features, feature_enables ); this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY; ok = 0; -- cgit v1.2.3 From fd02e4d93b00d02cf784018c274c26a142324003 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 31 Dec 2008 00:35:26 +0000 Subject: Honour deinterlace setting (tvtime method must be use_vo_driver). --- src/video_out/video_out_vdpau.c | 33 ++++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 54736c79a..857076869 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -244,6 +244,7 @@ typedef struct { int saturation; int brightness; int contrast; + int deinterlace; int allocated_surfaces; @@ -763,6 +764,24 @@ static void vdpau_backup_frame( vo_driver_t *this_gen, vo_frame_t *frame_gen ) +static void vdpau_set_deinterlace( vo_driver_t *this_gen ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpBool feature_enables[2]; + if ( this->deinterlace ) + feature_enables[0] = feature_enables[1] = 1; + else + feature_enables[0] = feature_enables[1] = 0; + vdp_video_mixer_set_feature_enables( this->video_mixer, 2, features, feature_enables ); + printf("vo_vdpau: asked features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); + vdp_video_mixer_get_feature_enables( this->video_mixer, 2, features, feature_enables ); + printf("vo_vdpau: enabled features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); +} + + + static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -842,10 +861,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) int num_layers = 3; void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); - vdp_video_mixer_set_feature_enables( this->video_mixer, 2, features, feature_enables ); - printf("vo_vdpau: asked features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); - vdp_video_mixer_get_feature_enables( this->video_mixer, 2, features, feature_enables ); - printf("vo_vdpau: enabled features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); + vdpau_set_deinterlace( this_gen ); this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; this->video_mixer_height = mix_h; @@ -910,7 +926,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) layer[layer_count-1].struct_version = VDP_LAYER_VERSION; } - if ( frame->vo_frame.duration>2500 && !frame->vo_frame.progressive_frame && frame->format==XINE_IMGFMT_VDPAU ) { + if ( this->deinterlace && !frame->vo_frame.progressive_frame && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; VdpVideoSurface future[1]; @@ -1056,6 +1072,10 @@ static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) printf("vdpau_set_property: property=%d, value=%d\n", property, value ); switch (property) { + case VO_PROP_INTERLACED: + this->deinterlace = value; + vdpau_set_deinterlace( this_gen ); + break; case VO_PROP_ZOOM_X: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; @@ -1483,8 +1503,6 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdp_output_surface_destroy( this->output_surface[1] ); return NULL; } - VdpBool feature_enables[] = { 0, 1 }; - vdp_video_mixer_set_feature_enables( this->video_mixer, 2, features, feature_enables ); this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY; ok = 0; @@ -1512,6 +1530,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->saturation = 100; this->contrast = 100; this->brightness = 0; + this->deinterlace = 0; this->allocated_surfaces = 0; -- cgit v1.2.3 From db791923958fd4c72f75d4fede7aff189ff879a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Fri, 2 Jan 2009 18:00:01 +0000 Subject: Add framegrabbing support; extend ARGB OSD interface. --- include/xine.h.in | 24 +++++- src/video_out/video_out_vdpau.c | 168 ++++++++++++++++++++++++++++++++----- src/xine-engine/osd.c | 173 ++++++++++++++++++++++++++------------- src/xine-engine/osd.h | 25 +++++- src/xine-engine/video_out.h | 24 +++++- src/xine-engine/xine.c | 48 ++++++++--- src/xine-engine/xine_interface.c | 8 +- 7 files changed, 369 insertions(+), 101 deletions(-) diff --git a/include/xine.h.in b/include/xine.h.in index f66ed0d3e..e27a58e29 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -2134,8 +2134,10 @@ void xine_event_send (xine_stream_t *stream, const xine_event_t *event) XINE_PRO /* yellow text, black border, transparent background */ #define XINE_TEXTPALETTE_YELLOW_BLACK_TRANSPARENT 3 -#define XINE_OSD_CAP_FREETYPE2 0x0001 /* freetype2 support compiled in */ -#define XINE_OSD_CAP_UNSCALED 0x0002 /* unscaled overlays supp. by vo drv */ +#define XINE_OSD_CAP_FREETYPE2 0x0001 /* freetype2 support compiled in */ +#define XINE_OSD_CAP_UNSCALED 0x0002 /* unscaled overlays supp. by vo drv */ +#define XINE_OSD_CAP_CUSTOM_EXTENT 0x0004 /* hardware scaled to match video output window */ +#define XINE_OSD_CAP_ARGB_LAYER 0x0008 /* supports separate true color layer */ typedef struct xine_osd_s xine_osd_t; @@ -2203,10 +2205,24 @@ void xine_osd_set_palette (xine_osd_t *self, /* * set an argb buffer to be blended into video - * this is currently only supported with vdpau + * the buffer must exactly match the osd dimensions + * and stay valid while the osd is on screen. pass + * a NULL pointer to safely remove the buffer from + * the osd layer. only the dirty area will be + * updated on screen. for convinience the whole + * osd object will be considered dirty when setting + * a different buffer pointer. + * see also XINE_OSD_CAP_ARGB_LAYER */ void xine_osd_set_argb_buffer(xine_osd_t *self, uint32_t *argb_buffer, - int x, int y, int width, int height) XINE_PROTECTED; + int dirty_x, int dirty_y, int dirty_width, int dirty_height) XINE_PROTECTED; + +/* + * define extent of reference coordinate system + * for video resolution independent osds. + * see also XINE_OSD_CAP_CUSTOM_EXTENT + */ +void xine_osd_set_extent(xine_osd_t *self, int extent_width, int extent_height) XINE_PROTECTED; /* * close osd rendering engine diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 857076869..e9f561579 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -216,6 +216,10 @@ typedef struct { uint32_t argb_overlay_width; uint32_t argb_overlay_height; int has_argb_overlay; + int argb_osd_x; + int argb_osd_y; + int argb_osd_w; + int argb_osd_h; VdpVideoSurface soft_surface; uint32_t soft_surface_width; @@ -280,33 +284,78 @@ static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *over -static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) +static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - if(overlay->argb_buffer == NULL) + if(overlay->argb_layer == NULL) return 0; - if ( (this->argb_overlay_width < overlay->width ) || (this->argb_overlay_height < overlay->height) || (this->argb_overlay == VDP_INVALID_HANDLE) ) { - if (this->argb_overlay != VDP_INVALID_HANDLE) { - vdp_output_surface_destroy( this->argb_overlay ); + pthread_mutex_lock(&overlay->argb_layer->mutex); + + if (overlay->argb_layer->buffer != NULL) { + int extent_width = overlay->extent_width; + int extent_height = overlay->extent_height; + if (extent_width <= 0 || extent_height <= 0) { + extent_width = frame_gen->width; + extent_height = frame_gen->height; } - VdpStatus st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, overlay->width, overlay->height, &this->argb_overlay ); - if ( st != VDP_STATUS_OK ) { - printf( "vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + + if (extent_width > 0 && extent_height > 0) { + if ( (this->argb_overlay_width != extent_width ) || (this->argb_overlay_height != extent_height) || (this->argb_overlay == VDP_INVALID_HANDLE) ) { + if (this->argb_overlay != VDP_INVALID_HANDLE) { + vdp_output_surface_destroy( this->argb_overlay ); + } + VdpStatus st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, extent_width, extent_height, &this->argb_overlay ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + } + this->argb_overlay_width = extent_width; + this->argb_overlay_height = extent_height; + + /* set stored osd location to extent as any smaller osd requires to clear the surface first */ + this->argb_osd_x = 0; + this->argb_osd_y = 0; + this->argb_osd_w = extent_width; + this->argb_osd_h = extent_height; + } + + /* wipe surface if osd layout changed */ + if (overlay->x != this->argb_osd_x || overlay->y != this->argb_osd_y || overlay->width != this->argb_osd_w || overlay->height != this->argb_osd_h) { + this->argb_osd_x = overlay->x; + this->argb_osd_y = overlay->y; + this->argb_osd_w = overlay->width; + this->argb_osd_h = overlay->height; + + uint32_t *zeros = calloc(4 * extent_width, extent_height); + if (zeros) { + uint32_t pitch = extent_width * 4; + VdpRect dest = { 0, 0, extent_width, extent_height }; + VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(zeros), &pitch, &dest ); + if ( st != VDP_STATUS_OK ) + printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) ); + free(zeros); + } + } + + /* set destination area according to dirty area of argb layer and reset dirty area */ + uint32_t pitch = overlay->width * 4; + uint32_t *buffer_start = overlay->argb_layer->buffer + overlay->argb_layer->y1 * overlay->width + overlay->argb_layer->x1; + VdpRect dest = { overlay->x + overlay->argb_layer->x1, overlay->y + overlay->argb_layer->y1, overlay->x + overlay->argb_layer->x2, overlay->y + overlay->argb_layer->y2 }; + overlay->argb_layer->x1 = overlay->width; + overlay->argb_layer->y1 = overlay->height; + overlay->argb_layer->x2 = 0; + overlay->argb_layer->y2 = 0; + + VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(buffer_start), &pitch, &dest ); + if ( st != VDP_STATUS_OK ) { + printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) ); + } else + this->has_argb_overlay = 1; } - this->argb_overlay_width = overlay->width; - this->argb_overlay_height = overlay->height; } - uint32_t pitch = this->argb_overlay_width*4; - VdpRect dest = { 0, overlay->y, this->argb_overlay_width, overlay->y + overlay->height }; - uint32_t *buffer_start = overlay->argb_buffer + overlay->y*this->argb_overlay_width; - VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(buffer_start), &pitch, &dest ); - if ( st != VDP_STATUS_OK ) { - printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) ); - } else - this->has_argb_overlay = 1; + pthread_mutex_unlock(&overlay->argb_layer->mutex); return 1; } @@ -418,8 +467,8 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v ++this->ovl_changed; } - if(overlay->argb_buffer) - vdpau_process_argb_ovl( this, overlay ); + if(overlay->argb_layer) + vdpau_process_argb_ovl( this, frame_gen, overlay ); } @@ -603,6 +652,81 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) +static void vdpau_provide_standard_frame_data (vo_frame_t *this_gen, xine_current_frame_data_t *data) +{ + vdpau_frame_t *this = (vdpau_frame_t *)this_gen; + VdpStatus st; + VdpYCbCrFormat format; + + if (this->vo_frame.format != XINE_IMGFMT_VDPAU) { + fprintf(stderr, "vdpau_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->vo_frame.format); + return; + } + + if (!(this->flags & VO_CHROMA_422)) { + data->format = XINE_IMGFMT_YV12; + data->img_size = this->vo_frame.width * this->vo_frame.height + + ((this->vo_frame.width + 1) / 2) * ((this->vo_frame.height + 1) / 2) + + ((this->vo_frame.width + 1) / 2) * ((this->vo_frame.height + 1) / 2); + if (data->img) { + this->vo_frame.pitches[0] = 8*((this->vo_frame.width + 7) / 8); + this->vo_frame.pitches[1] = 8*((this->vo_frame.width + 15) / 16); + this->vo_frame.pitches[2] = 8*((this->vo_frame.width + 15) / 16); + this->vo_frame.base[0] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * this->vo_frame.height, (void **)&this->chunk[0]); + this->vo_frame.base[1] = xine_xmalloc_aligned(16, this->vo_frame.pitches[1] * ((this->vo_frame.height+1)/2), (void **)&this->chunk[1]); + this->vo_frame.base[2] = xine_xmalloc_aligned(16, this->vo_frame.pitches[2] * ((this->vo_frame.height+1)/2), (void **)&this->chunk[2]); + format = VDP_YCBCR_FORMAT_YV12; + } + } else { + data->format = XINE_IMGFMT_YUY2; + data->img_size = this->vo_frame.width * this->vo_frame.height + + ((this->vo_frame.width + 1) / 2) * this->vo_frame.height + + ((this->vo_frame.width + 1) / 2) * this->vo_frame.height; + if (data->img) { + this->vo_frame.pitches[0] = 8*((this->vo_frame.width + 3) / 4); + this->vo_frame.base[0] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * this->vo_frame.height, (void **)&this->chunk[0]); + format = VDP_YCBCR_FORMAT_YUYV; + } + } + + if (data->img) { + st = vdp_video_surface_getbits_ycbcr(this->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches); + if (st != VDP_STATUS_OK) + printf("vo_vdpau: failed to get surface bits !! %s\n", vdp_get_error_string(st)); + + if (format == VDP_YCBCR_FORMAT_YV12) { + yv12_to_yv12( + /* Y */ + this->vo_frame.base[0], this->vo_frame.pitches[0], + data->img, this->vo_frame.width, + /* U */ + this->vo_frame.base[1], this->vo_frame.pitches[1], + data->img+this->vo_frame.width*this->vo_frame.height, this->vo_frame.width/2, + /* V */ + this->vo_frame.base[2], this->vo_frame.pitches[2], + data->img+this->vo_frame.width*this->vo_frame.height+this->vo_frame.width*this->vo_frame.height/4, this->vo_frame.width/2, + /* width x height */ + this->vo_frame.width, this->vo_frame.height); + } else { + yuy2_to_yuy2( + /* src */ + this->vo_frame.base[0], this->vo_frame.pitches[0], + /* dst */ + data->img, this->vo_frame.width*2, + /* width x height */ + this->vo_frame.width, this->vo_frame.height); + } + + if (this->chunk[0]) + free(this->chunk[0]); + if (this->chunk[1]) + free(this->chunk[1]); + if (this->chunk[2]) + free(this->chunk[2]); + this->chunk[0] = this->chunk[1] = this->chunk[2] = NULL; + } +} + static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original) { vdpau_frame_t *this = (vdpau_frame_t *)this_gen; @@ -690,6 +814,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; --this->allocated_surfaces; frame->vo_frame.proc_duplicate_frame_data = NULL; + frame->vo_frame.proc_provide_standard_frame_data = NULL; } } @@ -701,6 +826,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ frame->vdpau_accel_data.chroma = chroma; ++this->allocated_surfaces; frame->vo_frame.proc_duplicate_frame_data = vdpau_duplicate_frame_data; + frame->vo_frame.proc_provide_standard_frame_data = vdpau_provide_standard_frame_data; } } @@ -1504,7 +1630,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } - this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY; + this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY; ok = 0; uint32_t mw, mh, ml, mr; st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_H264_MAIN, &ok, &ml, &mr, &mw, &mh ); diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 4b521e539..7f4e6aefb 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -143,16 +143,19 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width osd->next = this->osds; this->osds = osd; + osd->extent_width = 0; + osd->extent_height = 0; osd->width = width; osd->height = height; osd->area = calloc(width, height); + osd->area_touched = 0; - osd->x1 = width; - osd->y1 = height; - osd->x2 = 0; - osd->y2 = 0; + osd->x1 = osd->argb_layer.x1 = width; + osd->y1 = osd->argb_layer.y1 = height; + osd->x2 = osd->argb_layer.x2 = 0; + osd->y2 = osd->argb_layer.y2 = 0; - osd->argb_buffer = NULL; + pthread_mutex_init(&osd->argb_layer.mutex, NULL); memcpy(osd->color, textpalettes_color[0], sizeof(textpalettes_color[0])); memcpy(osd->trans, textpalettes_trans[0], sizeof(textpalettes_trans[0])); @@ -171,6 +174,18 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width return osd; } +/* + * osd extent must be set to achive video resolution independent osds + * both sizes must be > 0 to take effect. otherwise, video resolution + * will still be used. the extent defines the reference coordinate + * system which is matched to the video output area. + */ +static void osd_set_extent (osd_object_t *osd, int extent_width, int extent_height) { + + osd->extent_width = extent_width; + osd->extent_height = extent_height; +} + /* @@ -231,7 +246,7 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { memset( this->event.object.overlay, 0, sizeof(*this->event.object.overlay) ); - this->event.object.overlay->argb_buffer = osd->argb_buffer; + this->event.object.overlay->argb_layer = &osd->argb_layer; this->event.object.overlay->unscaled = unscaled; this->event.object.overlay->x = osd->display_x + osd->x1; @@ -239,6 +254,9 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { this->event.object.overlay->width = osd->x2 - osd->x1; this->event.object.overlay->height = osd->y2 - osd->y1; + this->event.object.overlay->extent_width = osd->extent_width; + this->event.object.overlay->extent_height = osd->extent_height; + this->event.object.overlay->hili_top = 0; this->event.object.overlay->hili_bottom = this->event.object.overlay->height; this->event.object.overlay->hili_left = 0; @@ -246,53 +264,59 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { /* there will be at least that many rle objects (one for each row) */ this->event.object.overlay->num_rle = 0; - /* We will never need more rle objects than columns in any row - Rely on lazy page allocation to avoid us actually taking up - this much RAM */ - this->event.object.overlay->data_size = osd->width * osd->height; - rle_p = this->event.object.overlay->rle = - malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) ); + if (!osd->area_touched) { + /* avoid rle encoding when only argb_layer is modified */ + this->event.object.overlay->data_size = 0; + rle_p = this->event.object.overlay->rle = NULL; + } else { + /* We will never need more rle objects than columns in any row + Rely on lazy page allocation to avoid us actually taking up + this much RAM */ + this->event.object.overlay->data_size = osd->width * osd->height; + rle_p = this->event.object.overlay->rle = + malloc(this->event.object.overlay->data_size * sizeof(rle_elem_t) ); - for( y = osd->y1; y < osd->y2; y++ ) { + for( y = osd->y1; y < osd->y2; y++ ) { #ifdef DEBUG_RLE - lprintf("osd_show %p y = %d: ", osd, y); + lprintf("osd_show %p y = %d: ", osd, y); #endif - c = osd->area + y * osd->width + osd->x1; + c = osd->area + y * osd->width + osd->x1; - /* initialize a rle object with the first pixel's color */ - rle.len = 1; - rle.color = *c++; + /* initialize a rle object with the first pixel's color */ + rle.len = 1; + rle.color = *c++; - /* loop over the remaining pixels in the row */ - for( x = osd->x1 + rle.len; x < osd->x2; x++, c++ ) { - if( rle.color != *c ) { + /* loop over the remaining pixels in the row */ + for( x = osd->x1 + rle.len; x < osd->x2; x++, c++ ) { + if( rle.color != *c ) { #ifdef DEBUG_RLE - lprintf("(%d, %d), ", rle.len, rle.color); + lprintf("(%d, %d), ", rle.len, rle.color); #endif - *rle_p++ = rle; - this->event.object.overlay->num_rle++; + *rle_p++ = rle; + this->event.object.overlay->num_rle++; - rle.color = *c; - rle.len = 1; - } else { - rle.len++; + rle.color = *c; + rle.len = 1; + } else { + rle.len++; + } } - } #ifdef DEBUG_RLE - lprintf("(%d, %d)\n", rle.len, rle.color); + lprintf("(%d, %d)\n", rle.len, rle.color); #endif - *rle_p++ = rle; - this->event.object.overlay->num_rle++; - } + *rle_p++ = rle; + this->event.object.overlay->num_rle++; + } #ifdef DEBUG_RLE - lprintf("osd_show %p rle ends\n", osd); + lprintf("osd_show %p rle ends\n", osd); #endif - lprintf("num_rle = %d\n", this->event.object.overlay->num_rle); - - memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color)); - memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans)); - memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color)); - memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans)); + lprintf("num_rle = %d\n", this->event.object.overlay->num_rle); + + memcpy(this->event.object.overlay->hili_color, osd->color, sizeof(osd->color)); + memcpy(this->event.object.overlay->hili_trans, osd->trans, sizeof(osd->trans)); + memcpy(this->event.object.overlay->color, osd->color, sizeof(osd->color)); + memcpy(this->event.object.overlay->trans, osd->trans, sizeof(osd->trans)); + } this->event.event_type = OVERLAY_EVENT_SHOW; this->event.vpts = vpts; @@ -376,11 +400,14 @@ static int osd_hide (osd_object_t *osd, int64_t vpts) { static void osd_clear (osd_object_t *osd) { lprintf("osd=%p\n",osd); - memset(osd->area, 0, osd->width * osd->height); - osd->x1 = osd->width; - osd->y1 = osd->height; - osd->x2 = 0; - osd->y2 = 0; + if (osd->area_touched) { + osd->area_touched = 0; + memset(osd->area, 0, osd->width * osd->height); + } + osd->x1 = osd->argb_layer.x1 = osd->width; + osd->y1 = osd->argb_layer.y1 = osd->height; + osd->x2 = osd->argb_layer.x2 = 0; + osd->y2 = osd->argb_layer.y2 = 0; } /* @@ -402,6 +429,7 @@ static void osd_point (osd_object_t *osd, int x, int y, int color) { osd->x2 = MAX(osd->x2, (x + 1)); osd->y1 = MIN(osd->y1, y); osd->y2 = MAX(osd->y2, (y + 1)); + osd->area_touched = 1; c = osd->area + y * osd->width + x; *c = color; @@ -461,6 +489,7 @@ static void osd_line (osd_object_t *osd, osd->x2 = MAX( osd->x2, x2 ); osd->y1 = MIN( osd->y1, y1 ); osd->y2 = MAX( osd->y2, y2 ); + osd->area_touched = 1; dx = x2 - x1; dy = y2 - y1; @@ -574,6 +603,7 @@ static void osd_filled_rect (osd_object_t *osd, osd->x2 = MAX( osd->x2, dx ); osd->y1 = MIN( osd->y1, y ); osd->y2 = MAX( osd->y2, dy ); + osd->area_touched = 1; dx -= x; dy -= y; @@ -1131,6 +1161,7 @@ static int osd_render_text (osd_object_t *osd, int x1, int y1, if( x1 < osd->x1 ) osd->x1 = x1; if( y1 < osd->y1 ) osd->y1 = y1; + osd->area_touched = 1; inbuf = text; inbytesleft = strlen(text); @@ -1479,6 +1510,7 @@ static void osd_free_object (osd_object_t *osd_to_close) { else this->osds = osd->next; + pthread_mutex_destroy(&osd->argb_layer.mutex); free( osd ); break; } @@ -1524,6 +1556,7 @@ static void osd_draw_bitmap(osd_object_t *osd, uint8_t *bitmap, osd->x2 = MAX( osd->x2, x1+width ); osd->y1 = MIN( osd->y1, y1 ); osd->y2 = MAX( osd->y2, y1+height ); + osd->area_touched = 1; for( y=0; yargb_buffer = argb_buffer; - if(osd->x1 == 0 || x < osd->x1) - osd->x1 = x; - if(osd->x2 == 0 || (x + width) > osd->x2) - osd->x2 = x + width; - if(osd->y1 == 0 || y < osd->y1) - osd->y1 = y; - if(osd->y2 == 0 || (y + height) > osd->y2) - osd->y2 = y + height; + if (osd->argb_layer.buffer != argb_buffer) { + dirty_x = 0; + dirty_y = 0; + dirty_width = osd->width; + dirty_height = osd->height; + } + + /* keep osd_object clipping behavior */ + osd->x1 = MIN( osd->x1, dirty_x ); + osd->x2 = MAX( osd->x2, dirty_x + dirty_width ); + osd->y1 = MIN( osd->y1, dirty_y ); + osd->y2 = MAX( osd->y2, dirty_y + dirty_height ); + + pthread_mutex_lock(&osd->argb_layer.mutex); + + /* argb layer update area accumulation */ + osd->argb_layer.x1 = MIN( osd->argb_layer.x1, dirty_x ); + osd->argb_layer.x2 = MAX( osd->argb_layer.x2, dirty_x + dirty_width ); + osd->argb_layer.y1 = MIN( osd->argb_layer.y1, dirty_y ); + osd->argb_layer.y2 = MAX( osd->argb_layer.y2, dirty_y + dirty_height ); + + osd->argb_layer.buffer = argb_buffer; + + pthread_mutex_unlock(&osd->argb_layer.mutex); } static uint32_t osd_get_capabilities (osd_object_t *osd) { osd_renderer_t *this = osd->renderer; uint32_t capabilities = 0; + uint32_t vo_capabilities; #ifdef HAVE_FT2 capabilities |= XINE_OSD_CAP_FREETYPE2; #endif this->stream->xine->port_ticket->acquire(this->stream->xine->port_ticket, 1); - if( this->stream->video_out->get_capabilities(this->stream->video_out) & - VO_CAP_UNSCALED_OVERLAY) - capabilities |= XINE_OSD_CAP_UNSCALED; + vo_capabilities = this->stream->video_out->get_capabilities(this->stream->video_out); this->stream->xine->port_ticket->release(this->stream->xine->port_ticket, 1); + + if (vo_capabilities & VO_CAP_UNSCALED_OVERLAY) + capabilities |= XINE_OSD_CAP_UNSCALED; + + if (vo_capabilities & VO_CAP_CUSTOM_EXTENT_OVERLAY) + capabilities |= XINE_OSD_CAP_CUSTOM_EXTENT; + + if (vo_capabilities & VO_CAP_ARGB_LAYER_OVERLAY) + capabilities |= XINE_OSD_CAP_ARGB_LAYER; return capabilities; } @@ -1634,6 +1690,7 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { this->set_argb_buffer = osd_set_argb_buffer; this->show_unscaled = osd_show_unscaled; this->get_capabilities = osd_get_capabilities; + this->set_extent = osd_set_extent; return this; } diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h index a6acc11ab..36e6fc0ae 100644 --- a/src/xine-engine/osd.h +++ b/src/xine-engine/osd.h @@ -47,8 +47,12 @@ struct osd_object_s { int width, height; /* work area dimentions */ uint8_t *area; /* work area */ + int area_touched; /* work area was used for painting */ int display_x,display_y; /* where to display it in screen */ + /* extent of reference coordinate system */ + int extent_width, extent_height; + /* clipping box inside work area */ int x1, y1; int x2, y2; @@ -70,7 +74,7 @@ struct osd_object_s { /* this holds an optional ARGB overlay, which * is only be used by supported video_out modules. * right now this is only vdpau */ - uint32_t *argb_buffer; + argb_layer_t argb_layer; }; @@ -219,10 +223,25 @@ struct osd_renderer_s { uint32_t (*get_capabilities) (osd_object_t *osd); /* - * set a buffer to an argb buffer + * define extent of reference coordinate system for video + * resolution independent osds. both sizes must be > 0 to + * take effect. otherwise, video resolution will be used. + */ + void (*set_extent) (osd_object_t *osd, int extent_width, int extent_height); + + /* + * set an argb buffer to be blended into video + * the buffer must exactly match the osd dimensions + * and stay valid while the osd is on screen. pass + * a NULL pointer to safely remove the buffer from + * the osd layer. only the dirty area will be + * updated on screen. for convinience the whole + * osd object will be considered dirty when setting + * a different buffer pointer. + * see also XINE_OSD_CAP_ARGB_LAYER */ void (*set_argb_buffer) (osd_object_t *osd, uint32_t *argb_buffer, - int x, int y, int width, int height); + int dirty_x, int dirty_y, int dirty_width, int dirty_height); /* private stuff */ diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 76b347a41..0c73ddafa 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -68,6 +68,14 @@ struct vo_frame_s { * member functions */ + /* Provide a copy of the frame's image in an image format already known to xine. data's member */ + /* have already been intialized to frame's content on entry, so it's usually only necessary to */ + /* change format and img_size. In case img is set, it will point to a memory block of suitable */ + /* size (size has been determined by a previous call with img == NULL). img content and img_size */ + /* must adhere to the specification of _x_get_current_frame_data(). */ + /* Currently this is needed for all image formats except XINE_IMGFMT_YV12 and XINE_IMGFMT_YUY2. */ + void (*proc_provide_standard_frame_data) (vo_frame_t *vo_img, xine_current_frame_data_t *data); + /* Duplicate picture data and acceleration specific data of a frame. */ /* if the image format isn't already known by Xine. Currently this is needed */ /* For all image formats except XINE_IMGFMT_YV12 and XINE_IMGFMT_YUY2 */ @@ -286,6 +294,8 @@ struct xine_video_port_s { #define VO_CAP_XXMC 0x00000040 /* driver can use extended XvMC */ #define VO_CAP_VDPAU_H264 0x00000080 /* driver can use VDPAU for H264 */ #define VO_CAP_VDPAU_MPEG12 0x00000100 /* driver can use VDPAU for mpeg1/2 */ +#define VO_CAP_CUSTOM_EXTENT_OVERLAY 0x01000000 /* driver can blend custom extent overlay to output extent */ +#define VO_CAP_ARGB_LAYER_OVERLAY 0x02000000 /* driver supports true color overlay */ /* @@ -398,6 +408,14 @@ typedef struct rle_elem_s { uint16_t color; } rle_elem_t; +typedef struct argb_layer_s { + pthread_mutex_t mutex; + uint32_t *buffer; + /* dirty area */ + int x1, y1; + int x2, y2; +} argb_layer_t; + struct vo_overlay_s { rle_elem_t *rle; /* rle code buffer */ @@ -408,6 +426,10 @@ struct vo_overlay_s { int width; /* width of subpicture area */ int height; /* height of subpicture area */ + /* extent of reference coordinate system */ + int extent_width; + int extent_height; + uint32_t color[OVL_PALETTE_SIZE]; /* color lookup table */ uint8_t trans[OVL_PALETTE_SIZE]; /* mixer key table */ int rgb_clut; /* true if clut was converted to rgb */ @@ -423,7 +445,7 @@ struct vo_overlay_s { int unscaled; /* true if it should be blended unscaled */ - uint32_t *argb_buffer; + argb_layer_t *argb_layer; }; diff --git a/src/xine-engine/xine.c b/src/xine-engine/xine.c index e4e36527f..e0c98c018 100644 --- a/src/xine-engine/xine.c +++ b/src/xine-engine/xine.c @@ -1963,6 +1963,8 @@ static int _x_get_current_frame_data (xine_stream_t *stream, stream->xine->port_ticket->acquire(stream->xine->port_ticket, 0); frame = stream->video_out->get_last_frame (stream->video_out); + if (frame) + frame->lock(frame); stream->xine->port_ticket->release(stream->xine->port_ticket, 0); if (!frame) { @@ -1994,6 +1996,30 @@ static int _x_get_current_frame_data (xine_stream_t *stream, switch (frame->format) { + default: + if (frame->proc_provide_standard_frame_data) { + uint8_t *img = data->img; + size_t img_size = data->img_size; + data->img = 0; + data->img_size = 0; + + /* ask frame implementation for required img buffer size */ + frame->proc_provide_standard_frame_data(frame, data); + required_size = data->img_size; + + data->img = img; + data->img_size = img_size; + break; + } + + if (!data->img && !(flags & XINE_FRAME_DATA_ALLOCATE_IMG)) + break; /* not interested in image data */ + + xprintf (stream->xine, XINE_VERBOSITY_DEBUG, + "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); + /* fall though and provide "green" YV12 image */ + data->format = XINE_IMGFMT_YV12; + case XINE_IMGFMT_YV12: required_size = frame->width * frame->height + ((frame->width + 1) / 2) * ((frame->height + 1) / 2) @@ -2006,26 +2032,21 @@ static int _x_get_current_frame_data (xine_stream_t *stream, + ((frame->width + 1) / 2) * frame->height; break; - default: - if (data->img || (flags & XINE_FRAME_DATA_ALLOCATE_IMG)) { - xprintf (stream->xine, XINE_VERBOSITY_DEBUG, - "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); - _x_abort (); - } - - required_size = 0; } if (flags & XINE_FRAME_DATA_ALLOCATE_IMG) { /* return allocated buffer size */ data->img_size = required_size; /* allocate img or fail */ - if (!(data->img = calloc(1, required_size))) + if (!(data->img = calloc(1, required_size))) { + frame->free(frame); return 0; + } } else { /* fail if supplied buffer is to small */ if (data->img && !img_size_unknown && data->img_size < required_size) { data->img_size = required_size; + frame->free(frame); return 0; } /* return used buffer size */ @@ -2061,11 +2082,14 @@ static int _x_get_current_frame_data (xine_stream_t *stream, break; default: - xprintf (stream->xine, XINE_VERBOSITY_DEBUG, - "xine: error, snapshot function not implemented for format 0x%x\n", frame->format); - _x_abort (); + if (frame->proc_provide_standard_frame_data) + frame->proc_provide_standard_frame_data(frame, data); + else if (!(flags & XINE_FRAME_DATA_ALLOCATE_IMG)) + memset(data->img, 0, data->img_size); } } + + frame->free(frame); return 1; } diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 4f59785a1..08ff4dc22 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -856,8 +856,12 @@ void xine_osd_draw_bitmap(xine_osd_t *this, uint8_t *bitmap, } void xine_osd_set_argb_buffer(xine_osd_t *this, uint32_t *argb_buffer, - int x, int y, int width, int height) { - this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer, x, y, width, height); + int dirty_x, int dirty_y, int dirty_width, int dirty_height) { + this->osd.renderer->set_argb_buffer(&this->osd, argb_buffer, dirty_x, dirty_y, dirty_width, dirty_height); +} + +void xine_osd_set_extent(xine_osd_t *this, int extent_width, int extent_height) { + this->osd.renderer->set_extent(&this->osd, extent_width, extent_height); } -- cgit v1.2.3 From 55c36dc13a02f3be136f51943ad28d3ae18ce876 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 4 Jan 2009 13:37:01 +0000 Subject: Deinterlacer options. --- src/video_out/video_out_vdpau.c | 64 +++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index e9f561579..1e6b497dd 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -52,6 +52,16 @@ #define NUM_FRAMES_BACK 1 + +const char *vdpau_deinterlace_methods[] = { + "bob", + "temporal", + "temporal_spatial", + NULL +}; + + + VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE , VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, @@ -249,6 +259,7 @@ typedef struct { int brightness; int contrast; int deinterlace; + int deinterlace_method; int allocated_surfaces; @@ -896,18 +907,38 @@ static void vdpau_set_deinterlace( vo_driver_t *this_gen ) VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; VdpBool feature_enables[2]; - if ( this->deinterlace ) - feature_enables[0] = feature_enables[1] = 1; + if ( this->deinterlace ) { + if ( this->video_mixer_width<800 ) + feature_enables[0] = feature_enables[1] = 1; + else { + switch ( this->deinterlace_method ) { + case 0: feature_enables[0] = feature_enables[1] = 0; break; /* bob */ + case 1: feature_enables[0] = 1; feature_enables[1] = 0; break; /* temporal */ + case 2: feature_enables[0] = feature_enables[1] = 1; break; /* temporal_spatial */ + } + } + } else feature_enables[0] = feature_enables[1] = 0; + vdp_video_mixer_set_feature_enables( this->video_mixer, 2, features, feature_enables ); - printf("vo_vdpau: asked features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); vdp_video_mixer_get_feature_enables( this->video_mixer, 2, features, feature_enables ); printf("vo_vdpau: enabled features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); } +static void vdpau_update_deinterlace_method( void *this_gen, xine_cfg_entry_t *entry ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + this->deinterlace_method = entry->num_value; + printf( "vo_vdpau: deinterlace_method=%d\n", this->deinterlace_method ); + vdpau_set_deinterlace( (vo_driver_t*)this_gen ); +} + + + static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -982,15 +1013,14 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; - VdpBool feature_enables[] = { 1, 1 }; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); - vdpau_set_deinterlace( this_gen ); this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; this->video_mixer_height = mix_h; + vdpau_set_deinterlace( this_gen ); } if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { @@ -1585,22 +1615,22 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; /* choose almost magenta as backcolor for color keying */ - this->back_color.red = 0.98; - this->back_color.green = 0.01; - this->back_color.blue = 0.99; + this->back_color.red = 0.02;//0.98; + this->back_color.green = 0.01;//0.01; + this->back_color.blue = 0.03;//0.99; this->back_color.alpha = 1; vdp_queue_set_background_color( vdp_queue, &this->back_color ); - this->soft_surface_width = 1280; - this->soft_surface_height = 720; + this->soft_surface_width = 320; + this->soft_surface_height = 240; this->soft_surface_format = XINE_IMGFMT_YV12; VdpChromaType chroma = VDP_CHROMA_TYPE_420; st = vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) return NULL; - this->output_surface_width[0] = this->output_surface_width[1] = 1280; - this->output_surface_height[0] = this->output_surface_height[1] = 720; + this->output_surface_width[0] = this->output_surface_width[1] = 320; + this->output_surface_height[0] = this->output_surface_height[1] = 240; this->current_output_surface = 0; this->init_queue = 0; st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] ); @@ -1630,6 +1660,16 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } + this->deinterlace_method = config->register_enum (config, "video.output.vdpau_deinterlace_method", 1, + vdpau_deinterlace_methods, _("vdpau HD deinterlace method"), + _("bob\n" + "Basic deinterlacing, doing 50i->50p.\n\n" + "temporal\n" + "Very good, 50i->50p\n\n" + "temporal_spatial\n" + "The best, but very GPU intensive.\n\n"), + 10, vdpau_update_deinterlace_method, this); + this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY; ok = 0; uint32_t mw, mh, ml, mr; -- cgit v1.2.3 From f82162c8b1fac19514e767809f5fdbbb27692f82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Sun, 4 Jan 2009 14:01:21 +0000 Subject: Clear PTS in DPB in case of discontinuity. --- src/libvdpau/dpb.c | 10 ++++++++++ src/libvdpau/dpb.h | 1 + src/libvdpau/vdpau_h264.c | 2 +- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 561b1efa7..4236909db 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -316,6 +316,16 @@ void dpb_free_all( struct dpb *dpb ) dpb->pictures = NULL; } +void dpb_clear_all_pts( struct dpb *dpb ) +{ + struct decoded_picture *pic = dpb->pictures; + + while (pic != NULL) { + pic->img->pts = 0; + pic = pic->next; + } +} + int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) { struct decoded_picture *pic = dpb->pictures; diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 8ecde5d92..6578aa42f 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -73,6 +73,7 @@ int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic); int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames); int dpb_flush(struct dpb *dpb); void dpb_free_all( struct dpb *dpb ); +void dpb_clear_all_pts( struct dpb *dpb ); int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 5ba905ade..46923b557 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -584,7 +584,7 @@ static void vdpau_h264_discontinuity (video_decoder_t *this_gen) { this->curr_pts = 0; this->next_pts = 0; - + dpb_clear_all_pts(&this->nal_parser->dpb); } /* -- cgit v1.2.3 From 63ec09d9a95819bad3131181a3641443eb199432 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 4 Jan 2009 15:00:47 +0000 Subject: Parse sei->pic_struct for better progressive_frame marking. --- src/libvdpau/h264_parser.c | 31 +++++++++++++++++++++++++++++++ src/libvdpau/nal.h | 29 ++++++++++++++++++++++++++++- src/libvdpau/vdpau_h264.c | 10 +++++++++- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index bb2bad31e..fdc48f043 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -246,6 +246,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) } break; case NAL_SEI: + memset(&(nal->sei), 0x00, sizeof(struct sei_message)); parse_sei(buf, parser); ret = nal->nal_unit_type; break; @@ -470,6 +471,7 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) void parse_sei(struct buf_reader *buf, struct nal_parser *parser) { struct sei_message *sei = &(parser->current_nal->sei); + struct seq_parameter_set_rbsp *sps = parser->current_nal->sps; uint8_t tmp; sei->payload_type = 0; @@ -492,6 +494,35 @@ void parse_sei(struct buf_reader *buf, struct nal_parser *parser) sei->pic_timing.cpb_removal_delay = read_bits(buf, 5); sei->pic_timing.dpb_output_delay = read_bits(buf, 5); } + + if(sps && sps->vui_parameters_present_flag && + sps->vui_parameters.pic_struct_present_flag) { + sei->pic_timing.pic_struct = read_bits(buf, 4); + switch(sei->pic_timing.pic_struct) { + case DISP_FRAME: + parser->current_nal->interlaced = 0; + parser->current_nal->repeat_pic = 0; + break; + case DISP_TOP: + case DISP_BOTTOM: + case DISP_TOP_BOTTOM: + case DISP_BOTTOM_TOP: + parser->current_nal->interlaced = 1; + break; + case DISP_TOP_BOTTOM_TOP: + case DISP_BOTTOM_TOP_BOTTOM: + parser->current_nal->interlaced = 1; + parser->current_nal->repeat_pic = 1; + break; + case DISP_FRAME_DOUBLING: + parser->current_nal->interlaced = 0; + parser->current_nal->repeat_pic = 2; + break; + case DISP_FRAME_TRIPLING: + parser->current_nal->interlaced = 0; + parser->current_nal->repeat_pic = 3; + } + } } } diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index 40e463716..2fbbeff97 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -43,6 +43,19 @@ enum nal_unit_types NAL_SPS_EXT }; +enum pic_struct { + DISP_FRAME = 0, + DISP_TOP, + DISP_BOTTOM, + DISP_TOP_BOTTOM, + DISP_BOTTOM_TOP, + DISP_TOP_BOTTOM_TOP, + DISP_TOP_TOP_BOTTOM, + DISP_BOTTOM_TOP_BOTTOM, + DISP_FRAME_DOUBLING, + DISP_FRAME_TRIPLING +}; + /* slice types repeat from 5-9, we * need a helper function for comparison */ @@ -274,6 +287,16 @@ struct pic_parameter_set_rbsp int32_t second_chroma_qp_index_offset; }; +/*struct clock_timestamp { + uint8_t ct_type; + uint8_t nuit_fiel_based_flag; + uint8_t counting_type; + uint8_t full_timestamp_flag; + uint8_t discontinuity_flag; + uint8_t cnt_dropped_flag; + uint8_t n_frames +};*/ + /* sei contains several additional info, we do * only care for pic_timing, to handle display * reordering @@ -291,7 +314,8 @@ struct sei_message uint8_t cpb_removal_delay; uint8_t dpb_output_delay; - /* ignore the rest */ + uint8_t pic_struct; + //uint8_t clock_timestamp_flag[3]; } pic_timing; }; @@ -397,6 +421,9 @@ struct nal_unit uint32_t top_field_order_cnt; uint32_t bottom_field_order_cnt; + uint8_t interlaced; + uint8_t repeat_pic; + struct sei_message sei; struct seq_parameter_set_rbsp *sps; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 46923b557..0f6639125 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -475,11 +475,19 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, else { img->bad_frame = 0; - if(!pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag) + if((sps->vui_parameters_present_flag && + sps->vui_parameters.pic_struct_present_flag && + !this->nal_parser->current_nal->interlaced) || + !pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag) img->progressive_frame = 1; else img->progressive_frame = 0; + if(!img->progressive_frame && this->nal_parser->current_nal->repeat_pic) + img->repeat_first_field = 1; + else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic) + img->duration *= this->nal_parser->current_nal->repeat_pic; + struct decoded_picture *decoded_pic = NULL; if(pic.is_reference) { if(!slc->field_pic_flag || !this->wait_for_bottom_field) { -- cgit v1.2.3 From 012932581636f44ad0e991570f6ff069a8421619 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 5 Jan 2009 07:20:47 +0000 Subject: Enable sharpness and noise_reduction; add an option for progressive_flag. --- include/xine.h.in | 3 +- src/video_out/video_out_vdpau.c | 166 ++++++++++++++++++++++++++++++--------- src/xine-engine/video_out.c | 4 + src/xine-engine/video_out.h | 4 +- src/xine-engine/xine_interface.c | 4 + 5 files changed, 140 insertions(+), 41 deletions(-) diff --git a/include/xine.h.in b/include/xine.h.in index e27a58e29..a2a658611 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -375,12 +375,13 @@ int xine_get_param (xine_stream_t *stream, int param) XINE_PROTECTED; #define XINE_PARAM_VO_TVMODE 0x0100000a /* ??? */ #define XINE_PARAM_VO_WINDOW_WIDTH 0x0100000f /* readonly */ #define XINE_PARAM_VO_WINDOW_HEIGHT 0x01000010 /* readonly */ +#define XINE_PARAM_VO_SHARPNESS 0x01000018 /* 0..65535 */ +#define XINE_PARAM_VO_NOISE_REDUCTION 0x01000019 /* 0..65535 */ #define XINE_PARAM_VO_CROP_LEFT 0x01000020 /* crop frame pixels */ #define XINE_PARAM_VO_CROP_RIGHT 0x01000021 /* crop frame pixels */ #define XINE_PARAM_VO_CROP_TOP 0x01000022 /* crop frame pixels */ #define XINE_PARAM_VO_CROP_BOTTOM 0x01000023 /* crop frame pixels */ - #define XINE_VO_ZOOM_STEP 100 #define XINE_VO_ZOOM_MAX 400 #define XINE_VO_ZOOM_MIN -85 diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 1e6b497dd..eafaac23a 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -258,8 +258,11 @@ typedef struct { int saturation; int brightness; int contrast; + int sharpness; + int noise; int deinterlace; int deinterlace_method; + int honnor_progressive; int allocated_surfaces; @@ -939,6 +942,93 @@ static void vdpau_update_deinterlace_method( void *this_gen, xine_cfg_entry_t *e +static void vdpau_honnor_progressive_flag( void *this_gen, xine_cfg_entry_t *entry ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + this->honnor_progressive = entry->num_value; +} + + + +static void vdpau_update_noise( vdpau_driver_t *this_gen ) +{ + float value = this_gen->noise/100.0; + if ( value==0 ) { + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; + VdpBool feature_enables[] = { 0 }; + vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); + printf( "vo_vdpau: disable noise reduction !!\n" ); + return; + } + else { + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; + VdpBool feature_enables[] = { 1 }; + vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); + printf( "vo_vdpau: enable noise reduction !!\n" ); + } + + VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL }; + void* attribute_values[] = { &value }; + VdpStatus st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: error, can't set noise reduction level !!\n" ); +} + + + +static void vdpau_update_sharpness( vdpau_driver_t *this_gen ) +{ + float value = this_gen->sharpness/100.0; + if ( value==0 ) { + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS }; + VdpBool feature_enables[] = { 0 }; + vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); + printf( "vo_vdpau: disable sharpness !!\n" ); + return; + } + else { + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS }; + VdpBool feature_enables[] = { 1 }; + vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); + printf( "vo_vdpau: enable sharpness !!\n" ); + } + + VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL }; + void* attribute_values[] = { &value }; + VdpStatus st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: error, can't set sharpness level !!\n" ); +} + + + +static void vdpau_update_csc( vdpau_driver_t *this_gen ) +{ + float hue = this_gen->hue/100.0; + float saturation = this_gen->saturation/100.0; + float contrast = this_gen->contrast/100.0; + float brightness = this_gen->brightness/100.0; + + printf( "vo_vdpau: vdpau_update_csc: hue=%f, saturation=%f, contrast=%f, brightness=%f\n", hue, saturation, contrast, brightness ); + + VdpCSCMatrix matrix; + VdpProcamp procamp = { VDP_PROCAMP_VERSION, brightness, contrast, saturation, hue }; + + VdpStatus st = vdp_generate_csc_matrix( &procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &matrix ); + if ( st != VDP_STATUS_OK ) { + printf( "vo_vdpau: error, can't generate csc matrix !!\n" ); + return; + } + VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX }; + void* attribute_values[] = { &matrix }; + st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: error, can't set csc matrix !!\n" ); +} + + + static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -1012,15 +1102,19 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_release_back_frames( this_gen ); /* empty past frames array */ printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, + VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, + VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; - vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); + vdp_video_mixer_create( vdp_device, 4, features, 4, params, param_values, &this->video_mixer ); this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; this->video_mixer_height = mix_h; vdpau_set_deinterlace( this_gen ); + vdpau_update_noise( this ); + vdpau_update_sharpness( this ); } if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { @@ -1082,7 +1176,8 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) layer[layer_count-1].struct_version = VDP_LAYER_VERSION; } - if ( this->deinterlace && !frame->vo_frame.progressive_frame && frame->format==XINE_IMGFMT_VDPAU ) { + int non_progressive = (this->honnor_progressive && !frame->vo_frame.progressive_frame) || !this->honnor_progressive; + if ( frame->vo_frame.duration>2500 && this->deinterlace && non_progressive && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; VdpVideoSurface future[1]; @@ -1181,13 +1276,17 @@ static int vdpau_get_property (vo_driver_t *this_gen, int property) case VO_PROP_OUTPUT_YOFFSET: return this->sc.output_yoffset; case VO_PROP_HUE: - return 0; + return this->hue; case VO_PROP_SATURATION: - return 100; + return this->saturation; case VO_PROP_CONTRAST: - return 100; + return this->contrast; case VO_PROP_BRIGHTNESS: - return 0; + return this->brightness; + case VO_PROP_SHARPNESS: + return this->sharpness; + case VO_PROP_NOISE_REDUCTION: + return this->noise; } return -1; @@ -1195,32 +1294,6 @@ static int vdpau_get_property (vo_driver_t *this_gen, int property) -static void vdpau_update_csc( vdpau_driver_t *this_gen ) -{ - /*float hue = this_gen->hue/100.0; - float saturation = this_gen->saturation/100.0; - float contrast = this_gen->contrast/100.0; - float brightness = this_gen->brightness/100.0; - - printf( "vo_vdpau: vdpau_update_csc: hue=%f, saturation=%f, contrast=%f, brightness=%f\n", hue, saturation, contrast, brightness ); - - VdpCSCMatrix matrix; - VdpProcamp procamp = { VDP_PROCAMP_VERSION, brightness, contrast, saturation, hue }; - - VdpStatus st = vdp_generate_csc_matrix( &procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &matrix ); - if ( st != VDP_STATUS_OK ) { - printf( "vo_vdpau: error, can't generate csc matrix !!\n" ); - return; - } - VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX }; - void* attribute_values[] = { &matrix }; - st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); - if ( st != VDP_STATUS_OK ) - printf( "vo_vdpau: error, can't set csc matrix !!\n" );*/ -} - - - static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) { vdpau_driver_t *this = (vdpau_driver_t*)this_gen; @@ -1256,6 +1329,8 @@ static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) case VO_PROP_SATURATION: this->saturation = value; vdpau_update_csc( this ); break; case VO_PROP_CONTRAST: this->contrast = value; vdpau_update_csc( this ); break; case VO_PROP_BRIGHTNESS: this->brightness = value; vdpau_update_csc( this ); break; + case VO_PROP_SHARPNESS: this->sharpness = value; vdpau_update_sharpness( this ); break; + case VO_PROP_NOISE_REDUCTION: this->noise = value; vdpau_update_noise( this ); break; } return value; @@ -1274,6 +1349,10 @@ static void vdpau_get_property_min_max (vo_driver_t *this_gen, int property, int *max = 1000; *min = 0; break; case VO_PROP_BRIGHTNESS: *max = 100; *min = -100; break; + case VO_PROP_SHARPNESS: + *max = 100; *min = -100; break; + case VO_PROP_NOISE_REDUCTION: + *max = 100; *min = 0; break; default: *max = 0; *min = 0; } @@ -1648,11 +1727,12 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->video_mixer_chroma = chroma; this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, + VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; - st = vdp_video_mixer_create( vdp_device, 2, features, 4, params, param_values, &this->video_mixer ); + st = vdp_video_mixer_create( vdp_device, 4, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); vdp_output_surface_destroy( this->output_surface[0] ); @@ -1660,15 +1740,21 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } - this->deinterlace_method = config->register_enum (config, "video.output.vdpau_deinterlace_method", 1, - vdpau_deinterlace_methods, _("vdpau HD deinterlace method"), + this->deinterlace_method = config->register_enum( config, "video.output.vdpau_deinterlace_method", 1, + vdpau_deinterlace_methods, _("vdpau: HD deinterlace method"), _("bob\n" "Basic deinterlacing, doing 50i->50p.\n\n" "temporal\n" "Very good, 50i->50p\n\n" "temporal_spatial\n" "The best, but very GPU intensive.\n\n"), - 10, vdpau_update_deinterlace_method, this); + 10, vdpau_update_deinterlace_method, this ); + + this->honnor_progressive = config->register_bool( config, "video.output.vdpau_honnor_progressive", 0, + _("vdpau: disable deinterlacing when progressive_frame flag is set"), + _("Set to true if you want to trust the progressive_frame stream's flag.\n" + "This flag is not always reliable.\n\n"), + 10, vdpau_honnor_progressive_flag, this ); this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY; ok = 0; @@ -1696,6 +1782,8 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->saturation = 100; this->contrast = 100; this->brightness = 0; + this->sharpness = 0; + this->noise = 0; this->deinterlace = 0; this->allocated_surfaces = 0; diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index f99067ad4..171190bc5 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -1434,6 +1434,8 @@ static int vo_get_property (xine_video_port_t *this_gen, int property) { ret = this->crop_bottom; break; + case XINE_PARAM_VO_SHARPNESS: + case XINE_PARAM_VO_NOISE_REDUCTION: case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: @@ -1523,6 +1525,8 @@ static int vo_set_property (xine_video_port_t *this_gen, int property, int value ret = this->crop_bottom = value; break; + case XINE_PARAM_VO_SHARPNESS: + case XINE_PARAM_VO_NOISE_REDUCTION: case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 0c73ddafa..845ab0079 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -260,7 +260,9 @@ struct xine_video_port_s { #define VO_PROP_OUTPUT_HEIGHT 20 /* read-only */ #define VO_PROP_OUTPUT_XOFFSET 21 /* read-only */ #define VO_PROP_OUTPUT_YOFFSET 22 /* read-only */ -#define VO_NUM_PROPERTIES 23 +#define VO_PROP_SHARPNESS 24 +#define VO_PROP_NOISE_REDUCTION 25 +#define VO_NUM_PROPERTIES 26 /* number of colors in the overlay palette. Currently limited to 256 at most, because some alphablend functions use an 8-bit index into diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 08ff4dc22..20101b436 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -474,6 +474,8 @@ void xine_set_param (xine_stream_t *stream, int param, int value) { stream->xine->verbosity = value; break; + case XINE_PARAM_VO_SHARPNESS: + case XINE_PARAM_VO_NOISE_REDUCTION: case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: @@ -635,6 +637,8 @@ int xine_get_param (xine_stream_t *stream, int param) { ret = stream->xine->verbosity; break; + case XINE_PARAM_VO_SHARPNESS: + case XINE_PARAM_VO_NOISE_REDUCTION: case XINE_PARAM_VO_HUE: case XINE_PARAM_VO_SATURATION: case XINE_PARAM_VO_CONTRAST: -- cgit v1.2.3 From 9c7d9494c7b2131feab6c20449358c61f0f7d553 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 6 Jan 2009 12:15:54 +0000 Subject: Add enable_inverse_telecine option; rename honnor_progressive -> honor_progressive. --- src/video_out/video_out_vdpau.c | 44 +++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index eafaac23a..c7a7f3299 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -262,7 +262,8 @@ typedef struct { int noise; int deinterlace; int deinterlace_method; - int honnor_progressive; + int enable_inverse_telecine; + int honor_progressive; int allocated_surfaces; @@ -714,10 +715,10 @@ static void vdpau_provide_standard_frame_data (vo_frame_t *this_gen, xine_curren this->vo_frame.base[0], this->vo_frame.pitches[0], data->img, this->vo_frame.width, /* U */ - this->vo_frame.base[1], this->vo_frame.pitches[1], + this->vo_frame.base[2], this->vo_frame.pitches[2], data->img+this->vo_frame.width*this->vo_frame.height, this->vo_frame.width/2, /* V */ - this->vo_frame.base[2], this->vo_frame.pitches[2], + this->vo_frame.base[1], this->vo_frame.pitches[1], data->img+this->vo_frame.width*this->vo_frame.height+this->vo_frame.width*this->vo_frame.height/4, this->vo_frame.width/2, /* width x height */ this->vo_frame.width, this->vo_frame.height); @@ -929,7 +930,21 @@ static void vdpau_set_deinterlace( vo_driver_t *this_gen ) printf("vo_vdpau: enabled features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); } +static void vdpau_set_inverse_telecine( vo_driver_t *this_gen ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE }; + VdpBool feature_enables[1]; + if ( this->deinterlace && this->enable_inverse_telecine ) + feature_enables[0] = 1; + else + feature_enables[0] = 0; + + vdp_video_mixer_set_feature_enables( this->video_mixer, 1, features, feature_enables ); + vdp_video_mixer_get_feature_enables( this->video_mixer, 1, features, feature_enables ); + printf("vo_vdpau: enabled features: inverse_telecine=%d\n", feature_enables[0] ); +} static void vdpau_update_deinterlace_method( void *this_gen, xine_cfg_entry_t *entry ) { @@ -940,13 +955,20 @@ static void vdpau_update_deinterlace_method( void *this_gen, xine_cfg_entry_t *e vdpau_set_deinterlace( (vo_driver_t*)this_gen ); } +static void vdpau_update_enable_inverse_telecine( void *this_gen, xine_cfg_entry_t *entry ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + this->enable_inverse_telecine = entry->num_value; + printf( "vo_vdpau: enable inverse_telecine=%d\n", this->enable_inverse_telecine ); + vdpau_set_inverse_telecine( (vo_driver_t*)this_gen ); +} -static void vdpau_honnor_progressive_flag( void *this_gen, xine_cfg_entry_t *entry ) +static void vdpau_honor_progressive_flag( void *this_gen, xine_cfg_entry_t *entry ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - this->honnor_progressive = entry->num_value; + this->honor_progressive = entry->num_value; } @@ -1176,7 +1198,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) layer[layer_count-1].struct_version = VDP_LAYER_VERSION; } - int non_progressive = (this->honnor_progressive && !frame->vo_frame.progressive_frame) || !this->honnor_progressive; + int non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive; if ( frame->vo_frame.duration>2500 && this->deinterlace && non_progressive && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; @@ -1750,11 +1772,17 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo "The best, but very GPU intensive.\n\n"), 10, vdpau_update_deinterlace_method, this ); - this->honnor_progressive = config->register_bool( config, "video.output.vdpau_honnor_progressive", 0, + this->enable_inverse_telecine = config->register_bool( config, "video.output.vdpau_enable_inverse_telecine", 1, + _("vdpau: Try to recreatea progressive frames pulldown material"), + _("Enable this to detect bad-flagged progressive content to which\n" + "a 2:2 or 3:2 pulldown was applied.\n\n"), + 10, vdpau_update_enable_inverse_telecine, this ); + + this->honor_progressive = config->register_bool( config, "video.output.vdpau_honor_progressive", 0, _("vdpau: disable deinterlacing when progressive_frame flag is set"), _("Set to true if you want to trust the progressive_frame stream's flag.\n" "This flag is not always reliable.\n\n"), - 10, vdpau_honnor_progressive_flag, this ); + 10, vdpau_honor_progressive_flag, this ); this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY; ok = 0; -- cgit v1.2.3 From ff79b3c43b90c2b76e5557e9606461a775c71488 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Wed, 7 Jan 2009 17:34:55 +0000 Subject: Fix a possible buf underrun -> crash. --- src/libvdpau/h264_parser.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index fdc48f043..fcec0b92e 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1201,6 +1201,13 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, * copy the left data into prebuf */ if(parsed_len < inbuf_len) { + if (inbuf_len-parsed_len + parser->prebuf_len > MAX_FRAME_SIZE) { + printf("buf underrun!!\n"); + parser->prebuf_len = 0; + *ret_len = 0; + *ret_buf = NULL; + return parsed_len; + } parser->incomplete_nal = 1; xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len-parsed_len); parser->prebuf_len += inbuf_len-parsed_len; -- cgit v1.2.3 From 4649f23f1841a95c0630eff250d13868b98ac3f0 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 9 Jan 2009 17:03:29 +0000 Subject: Add preemption reinit support. --- src/libvdpau/h264_parser.c | 2 +- src/libvdpau/vdpau_h264.c | 58 +++++++++++++++------- src/libvdpau/vdpau_mpeg12.c | 14 ++++++ src/video_out/video_out_vdpau.c | 105 +++++++++++++++++++++++++++++++++++++++- src/xine-engine/accel_vdpau.h | 3 ++ 5 files changed, 162 insertions(+), 20 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index fcec0b92e..dff73f235 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1139,7 +1139,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->last_nal_res = parse_nal(prebuf+3, parser->prebuf_len-3, parser); if (parser->last_nal_res == 1 && parser->buf_len > 0) { - //printf("Frame complete: %d bytes\n", parser->buf_len); + printf("Frame complete: %d bytes\n", parser->buf_len); *ret_buf = malloc(parser->buf_len); xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); *ret_len = parser->buf_len; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 0f6639125..ca9407063 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -82,6 +82,8 @@ typedef struct vdpau_h264_decoder_s { vo_frame_t *last_img; vo_frame_t *dangling_img; + int vdp_runtime_nr; + } vdpau_h264_decoder_t; /************************************************************************** @@ -186,7 +188,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->video_step = buf->decoder_info[0]; _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } - if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ xine_bmiheader *bih = (xine_bmiheader*)buf->content; this->width = bih->biWidth; @@ -196,14 +197,17 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /* parse the first nal packages to retrieve profile type */ int len = 0; + int write_start_seq = 0; uint32_t slice_count; if(buf->pts != 0) this->next_pts = buf->pts; - while(len < buf->size) { - len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, - (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); + while(len < buf->size || write_start_seq == 1) { + if(!write_start_seq) { + len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, + (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); + } if(!this->decoder_initialized && this->nal_parser->current_nal != NULL && @@ -340,18 +344,19 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, /*VdpBool is_supported; uint32_t max_level, max_references, max_width, max_height;*/ - xprintf(this->xine, XINE_VERBOSITY_LOG, - "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n", - this->vdpau_accel->vdp_device, this->profile, this->width, this->height); - - VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, - this->profile, this->width, this->height, 16, &this->decoder); - - if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status)); - else - this->decoder_initialized = 1; - + if(this->vdpau_accel->vdp_runtime_nr > 0) { + xprintf(this->xine, XINE_VERBOSITY_LOG, + "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n", + this->vdpau_accel->vdp_device, this->profile, this->width, this->height); + + VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, + this->profile, this->width, this->height, 16, &this->decoder); + + if(status != VDP_STATUS_OK) + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status)); + else + this->decoder_initialized = 1; + } img->free(img); img = NULL; } @@ -361,7 +366,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->slc != NULL && this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { - struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; struct slice_header *slc = this->nal_parser->current_nal->slc; @@ -452,6 +456,23 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->dangling_img = img; } + if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) { + printf("VDPAU was preempted. Reinitialise the decoder.\n"); + this->decoder_initialized = 0; + this->decoder_started = 0; + this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; + this->last_img = NULL; + this->last_ref_pic = NULL; + dpb_free_all(&this->nal_parser->dpb); + free_parser(this->nal_parser); + this->nal_parser = init_parser(); + if(img) { + img->free(img); + img = NULL; + } + continue; + } + VdpVideoSurface surface = this->vdpau_accel->surface; //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->curr_pts); @@ -543,6 +564,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } } } + } } @@ -649,6 +671,8 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->xine = stream->xine; this->class = (vdpau_h264_class_t *) class_gen; + this->vdp_runtime_nr = 1; + this->nal_parser = init_parser(); (this->stream->video_out->open) (this->stream->video_out, this->stream); diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 7978a7682..819796d0f 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -143,6 +143,8 @@ typedef struct { vdpau_accel_t *accel_vdpau; + int vdp_runtime_nr; + } sequence_t; @@ -578,6 +580,7 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) vd->decoder_profile = seq->profile; vd->decoder_width = seq->coded_width; vd->decoder_height = seq->coded_height; + seq->vdp_runtime_nr = accel->vdp_runtime_nr; } } @@ -671,6 +674,16 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) if ( !seq->accel_vdpau ) seq->accel_vdpau = accel; + if( seq->vdp_runtime_nr != *(seq->accel_vdpau->current_vdp_runtime_nr) ) { + seq->accel_vdpau = accel; + if ( seq->forward_ref ) + seq->forward_ref->free( seq->forward_ref ); + seq->forward_ref = NULL; + if ( seq->backward_ref ) + seq->backward_ref->free( seq->backward_ref ); + seq->backward_ref = NULL; + vd->decoder = VDP_INVALID_HANDLE; + } img->drawn = 0; //printf("vdpau_mpeg12: .. got image %d\n", img); @@ -870,6 +883,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize); this->sequence.forward_ref = 0; this->sequence.backward_ref = 0; + this->sequence.vdp_runtime_nr = 1; reset_sequence( &this->sequence ); init_picture( &this->sequence.picture ); diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index c7a7f3299..de305d05e 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -120,7 +120,9 @@ VdpDecoderCreate *vdp_decoder_create; VdpDecoderDestroy *vdp_decoder_destroy; VdpDecoderRender *vdp_decoder_render; - +VdpPreemptionCallbackRegister *vdp_preemption_callback_register; +static void vdp_preemption_callback( VdpDevice device, void *context ); +static void vdpau_reinit( vo_driver_t *this_gen ); static VdpVideoSurfaceCreate *orig_vdp_video_surface_create; static VdpVideoSurfaceDestroy *orig_vdp_video_surface_destroy; @@ -199,6 +201,7 @@ typedef struct { typedef struct { + vo_driver_t vo_driver; vo_scale_t sc; @@ -265,6 +268,9 @@ typedef struct { int enable_inverse_telecine; int honor_progressive; + int vdp_runtime_nr; + int reinit_needed; + int allocated_surfaces; } vdpau_driver_t; @@ -661,6 +667,8 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vdpau_accel_data.vdp_decoder_destroy = vdp_decoder_destroy; frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render; frame->vdpau_accel_data.vdp_get_error_string = vdp_get_error_string; + frame->vdpau_accel_data.vdp_runtime_nr = this->vdp_runtime_nr; + frame->vdpau_accel_data.current_vdp_runtime_nr = &this->vdp_runtime_nr; return (vo_frame_t *) frame; } @@ -796,7 +804,8 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ VdpChromaType chroma = (flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420; /* Check frame size and format and reallocate if necessary */ - if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) ) { + if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) || + (frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr)) { //printf("vo_vdpau: updating frame to %d x %d (ratio=%g, format=%08X)\n", width, height, ratio, format); /* (re-) allocate render space */ @@ -833,6 +842,12 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ } } + if ( frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr ) { + frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; + frame->vdpau_accel_data.vdp_runtime_nr = this->vdp_runtime_nr; + frame->vdpau_accel_data.vdp_device = vdp_device; + } + if ( (format == XINE_IMGFMT_VDPAU) && (frame->vdpau_accel_data.surface == VDP_INVALID_HANDLE) ) { VdpStatus st = vdp_video_surface_create( vdp_device, chroma, width, height, &frame->vdpau_accel_data.surface ); if ( st!=VDP_STATUS_OK ) @@ -1063,6 +1078,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpTime stream_speed; + if(this->reinit_needed) + vdpau_reinit(this_gen); + if ( (frame->width != this->sc.delivered_width) || (frame->height != this->sc.delivered_height) || (frame->ratio != this->sc.delivered_ratio) ) { this->sc.force_redraw = 1; /* trigger re-calc of output size */ } @@ -1507,7 +1525,81 @@ static int vdpau_init_error( VdpStatus st, const char *msg, vo_driver_t *driver, return 0; } +static void vdpau_reinit( vo_driver_t *this_gen ) +{ + printf("VDPAU was pre-empted. Reinit.\n"); + vdpau_driver_t *this = (vdpau_driver_t *)this_gen; + + XLockDisplay(guarded_display); + vdpau_release_back_frames(this_gen); + VdpStatus st = vdp_device_create_x11( this->display, this->screen, &vdp_device, &vdp_get_proc_address ); + + if ( st != VDP_STATUS_OK ) { + printf( "vo_vdpau: Can't create vdp device : " ); + if ( st == VDP_STATUS_NO_IMPLEMENTATION ) + printf( "No vdpau implementation.\n" ); + else + printf( "unsupported GPU?\n" ); + vdpau_dispose( &this->vo_driver ); + return; + } + + st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); + if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) ) + return; + st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); + if ( vdpau_init_error( st, "Can't create presentation queue !!", &this->vo_driver, 1 ) ) + return; + + + VdpChromaType chroma = VDP_CHROMA_TYPE_420; + st = orig_vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); + if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) + return; + + this->current_output_surface = 0; + this->init_queue = 0; + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] ); + if ( vdpau_init_error( st, "Can't create first output surface !!", &this->vo_driver, 1 ) ) { + orig_vdp_video_surface_destroy( this->soft_surface ); + return; + } + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[1] ); + if ( vdpau_init_error( st, "Can't create second output surface !!", &this->vo_driver, 1 ) ) { + orig_vdp_video_surface_destroy( this->soft_surface ); + vdp_output_surface_destroy( this->output_surface[0] ); + return; + } + + this->video_mixer_chroma = chroma; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, + VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; + int num_layers = 3; + void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; + st = vdp_video_mixer_create( vdp_device, 4, features, 4, params, param_values, &this->video_mixer ); + if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { + orig_vdp_video_surface_destroy( this->soft_surface ); + vdp_output_surface_destroy( this->output_surface[0] ); + vdp_output_surface_destroy( this->output_surface[1] ); + return; + } + + vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this); + + XUnlockDisplay(guarded_display); + printf("Reinit done.\n"); + this->vdp_runtime_nr++; + this->reinit_needed = 0; +} + +static void vdp_preemption_callback(VdpDevice device, void *context) +{ + printf("VDPAU preemption callback\n"); + vdpau_driver_t *this = (vdpau_driver_t *)context; + this->reinit_needed = 1; +} static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { @@ -1707,6 +1799,13 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE , (void*)&vdp_bitmap_put_bits ); if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_PUT_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER, (void*)&vdp_preemption_callback_register ); + if ( vdpau_init_error( st, "Can't get PREEMPTION_CALLBACK_REGISTER proc address !!", &this->vo_driver, 1 ) ) + return NULL; + + st = vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this); + if ( vdpau_init_error( st, "Can't register preemption callback !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) ) @@ -1816,6 +1915,8 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->allocated_surfaces = 0; + this->vdp_runtime_nr = 1; + return &this->vo_driver; } diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h index e489408c5..99cea4568 100644 --- a/src/xine-engine/accel_vdpau.h +++ b/src/xine-engine/accel_vdpau.h @@ -49,6 +49,9 @@ typedef struct { VdpVideoSurface surface; VdpChromaType chroma; + int vdp_runtime_nr; /* this is used to keep in sync on preemptions */ + int *current_vdp_runtime_nr; + } vdpau_accel_t; #ifdef __cplusplus -- cgit v1.2.3 From 27e3c55b08fb07a77ea50932871558567f297ab2 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 9 Jan 2009 17:45:01 +0000 Subject: H.264 decoder code cleanup. --- src/libvdpau/vdpau_h264.c | 768 ++++++++++++++++++++++++---------------------- 1 file changed, 394 insertions(+), 374 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ca9407063..db073fdaa 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -50,9 +50,6 @@ typedef struct vdpau_h264_decoder_s { /* these are traditional variables in a video decoder object */ uint64_t video_step; /* frame duration in pts units */ - int decoder_started; /* current decoder status */ - int decoder_initialized; /* vdpau init state */ - int skipframes; unsigned char *buf; /* the accumulated buffer data */ int bufsize; /* the maximum size of buf */ @@ -71,7 +68,6 @@ typedef struct vdpau_h264_decoder_s { VdpDecoder decoder; VdpDecoderProfile profile; - VdpPictureInfoH264 vdp_picture_info; vdpau_accel_t *vdpau_accel; xine_t *xine; @@ -166,6 +162,371 @@ static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) } +static void set_ratio(video_decoder_t *this_gen) +{ + vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; + + this->ratio = (double)this->width / (double)this->height; + if(this->nal_parser->current_nal->sps->vui_parameters.aspect_ration_info_present_flag) { + switch(this->nal_parser->current_nal->sps->vui_parameters.aspect_ratio_idc) { + case ASPECT_1_1: + this->ratio = 1 * this->ratio; + break; + case ASPECT_12_11: + this->ratio *= 12.0/11.0; + break; + case ASPECT_10_11: + this->ratio *= 10.0/11.0; + break; + case ASPECT_16_11: + this->ratio *= 16.0/11.0; + break; + case ASPECT_40_33: + this->ratio *= 40.0/33.0; + break; + case ASPECT_24_11: + this->ratio *= 24.0/11.0; + break; + case ASPECT_20_11: + this->ratio *= 20.0/11.0; + break; + case ASPECT_32_11: + this->ratio *= 32.0/11.0; + break; + case ASPECT_80_33: + this->ratio *= 80.0/33.0; + break; + case ASPECT_18_11: + this->ratio *= 18.0/11.0; + break; + case ASPECT_15_11: + this->ratio *= 15.0/11.0; + break; + case ASPECT_64_33: + this->ratio *= 64.0/33.0; + break; + case ASPECT_160_99: + this->ratio *= 160.0/99.0; + break; + case ASPECT_4_3: + this->ratio *= 4.0/3.0; + break; + case ASPECT_3_2: + this->ratio *= 3.0/2.0; + break; + case ASPECT_2_1: + this->ratio *= 2.0/1.0; + break; + case ASPECT_EXTENDED_SAR: + this->ratio *= + (double)this->nal_parser->current_nal->sps->vui_parameters.sar_width/ + (double)this->nal_parser->current_nal->sps->vui_parameters.sar_height; + break; + } + } +} + +static void fill_vdpau_pictureinfo_h264(video_decoder_t *this_gen, uint32_t slice_count, VdpPictureInfoH264 *pic) +{ + vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; + + struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; + struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; + struct slice_header *slc = this->nal_parser->current_nal->slc; + + pic->slice_count = slice_count; + pic->field_order_cnt[0] = this->nal_parser->current_nal->top_field_order_cnt; + pic->field_order_cnt[1] = this->nal_parser->current_nal->bottom_field_order_cnt; + pic->is_reference = + (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; + pic->frame_num = slc->frame_num; + pic->field_pic_flag = slc->field_pic_flag; + pic->bottom_field_flag = slc->bottom_field_flag; + //pic->num_ref_frames = sps->num_ref_frames; + pic->mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; + pic->constrained_intra_pred_flag = pps->constrained_intra_pred_flag; + pic->weighted_pred_flag = pps->weighted_pred_flag; + pic->weighted_bipred_idc = pps->weighted_bipred_idc; + pic->frame_mbs_only_flag = sps->frame_mbs_only_flag; + pic->transform_8x8_mode_flag = pps->transform_8x8_mode_flag; + pic->chroma_qp_index_offset = pps->chroma_qp_index_offset; + pic->second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; + pic->pic_init_qp_minus26 = pps->pic_init_qp_minus26; + pic->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1; + pic->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1; + pic->log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; + pic->pic_order_cnt_type = sps->pic_order_cnt_type; + pic->log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4; + pic->delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; + pic->direct_8x8_inference_flag = sps->direct_8x8_inference_flag; + pic->entropy_coding_mode_flag = pps->entropy_coding_mode_flag; + pic->pic_order_present_flag = pps->pic_order_present_flag; + pic->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; + pic->redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; + memcpy(pic->scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic->scaling_lists_4x4)); + memcpy(pic->scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic->scaling_lists_8x8)); + + /* set num_ref_frames to the number of actually available reference frames, + * if this is not set generation 3 decoders will fail. */ + pic->num_ref_frames = fill_vdpau_reference_list(&(this->nal_parser->dpb), pic->referenceFrames); + +} + +static int vdpau_decoder_init(video_decoder_t *this_gen) +{ + vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; + vo_frame_t *img; + + this->curr_pts = this->next_pts; + this->next_pts = 0; + + if(this->width == 0) { + this->width = this->nal_parser->current_nal->sps->pic_width; + this->height = this->nal_parser->current_nal->sps->pic_height; + } + + set_ratio(this_gen); + + _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->width ); + _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->height ); + _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*this->ratio) ); + _x_stream_info_set( this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step ); + _x_meta_info_set_utf8( this->stream, XINE_META_INFO_VIDEOCODEC, "H264/AVC (vdpau)" ); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = this->stream; + event.data = &data; + event.data_length = sizeof(data); + data.width = this->width; + data.height = this->height; + data.aspect = this->ratio; + xine_event_send( this->stream, &event ); + + switch(this->nal_parser->current_nal->sps->profile_idc) { + case 100: + this->profile = VDP_DECODER_PROFILE_H264_HIGH; + break; + case 77: + this->profile = VDP_DECODER_PROFILE_H264_MAIN; + break; + case 66: + default: + // nvidia's VDPAU doesn't support BASELINE. But most (every?) streams marked BASELINE do not use BASELINE specifics, + // so, just force MAIN. + //this->profile = VDP_DECODER_PROFILE_H264_BASELINE; + this->profile = VDP_DECODER_PROFILE_H264_MAIN; + break; + } + + // Level 4.1 limits: + int ref_frames = 0; + if(this->nal_parser->current_nal->sps->num_ref_frames) { + ref_frames = this->nal_parser->current_nal->sps->num_ref_frames; + } else { + uint32_t round_width = (this->width + 15) & ~15; + uint32_t round_height = (this->height + 15) & ~15; + uint32_t surf_size = (round_width * round_height * 3) / 2; + ref_frames = (12 * 1024 * 1024) / surf_size; + } + + if (ref_frames > 16) { + ref_frames = 16; + } + + printf("Allocate %d reference frames\n", ref_frames); + /* get the vdpau context from vo */ + //(this->stream->video_out->open) (this->stream->video_out, this->stream); + img = this->stream->video_out->get_frame (this->stream->video_out, + this->width, this->height, + this->ratio, + XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + + this->vdpau_accel = (vdpau_accel_t*)img->accel_data; + + /*VdpBool is_supported; + uint32_t max_level, max_references, max_width, max_height;*/ + if(this->vdpau_accel->vdp_runtime_nr > 0) { + xprintf(this->xine, XINE_VERBOSITY_LOG, + "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n", + this->vdpau_accel->vdp_device, this->profile, this->width, this->height); + + VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, + this->profile, this->width, this->height, 16, &this->decoder); + + if(status != VDP_STATUS_OK) { + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status)); + return 0; + } + } + this->last_img = img; + this->dangling_img = img; + + return 1; +} + +static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count) +{ + vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; + vo_frame_t *img = this->last_img; + + struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; + struct slice_header *slc = this->nal_parser->current_nal->slc; + + if(sps->vui_parameters_present_flag && + sps->vui_parameters.timing_info_present_flag && + this->video_step == 0) { + this->video_step = 2*90000/(1/((double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale)); + } + + /* flush the DPB if this frame was an IDR */ + //printf("is_idr: %d\n", this->nal_parser->is_idr); + if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { + dpb_flush(&(this->nal_parser->dpb)); + } + this->nal_parser->is_idr = 0; + + /* go and decode a frame */ + VdpPictureInfoH264 pic; + fill_vdpau_pictureinfo_h264(this_gen, slice_count, &pic); + + //dump_pictureinfo_h264(&pic); + + /*int i; + printf("Decode data: \n"); + for(i = 0; i < ((vdp_buffer.bitstream_bytes < 20) ? vdp_buffer.bitstream_bytes : 20); i++) { + printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); + if((i+1) % 10 == 0) + printf("\n"); + } + printf("\n...\n"); + for(i = vdp_buffer.bitstream_bytes - 20; i < vdp_buffer.bitstream_bytes; i++) { + printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); + if((i+1) % 10 == 0) + printf("\n"); + }*/ + + + if(img == NULL) { + img = this->stream->video_out->get_frame (this->stream->video_out, + this->width, this->height, + this->ratio, + XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); + this->vdpau_accel = (vdpau_accel_t*)img->accel_data; + + img->duration = this->video_step; + img->pts = this->curr_pts; + + this->dangling_img = img; + } + + if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) { + printf("VDPAU was preempted. Reinitialise the decoder.\n"); + this->decoder = VDP_INVALID_HANDLE; + this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; + this->last_img = NULL; + this->last_ref_pic = NULL; + dpb_free_all(&this->nal_parser->dpb); + free_parser(this->nal_parser); + this->nal_parser = init_parser(); + if(img) { + img->free(img); + img = NULL; + } + return 0; + } + + VdpVideoSurface surface = this->vdpau_accel->surface; + + //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->curr_pts); + VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, + surface, (VdpPictureInfo*)&pic, 1, vdp_buffer); + + // FIXME: do we really hit all cases here? + if(((uint8_t*)vdp_buffer->bitstream) != NULL) { + free((uint8_t*)vdp_buffer->bitstream); + } + + this->curr_pts = this->next_pts; + this->next_pts = 0; + + if(status != VDP_STATUS_OK) + { + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); + img->free(img); + img = this->last_img = this->dangling_img = NULL; + } + else { + img->bad_frame = 0; + + if((sps->vui_parameters_present_flag && + sps->vui_parameters.pic_struct_present_flag && + !this->nal_parser->current_nal->interlaced) || + (!pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag)) + img->progressive_frame = 1; + else + img->progressive_frame = 0; + + if(!img->progressive_frame && this->nal_parser->current_nal->repeat_pic) + img->repeat_first_field = 1; + else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic) + img->duration *= this->nal_parser->current_nal->repeat_pic; + + struct decoded_picture *decoded_pic = NULL; + if(pic.is_reference) { + if(!slc->field_pic_flag || !this->wait_for_bottom_field) { + decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + this->last_ref_pic = decoded_pic; + decoded_pic->used_for_reference = 1; + dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); + this->dangling_img = NULL; + } else if(slc->field_pic_flag && this->wait_for_bottom_field) { + if(this->last_ref_pic) { + decoded_pic = this->last_ref_pic; + //copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal); + decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; + this->last_ref_pic->bottom_is_reference = 1; + } + } + } + + if(!slc->field_pic_flag || + (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { + if(!decoded_pic) { + decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); + decoded_pic->delayed_output = 1; + dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); + this->dangling_img = NULL; + if(decoded_pic->nal->slc->bottom_field_flag) + decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; + } else + decoded_pic->delayed_output = 1; + + if(this->wait_for_bottom_field && slc->bottom_field_flag) + decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; + + this->last_img = img = NULL; + + /* now retrieve the next output frame */ + if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb))) != NULL) { + decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); + decoded_pic->img->draw(decoded_pic->img, this->stream); + dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); + } + + this->wait_for_bottom_field = 0; + + } else if(slc->field_pic_flag && !slc->bottom_field_flag) { + // don't draw yet, second field is missing. + this->last_top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt; + this->wait_for_bottom_field = 1; + this->last_img = img; + } + } + + return 1; +} + /* * This function receives a buffer of data from the demuxer layer and * figures out how to handle it based on its header flags. @@ -178,7 +539,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, VdpBitstreamBuffer vdp_buffer; vdp_buffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; - vo_frame_t *img = this->last_img; /* video out frame */ /* a video decoder does not care about this flag (?) */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) @@ -188,384 +548,43 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->video_step = buf->decoder_info[0]; _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } + if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ xine_bmiheader *bih = (xine_bmiheader*)buf->content; this->width = bih->biWidth; this->height = bih->biHeight; - } else { - - /* parse the first nal packages to retrieve profile type */ - int len = 0; - int write_start_seq = 0; - uint32_t slice_count; - - if(buf->pts != 0) - this->next_pts = buf->pts; - - while(len < buf->size || write_start_seq == 1) { - if(!write_start_seq) { - len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, - (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); - } + } - if(!this->decoder_initialized && - this->nal_parser->current_nal != NULL && - this->nal_parser->current_nal->sps != NULL && - this->nal_parser->current_nal->sps->pic_width > 0 && - this->nal_parser->current_nal->sps->pic_height > 0) { + /* parse the first nal packages to retrieve profile type */ + int len = 0; + uint32_t slice_count; - this->curr_pts = this->next_pts; - this->next_pts = 0; + if(buf->pts != 0) + this->next_pts = buf->pts; - if(this->width == 0) { - this->width = this->nal_parser->current_nal->sps->pic_width; - this->height = this->nal_parser->current_nal->sps->pic_height; - } + while(len < buf->size) { + len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, + (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); - /* FIXME: ratio should be calculated in some other way to - * support anamorph codings... - */ - this->ratio = (double)this->width / (double)this->height; - if(this->nal_parser->current_nal->sps->vui_parameters.aspect_ration_info_present_flag) { - switch(this->nal_parser->current_nal->sps->vui_parameters.aspect_ratio_idc) { - case ASPECT_1_1: - this->ratio = 1 * this->ratio; - break; - case ASPECT_12_11: - this->ratio *= 12.0/11.0; - break; - case ASPECT_10_11: - this->ratio *= 10.0/11.0; - break; - case ASPECT_16_11: - this->ratio *= 16.0/11.0; - break; - case ASPECT_40_33: - this->ratio *= 40.0/33.0; - break; - case ASPECT_24_11: - this->ratio *= 24.0/11.0; - break; - case ASPECT_20_11: - this->ratio *= 20.0/11.0; - break; - case ASPECT_32_11: - this->ratio *= 32.0/11.0; - break; - case ASPECT_80_33: - this->ratio *= 80.0/33.0; - break; - case ASPECT_18_11: - this->ratio *= 18.0/11.0; - break; - case ASPECT_15_11: - this->ratio *= 15.0/11.0; - break; - case ASPECT_64_33: - this->ratio *= 64.0/33.0; - break; - case ASPECT_160_99: - this->ratio *= 160.0/99.0; - break; - case ASPECT_4_3: - this->ratio *= 4.0/3.0; - break; - case ASPECT_3_2: - this->ratio *= 3.0/2.0; - break; - case ASPECT_2_1: - this->ratio *= 2.0/1.0; - break; - case ASPECT_EXTENDED_SAR: - this->ratio *= - (double)this->nal_parser->current_nal->sps->vui_parameters.sar_width/ - (double)this->nal_parser->current_nal->sps->vui_parameters.sar_height; - break; - } - } - - _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->width ); - _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->height ); - _x_stream_info_set( this->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*this->ratio) ); - _x_stream_info_set( this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step ); - _x_meta_info_set_utf8( this->stream, XINE_META_INFO_VIDEOCODEC, "H264/AVC (vdpau)" ); - xine_event_t event; - xine_format_change_data_t data; - event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; - event.stream = this->stream; - event.data = &data; - event.data_length = sizeof(data); - data.width = this->width; - data.height = this->height; - data.aspect = this->ratio; - xine_event_send( this->stream, &event ); - - switch(this->nal_parser->current_nal->sps->profile_idc) { - case 100: - this->profile = VDP_DECODER_PROFILE_H264_HIGH; - break; - case 77: - this->profile = VDP_DECODER_PROFILE_H264_MAIN; - break; - case 66: - default: - // nvidia's VDPAU doesn't support BASELINE. But most (every?) streams marked BASELINE do not use BASELINE specifics, - // so, just force MAIN. - //this->profile = VDP_DECODER_PROFILE_H264_BASELINE; - this->profile = VDP_DECODER_PROFILE_H264_MAIN; - break; - } + if(this->decoder == VDP_INVALID_HANDLE && + this->nal_parser->current_nal->sps != NULL && + this->nal_parser->current_nal->sps->pic_width > 0 && + this->nal_parser->current_nal->sps->pic_height > 0) { - // Level 4.1 limits: - int ref_frames = 0; - if(this->nal_parser->current_nal->sps->num_ref_frames) { - ref_frames = this->nal_parser->current_nal->sps->num_ref_frames; - } else { - uint32_t round_width = (this->width + 15) & ~15; - uint32_t round_height = (this->height + 15) & ~15; - uint32_t surf_size = (round_width * round_height * 3) / 2; - ref_frames = (12 * 1024 * 1024) / surf_size; - } - - if (ref_frames > 16) { - ref_frames = 16; - } - - printf("Allocate %d reference frames\n", ref_frames); - /* get the vdpau context from vo */ - //(this->stream->video_out->open) (this->stream->video_out, this->stream); - img = this->stream->video_out->get_frame (this->stream->video_out, - this->width, this->height, - this->ratio, - XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); - - this->vdpau_accel = (vdpau_accel_t*)img->accel_data; - - /*VdpBool is_supported; - uint32_t max_level, max_references, max_width, max_height;*/ - if(this->vdpau_accel->vdp_runtime_nr > 0) { - xprintf(this->xine, XINE_VERBOSITY_LOG, - "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n", - this->vdpau_accel->vdp_device, this->profile, this->width, this->height); - - VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, - this->profile, this->width, this->height, 16, &this->decoder); - - if(status != VDP_STATUS_OK) - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status)); - else - this->decoder_initialized = 1; - } - img->free(img); - img = NULL; - } + vdpau_decoder_init(this_gen); + } - if(this->decoder_initialized) { - if(vdp_buffer.bitstream_bytes > 0 && - this->nal_parser->current_nal->slc != NULL && - this->nal_parser->current_nal->sps != NULL && - this->nal_parser->current_nal->pps != NULL) { - struct pic_parameter_set_rbsp *pps = this->nal_parser->current_nal->pps; - struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; - struct slice_header *slc = this->nal_parser->current_nal->slc; - - if(sps->vui_parameters_present_flag && - sps->vui_parameters.timing_info_present_flag && - this->video_step == 0) { - this->video_step = 2*90000/(1/((double)sps->vui_parameters.num_units_in_tick/(double)sps->vui_parameters.time_scale)); - } - - /* flush the DPB if this frame was an IDR */ - //printf("is_idr: %d\n", this->nal_parser->is_idr); - if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { - dpb_flush(&(this->nal_parser->dpb)); - } - this->nal_parser->is_idr = 0; - - /* go and decode a frame */ - VdpPictureInfoH264 pic; - - pic.slice_count = slice_count; - pic.field_order_cnt[0] = this->nal_parser->current_nal->top_field_order_cnt; - pic.field_order_cnt[1] = this->nal_parser->current_nal->bottom_field_order_cnt; - pic.is_reference = - (this->nal_parser->current_nal->nal_ref_idc != 0) ? VDP_TRUE : VDP_FALSE; - pic.frame_num = slc->frame_num; - pic.field_pic_flag = slc->field_pic_flag; - pic.bottom_field_flag = slc->bottom_field_flag; - //pic.num_ref_frames = sps->num_ref_frames; - pic.mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; - pic.constrained_intra_pred_flag = pps->constrained_intra_pred_flag; - pic.weighted_pred_flag = pps->weighted_pred_flag; - pic.weighted_bipred_idc = pps->weighted_bipred_idc; - pic.frame_mbs_only_flag = sps->frame_mbs_only_flag; - pic.transform_8x8_mode_flag = pps->transform_8x8_mode_flag; - pic.chroma_qp_index_offset = pps->chroma_qp_index_offset; - pic.second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset; - pic.pic_init_qp_minus26 = pps->pic_init_qp_minus26; - pic.num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1; - pic.num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1; - pic.log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4; - pic.pic_order_cnt_type = sps->pic_order_cnt_type; - pic.log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4; - pic.delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag; - pic.direct_8x8_inference_flag = sps->direct_8x8_inference_flag; - pic.entropy_coding_mode_flag = pps->entropy_coding_mode_flag; - pic.pic_order_present_flag = pps->pic_order_present_flag; - pic.deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; - pic.redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; - memcpy(pic.scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic.scaling_lists_4x4)); - memcpy(pic.scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic.scaling_lists_8x8)); - - /* set num_ref_frames to the number of actually available reference frames, - * if this is not set generation 3 decoders will fail. */ - pic.num_ref_frames = fill_vdpau_reference_list(&(this->nal_parser->dpb), pic.referenceFrames); - - if(this->decoder_started || pic.is_reference) { - if(!this->decoder_started) - this->decoder_started = 1; - - //dump_pictureinfo_h264(&pic); - - /*int i; - printf("Decode data: \n"); - for(i = 0; i < ((vdp_buffer.bitstream_bytes < 20) ? vdp_buffer.bitstream_bytes : 20); i++) { - printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); - if((i+1) % 10 == 0) - printf("\n"); - } - printf("\n...\n"); - for(i = vdp_buffer.bitstream_bytes - 20; i < vdp_buffer.bitstream_bytes; i++) { - printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); - if((i+1) % 10 == 0) - printf("\n"); - }*/ - - - if(img == NULL) { - img = this->stream->video_out->get_frame (this->stream->video_out, - this->width, this->height, - this->ratio, - XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); - this->vdpau_accel = (vdpau_accel_t*)img->accel_data; - - img->duration = this->video_step; - img->pts = this->curr_pts; - - this->dangling_img = img; - } - - if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) { - printf("VDPAU was preempted. Reinitialise the decoder.\n"); - this->decoder_initialized = 0; - this->decoder_started = 0; - this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; - this->last_img = NULL; - this->last_ref_pic = NULL; - dpb_free_all(&this->nal_parser->dpb); - free_parser(this->nal_parser); - this->nal_parser = init_parser(); - if(img) { - img->free(img); - img = NULL; - } - continue; - } - - VdpVideoSurface surface = this->vdpau_accel->surface; - - //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->curr_pts); - VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, - surface, (VdpPictureInfo*)&pic, 1, &vdp_buffer); - - // FIXME: do we really hit all cases here? - if(((uint8_t*)vdp_buffer.bitstream) != NULL) { - free((uint8_t*)vdp_buffer.bitstream); - } - - this->curr_pts = this->next_pts; - this->next_pts = 0; - - if(status != VDP_STATUS_OK) - { - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); - img->free(img); - img = this->last_img = this->dangling_img = NULL; - } - else { - img->bad_frame = 0; - - if((sps->vui_parameters_present_flag && - sps->vui_parameters.pic_struct_present_flag && - !this->nal_parser->current_nal->interlaced) || - !pic.field_pic_flag && !pic.mb_adaptive_frame_field_flag) - img->progressive_frame = 1; - else - img->progressive_frame = 0; - - if(!img->progressive_frame && this->nal_parser->current_nal->repeat_pic) - img->repeat_first_field = 1; - else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic) - img->duration *= this->nal_parser->current_nal->repeat_pic; - - struct decoded_picture *decoded_pic = NULL; - if(pic.is_reference) { - if(!slc->field_pic_flag || !this->wait_for_bottom_field) { - decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); - this->last_ref_pic = decoded_pic; - decoded_pic->used_for_reference = 1; - dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); - this->dangling_img = NULL; - } else if(slc->field_pic_flag && this->wait_for_bottom_field) { - if(this->last_ref_pic) { - decoded_pic = this->last_ref_pic; - //copy_nal_unit(decoded_pic->nal, this->nal_parser->current_nal); - decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; - this->last_ref_pic->bottom_is_reference = 1; - } - } - } - - if(!slc->field_pic_flag || - (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { - if(!decoded_pic) { - decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); - decoded_pic->delayed_output = 1; - dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); - this->dangling_img = NULL; - if(decoded_pic->nal->slc->bottom_field_flag) - decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; - } else - decoded_pic->delayed_output = 1; - - if(this->wait_for_bottom_field && slc->bottom_field_flag) - decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; - - this->last_img = img = NULL; - - /* now retrieve the next output frame */ - if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb))) != NULL) { - decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); - decoded_pic->img->draw(decoded_pic->img, this->stream); - dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); - } - - this->wait_for_bottom_field = 0; - - } else if(slc->field_pic_flag && !slc->bottom_field_flag) { - // don't draw yet, second field is missing. - this->last_top_field_order_cnt = this->nal_parser->current_nal->top_field_order_cnt; - this->wait_for_bottom_field = 1; - this->last_img = img; - } - } - } - } - } + if(this->decoder != VDP_INVALID_HANDLE && + vdp_buffer.bitstream_bytes > 0 && + this->nal_parser->current_nal->slc != NULL && + this->nal_parser->current_nal->sps != NULL && + this->nal_parser->current_nal->pps != NULL) { + vdpau_decoder_render(this_gen, &vdp_buffer, slice_count); } } + } /* @@ -586,13 +605,13 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { dpb_free_all( &(this->nal_parser->dpb) ); - if (this->decoder_initialized) + if (this->decoder != VDP_INVALID_HANDLE) { this->vdpau_accel->vdp_decoder_destroy( this->decoder ); + this->decoder = VDP_INVALID_HANDLE; + } free_parser(this->nal_parser); - this->decoder_started = 0; - this->decoder_initialized = 0; this->nal_parser = init_parser(); this->buf = NULL; this->wait_for_bottom_field = 0; @@ -636,9 +655,9 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { dpb_free_all( &(this->nal_parser->dpb) ); - if (this->decoder_initialized) { + if (this->decoder != VDP_INVALID_HANDLE) { this->vdpau_accel->vdp_decoder_destroy( this->decoder ); - this->decoder_initialized = 0; + this->decoder = VDP_INVALID_HANDLE; } this->stream->video_out->close( this->stream->video_out, this->stream ); @@ -671,6 +690,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->xine = stream->xine; this->class = (vdpau_h264_class_t *) class_gen; + this->decoder = VDP_INVALID_HANDLE; this->vdp_runtime_nr = 1; this->nal_parser = init_parser(); -- cgit v1.2.3 From d5337f77900d89104a3a9cb5aba52b8199a71803 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 9 Jan 2009 18:49:24 +0000 Subject: Wait for reference-frame before starting decoder. --- src/libvdpau/vdpau_h264.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index db073fdaa..28fc3b109 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -66,6 +66,7 @@ typedef struct vdpau_h264_decoder_s { uint32_t last_top_field_order_cnt; VdpDecoder decoder; + int decoder_started; VdpDecoderProfile profile; vdpau_accel_t *vdpau_accel; @@ -370,6 +371,14 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; vo_frame_t *img = this->last_img; + VdpPictureInfoH264 pic; + fill_vdpau_pictureinfo_h264(this_gen, slice_count, &pic); + + if(!this->decoder_started && !pic.is_reference) + return; + + this->decoder_started = 1; + struct seq_parameter_set_rbsp *sps = this->nal_parser->current_nal->sps; struct slice_header *slc = this->nal_parser->current_nal->slc; @@ -387,8 +396,6 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v this->nal_parser->is_idr = 0; /* go and decode a frame */ - VdpPictureInfoH264 pic; - fill_vdpau_pictureinfo_h264(this_gen, slice_count, &pic); //dump_pictureinfo_h264(&pic); @@ -423,6 +430,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) { printf("VDPAU was preempted. Reinitialise the decoder.\n"); this->decoder = VDP_INVALID_HANDLE; + this->decoder_started = 0; this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; this->last_img = NULL; this->last_ref_pic = NULL; @@ -539,7 +547,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, VdpBitstreamBuffer vdp_buffer; vdp_buffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; - /* a video decoder does not care about this flag (?) */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; @@ -691,6 +698,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->class = (vdpau_h264_class_t *) class_gen; this->decoder = VDP_INVALID_HANDLE; + this->decoder_started = 0; this->vdp_runtime_nr = 1; this->nal_parser = init_parser(); -- cgit v1.2.3 From ed6e1b87e318408a8ad69a7c7769db7e31d7f164 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 10 Jan 2009 11:55:24 +0000 Subject: Fix some bugs. --- src/libvdpau/vdpau_h264.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 28fc3b109..daf10939c 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -83,6 +83,8 @@ typedef struct vdpau_h264_decoder_s { } vdpau_h264_decoder_t; +static void vdpau_h264_reset (video_decoder_t *this_gen); + /************************************************************************** * vdpau_h264 specific decode functions *************************************************************************/ @@ -429,18 +431,9 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) { printf("VDPAU was preempted. Reinitialise the decoder.\n"); - this->decoder = VDP_INVALID_HANDLE; - this->decoder_started = 0; + vdpau_h264_reset(this_gen); this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; this->last_img = NULL; - this->last_ref_pic = NULL; - dpb_free_all(&this->nal_parser->dpb); - free_parser(this->nal_parser); - this->nal_parser = init_parser(); - if(img) { - img->free(img); - img = NULL; - } return 0; } @@ -698,7 +691,6 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->class = (vdpau_h264_class_t *) class_gen; this->decoder = VDP_INVALID_HANDLE; - this->decoder_started = 0; this->vdp_runtime_nr = 1; this->nal_parser = init_parser(); -- cgit v1.2.3 From 75c08203eda48da5adce7f26f507ecf033714ea6 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 10 Jan 2009 11:59:22 +0000 Subject: Remove debug output. --- src/libvdpau/h264_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index dff73f235..fcec0b92e 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1139,7 +1139,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->last_nal_res = parse_nal(prebuf+3, parser->prebuf_len-3, parser); if (parser->last_nal_res == 1 && parser->buf_len > 0) { - printf("Frame complete: %d bytes\n", parser->buf_len); + //printf("Frame complete: %d bytes\n", parser->buf_len); *ret_buf = malloc(parser->buf_len); xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); *ret_len = parser->buf_len; -- cgit v1.2.3 From 25ee70c59a4a67b5cf30f480ad06209486b1ac81 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 10 Jan 2009 13:01:06 +0000 Subject: Fix weird field_order_cnt encoding seen for example on Sky HD. --- src/libvdpau/dpb.c | 2 ++ src/libvdpau/nal.h | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 4236909db..f83a5d2da 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -65,6 +65,8 @@ struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) (outpic == NULL || (pic->nal->top_field_order_cnt <= outpic->nal->top_field_order_cnt && pic->nal->bottom_field_order_cnt <= outpic->nal->bottom_field_order_cnt)|| + (outpic->nal->top_field_order_cnt < 0 && pic->nal->top_field_order_cnt > 0 && + outpic->nal->bottom_field_order_cnt < 0 && pic->nal->bottom_field_order_cnt > 0)|| outpic->nal->nal_unit_type == NAL_SLICE_IDR)) outpic = pic; } while ((pic = pic->next) != NULL); diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index 2fbbeff97..ee5a4bb05 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -418,8 +418,8 @@ struct nal_unit uint32_t long_term_pic_num; uint32_t long_term_frame_idx; - uint32_t top_field_order_cnt; - uint32_t bottom_field_order_cnt; + int32_t top_field_order_cnt; + int32_t bottom_field_order_cnt; uint8_t interlaced; uint8_t repeat_pic; -- cgit v1.2.3 From fdb2d00cb4a636a21fbb87688b83246b8c468a7f Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 10 Jan 2009 13:59:41 +0000 Subject: Fix a pts error on the first decoded img. --- src/libvdpau/vdpau_h264.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index daf10939c..7064f7799 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -345,27 +345,30 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) this->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS); - this->vdpau_accel = (vdpau_accel_t*)img->accel_data; - - /*VdpBool is_supported; - uint32_t max_level, max_references, max_width, max_height;*/ - if(this->vdpau_accel->vdp_runtime_nr > 0) { - xprintf(this->xine, XINE_VERBOSITY_LOG, - "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n", - this->vdpau_accel->vdp_device, this->profile, this->width, this->height); - - VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, - this->profile, this->width, this->height, 16, &this->decoder); - - if(status != VDP_STATUS_OK) { - xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status)); - return 0; - } + img->duration = this->video_step; + img->pts = this->curr_pts; + + this->vdpau_accel = (vdpau_accel_t*)img->accel_data; + + /*VdpBool is_supported; + uint32_t max_level, max_references, max_width, max_height;*/ + if(this->vdpau_accel->vdp_runtime_nr > 0) { + xprintf(this->xine, XINE_VERBOSITY_LOG, + "Create decoder: vdp_device: %d, profile: %d, res: %dx%d\n", + this->vdpau_accel->vdp_device, this->profile, this->width, this->height); + + VdpStatus status = this->vdpau_accel->vdp_decoder_create(this->vdpau_accel->vdp_device, + this->profile, this->width, this->height, 16, &this->decoder); + + if(status != VDP_STATUS_OK) { + xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: ERROR: VdpDecoderCreate returned status != OK (%s)\n", this->vdpau_accel->vdp_get_error_string(status)); + return 0; } - this->last_img = img; - this->dangling_img = img; + } + this->last_img = img; + this->dangling_img = img; - return 1; + return 1; } static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count) -- cgit v1.2.3 From a1ff25f8d2cf49ab7dc694968980d1ce9e00c999 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 10 Jan 2009 14:41:55 +0000 Subject: Some fixes. --- src/libvdpau/vdpau_mpeg12.c | 1 + src/video_out/video_out_vdpau.c | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 819796d0f..4f9a692a5 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -640,6 +640,7 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) pic->vdp_infos.picture_structure=PICTURE_FRAME; if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME && !pic->slices_count2 ) { + /* waiting second field */ lprintf("********************* no slices_count2 **********************\n"); return; } diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index de305d05e..8ff418b4b 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -831,6 +831,14 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ frame->chunk[2] = NULL; } + if ( frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr ) { + frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; + frame->vdpau_accel_data.vdp_runtime_nr = this->vdp_runtime_nr; + frame->vdpau_accel_data.vdp_device = vdp_device; + frame->vo_frame.proc_duplicate_frame_data = NULL; + frame->vo_frame.proc_provide_standard_frame_data = NULL; + } + if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) { if ( (frame->width != width) || (frame->height != height) || (format != XINE_IMGFMT_VDPAU) || frame->vdpau_accel_data.chroma != chroma ) { printf("vo_vdpau: update_frame - destroy surface\n"); @@ -842,12 +850,6 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ } } - if ( frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr ) { - frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; - frame->vdpau_accel_data.vdp_runtime_nr = this->vdp_runtime_nr; - frame->vdpau_accel_data.vdp_device = vdp_device; - } - if ( (format == XINE_IMGFMT_VDPAU) && (frame->vdpau_accel_data.surface == VDP_INVALID_HANDLE) ) { VdpStatus st = vdp_video_surface_create( vdp_device, chroma, width, height, &frame->vdpau_accel_data.surface ); if ( st!=VDP_STATUS_OK ) @@ -945,6 +947,8 @@ static void vdpau_set_deinterlace( vo_driver_t *this_gen ) printf("vo_vdpau: enabled features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); } + + static void vdpau_set_inverse_telecine( vo_driver_t *this_gen ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -961,6 +965,8 @@ static void vdpau_set_inverse_telecine( vo_driver_t *this_gen ) printf("vo_vdpau: enabled features: inverse_telecine=%d\n", feature_enables[0] ); } + + static void vdpau_update_deinterlace_method( void *this_gen, xine_cfg_entry_t *entry ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -970,6 +976,8 @@ static void vdpau_update_deinterlace_method( void *this_gen, xine_cfg_entry_t *e vdpau_set_deinterlace( (vo_driver_t*)this_gen ); } + + static void vdpau_update_enable_inverse_telecine( void *this_gen, xine_cfg_entry_t *entry ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -979,6 +987,8 @@ static void vdpau_update_enable_inverse_telecine( void *this_gen, xine_cfg_entry vdpau_set_inverse_telecine( (vo_driver_t*)this_gen ); } + + static void vdpau_honor_progressive_flag( void *this_gen, xine_cfg_entry_t *entry ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -1153,8 +1163,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->video_mixer_width = mix_w; this->video_mixer_height = mix_h; vdpau_set_deinterlace( this_gen ); + vdpau_set_inverse_telecine( this_gen ); vdpau_update_noise( this ); vdpau_update_sharpness( this ); + vdpau_update_csc( this ); } if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { @@ -1525,6 +1537,8 @@ static int vdpau_init_error( VdpStatus st, const char *msg, vo_driver_t *driver, return 0; } + + static void vdpau_reinit( vo_driver_t *this_gen ) { printf("VDPAU was pre-empted. Reinit.\n"); @@ -1594,6 +1608,8 @@ static void vdpau_reinit( vo_driver_t *this_gen ) this->reinit_needed = 0; } + + static void vdp_preemption_callback(VdpDevice device, void *context) { printf("VDPAU preemption callback\n"); @@ -1601,6 +1617,8 @@ static void vdp_preemption_callback(VdpDevice device, void *context) this->reinit_needed = 1; } + + static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { vdpau_class_t *class = (vdpau_class_t *) class_gen; @@ -1872,7 +1890,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo 10, vdpau_update_deinterlace_method, this ); this->enable_inverse_telecine = config->register_bool( config, "video.output.vdpau_enable_inverse_telecine", 1, - _("vdpau: Try to recreatea progressive frames pulldown material"), + _("vdpau: Try to recreate progressive frames from pulldown material"), _("Enable this to detect bad-flagged progressive content to which\n" "a 2:2 or 3:2 pulldown was applied.\n\n"), 10, vdpau_update_enable_inverse_telecine, this ); -- cgit v1.2.3 From d24d9d256f20e7aadf30aca14d017c300caa0981 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 12 Jan 2009 11:54:41 +0000 Subject: Fix a possible crash. --- src/libvdpau/dpb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index f83a5d2da..cd3c6ef9a 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -260,7 +260,7 @@ int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum) int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames) { int i = 0; - struct decoded_picture *last_pic; + struct decoded_picture *last_pic = dpb->pictures; pic->next = dpb->pictures; dpb->pictures = pic; @@ -273,10 +273,15 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r i++; if(i>num_ref_frames) { pic->used_for_reference = 0; + if(pic == dpb->pictures) + last_pic = pic->next; + if(!pic->delayed_output) { dpb_remove_picture(dpb, pic); } pic = last_pic; + if(pic == dpb->pictures) + continue; } last_pic = pic; } -- cgit v1.2.3 From b28ebf65cb4b615d658e5ff5f1cac68e01459bce Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 13 Jan 2009 19:40:28 +0000 Subject: MKV support. --- src/libvdpau/h264_parser.c | 122 +++++++++++++++++++++++++++++++++++++++------ src/libvdpau/h264_parser.h | 7 ++- src/libvdpau/nal.c | 9 ++-- src/libvdpau/vdpau_h264.c | 92 ++++++++++++++++++++-------------- 4 files changed, 173 insertions(+), 57 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index fcec0b92e..d7e4940ae 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1073,6 +1073,7 @@ struct nal_parser* init_parser() parser->nal1 = init_nal_unit(); parser->current_nal = parser->nal0; parser->last_nal = parser->nal1; + parser->slice_cnt = 1; parser->field = -1; @@ -1091,21 +1092,81 @@ void free_parser(struct nal_parser *parser) free(parser); } -void parse_prebuf() +void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len) { + struct buf_reader bufr; + + bufr.buf = inbuf; + bufr.cur_pos = inbuf; + bufr.cur_offset = 8; + bufr.len = inbuf_len; + + struct nal_unit *nal = parser->current_nal; + struct nal_unit *nal1 = parser->last_nal; + + if (!nal->sps) + nal->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); + else + memset(nal->sps, 0x00, sizeof(struct seq_parameter_set_rbsp)); + + /* reserved */ + read_bits(&bufr, 8); + nal->sps->profile_idc = read_bits(&bufr, 8); + read_bits(&bufr, 8); + nal->sps->level_idc = read_bits(&bufr, 8); + read_bits(&bufr, 6); + + parser->nal_size_length = read_bits(&bufr, 2) + 1; + read_bits(&bufr, 3); + uint8_t sps_count = read_bits(&bufr, 5); + + inbuf += 6; + inbuf_len -= 6; + int i; + for(i = 0; i < sps_count; i++) { + uint16_t sps_size = read_bits(&bufr, 16); + inbuf += 2; + inbuf_len -= 2; + parse_nal(inbuf, sps_size, parser); + inbuf += sps_size; + inbuf_len -= sps_size; + } + + bufr.buf = inbuf; + bufr.cur_pos = inbuf; + bufr.cur_offset = 8; + bufr.len = inbuf_len; + + uint8_t pps_count = read_bits(&bufr, 8); + inbuf += 1; + for(i = 0; i < pps_count; i++) { + uint16_t pps_size = read_bits(&bufr, 16); + inbuf += 2; + inbuf_len -= 2; + parse_nal(inbuf, pps_size, parser); + inbuf += pps_size; + inbuf_len -= pps_size; + } + copy_nal_unit(nal1, nal); + printf("done parsing extradata\n"); } + int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) { int32_t next_nal = 0; int parsed_len = 0; int search_offset = 0; + int start_seq_len = 3; uint8_t completed_nal = 0; uint8_t *prebuf = parser->prebuf; + if(parser->nal_size_length > 0) + start_seq_len = 4; + if(parser->last_nal_res == 1 && parser->current_nal && parser->current_nal->slc) { int i; @@ -1117,8 +1178,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser); } } - - while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset)) >= 0) { + while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset, parser)) >= 0) { next_nal += search_offset; if(parser->incomplete_nal || completed_nal || next_nal == 0) { @@ -1137,12 +1197,16 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parsed_len += next_nal; inbuf += next_nal; - parser->last_nal_res = parse_nal(prebuf+3, parser->prebuf_len-3, parser); + parser->last_nal_res = parse_nal(prebuf+start_seq_len, parser->prebuf_len-start_seq_len, parser); if (parser->last_nal_res == 1 && parser->buf_len > 0) { - //printf("Frame complete: %d bytes\n", parser->buf_len); - *ret_buf = malloc(parser->buf_len); - xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); - *ret_len = parser->buf_len; + int offset = 0; + if(parser->nal_size_length > 0) + offset = start_seq_len; + + //printf("Frame complete: %d bytes\n", parser->buf_len-offset); + *ret_len = parser->buf_len-offset; + *ret_buf = malloc(*ret_len); + xine_fast_memcpy(*ret_buf, parser->buf+offset, *ret_len); *ret_slice_cnt = parser->slice_cnt; //memset(parser->buf, 0x00, parser->buf_len); @@ -1193,8 +1257,8 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, inbuf += next_nal; } - - search_offset = 3; + if(!parser->nal_size_length) + search_offset = start_seq_len; } /* if inbuf does not end with the start of a new nal @@ -1218,11 +1282,11 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, * this might happen if the nal start sequence is split * over the buf-boundary - if this is the case we */ - if(parsed_len > 2 && - (next_nal = seek_for_nal(prebuf+3, parser->prebuf_len)) >= 0) { - inbuf -= parser->prebuf_len-next_nal-3; - parsed_len -= parser->prebuf_len-next_nal-3; - parser->prebuf_len = next_nal+3; + if(!parser->nal_size_length && parsed_len > 2 && + (next_nal = seek_for_nal(prebuf+start_seq_len, parser->prebuf_len, parser)) >= 0) { + inbuf -= parser->prebuf_len-next_nal-start_seq_len; + parsed_len -= parser->prebuf_len-next_nal-start_seq_len; + parser->prebuf_len = next_nal+start_seq_len; } } @@ -1361,8 +1425,34 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) return 0; } -int seek_for_nal(uint8_t *buf, int buf_len) +int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { + if(parser->nal_size_length > 0) { + + if(buf_len <= 0) + return -1; + + int next_nal = parser->next_nal_position; + if(!next_nal) { + struct buf_reader bufr; + + bufr.buf = buf; + bufr.cur_pos = buf; + bufr.cur_offset = 8; + bufr.len = buf_len; + + next_nal = read_bits(&bufr, parser->nal_size_length*8)+4; + } + + if(next_nal > buf_len) { + parser->next_nal_position = next_nal-buf_len; + return -1; + } else + parser->next_nal_position = 0; + + return next_nal; + } + int i; for (i = 0; i < buf_len - 2; i++) { if (buf[i] == 0x00 && buf[i + 1] == 0x00 && buf[i + 2] == 0x01) { diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index e40a9b985..bb9e12f79 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -55,6 +55,9 @@ struct nal_parser { uint8_t have_top; uint8_t have_frame; + uint8_t nal_size_length; + uint32_t next_nal_size; + struct nal_unit *nal0; struct nal_unit *nal1; struct nal_unit *current_nal; @@ -75,11 +78,13 @@ struct nal_parser { int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); -int seek_for_nal(uint8_t *buf, int buf_len); +int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser); struct nal_parser* init_parser(); void free_parser(struct nal_parser *parser); int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt); +void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len); + #endif diff --git a/src/libvdpau/nal.c b/src/libvdpau/nal.c index eaa32c700..541699dbd 100644 --- a/src/libvdpau/nal.c +++ b/src/libvdpau/nal.c @@ -66,7 +66,10 @@ void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src) if(!dest->slc) dest->slc = malloc(sizeof(struct slice_header)); - xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp)); - xine_fast_memcpy(dest->pps, src->pps, sizeof(struct pic_parameter_set_rbsp)); - xine_fast_memcpy(dest->slc, src->slc, sizeof(struct slice_header)); + if(src->sps) + xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp)); + if(src->pps) + xine_fast_memcpy(dest->pps, src->pps, sizeof(struct pic_parameter_set_rbsp)); + if(src->slc) + xine_fast_memcpy(dest->slc, src->slc, sizeof(struct slice_header)); } diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 7064f7799..971876abd 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -371,16 +371,17 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) return 1; } -static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count) +static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count, int use_vdp_buffers) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; vo_frame_t *img = this->last_img; VdpPictureInfoH264 pic; + fill_vdpau_pictureinfo_h264(this_gen, slice_count, &pic); if(!this->decoder_started && !pic.is_reference) - return; + return 0; this->decoder_started = 1; @@ -406,14 +407,14 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v /*int i; printf("Decode data: \n"); - for(i = 0; i < ((vdp_buffer.bitstream_bytes < 20) ? vdp_buffer.bitstream_bytes : 20); i++) { - printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); + for(i = 0; i < ((vdp_buffer[use_vdp_buffers-1].bitstream_bytes < 20) ? vdp_buffer[use_vdp_buffers-1].bitstream_bytes : 20); i++) { + printf("%02x ", ((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream)[i]); if((i+1) % 10 == 0) printf("\n"); } printf("\n...\n"); - for(i = vdp_buffer.bitstream_bytes - 20; i < vdp_buffer.bitstream_bytes; i++) { - printf("%02x ", ((uint8_t*)vdp_buffer.bitstream)[i]); + for(i = vdp_buffer[use_vdp_buffers-1].bitstream_bytes - 20; i < vdp_buffer[use_vdp_buffers-1].bitstream_bytes; i++) { + printf("%02x ", ((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream)[i]); if((i+1) % 10 == 0) printf("\n"); }*/ @@ -444,11 +445,12 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->curr_pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, - surface, (VdpPictureInfo*)&pic, 1, vdp_buffer); + surface, (VdpPictureInfo*)&pic, use_vdp_buffers, vdp_buffer); - // FIXME: do we really hit all cases here? - if(((uint8_t*)vdp_buffer->bitstream) != NULL) { - free((uint8_t*)vdp_buffer->bitstream); + /* only free the actual data, as the start seq is only + * locally allocated anyway. */ + if(((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream) != NULL) { + free((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream); } this->curr_pts = this->next_pts; @@ -540,8 +542,16 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; - VdpBitstreamBuffer vdp_buffer; - vdp_buffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; + VdpBitstreamBuffer vdp_buffer[2]; + uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + vdp_buffer[0].struct_version = vdp_buffer[1].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + int use_vdp_buffers = 1; + + if(this->nal_parser->nal_size_length > 0) { + vdp_buffer[0].bitstream_bytes = 3; + vdp_buffer[0].bitstream = start_seq; + use_vdp_buffers = 2; + } /* a video decoder does not care about this flag (?) */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) @@ -557,37 +567,40 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->width = bih->biWidth; this->height = bih->biHeight; - } + uint8_t *codec_private = buf->content + sizeof(xine_bmiheader); + uint32_t codec_private_len = bih->biSize - sizeof(xine_bmiheader); - /* parse the first nal packages to retrieve profile type */ - int len = 0; - uint32_t slice_count; + parse_codec_private(this->nal_parser, codec_private, codec_private_len); + } else { + /* parse the first nal packages to retrieve profile type */ + int len = 0; + uint32_t slice_count; - if(buf->pts != 0) - this->next_pts = buf->pts; + if(buf->pts != 0) + this->next_pts = buf->pts; - while(len < buf->size) { - len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, - (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); + while(len < buf->size) { + len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, + (void*)&vdp_buffer[use_vdp_buffers-1].bitstream, &vdp_buffer[use_vdp_buffers-1].bitstream_bytes, &slice_count); - if(this->decoder == VDP_INVALID_HANDLE && - this->nal_parser->current_nal->sps != NULL && - this->nal_parser->current_nal->sps->pic_width > 0 && - this->nal_parser->current_nal->sps->pic_height > 0) { + if(this->decoder == VDP_INVALID_HANDLE && + this->nal_parser->current_nal->sps != NULL && + this->nal_parser->current_nal->sps->pic_width > 0 && + this->nal_parser->current_nal->sps->pic_height > 0) { - vdpau_decoder_init(this_gen); - } + vdpau_decoder_init(this_gen); + } - if(this->decoder != VDP_INVALID_HANDLE && - vdp_buffer.bitstream_bytes > 0 && - this->nal_parser->current_nal->slc != NULL && - this->nal_parser->current_nal->sps != NULL && - this->nal_parser->current_nal->pps != NULL) { - vdpau_decoder_render(this_gen, &vdp_buffer, slice_count); - } + if(this->decoder != VDP_INVALID_HANDLE && + vdp_buffer[use_vdp_buffers-1].bitstream_bytes > 0 && + this->nal_parser->current_nal->slc != NULL && + this->nal_parser->current_nal->sps != NULL && + this->nal_parser->current_nal->pps != NULL) { + vdpau_decoder_render(this_gen, vdp_buffer, slice_count, use_vdp_buffers); + } + } } - } /* @@ -613,9 +626,14 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->decoder = VDP_INVALID_HANDLE; } - free_parser(this->nal_parser); + /* only reset the parser for continous streams + * like ts or pes + */ + if(!this->nal_parser->nal_size_length) { + free_parser(this->nal_parser); + this->nal_parser = init_parser(); + } - this->nal_parser = init_parser(); this->buf = NULL; this->wait_for_bottom_field = 0; this->video_step = 0; -- cgit v1.2.3 From 64d1fe71f41003895869a246fdaa8817ec6f0a9b Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 14 Jan 2009 05:30:33 +0000 Subject: Fix quant_extension_matrix. --- src/libvdpau/h264_parser.c | 2 +- src/libvdpau/vdpau_mpeg12.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index d7e4940ae..6187ef8c0 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -967,7 +967,7 @@ void decode_ref_pic_marking(struct nal_unit *nal, printf("FIXME: B Set frame %d to long-term ref\n", pic_num_x); } else { - printf("memory_management_control_operation: 3 failed. No such picture."); + printf("memory_management_control_operation: 3 failed. No such picture.\n"); } } diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 4f9a692a5..c18b35510 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -441,7 +441,7 @@ static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int le static void quant_matrix_extension( sequence_t *sequence, uint8_t *buf, int len ) { - int i, j, off; + int i, j, off=0; i = get_bits( buf,4,1 ); lprintf( "load_intra_quantizer_matrix: %d\n", i ); -- cgit v1.2.3 From 45c28e591edaa45100abe73f2938645b492fe676 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 14 Jan 2009 05:31:53 +0000 Subject: Cleanups. --- src/video_out/video_out_vdpau.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 8ff418b4b..6001fb0da 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -460,6 +460,7 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) } + static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -473,6 +474,7 @@ static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, i } + static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -493,6 +495,7 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v } + static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -599,6 +602,7 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) } + static void vdpau_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { vdpau_frame_t *frame = (vdpau_frame_t *) vo_img ; @@ -1005,14 +1009,14 @@ static void vdpau_update_noise( vdpau_driver_t *this_gen ) VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; VdpBool feature_enables[] = { 0 }; vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); - printf( "vo_vdpau: disable noise reduction !!\n" ); + printf( "vo_vdpau: disable noise reduction.\n" ); return; } else { VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; VdpBool feature_enables[] = { 1 }; vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); - printf( "vo_vdpau: enable noise reduction !!\n" ); + printf( "vo_vdpau: enable noise reduction.\n" ); } VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL }; @@ -1031,14 +1035,14 @@ static void vdpau_update_sharpness( vdpau_driver_t *this_gen ) VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS }; VdpBool feature_enables[] = { 0 }; vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); - printf( "vo_vdpau: disable sharpness !!\n" ); + printf( "vo_vdpau: disable sharpness.\n" ); return; } else { VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS }; VdpBool feature_enables[] = { 1 }; vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables ); - printf( "vo_vdpau: enable sharpness !!\n" ); + printf( "vo_vdpau: enable sharpness.\n" ); } VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL }; @@ -1819,11 +1823,11 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER, (void*)&vdp_preemption_callback_register ); if ( vdpau_init_error( st, "Can't get PREEMPTION_CALLBACK_REGISTER proc address !!", &this->vo_driver, 1 ) ) - return NULL; + return NULL; st = vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this); if ( vdpau_init_error( st, "Can't register preemption callback !!", &this->vo_driver, 1 ) ) - return NULL; + return NULL; st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) ) @@ -1832,10 +1836,10 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if ( vdpau_init_error( st, "Can't create presentation queue !!", &this->vo_driver, 1 ) ) return NULL; - /* choose almost magenta as backcolor for color keying */ - this->back_color.red = 0.02;//0.98; - this->back_color.green = 0.01;//0.01; - this->back_color.blue = 0.03;//0.99; + /* choose almost black as backcolor for color keying */ + this->back_color.red = 0.02; + this->back_color.green = 0.01; + this->back_color.blue = 0.03; this->back_color.alpha = 1; vdp_queue_set_background_color( vdp_queue, &this->back_color ); -- cgit v1.2.3 From 0438996eb92b438affca59c2418498f6d5a558c5 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Wed, 14 Jan 2009 09:42:56 +0000 Subject: Fix parsing of rbsp_trailing_bits. --- src/libvdpau/h264_parser.c | 50 +++++++++++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 6187ef8c0..568901829 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -111,6 +111,15 @@ static inline void dump_bits(uint32_t bits) printf("\n"); } +static inline uint32_t bits_read(struct buf_reader *buf) +{ + int bits_read = 0; + bits_read = (buf->cur_pos - buf->buf)*8; + bits_read += (8-buf->cur_offset); + + return bits_read; +} + static inline uint32_t read_bits(struct buf_reader *buf, int len) { static uint32_t i_mask[33] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, @@ -145,29 +154,26 @@ static inline uint32_t read_bits(struct buf_reader *buf, int len) } /* determines if following bits are rtsb_trailing_bits */ -static inline uint8_t rbsp_trailing_bits(struct buf_reader *buf) +static inline int rbsp_trailing_bits(uint8_t *buf, int buf_len) { - // store the offset and pos in buffer - // to revert this afterwards. - int last_offset; - uint8_t *last_pos; - - uint8_t rbsp_trailing_bits = 1; - - last_offset = buf->cur_offset; - last_pos = buf->cur_pos; + uint8_t *cur_buf = buf+(buf_len-1); + uint8_t cur_val; + int parsed_bits = 0; + int i; - if (read_bits(buf, 1) == 1) { - while (buf->cur_offset != 8) - if (read_bits(buf, 1) == 1) - rbsp_trailing_bits = 0; + while(buf_len > 0) { + cur_val = *cur_buf; + for(i = 0; i < 9; i++) { + if (cur_val&1) + return parsed_bits+i; + cur_val>>=1; + } + parsed_bits += 8; + cur_buf--; } - // revert buffer - buf->cur_offset = last_offset; - buf->cur_pos = last_pos; - - return rbsp_trailing_bits; + printf("rbsp trailing bits could not be found\n"); + return 0; } uint32_t read_exp_golomb(struct buf_reader *buf) @@ -665,7 +671,11 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, pps->constrained_intra_pred_flag = read_bits(buf, 1); pps->redundant_pic_cnt_present_flag = read_bits(buf, 1); - if (!rbsp_trailing_bits(buf)) { + int bit_length = (buf->len*8)-rbsp_trailing_bits(buf->buf, buf->len); + int bit_read = bits_read(buf); + + if (bit_length-bit_read > 1) { + printf("Read transform 8x8\n"); pps->transform_8x8_mode_flag = read_bits(buf, 1); pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); if (pps->pic_scaling_matrix_present_flag) { -- cgit v1.2.3 From 6c6068d4b935c3eb90a3d3b8b94a3fc0bceaa607 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Wed, 14 Jan 2009 16:50:33 +0000 Subject: Rework slicing, so that it works for all containers. Supports at least ts,pes,mkv, mov, mp4 now. --- src/libvdpau/h264_parser.c | 105 ++++++++++++++++++++++++++++++++------------- src/libvdpau/h264_parser.h | 2 + src/libvdpau/nal.c | 6 +-- src/libvdpau/vdpau_h264.c | 62 +++++++++++++------------- 4 files changed, 110 insertions(+), 65 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 568901829..abd4c329d 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -70,7 +70,8 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, void parse_sei(struct buf_reader *buf, struct nal_parser *parser); uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser); void - parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal); + parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal, + struct nal_parser *parser); void decode_ref_pic_marking(struct nal_unit *nal, uint32_t memory_management_control_operation, uint32_t marking_nr, @@ -722,6 +723,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) slc->first_mb_in_slice = read_exp_golomb(buf); /* we do some parsing on the slice type, because the list is doubled */ slc->slice_type = slice_type(read_exp_golomb(buf)); + //print_slice_type(slc->slice_type); slc->pic_parameter_set_id = read_exp_golomb(buf); slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); @@ -778,7 +780,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) } /* --- ref_pic_list_reordering --- */ - parse_ref_pic_list_reordering(buf, nal); + parse_ref_pic_list_reordering(buf, nal, parser); /* --- pred_weight_table --- */ if ((pps->weighted_pred_flag && (slc->slice_type == SLICE_P @@ -796,7 +798,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) return 0; } -void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal) +void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal, struct nal_parser *parser) { struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; @@ -1127,6 +1129,7 @@ void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_le read_bits(&bufr, 6); parser->nal_size_length = read_bits(&bufr, 2) + 1; + parser->nal_size_length_buf = calloc(1, parser->nal_size_length); read_bits(&bufr, 3); uint8_t sps_count = read_bits(&bufr, 5); @@ -1175,7 +1178,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t *prebuf = parser->prebuf; if(parser->nal_size_length > 0) - start_seq_len = 4; + start_seq_len = 4-parser->have_nal_size_length_buf; if(parser->last_nal_res == 1 && parser->current_nal && parser->current_nal->slc) { @@ -1188,10 +1191,14 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser); } } + while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset, parser)) >= 0) { next_nal += search_offset; + if(parser->nal_size_length > 0) + start_seq_len = 4-parser->have_nal_size_length_buf; - if(parser->incomplete_nal || completed_nal || next_nal == 0) { + if(parser->incomplete_nal || completed_nal || next_nal == 0 || + parser->nal_size_length) { if (parser->prebuf_len + next_nal > MAX_FRAME_SIZE) { printf("buf underrun!!\n"); @@ -1209,25 +1216,29 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->last_nal_res = parse_nal(prebuf+start_seq_len, parser->prebuf_len-start_seq_len, parser); if (parser->last_nal_res == 1 && parser->buf_len > 0) { - int offset = 0; - if(parser->nal_size_length > 0) - offset = start_seq_len; - //printf("Frame complete: %d bytes\n", parser->buf_len-offset); - *ret_len = parser->buf_len-offset; + //printf("Frame complete: %d bytes\n", parser->buf_len); + *ret_len = parser->buf_len; *ret_buf = malloc(*ret_len); - xine_fast_memcpy(*ret_buf, parser->buf+offset, *ret_len); + xine_fast_memcpy(*ret_buf, parser->buf, *ret_len); *ret_slice_cnt = parser->slice_cnt; - //memset(parser->buf, 0x00, parser->buf_len); - parser->buf_len = 0; - parser->last_nal_res = 1; parser->slice_cnt = 1; + parser->buf_len = 0; /* this is a SLICE, keep it in the buffer */ //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); - xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); - parser->buf_len += parser->prebuf_len; + if(parser->nal_size_length > 0) { + uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + xine_fast_memcpy(parser->buf, start_seq, 3); + parser->buf_len += 3; + } + + int offset = 0; + if(parser->nal_size_length > 0) + offset = start_seq_len; + xine_fast_memcpy(parser->buf+parser->buf_len, prebuf+offset, parser->prebuf_len-offset); + parser->buf_len += parser->prebuf_len-offset; parser->prebuf_len = 0; parser->incomplete_nal = 0; @@ -1242,7 +1253,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, if (parser->last_nal_res != 2) { if (parser->buf_len + parser->prebuf_len > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); + printf("buf underrun 1!!\n"); parser->buf_len = 0; *ret_len = 0; *ret_buf = NULL; @@ -1251,8 +1262,18 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); /* this is a SLICE, keep it in the buffer */ - xine_fast_memcpy(parser->buf + parser->buf_len, prebuf, parser->prebuf_len); - parser->buf_len += parser->prebuf_len; + if(parser->nal_size_length > 0) { + uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + xine_fast_memcpy(parser->buf + parser->buf_len, start_seq, 3); + parser->buf_len += 3; + } + + int offset = 0; + if(parser->nal_size_length > 0) + offset = start_seq_len; + + xine_fast_memcpy(parser->buf + parser->buf_len, prebuf+offset, parser->prebuf_len-offset); + parser->buf_len += (parser->prebuf_len-offset); } parser->prebuf_len = 0; @@ -1276,7 +1297,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, */ if(parsed_len < inbuf_len) { if (inbuf_len-parsed_len + parser->prebuf_len > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); + printf("buf underrun 0!!\n"); parser->prebuf_len = 0; *ret_len = 0; *ret_buf = NULL; @@ -1438,20 +1459,46 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { if(parser->nal_size_length > 0) { - - if(buf_len <= 0) + if(buf_len <= 0 || + (buf_len < parser->nal_size_length && + (parser->next_nal_position == 0 || + parser->next_nal_position > buf_len))) { + /* if we have less than nal_size_length bytes + * left in the buffer we need to store them, so + * that the next length calculation will be correct + */ + if(!parser->next_nal_position) { + memcpy(parser->nal_size_length_buf, buf, buf_len); + parser->have_nal_size_length_buf = buf_len; + } return -1; + } - int next_nal = parser->next_nal_position; + uint32_t next_nal = parser->next_nal_position; if(!next_nal) { - struct buf_reader bufr; + if(parser->have_nal_size_length_buf > 0) { + memcpy(parser->nal_size_length_buf+parser->have_nal_size_length_buf, buf, parser->nal_size_length-parser->have_nal_size_length_buf); + + struct buf_reader bufr; - bufr.buf = buf; - bufr.cur_pos = buf; - bufr.cur_offset = 8; - bufr.len = buf_len; + bufr.buf = parser->nal_size_length_buf; + bufr.cur_pos = parser->nal_size_length_buf; + bufr.cur_offset = 8; + bufr.len = parser->nal_size_length; - next_nal = read_bits(&bufr, parser->nal_size_length*8)+4; + next_nal = read_bits(&bufr, parser->nal_size_length*8)+4-parser->have_nal_size_length_buf; + + parser->have_nal_size_length_buf = 0; + } else { + struct buf_reader bufr; + + bufr.buf = buf; + bufr.cur_pos = buf; + bufr.cur_offset = 8; + bufr.len = buf_len; + + next_nal = read_bits(&bufr, parser->nal_size_length*8)+4; + } } if(next_nal > buf_len) { diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index bb9e12f79..c99c3cd80 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -57,6 +57,8 @@ struct nal_parser { uint8_t nal_size_length; uint32_t next_nal_size; + uint8_t *nal_size_length_buf; + uint8_t have_nal_size_length_buf; struct nal_unit *nal0; struct nal_unit *nal1; diff --git a/src/libvdpau/nal.c b/src/libvdpau/nal.c index 541699dbd..7e0cbdf7f 100644 --- a/src/libvdpau/nal.c +++ b/src/libvdpau/nal.c @@ -58,13 +58,13 @@ void copy_nal_unit(struct nal_unit *dest, struct nal_unit *src) xine_fast_memcpy(dest, src, size); if(!dest->sps) - dest->sps = malloc(sizeof(struct seq_parameter_set_rbsp)); + dest->sps = calloc(1, sizeof(struct seq_parameter_set_rbsp)); if(!dest->pps) - dest->pps = malloc(sizeof(struct pic_parameter_set_rbsp)); + dest->pps = calloc(1, sizeof(struct pic_parameter_set_rbsp)); if(!dest->slc) - dest->slc = malloc(sizeof(struct slice_header)); + dest->slc = calloc(1, sizeof(struct slice_header)); if(src->sps) xine_fast_memcpy(dest->sps, src->sps, sizeof(struct seq_parameter_set_rbsp)); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 971876abd..1124cfa31 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -51,10 +51,6 @@ typedef struct vdpau_h264_decoder_s { /* these are traditional variables in a video decoder object */ uint64_t video_step; /* frame duration in pts units */ - unsigned char *buf; /* the accumulated buffer data */ - int bufsize; /* the maximum size of buf */ - int size; /* the current size of buf */ - int width; /* the width of a video frame */ int height; /* the height of a video frame */ double ratio; /* the width to height ratio */ @@ -371,7 +367,7 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) return 1; } -static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count, int use_vdp_buffers) +static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *vdp_buffer, uint32_t slice_count) { vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; vo_frame_t *img = this->last_img; @@ -407,14 +403,14 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v /*int i; printf("Decode data: \n"); - for(i = 0; i < ((vdp_buffer[use_vdp_buffers-1].bitstream_bytes < 20) ? vdp_buffer[use_vdp_buffers-1].bitstream_bytes : 20); i++) { - printf("%02x ", ((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream)[i]); + for(i = 0; i < ((vdp_buffer->bitstream_bytes < 20) ? vdp_buffer->bitstream_bytes : 20); i++) { + printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]); if((i+1) % 10 == 0) printf("\n"); } printf("\n...\n"); - for(i = vdp_buffer[use_vdp_buffers-1].bitstream_bytes - 20; i < vdp_buffer[use_vdp_buffers-1].bitstream_bytes; i++) { - printf("%02x ", ((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream)[i]); + for(i = vdp_buffer->bitstream_bytes - 20; i < vdp_buffer->bitstream_bytes; i++) { + printf("%02x ", ((uint8_t*)vdp_buffer->bitstream)[i]); if((i+1) % 10 == 0) printf("\n"); }*/ @@ -435,6 +431,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(this->vdp_runtime_nr != *(this->vdpau_accel->current_vdp_runtime_nr)) { printf("VDPAU was preempted. Reinitialise the decoder.\n"); + this->decoder = VDP_INVALID_HANDLE; vdpau_h264_reset(this_gen); this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; this->last_img = NULL; @@ -445,12 +442,12 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->curr_pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, - surface, (VdpPictureInfo*)&pic, use_vdp_buffers, vdp_buffer); + surface, (VdpPictureInfo*)&pic, 1, vdp_buffer); /* only free the actual data, as the start seq is only * locally allocated anyway. */ - if(((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream) != NULL) { - free((uint8_t*)vdp_buffer[use_vdp_buffers-1].bitstream); + if(((uint8_t*)vdp_buffer->bitstream) != NULL) { + free((uint8_t*)vdp_buffer->bitstream); } this->curr_pts = this->next_pts; @@ -542,16 +539,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *) this_gen; - VdpBitstreamBuffer vdp_buffer[2]; - uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; - vdp_buffer[0].struct_version = vdp_buffer[1].struct_version = VDP_BITSTREAM_BUFFER_VERSION; - int use_vdp_buffers = 1; - - if(this->nal_parser->nal_size_length > 0) { - vdp_buffer[0].bitstream_bytes = 3; - vdp_buffer[0].bitstream = start_seq; - use_vdp_buffers = 2; - } + VdpBitstreamBuffer vdp_buffer; + vdp_buffer.struct_version = VDP_BITSTREAM_BUFFER_VERSION; /* a video decoder does not care about this flag (?) */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) @@ -570,7 +559,21 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, uint8_t *codec_private = buf->content + sizeof(xine_bmiheader); uint32_t codec_private_len = bih->biSize - sizeof(xine_bmiheader); - parse_codec_private(this->nal_parser, codec_private, codec_private_len); + if(codec_private_len > 0) { + parse_codec_private(this->nal_parser, codec_private, codec_private_len); + vdpau_decoder_init(this_gen); + } + } else if (buf->decoder_flags & BUF_FLAG_SPECIAL) { + if(buf->decoder_info[1] == BUF_SPECIAL_DECODER_CONFIG) { + uint8_t *codec_private = buf->decoder_info_ptr[2]; + uint32_t codec_private_len = buf->decoder_info[2]; + + if(codec_private_len > 0) { + parse_codec_private(this->nal_parser, codec_private, codec_private_len); + vdpau_decoder_init(this_gen); + } + } + } else { /* parse the first nal packages to retrieve profile type */ int len = 0; @@ -581,7 +584,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, while(len < buf->size) { len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, - (void*)&vdp_buffer[use_vdp_buffers-1].bitstream, &vdp_buffer[use_vdp_buffers-1].bitstream_bytes, &slice_count); + (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); if(this->decoder == VDP_INVALID_HANDLE && this->nal_parser->current_nal->sps != NULL && @@ -592,11 +595,11 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } if(this->decoder != VDP_INVALID_HANDLE && - vdp_buffer[use_vdp_buffers-1].bitstream_bytes > 0 && + vdp_buffer.bitstream_bytes > 0 && this->nal_parser->current_nal->slc != NULL && this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { - vdpau_decoder_render(this_gen, vdp_buffer, slice_count, use_vdp_buffers); + vdpau_decoder_render(this_gen, &vdp_buffer, slice_count); } } @@ -617,8 +620,6 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { printf("vdpau_h264_reset\n"); - this->size = 0; - dpb_free_all( &(this->nal_parser->dpb) ); if (this->decoder != VDP_INVALID_HANDLE) { @@ -634,7 +635,6 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->nal_parser = init_parser(); } - this->buf = NULL; this->wait_for_bottom_field = 0; this->video_step = 0; this->curr_pts = 0; @@ -669,10 +669,6 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { this->dangling_img = NULL; } - if (this->buf) { - free (this->buf); - this->buf = NULL; - } dpb_free_all( &(this->nal_parser->dpb) ); -- cgit v1.2.3 From 1daabdb304c4d9d24b9b2937479ec3e929b9ded8 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 15 Jan 2009 08:37:02 +0000 Subject: Reinit fixes. --- src/video_out/video_out_vdpau.c | 42 +++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 6001fb0da..4ed4354be 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1528,14 +1528,10 @@ static void vdpau_dispose (vo_driver_t *this_gen) -static int vdpau_init_error( VdpStatus st, const char *msg, vo_driver_t *driver, int error_string ) +static int vdpau_reinit_error( VdpStatus st, const char *msg ) { if ( st != VDP_STATUS_OK ) { - if ( error_string ) - printf( "vo_vdpau: %s : %s\n", msg, vdp_get_error_string( st ) ); - else - printf( "vo_vdpau: %s\n", msg ); - vdpau_dispose( driver ); + printf( "vo_vdpau: %s : %s\n", msg, vdp_get_error_string( st ) ); return 1; } return 0; @@ -1545,7 +1541,7 @@ static int vdpau_init_error( VdpStatus st, const char *msg, vo_driver_t *driver, static void vdpau_reinit( vo_driver_t *this_gen ) { - printf("VDPAU was pre-empted. Reinit.\n"); + printf("vo_vdpau: VDPAU was pre-empted. Reinit.\n"); vdpau_driver_t *this = (vdpau_driver_t *)this_gen; XLockDisplay(guarded_display); @@ -1559,32 +1555,31 @@ static void vdpau_reinit( vo_driver_t *this_gen ) printf( "No vdpau implementation.\n" ); else printf( "unsupported GPU?\n" ); - vdpau_dispose( &this->vo_driver ); return; } st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); - if ( vdpau_init_error( st, "Can't create presentation queue target !!", &this->vo_driver, 1 ) ) + if ( vdpau_reinit_error( st, "Can't create presentation queue target !!" ) ) return; st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); - if ( vdpau_init_error( st, "Can't create presentation queue !!", &this->vo_driver, 1 ) ) + if ( vdpau_reinit_error( st, "Can't create presentation queue !!" ) ) return; VdpChromaType chroma = VDP_CHROMA_TYPE_420; st = orig_vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); - if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) + if ( vdpau_reinit_error( st, "Can't create video surface !!" ) ) return; this->current_output_surface = 0; this->init_queue = 0; st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] ); - if ( vdpau_init_error( st, "Can't create first output surface !!", &this->vo_driver, 1 ) ) { + if ( vdpau_reinit_error( st, "Can't create first output surface !!" ) ) { orig_vdp_video_surface_destroy( this->soft_surface ); return; } st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[1] ); - if ( vdpau_init_error( st, "Can't create second output surface !!", &this->vo_driver, 1 ) ) { + if ( vdpau_reinit_error( st, "Can't create second output surface !!" ) ) { orig_vdp_video_surface_destroy( this->soft_surface ); vdp_output_surface_destroy( this->output_surface[0] ); return; @@ -1597,7 +1592,7 @@ static void vdpau_reinit( vo_driver_t *this_gen ) int num_layers = 3; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; st = vdp_video_mixer_create( vdp_device, 4, features, 4, params, param_values, &this->video_mixer ); - if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { + if ( vdpau_reinit_error( st, "Can't create video mixer !!" ) ) { orig_vdp_video_surface_destroy( this->soft_surface ); vdp_output_surface_destroy( this->output_surface[0] ); vdp_output_surface_destroy( this->output_surface[1] ); @@ -1607,7 +1602,7 @@ static void vdpau_reinit( vo_driver_t *this_gen ) vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this); XUnlockDisplay(guarded_display); - printf("Reinit done.\n"); + printf("vo_vdpau: Reinit done.\n"); this->vdp_runtime_nr++; this->reinit_needed = 0; } @@ -1616,13 +1611,28 @@ static void vdpau_reinit( vo_driver_t *this_gen ) static void vdp_preemption_callback(VdpDevice device, void *context) { - printf("VDPAU preemption callback\n"); + printf("vo_vdpau: VDPAU preemption callback\n"); vdpau_driver_t *this = (vdpau_driver_t *)context; this->reinit_needed = 1; } +static int vdpau_init_error( VdpStatus st, const char *msg, vo_driver_t *driver, int error_string ) +{ + if ( st != VDP_STATUS_OK ) { + if ( error_string ) + printf( "vo_vdpau: %s : %s\n", msg, vdp_get_error_string( st ) ); + else + printf( "vo_vdpau: %s\n", msg ); + vdpau_dispose( driver ); + return 1; + } + return 0; +} + + + static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { vdpau_class_t *class = (vdpau_class_t *) class_gen; -- cgit v1.2.3 From 1553b462393d3e20ed838d4326c9d62ca5317b1a Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Thu, 15 Jan 2009 13:07:06 +0000 Subject: Use sps->scaling_matrix instead of pps. --- src/libvdpau/vdpau_h264.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 1124cfa31..e351ba8cc 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -262,8 +262,8 @@ static void fill_vdpau_pictureinfo_h264(video_decoder_t *this_gen, uint32_t slic pic->pic_order_present_flag = pps->pic_order_present_flag; pic->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; pic->redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; - memcpy(pic->scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic->scaling_lists_4x4)); - memcpy(pic->scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic->scaling_lists_8x8)); + memcpy(pic->scaling_lists_4x4, sps->scaling_lists_4x4, sizeof(pic->scaling_lists_4x4)); + memcpy(pic->scaling_lists_8x8, sps->scaling_lists_8x8, sizeof(pic->scaling_lists_8x8)); /* set num_ref_frames to the number of actually available reference frames, * if this is not set generation 3 decoders will fail. */ @@ -572,7 +572,10 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, parse_codec_private(this->nal_parser, codec_private, codec_private_len); vdpau_decoder_init(this_gen); } - } + } else if (buf->decoder_info[1] == BUF_SPECIAL_PALETTE) { + printf("SPECIAL PALETTE is not yet handled\n"); + } else + printf("UNKNOWN SPECIAL HEADER\n"); } else { /* parse the first nal packages to retrieve profile type */ -- cgit v1.2.3 From 4203256b53c19121243ef38d679471703b4433ac Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Thu, 15 Jan 2009 19:26:55 +0000 Subject: Properly parse scaling_lists (zigzag order, defaults)... This fixed wrong colors/artefacts for several mkv samples. --- src/libvdpau/h264_parser.c | 15 ++++++++------- src/libvdpau/nal.h | 26 ++++++++++++++++++++++++++ src/libvdpau/vdpau_h264.c | 21 +++++++++++---------- 3 files changed, 45 insertions(+), 17 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index abd4c329d..da375fa78 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -344,6 +344,8 @@ void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, uint8_t use_default_scaling_matrix_flag = 0; int i; + uint8_t *zigzag = (length==64) ? zigzag_8x8 : zigzag_4x4; + for (i = 0; i < length; i++) { if (next_scale != 0) { delta_scale = read_exp_golomb_s(buf); @@ -353,8 +355,7 @@ void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, break; } } - scaling_list[i] = (next_scale == 0) ? last_scale : next_scale; - last_scale = scaling_list[i]; + scaling_list[zigzag[i]] = last_scale = (next_scale == 0) ? last_scale : next_scale; } if (use_default_scaling_matrix_flag) { @@ -388,6 +389,9 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) buf->cur_pos = buf->buf + 3; sps->seq_parameter_set_id = read_exp_golomb(buf); + + memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); + memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_4x4)); if (sps->profile_idc == 100 || sps->profile_idc == 110 || sps->profile_idc == 122 || sps->profile_idc == 144) { sps->chroma_format_idc = read_exp_golomb(buf); @@ -414,11 +418,6 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) } } - if (!sps->seq_scaling_matrix_present_flag) { - memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); - memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_4x4)); - } - sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); sps->pic_order_cnt_type = read_exp_golomb(buf); @@ -675,6 +674,8 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, int bit_length = (buf->len*8)-rbsp_trailing_bits(buf->buf, buf->len); int bit_read = bits_read(buf); + memset(pps->scaling_lists_4x4, 16, sizeof(pps->scaling_lists_4x4)); + memset(pps->scaling_lists_8x8, 16, sizeof(pps->scaling_lists_4x4)); if (bit_length-bit_read > 1) { printf("Read transform 8x8\n"); pps->transform_8x8_mode_flag = read_bits(buf, 1); diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index ee5a4bb05..f892e1a3a 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -87,6 +87,32 @@ enum aspect_ratio ASPECT_EXTENDED_SAR=255 }; +static const uint8_t zigzag_4x4[16] = { + 0+0*4, 1+0*4, 0+1*4, 0+2*4, + 1+1*4, 2+0*4, 3+0*4, 2+1*4, + 1+2*4, 0+3*4, 1+3*4, 2+2*4, + 3+1*4, 3+2*4, 2+3*4, 3+3*4, +}; + +static const uint8_t zigzag_8x8[64] = { + 0+0*8, 1+0*8, 0+1*8, 0+2*8, + 1+1*8, 2+0*8, 3+0*8, 2+1*8, + 1+2*8, 0+3*8, 0+4*8, 1+3*8, + 2+2*8, 3+1*8, 4+0*8, 5+0*8, + 4+1*8, 3+2*8, 2+3*8, 1+4*8, + 0+5*8, 0+6*8, 1+5*8, 2+4*8, + 3+3*8, 4+2*8, 5+1*8, 6+0*8, + 7+0*8, 6+1*8, 5+2*8, 4+3*8, + 3+4*8, 2+5*8, 1+6*8, 0+7*8, + 1+7*8, 2+6*8, 3+5*8, 4+4*8, + 5+3*8, 6+2*8, 7+1*8, 7+2*8, + 6+3*8, 5+4*8, 4+5*8, 3+6*8, + 2+7*8, 3+7*8, 4+6*8, 5+5*8, + 6+4*8, 7+3*8, 7+4*8, 6+5*8, + 5+6*8, 4+7*8, 5+7*8, 6+6*8, + 7+5*8, 7+6*8, 6+7*8, 7+7*8, +}; + static inline uint32_t slice_type(uint32_t slice_type) { return (slice_type < 10 ? slice_type % 5 : slice_type); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index e351ba8cc..9060ad1c1 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -123,22 +123,22 @@ static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) /*int i, j; for(i = 0; i < 6; i++) { - printf("scalint_list4x4[%d]: ", i); + printf("C: scalint_list4x4[%d]:\nC:", i); for(j = 0; j < 16; j++) { - printf("[%d] ", pic->scaling_lists_4x4[i][j]); + printf(" [%d]", pic->scaling_lists_4x4[i][j]); if(j%8 == 0) - printf("\n"); + printf("\nC:"); } - printf("\n"); + printf("C: \n"); } for(i = 0; i < 2; i++) { - printf("scalint_list4x4[%d]: ", i); + printf("C: scalint_list8x8[%d]:\nC:", i); for(j = 0; j < 64; j++) { - printf("[%d] ", pic->scaling_lists_4x4[i][j]); + printf(" [%d] ", pic->scaling_lists_8x8[i][j]); if(j%8 == 0) - printf("\n"); + printf("\nC:"); } - printf("\n"); + printf("C: \n"); }*/ int i; @@ -262,8 +262,9 @@ static void fill_vdpau_pictureinfo_h264(video_decoder_t *this_gen, uint32_t slic pic->pic_order_present_flag = pps->pic_order_present_flag; pic->deblocking_filter_control_present_flag = pps->deblocking_filter_control_present_flag; pic->redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag; - memcpy(pic->scaling_lists_4x4, sps->scaling_lists_4x4, sizeof(pic->scaling_lists_4x4)); - memcpy(pic->scaling_lists_8x8, sps->scaling_lists_8x8, sizeof(pic->scaling_lists_8x8)); + + memcpy(pic->scaling_lists_4x4, pps->scaling_lists_4x4, sizeof(pic->scaling_lists_4x4)); + memcpy(pic->scaling_lists_8x8, pps->scaling_lists_8x8, sizeof(pic->scaling_lists_8x8)); /* set num_ref_frames to the number of actually available reference frames, * if this is not set generation 3 decoders will fail. */ -- cgit v1.2.3 From d31f69af029d467470d141e605509ac6b287b2d9 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 16 Jan 2009 11:02:29 +0000 Subject: Update README. --- README-VDPAU | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/README-VDPAU b/README-VDPAU index 87cb71ea5..51e087f09 100644 --- a/README-VDPAU +++ b/README-VDPAU @@ -4,7 +4,7 @@ xine-vdpau README: So, you want to give it a try, but wonder which steps are required. Ok, so here it is: -0) you need nvidia's driver 180.16 or later. +0) you need nvidia's driver 180.22 or later. 1) get the sources: svn co svn://jusst.de/xine-vdpau @@ -22,13 +22,9 @@ nano $HOME/.xine/config (if it does not exist, first run "xine --no-logo" then q search for "engine.buffers.video_num_frames" and set it to 22 4) running the beast: -xine --no-logo --verbose /path/to/a/working/sample - ** the --no-logo will tell xine to not play its crappy mpv logo (which, atm, doesn't work with vdpau_mpeg12) - ** --verbose will print some usefull things in your console (in case of problems, that are very likely to happen, +xine -verbose /path/to/a/working/sample + ** --verbose will print some usefull things in your console (in case of problems, the developers will ask you to give this output, at least) - ** You can find working h264 samples at http://hftom.free.fr/video_samples/ - ** MKV or MOV WON'T WORK, at that moment. (we are concentrating on TS streams, but yes, it will work in the future) - ** most mpeg2 should work, if you have a non working one, please provide a sample. 5) update your svn copy quite often -- cgit v1.2.3 From 867f54cd47b81793f8ca0ac1152ac27520f4946a Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 16 Jan 2009 11:28:04 +0000 Subject: Fix a possible crash in dpb. --- src/libvdpau/dpb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index cd3c6ef9a..acc3f0865 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -267,7 +267,7 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r dpb->num_ref_frames = num_ref_frames; dpb->used++; - if(dpb->used > num_ref_frames) { + if(pic != NULL && dpb->used > num_ref_frames) { do { if(pic->used_for_reference) { i++; @@ -285,7 +285,7 @@ int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_r } last_pic = pic; } - } while ((pic = pic->next) != NULL); + } while (pic != NULL && (pic = pic->next) != NULL); } return 0; -- cgit v1.2.3 From 310b03b3a231f0c9f71926bd15c5babb075c0e33 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 16 Jan 2009 11:28:04 +0000 Subject: Add support for pic_order_cnt_type=2. --- src/libvdpau/h264_parser.c | 55 +++++++++++++++++++++++++++------------------- src/libvdpau/h264_parser.h | 1 + 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index da375fa78..cdf3b6b2b 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -275,12 +275,13 @@ void calculate_pic_order(struct nal_parser *parser) if (!sps || !pps || !slc) return; + if (nal->nal_unit_type == NAL_SLICE_IDR) { + parser->prev_pic_order_cnt_lsb = 0; + parser->prev_pic_order_cnt_msb = 0; + parser->frame_num_offset = 0; + } + if (sps->pic_order_cnt_type == 0) { - if (nal->nal_unit_type == NAL_SLICE_IDR) { - //printf("IDR SLICE\n"); - parser->prev_pic_order_cnt_lsb = 0; - parser->prev_pic_order_cnt_msb = 0; - } const int max_poc_lsb = 1 << (sps->log2_max_pic_order_cnt_lsb_minus4 + 4); @@ -295,23 +296,6 @@ void calculate_pic_order(struct nal_parser *parser) else parser->pic_order_cnt_msb = parser->prev_pic_order_cnt_msb; - /*if (!slc->bottom_field_flag) { - nal->top_field_order_cnt = parser->pic_order_cnt_msb - + slc->pic_order_cnt_lsb; - - if (!slc->field_pic_flag) - nal->bottom_field_order_cnt = nal->top_field_order_cnt; - else - nal->bottom_field_order_cnt = 0; - } - else - nal->bottom_field_order_cnt = parser->pic_order_cnt_msb - + slc->pic_order_cnt_lsb; - - if (parser->field == -1) - nal->bottom_field_order_cnt += slc->delta_pic_order_cnt_bottom; - */ - if(!slc->field_pic_flag || !slc->bottom_field_flag) nal->top_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; @@ -321,6 +305,33 @@ void calculate_pic_order(struct nal_parser *parser) nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; + } else if (sps->pic_order_cnt_type == 2) { + uint32_t prev_frame_num = parser->last_nal->slc->frame_num; + uint32_t prev_frame_num_offset = parser->frame_num_offset; + uint32_t max_frame_num = 1 << (sps->log2_max_frame_num_minus4+4); + uint32_t temp_pic_order_cnt = 0; + + if (parser->is_idr) + parser->frame_num_offset = 0; + else if (prev_frame_num > slc->frame_num) + parser->frame_num_offset = prev_frame_num_offset + max_frame_num; + else + parser->frame_num_offset = prev_frame_num_offset; + + if(parser->is_idr) + temp_pic_order_cnt = 0; + else if(nal->nal_ref_idc == 0) + temp_pic_order_cnt = 2 * (parser->frame_num_offset + slc->frame_num)-1; + else + temp_pic_order_cnt = 2 * (parser->frame_num_offset + slc->frame_num); + + if(!slc->field_pic_flag) + nal->top_field_order_cnt = nal->bottom_field_order_cnt = temp_pic_order_cnt; + else if(slc->bottom_field_flag) + nal->bottom_field_order_cnt = temp_pic_order_cnt; + else + nal->top_field_order_cnt = temp_pic_order_cnt; + } else { printf("FIXME: Unsupported poc_type: %d\n", sps->pic_order_cnt_type); } diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index c99c3cd80..c726f7b90 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -71,6 +71,7 @@ struct nal_parser { uint32_t pic_order_cnt_msb; uint32_t prev_pic_order_cnt_lsb; uint32_t prev_pic_order_cnt_msb; + uint32_t frame_num_offset; /* this is dpb used for reference frame * heading to vdpau + unordered frames -- cgit v1.2.3 From e5acf99657421ad585883c9f3b9a17ad7859cf35 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 16 Jan 2009 13:32:31 +0000 Subject: Fix seeking in mkv/mov files. Don't show pictures which miss reference frames: they are likely garbled. --- src/libvdpau/dpb.h | 2 ++ src/libvdpau/vdpau_h264.c | 49 +++++++++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 6578aa42f..ab4e71809 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -40,6 +40,8 @@ struct decoded_picture { uint8_t delayed_output; + uint8_t misses_references; + struct decoded_picture *next; }; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 9060ad1c1..b9cd38bc5 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -61,6 +61,9 @@ typedef struct vdpau_h264_decoder_s { struct decoded_picture *last_ref_pic; uint32_t last_top_field_order_cnt; + int have_frame_boundary_marks; + int wait_for_frame_start; + VdpDecoder decoder; int decoder_started; @@ -75,6 +78,9 @@ typedef struct vdpau_h264_decoder_s { vo_frame_t *last_img; vo_frame_t *dangling_img; + uint8_t *codec_private; + uint32_t codec_private_len; + int vdp_runtime_nr; } vdpau_h264_decoder_t; @@ -482,6 +488,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); this->last_ref_pic = decoded_pic; decoded_pic->used_for_reference = 1; + if(pic.num_ref_frames < this->nal_parser->current_nal->sps->num_ref_frames) + decoded_pic->misses_references = 1; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); this->dangling_img = NULL; } else if(slc->field_pic_flag && this->wait_for_bottom_field) { @@ -514,7 +522,10 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v /* now retrieve the next output frame */ if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb))) != NULL) { decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); - decoded_pic->img->draw(decoded_pic->img, this->stream); + if(!decoded_pic->misses_references) + decoded_pic->img->draw(decoded_pic->img, this->stream); + else + printf("skip frame, it misses references!"); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); } @@ -547,31 +558,42 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if (buf->decoder_flags & BUF_FLAG_PREVIEW) return; + if(buf->decoder_flags & BUF_FLAG_FRAME_START || buf->decoder_flags & BUF_FLAG_FRAME_END) + this->have_frame_boundary_marks = 1; + if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { this->video_step = buf->decoder_info[0]; _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } if (buf->decoder_flags & BUF_FLAG_STDHEADER) { /* need to initialize */ + this->have_frame_boundary_marks = 0; + xine_bmiheader *bih = (xine_bmiheader*)buf->content; this->width = bih->biWidth; this->height = bih->biHeight; uint8_t *codec_private = buf->content + sizeof(xine_bmiheader); uint32_t codec_private_len = bih->biSize - sizeof(xine_bmiheader); + this->codec_private_len = codec_private_len; + this->codec_private = malloc(codec_private_len); + memcpy(this->codec_private, codec_private, codec_private_len); if(codec_private_len > 0) { parse_codec_private(this->nal_parser, codec_private, codec_private_len); - vdpau_decoder_init(this_gen); } } else if (buf->decoder_flags & BUF_FLAG_SPECIAL) { + this->have_frame_boundary_marks = 0; + if(buf->decoder_info[1] == BUF_SPECIAL_DECODER_CONFIG) { uint8_t *codec_private = buf->decoder_info_ptr[2]; uint32_t codec_private_len = buf->decoder_info[2]; + this->codec_private_len = codec_private_len; + this->codec_private = malloc(codec_private_len); + memcpy(this->codec_private, codec_private, codec_private_len); if(codec_private_len > 0) { parse_codec_private(this->nal_parser, codec_private, codec_private_len); - vdpau_decoder_init(this_gen); } } else if (buf->decoder_info[1] == BUF_SPECIAL_PALETTE) { printf("SPECIAL PALETTE is not yet handled\n"); @@ -586,7 +608,8 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(buf->pts != 0) this->next_pts = buf->pts; - while(len < buf->size) { + while(len < buf->size && !(this->wait_for_frame_start && !(buf->decoder_flags & BUF_FLAG_FRAME_START))) { + this->wait_for_frame_start = 0; len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); @@ -608,6 +631,9 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, } } + + if(buf->decoder_flags & BUF_FLAG_FRAME_END) + this->wait_for_frame_start = 0; } /* @@ -626,17 +652,16 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { dpb_free_all( &(this->nal_parser->dpb) ); - if (this->decoder != VDP_INVALID_HANDLE) { + /*if (this->decoder != VDP_INVALID_HANDLE) { this->vdpau_accel->vdp_decoder_destroy( this->decoder ); this->decoder = VDP_INVALID_HANDLE; - } + }*/ - /* only reset the parser for continous streams - * like ts or pes - */ - if(!this->nal_parser->nal_size_length) { - free_parser(this->nal_parser); - this->nal_parser = init_parser(); + free_parser(this->nal_parser); + this->nal_parser = init_parser(); + if(this->codec_private_len > 0) { + parse_codec_private(this->nal_parser, this->codec_private, this->codec_private_len); + this->wait_for_frame_start = this->have_frame_boundary_marks; } this->wait_for_bottom_field = 0; -- cgit v1.2.3 From b53b61a99e30cf8d5524d2bd5ef722edf94705a5 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 16 Jan 2009 13:35:08 +0000 Subject: Reset vdpau decoder on xine decoder reset. Fixes freezes when seeking in ts streams. --- src/libvdpau/vdpau_h264.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index b9cd38bc5..95e3ff018 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -652,10 +652,10 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { dpb_free_all( &(this->nal_parser->dpb) ); - /*if (this->decoder != VDP_INVALID_HANDLE) { + if (this->decoder != VDP_INVALID_HANDLE) { this->vdpau_accel->vdp_decoder_destroy( this->decoder ); this->decoder = VDP_INVALID_HANDLE; - }*/ + } free_parser(this->nal_parser); this->nal_parser = init_parser(); -- cgit v1.2.3 From 1632fa30f517c25e419201d3402e216abc7c51ca Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 16 Jan 2009 13:37:07 +0000 Subject: Add some comment... --- src/libvdpau/vdpau_h264.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 95e3ff018..bdbe713a7 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -661,6 +661,11 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->nal_parser = init_parser(); if(this->codec_private_len > 0) { parse_codec_private(this->nal_parser, this->codec_private, this->codec_private_len); + + /* if the stream does not contain frame boundary marks we + * have to hope that the next nal will start with the next + * incoming buf... seems to work, though... + */ this->wait_for_frame_start = this->have_frame_boundary_marks; } -- cgit v1.2.3 From 7b6b9c5af1f76b21a07902a4f0c3b106b56a93c5 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 16 Jan 2009 13:47:06 +0000 Subject: Revert skip images with missing references - it may cause skips at unwanted situations... --- src/libvdpau/dpb.h | 2 -- src/libvdpau/vdpau_h264.c | 7 +------ 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index ab4e71809..6578aa42f 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -40,8 +40,6 @@ struct decoded_picture { uint8_t delayed_output; - uint8_t misses_references; - struct decoded_picture *next; }; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index bdbe713a7..2d053f239 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -488,8 +488,6 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); this->last_ref_pic = decoded_pic; decoded_pic->used_for_reference = 1; - if(pic.num_ref_frames < this->nal_parser->current_nal->sps->num_ref_frames) - decoded_pic->misses_references = 1; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); this->dangling_img = NULL; } else if(slc->field_pic_flag && this->wait_for_bottom_field) { @@ -522,10 +520,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v /* now retrieve the next output frame */ if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb))) != NULL) { decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); - if(!decoded_pic->misses_references) - decoded_pic->img->draw(decoded_pic->img, this->stream); - else - printf("skip frame, it misses references!"); + decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); } -- cgit v1.2.3 From 6181870dc2104fa11863ed8c151b609e5b1b3ba8 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 17 Jan 2009 10:37:07 +0000 Subject: Fix pts for progressive ts streams. --- src/libvdpau/vdpau_h264.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 2d053f239..2138121a2 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -383,6 +383,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v fill_vdpau_pictureinfo_h264(this_gen, slice_count, &pic); + //printf("next decode: %d, %d\n", pic.field_order_cnt[0], pic.field_order_cnt[1]); + if(!this->decoder_started && !pic.is_reference) return 0; @@ -520,6 +522,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v /* now retrieve the next output frame */ if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb))) != NULL) { decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); + //printf("draw pts: %lld\n", decoded_pic->img->pts); decoded_pic->img->draw(decoded_pic->img, this->stream); dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); } @@ -600,9 +603,6 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, int len = 0; uint32_t slice_count; - if(buf->pts != 0) - this->next_pts = buf->pts; - while(len < buf->size && !(this->wait_for_frame_start && !(buf->decoder_flags & BUF_FLAG_FRAME_START))) { this->wait_for_frame_start = 0; len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, @@ -619,11 +619,14 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, if(this->decoder != VDP_INVALID_HANDLE && vdp_buffer.bitstream_bytes > 0 && this->nal_parser->current_nal->slc != NULL && - this->nal_parser->current_nal->sps != NULL && this->nal_parser->current_nal->pps != NULL) { vdpau_decoder_render(this_gen, &vdp_buffer, slice_count); } + } + if(buf->pts != 0 && buf->pts != this->next_pts) { + //printf("next pts: %lld\n", buf->pts); + this->next_pts = buf->pts; } } -- cgit v1.2.3 From 2bae6e522612ef9bfbb81b6e031e933584d748a3 Mon Sep 17 00:00:00 2001 From: Mike Lampard Date: Sat, 17 Jan 2009 20:18:34 +0000 Subject: Fix zoom for vdpau video out. --- src/video_out/video_out_vdpau.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 4ed4354be..7ec9a8fb8 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -272,7 +272,8 @@ typedef struct { int reinit_needed; int allocated_surfaces; - + int zoom_x; + int zoom_y; } vdpau_driver_t; @@ -1343,6 +1344,10 @@ static int vdpau_get_property (vo_driver_t *this_gen, int property) return this->sharpness; case VO_PROP_NOISE_REDUCTION: return this->noise; + case VO_PROP_ZOOM_X: + return this->zoom_x; + case VO_PROP_ZOOM_Y: + return this->zoom_y; } return -1; @@ -1363,6 +1368,7 @@ static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) break; case VO_PROP_ZOOM_X: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { + this->zoom_x = value; this->sc.zoom_factor_x = (double)value / (double)XINE_VO_ZOOM_STEP; _x_vo_scale_compute_ideal_size( &this->sc ); this->sc.force_redraw = 1; /* trigger re-calc of output size */ @@ -1370,6 +1376,7 @@ static int vdpau_set_property (vo_driver_t *this_gen, int property, int value) break; case VO_PROP_ZOOM_Y: if ((value >= XINE_VO_ZOOM_MIN) && (value <= XINE_VO_ZOOM_MAX)) { + this->zoom_y = value; this->sc.zoom_factor_y = (double)value / (double)XINE_VO_ZOOM_STEP; _x_vo_scale_compute_ideal_size( &this->sc ); this->sc.force_redraw = 1; /* trigger re-calc of output size */ @@ -1656,6 +1663,8 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->sc.dest_size_cb = visual->dest_size_cb; this->sc.user_data = visual->user_data; this->sc.user_ratio = XINE_VO_ASPECT_AUTO; + this->zoom_x = 100; + this->zoom_y = 100; this->xine = class->xine; this->config = config; -- cgit v1.2.3 From b8ca90c4fcac747e743d4df4969a68f0e18b1a93 Mon Sep 17 00:00:00 2001 From: Mike Lampard Date: Mon, 19 Jan 2009 07:27:06 +0000 Subject: Return the aspect ratio property value. --- src/video_out/video_out_vdpau.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 7ec9a8fb8..5be71ceae 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1348,6 +1348,8 @@ static int vdpau_get_property (vo_driver_t *this_gen, int property) return this->zoom_x; case VO_PROP_ZOOM_Y: return this->zoom_y; + case VO_PROP_ASPECT_RATIO: + return this->sc.user_ratio; } return -1; -- cgit v1.2.3 From 83c558ce5a21df2b9ae6a5b9432d57fc9ec5b9bd Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 19 Jan 2009 11:13:22 +0000 Subject: Scaling list fixes; duration fixes. --- src/libvdpau/h264_parser.c | 4 ++-- src/libvdpau/vdpau_h264.c | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index cdf3b6b2b..315ae6420 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -402,7 +402,7 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) sps->seq_parameter_set_id = read_exp_golomb(buf); memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); - memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_4x4)); + memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_8x8)); if (sps->profile_idc == 100 || sps->profile_idc == 110 || sps->profile_idc == 122 || sps->profile_idc == 144) { sps->chroma_format_idc = read_exp_golomb(buf); @@ -686,7 +686,7 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, int bit_read = bits_read(buf); memset(pps->scaling_lists_4x4, 16, sizeof(pps->scaling_lists_4x4)); - memset(pps->scaling_lists_8x8, 16, sizeof(pps->scaling_lists_4x4)); + memset(pps->scaling_lists_8x8, 16, sizeof(pps->scaling_lists_8x8)); if (bit_length-bit_read > 1) { printf("Read transform 8x8\n"); pps->transform_8x8_mode_flag = read_bits(buf, 1); diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 2138121a2..516b279bb 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -127,7 +127,7 @@ static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) printf("C: deblocking_filter_control_present_flag: %d\n", pic->deblocking_filter_control_present_flag); printf("C: redundant_pic_cnt_present_flag: %d\n", pic->redundant_pic_cnt_present_flag); - /*int i, j; + int i, j; for(i = 0; i < 6; i++) { printf("C: scalint_list4x4[%d]:\nC:", i); for(j = 0; j < 16; j++) { @@ -145,9 +145,9 @@ static inline void dump_pictureinfo_h264(VdpPictureInfoH264 *pic) printf("\nC:"); } printf("C: \n"); - }*/ + } - int i; + //int i; for(i = 0; i < 16; i++) { if(pic->referenceFrames[i].surface != VDP_INVALID_HANDLE) { printf("C: -------------------\n"); @@ -379,6 +379,10 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t *)this_gen; vo_frame_t *img = this->last_img; + if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { + dpb_flush(&(this->nal_parser->dpb)); + } + VdpPictureInfoH264 pic; fill_vdpau_pictureinfo_h264(this_gen, slice_count, &pic); @@ -401,9 +405,6 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v /* flush the DPB if this frame was an IDR */ //printf("is_idr: %d\n", this->nal_parser->is_idr); - if(this->nal_parser->current_nal->nal_unit_type == NAL_SLICE_IDR) { - dpb_flush(&(this->nal_parser->dpb)); - } this->nal_parser->is_idr = 0; /* go and decode a frame */ @@ -481,8 +482,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(!img->progressive_frame && this->nal_parser->current_nal->repeat_pic) img->repeat_first_field = 1; - else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic) - img->duration *= this->nal_parser->current_nal->repeat_pic; + //else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic) + // img->duration *= this->nal_parser->current_nal->repeat_pic; struct decoded_picture *decoded_pic = NULL; if(pic.is_reference) { -- cgit v1.2.3 From 4973bf41cb25e8025acc6b09ec3a433889aade07 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 19 Jan 2009 11:23:28 +0000 Subject: Force a minimum video_num_frames of 22, allowing max of 30. --- src/video_out/video_out_vdpau.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 5be71ceae..e85e31545 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1319,7 +1319,7 @@ static int vdpau_get_property (vo_driver_t *this_gen, int property) switch (property) { case VO_PROP_MAX_NUM_FRAMES: - return 22; + return 30; case VO_PROP_WINDOW_WIDTH: return this->sc.gui_width; case VO_PROP_WINDOW_HEIGHT: @@ -1926,6 +1926,19 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo "This flag is not always reliable.\n\n"), 10, vdpau_honor_progressive_flag, this ); + /* number of video frames from config - register it with the default value. */ + int frame_num = config->register_num (config, "engine.buffers.video_num_frames", 15, /* default */ + _("default number of video frames"), + _("The default number of video frames to request " + "from xine video out driver. Some drivers will " + "override this setting with their own values."), + 20, NULL, this); + + /* now make sure we have at least 22 frames, to prevent + * locks with vdpau_h264 */ + if(frame_num < 22) + config->update_num(config,"engine.buffers.video_num_frames",22); + this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY; ok = 0; uint32_t mw, mh, ml, mr; -- cgit v1.2.3 From 54951edd20fcf04d9a3b29bf8dd4ced15cdac08a Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 19 Jan 2009 12:40:08 +0000 Subject: Fix fallback rules for scaling list parsing. --- src/libvdpau/h264_parser.c | 61 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 315ae6420..7a0a400b1 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -61,6 +61,8 @@ void skip_scaling_list(struct buf_reader *buf, int size); void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, int length, int index); int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser); +static void sps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, int i); +static void pps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, struct pic_parameter_set_rbsp *pps, int i); uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser); void parse_vui_parameters(struct buf_reader *buf, struct seq_parameter_set_rbsp *sps); @@ -374,23 +376,70 @@ void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, case 0: case 1: case 2: - memcpy(scaling_list, default_4x4_intra, length); + memcpy(scaling_list, default_4x4_intra, sizeof(default_4x4_intra)); break; case 3: case 4: case 5: - memcpy(scaling_list, default_4x4_inter, length); + memcpy(scaling_list, default_4x4_inter, sizeof(default_4x4_inter)); break; case 6: - memcpy(scaling_list, default_8x8_intra, length); + memcpy(scaling_list, default_8x8_intra, sizeof(default_8x8_intra)); break; case 7: - memcpy(scaling_list, default_8x8_inter, length); + memcpy(scaling_list, default_8x8_inter, sizeof(default_8x8_inter)); break; } } } +static void sps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, int i) +{ + switch (i) { + case 0: + memcpy(sps->scaling_lists_4x4[i], default_4x4_intra, sizeof(sps->scaling_lists_4x4[i])); + break; + case 3: + memcpy(sps->scaling_lists_4x4[i], default_4x4_inter, sizeof(sps->scaling_lists_4x4[i])); + break; + case 1: + case 2: + case 4: + case 5: + memcpy(sps->scaling_lists_4x4[i], sps->scaling_lists_4x4[i-1], sizeof(sps->scaling_lists_4x4[i])); + break; + case 6: + memcpy(sps->scaling_lists_8x8[i-6], default_8x8_intra, sizeof(sps->scaling_lists_8x8[i-6])); + break; + case 7: + memcpy(sps->scaling_lists_8x8[i-6], default_8x8_inter, sizeof(sps->scaling_lists_8x8[i-6])); + break; + + } +} + +static void pps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, struct pic_parameter_set_rbsp *pps, int i) +{ + switch (i) { + case 0: + case 3: + memcpy(pps->scaling_lists_4x4[i], sps->scaling_lists_4x4[i], sizeof(pps->scaling_lists_4x4[i])); + break; + case 1: + case 2: + case 4: + case 5: + memcpy(pps->scaling_lists_4x4[i], pps->scaling_lists_4x4[i-1], sizeof(sps->scaling_lists_4x4[i])); + break; + case 6: + case 7: + memcpy(pps->scaling_lists_8x8[i-6], sps->scaling_lists_8x8[i-6], sizeof(pps->scaling_lists_8x8[i-6])); + break; + + } +} + + uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) { struct seq_parameter_set_rbsp *sps = parser->current_nal->sps; @@ -424,6 +473,8 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) parse_scaling_list(buf, sps->scaling_lists_4x4[i], 16, i); else parse_scaling_list(buf, sps->scaling_lists_8x8[i - 6], 64, i); + } else { + sps_scaling_list_fallback(sps, i); } } } @@ -701,6 +752,8 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, parse_scaling_list(buf, pps->scaling_lists_4x4[i], 16, i); else parse_scaling_list(buf, pps->scaling_lists_8x8[i - 6], 64, i); + } else { + pps_scaling_list_fallback(sps, pps, i); } } } -- cgit v1.2.3 From a56dfc47addd295bd773ab3df9e64ddcc4224b6f Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 20 Jan 2009 10:45:38 +0000 Subject: Disable deint for static images (ie dvd menus). --- src/video_out/video_out_vdpau.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index e85e31545..a72b85674 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1234,7 +1234,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } int non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive; - if ( frame->vo_frame.duration>2500 && this->deinterlace && non_progressive && frame->format==XINE_IMGFMT_VDPAU ) { + if ( stream_speed && frame->vo_frame.duration>2500 && this->deinterlace && non_progressive && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; VdpVideoSurface future[1]; -- cgit v1.2.3 From 431ccd81e0c1bd30241731b6eec599058dbd5342 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 23 Jan 2009 09:19:11 +0000 Subject: Get pts at picture start. May fix a/v sync on some ts. --- src/libvdpau/vdpau_mpeg12.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index c18b35510..31cc891bb 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -332,6 +332,10 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) if ( sequence->picture.state!=WANT_HEADER ) return; + if ( sequence->cur_pts ) { + sequence->seq_pts = sequence->cur_pts; + } + if ( sequence->profile==VDP_DECODER_PROFILE_MPEG1 ) sequence->picture.vdp_infos.picture_structure = PICTURE_FRAME; @@ -685,6 +689,7 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) seq->backward_ref = NULL; vd->decoder = VDP_INVALID_HANDLE; } + img->drawn = 0; //printf("vdpau_mpeg12: .. got image %d\n", img); -- cgit v1.2.3 From 5b4d44a8f747f0182cc597150c1b9eab9c54d32e Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 25 Jan 2009 11:54:05 +0000 Subject: HD subs scaling with capable vo. --- src/libspudvb/xine_spudvb_decoder.c | 63 ++++++++++++++----------------------- 1 file changed, 24 insertions(+), 39 deletions(-) diff --git a/src/libspudvb/xine_spudvb_decoder.c b/src/libspudvb/xine_spudvb_decoder.c index e6e885e1f..1e33c48af 100644 --- a/src/libspudvb/xine_spudvb_decoder.c +++ b/src/libspudvb/xine_spudvb_decoder.c @@ -32,7 +32,11 @@ #include "osd.h" #define MAX_REGIONS 7 -/*#define LOG 1*/ +#define SPU_MAX_WIDTH 720 +#define SPU_MAX_HEIGHT 576 + +/*#define LOG*/ +#define LOG_MODULE "spudvb" typedef struct { int x, y; @@ -145,19 +149,15 @@ static void update_region (dvb_spu_decoder_t * this, int region_id, int region_w page_t *page = &dvbsub->page; /* reject invalid sizes and set some limits ! */ - if ( region_width<=0 || region_height<=0 || region_width>720 || region_height>576 ) { + if ( region_width<=0 || region_height<=0 || region_width>SPU_MAX_WIDTH || region_height>SPU_MAX_HEIGHT ) { free( reg->img ); reg->img = NULL; -#ifdef LOG - printf("SPUDVB: rejected region %d = %dx%d\n", region_id, region_width, region_height ); -#endif + lprintf("rejected region %d = %dx%d\n", region_id, region_width, region_height ); return; } if ( (reg->width*reg->height) < (region_width*region_height) ) { -#ifdef LOG - printf("SPUDVB: update size of region %d = %dx%d\n", region_id, region_width, region_height); -#endif + lprintf("update size of region %d = %dx%d\n", region_id, region_width, region_height); free( reg->img ); reg->img = NULL; } @@ -173,9 +173,7 @@ static void update_region (dvb_spu_decoder_t * this, int region_id, int region_w if ( fill ) { memset( reg->img, fill_color, region_width*region_height ); reg->empty = 1; -#ifdef LOG - printf("SPUDVB : FILL REGION %d\n", region_id); -#endif + lprintf("FILL REGION %d\n", region_id); } reg->width = region_width; reg->height = region_height; @@ -594,13 +592,11 @@ static void* dvbsub_timer_func(void *this_gen) if(this && this->stream && this->stream->osd_renderer) { int i; for ( i=0; idvbsub->regions[i].osd ) - continue; + if ( !this->dvbsub->regions[i].osd ) + continue; - this->stream->osd_renderer->hide( this->dvbsub->regions[i].osd, 0 ); -#ifdef LOG - printf("SPUDVB: thread hiding = %d\n",i); -#endif + this->stream->osd_renderer->hide( this->dvbsub->regions[i].osd, 0 ); + lprintf("thread hiding = %d\n",i); } } pthread_cond_wait(&this->dvbsub_restart_timeout, &this->dvbsub_osd_mutex); @@ -627,7 +623,7 @@ static void draw_subtitles (dvb_spu_decoder_t * this) int dest_width=0, dest_height; this->stream->video_out->status(this->stream->video_out, NULL, &dest_width, &dest_height, &dum); - if ( !dest_width ) + if ( !dest_width || !dest_height ) return; /* render all regions onto the page */ @@ -637,8 +633,8 @@ static void draw_subtitles (dvb_spu_decoder_t * this) int display = 0; for ( r=0; rdvbsub->page.regions[r].is_visible ) { - display = 1; - break; + display = 1; + break; } } if ( !display ) @@ -658,7 +654,7 @@ static void draw_subtitles (dvb_spu_decoder_t * this) uint8_t *reg; int reg_width; uint8_t tmp[dest_width*576]; - if (this->dvbsub->regions[r].width>dest_width) { + if ( this->dvbsub->regions[r].width>dest_width && !(this->stream->video_driver->get_capabilities(this->stream->video_driver) & VO_CAP_CUSTOM_EXTENT_OVERLAY)) { downscale_region_image(&this->dvbsub->regions[r], tmp, dest_width); reg = tmp; reg_width = dest_width; @@ -674,34 +670,25 @@ static void draw_subtitles (dvb_spu_decoder_t * this) } pthread_mutex_lock(&this->dvbsub_osd_mutex); -#ifdef LOG - printf("SPUDVB: this->vpts=%llu\n",this->vpts); -#endif + lprintf("this->vpts=%llu\n",this->vpts); for ( r=0; rdvbsub->page.regions[r].is_visible, this->dvbsub->regions[r].osd?1:0, this->dvbsub->regions[r].empty ); -#endif + lprintf("region=%d, visible=%d, osd=%d, empty=%d\n", r, this->dvbsub->page.regions[r].is_visible, this->dvbsub->regions[r].osd?1:0, this->dvbsub->regions[r].empty ); if ( this->dvbsub->page.regions[r].is_visible && this->dvbsub->regions[r].osd && !this->dvbsub->regions[r].empty ) { + this->stream->osd_renderer->set_extent(this->dvbsub->regions[r].osd, SPU_MAX_WIDTH, SPU_MAX_HEIGHT); this->stream->osd_renderer->set_position( this->dvbsub->regions[r].osd, this->dvbsub->page.regions[r].x, this->dvbsub->page.regions[r].y ); this->stream->osd_renderer->show( this->dvbsub->regions[r].osd, this->vpts ); -#ifdef LOG - printf("SPUDVB: show region = %d\n",r); -#endif + lprintf("show region = %d\n",r); } else { if ( this->dvbsub->regions[r].osd ) { this->stream->osd_renderer->hide( this->dvbsub->regions[r].osd, this->vpts ); -#ifdef LOG - printf("SPUDVB: hide region = %d\n",r); -#endif + lprintf("hide region = %d\n",r); } } } this->dvbsub_hide_timeout.tv_nsec = 0; this->dvbsub_hide_timeout.tv_sec = time(NULL) + this->dvbsub->page.page_time_out; -#ifdef LOG - printf("SPUDVB: page_time_out %d\n",this->dvbsub->page.page_time_out); -#endif + lprintf("page_time_out %d\n",this->dvbsub->page.page_time_out); pthread_cond_signal(&this->dvbsub_restart_timeout); pthread_mutex_unlock(&this->dvbsub_osd_mutex); } @@ -760,9 +747,7 @@ static void spudec_decode_data (spu_decoder_t * this_gen, buf_element_t * buf) metronom_clock_t *const clock = this->stream->xine->clock; const int64_t curvpts = clock->get_current_time( clock ); /* if buf->pts is unreliable, show page asap (better than nothing) */ -#ifdef LOG - printf("SPUDVB: spu_vpts=%lld - current_vpts=%lld\n", vpts, curvpts); -#endif + lprintf("spu_vpts=%lld - current_vpts=%lld\n", vpts, curvpts); if ( vpts<=curvpts || (vpts-curvpts)>(5*90000) ) this->vpts = 0; else -- cgit v1.2.3 From 79b351f83f2af0cadb1b076c060d1515c1f0a5b5 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 25 Jan 2009 11:56:11 +0000 Subject: Subs scaling. --- src/video_out/video_out_vdpau.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index a72b85674..14779db7e 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -186,6 +186,8 @@ typedef struct { int ovl_w, ovl_h; /* overlay's width and height */ int ovl_x, ovl_y; /* overlay's top-left display position */ int unscaled; + int expected_overlay_width; /*if >0 scale to video width*/ + int expected_overlay_height; /* if >0 sccale to video height */ } vdpau_overlay_t; @@ -407,6 +409,8 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) ovl->ovl_x = overlay->x; ovl->ovl_y = overlay->y; ovl->unscaled = overlay->unscaled; + ovl->expected_overlay_width = overlay->extent_width; + ovl->expected_overlay_height = overlay->extent_height; uint32_t *buf = (uint32_t*)malloc(ovl->ovl_w*ovl->ovl_h*4); if ( !buf ) return 0; @@ -514,6 +518,7 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) } int w=0, h=0; + int scaler = 0; for ( i=0; iovl_changed-1; ++i ) { if ( this->overlays[i].unscaled ) continue; @@ -521,6 +526,15 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) w = this->overlays[i].ovl_x+this->overlays[i].ovl_w; if ( h < (this->overlays[i].ovl_y+this->overlays[i].ovl_h) ) h = this->overlays[i].ovl_y+this->overlays[i].ovl_h; + if ( this->overlays[i].expected_overlay_width ) + scaler = 1; + if ( this->overlays[i].expected_overlay_height ) + scaler = 1; + } + + if ( scaler ) { + w = this->video_mixer_width; + h = this->video_mixer_height; } int out_w = (w>frame->width) ? w : frame->width; @@ -573,9 +587,8 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) w = (this->overlay_unscaled_width>this->overlay_output_width) ? this->overlay_unscaled_width : this->overlay_output_width; h = (this->overlay_unscaled_height>this->overlay_output_height) ? this->overlay_unscaled_height : this->overlay_output_height; - uint32_t *buf = (uint32_t*)malloc(w*h*4); + uint32_t *buf = (uint32_t*)calloc(w*4,h); uint32_t pitch = w*4; - memset( buf, 0, w*h*4 ); VdpRect clear = { 0, 0, this->overlay_output_width, this->overlay_output_height }; st = vdp_output_surface_put_bits( this->overlay_output, &buf, &pitch, &clear ); if ( st != VDP_STATUS_OK ) { @@ -591,6 +604,12 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) VdpOutputSurface *surface; for ( i=0; iovl_changed-1; ++i ) { VdpRect dest = { this->overlays[i].ovl_x, this->overlays[i].ovl_y, this->overlays[i].ovl_x+this->overlays[i].ovl_w, this->overlays[i].ovl_y+this->overlays[i].ovl_h }; + if ( this->overlays[i].expected_overlay_width ) { + double rx = (double)this->overlay_output_width/(double)this->overlays[i].expected_overlay_width; + double ry = (double)this->overlay_output_height/(double)this->overlays[i].expected_overlay_height; + dest.x0 *= rx; dest.y0 *= ry; dest.x1 *=rx; dest.y1 *= ry; + printf( "vdpau_overlay_end: overlay_width=%d overlay_height=%d rx=%f ry=%f\n", this->overlay_output_width, this->overlay_output_height, rx, ry ); + } VdpRect src = { 0, 0, this->overlays[i].ovl_w, this->overlays[i].ovl_h }; surface = (this->overlays[i].unscaled) ? &this->overlay_unscaled : &this->overlay_output; st = vdp_output_surface_render_bitmap_surface( *surface, &dest, this->overlays[i].ovl_bitmap, &src, 0, &blend, 0 ); @@ -1946,15 +1965,25 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: getting h264_supported failed! : %s\n", vdp_get_error_string( st ) ); else if ( !ok ) - printf( "vo_vdpau: no support for h264 ! : no ok\n" ); + printf( "vo_vdpau: this hardware doesn't support h264.\n" ); else this->capabilities |= VO_CAP_VDPAU_H264; + /*st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, &ok, &ml, &mr, &mw, &mh ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: getting vc1_supported failed! : %s\n", vdp_get_error_string( st ) ); + else if ( !ok ) + printf( "vo_vdpau: this hardware doesn't support vc1.\n" ); + else + this->capabilities |= VO_CAP_VDPAU_VC1; + + this->capabilities |= VO_CAP_VDPAU_VC1;*/ + st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, &ok, &ml, &mr, &mw, &mh ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: getting mpeg12_supported failed! : %s\n", vdp_get_error_string( st ) ); else if ( !ok ) - printf( "vo_vdpau: no support for mpeg1/2 ! : no ok\n" ); + printf( "vo_vdpau: this hardware doesn't support mpeg1/2.\n" ); else this->capabilities |= VO_CAP_VDPAU_MPEG12; -- cgit v1.2.3 From 7d6efe0205f1035e6c48c5a924432d34bc83bb36 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 25 Jan 2009 13:06:41 +0000 Subject: PTS fix. --- src/libvdpau/vdpau_mpeg12.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 31cc891bb..ee63b5fa7 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -695,6 +695,7 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) decode_render( vd, accel ); + img->pts = seq->seq_pts; img->bad_frame = 0; img->duration = seq->video_step; if ( pic->vdp_infos.top_field_first || pic->vdp_infos.picture_structure==PICTURE_FRAME ) @@ -717,16 +718,16 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) } seq->forward_ref = seq->backward_ref; if ( seq->forward_ref && !seq->forward_ref->drawn ) { - seq->forward_ref->pts = seq->seq_pts; + //seq->forward_ref->pts = seq->seq_pts; seq->forward_ref->draw( seq->forward_ref, vd->stream ); - //printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", seq->forward_ref->pts ); + printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", seq->forward_ref->pts ); } seq->backward_ref = img; } else { - img->pts = seq->seq_pts; + //img->pts = seq->seq_pts; img->draw( img, vd->stream ); - //printf( "vdpau_mpeg12: drawn image with pts=%lld\n", img->pts ); + printf( "vdpau_mpeg12: drawn image with pts=%lld\n", img->pts ); img->free( img ); //printf("vdpau_mpeg12: freed B image %d\n", img ); } -- cgit v1.2.3 From fe5559ddc4f88b56cb80802929dcbb115b7db391 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 25 Jan 2009 13:24:02 +0000 Subject: Remove some printfs. --- src/libvdpau/vdpau_mpeg12.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index ee63b5fa7..3087868d1 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -720,14 +720,13 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) if ( seq->forward_ref && !seq->forward_ref->drawn ) { //seq->forward_ref->pts = seq->seq_pts; seq->forward_ref->draw( seq->forward_ref, vd->stream ); - printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", seq->forward_ref->pts ); + //printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", seq->forward_ref->pts ); } seq->backward_ref = img; } else { - //img->pts = seq->seq_pts; img->draw( img, vd->stream ); - printf( "vdpau_mpeg12: drawn image with pts=%lld\n", img->pts ); + //printf( "vdpau_mpeg12: drawn image with pts=%lld\n", img->pts ); img->free( img ); //printf("vdpau_mpeg12: freed B image %d\n", img ); } -- cgit v1.2.3 From f11d9f9e4ed468bbf19853a9f021ac6078ee29a4 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 25 Jan 2009 16:03:53 +0000 Subject: POC calculation fixes. --- src/libvdpau/h264_parser.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 7a0a400b1..043ca3818 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -272,9 +272,8 @@ void calculate_pic_order(struct nal_parser *parser) struct nal_unit *nal = parser->current_nal; struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; - if (!sps || !pps || !slc) + if (!sps || !slc) return; if (nal->nal_unit_type == NAL_SLICE_IDR) { @@ -762,15 +761,11 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, } if (!pps->pic_scaling_matrix_present_flag && sps != NULL) { - //printf("MEMCPY SCALING LIST\n"); memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, sizeof(pps->scaling_lists_4x4)); memcpy(pps->scaling_lists_8x8, sps->scaling_lists_8x8, sizeof(pps->scaling_lists_8x8)); } - /*else if (sps == NULL) { - printf("sPS MISSING\n"); - }*/ return 0; } @@ -1062,6 +1057,8 @@ void decode_ref_pic_marking(struct nal_unit *nal, // mark all ref pics as unused for reference, // set max-long-term frame index = no long-term frame idxs dpb_flush(dpb); + parser->pic_order_cnt_lsb = 0; + parser->pic_order_cnt_msb = 0; parser->prev_pic_order_cnt_lsb = 0; parser->prev_pic_order_cnt_msb = 0; } @@ -1255,6 +1252,10 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, i, parser); } + if (parser->last_nal->slc != NULL) + parser->prev_pic_order_cnt_lsb + = parser->last_nal->slc->pic_order_cnt_lsb; + parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; } while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset, parser)) >= 0) { @@ -1307,12 +1308,6 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->prebuf_len = 0; parser->incomplete_nal = 0; - if (parser->last_nal->nal_ref_idc) { - if (parser->last_nal->slc != NULL) - parser->prev_pic_order_cnt_lsb - = parser->last_nal->slc->pic_order_cnt_lsb; - parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; - } return parsed_len; } -- cgit v1.2.3 From 183b9fb01f43bfd4b4877e2509a0cfe58fb7738a Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 25 Jan 2009 16:04:08 +0000 Subject: Select correct color standard for H.264. --- src/libvdpau/vdpau_h264.c | 14 ++++++++++++++ src/video_out/video_out_vdpau.c | 12 +++++++++--- src/xine-engine/accel_vdpau.h | 2 ++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 516b279bb..de3cf5d81 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -485,6 +485,20 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v //else if(img->progressive_frame && this->nal_parser->current_nal->repeat_pic) // img->duration *= this->nal_parser->current_nal->repeat_pic; + /* only bt601 and bt701 handled so far. others seem to be rarely used */ + if(sps->vui_parameters.colour_description_present) { + switch (sps->vui_parameters.colour_primaries) { + case 1: + this->vdpau_accel->color_standard = VDP_COLOR_STANDARD_ITUR_BT_709; + break; + case 5: + case 6: + default: + this->vdpau_accel->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; + break; + } + } + struct decoded_picture *decoded_pic = NULL; if(pic.is_reference) { if(!slc->field_pic_flag || !this->wait_for_bottom_field) { diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 14779db7e..fe387e02f 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -251,6 +251,7 @@ typedef struct { VdpChromaType video_mixer_chroma; uint32_t video_mixer_width; uint32_t video_mixer_height; + VdpColorStandard color_standard; VdpColor back_color; @@ -687,6 +688,7 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vdpau_accel_data.vdp_device = vdp_device; frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; frame->vdpau_accel_data.chroma = VDP_CHROMA_TYPE_420; + frame->vdpau_accel_data.color_standard = this->color_standard; frame->vdpau_accel_data.vdp_decoder_create = vdp_decoder_create; frame->vdpau_accel_data.vdp_decoder_destroy = vdp_decoder_destroy; frame->vdpau_accel_data.vdp_decoder_render = vdp_decoder_render; @@ -1081,12 +1083,12 @@ static void vdpau_update_csc( vdpau_driver_t *this_gen ) float contrast = this_gen->contrast/100.0; float brightness = this_gen->brightness/100.0; - printf( "vo_vdpau: vdpau_update_csc: hue=%f, saturation=%f, contrast=%f, brightness=%f\n", hue, saturation, contrast, brightness ); + printf( "vo_vdpau: vdpau_update_csc: hue=%f, saturation=%f, contrast=%f, brightness=%f, color_standard=%d\n", hue, saturation, contrast, brightness, this_gen->color_standard ); VdpCSCMatrix matrix; VdpProcamp procamp = { VDP_PROCAMP_VERSION, brightness, contrast, saturation, hue }; - VdpStatus st = vdp_generate_csc_matrix( &procamp, VDP_COLOR_STANDARD_ITUR_BT_601, &matrix ); + VdpStatus st = vdp_generate_csc_matrix( &procamp, this_gen->color_standard, &matrix ); if ( st != VDP_STATUS_OK ) { printf( "vo_vdpau: error, can't generate csc matrix !!\n" ); return; @@ -1107,6 +1109,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpStatus st; VdpVideoSurface surface; VdpChromaType chroma = this->video_mixer_chroma; + VdpColorStandard color_standard = this->color_standard; uint32_t mix_w = this->video_mixer_width; uint32_t mix_h = this->video_mixer_height; VdpTime stream_speed; @@ -1164,6 +1167,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) mix_w = frame->width; mix_h = frame->height; chroma = (frame->vo_frame.flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420; + color_standard = frame->vdpau_accel_data.color_standard; } else { /* unknown format */ @@ -1172,7 +1176,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) return; } - if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma) ) { + if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma) || (color_standard != this->color_standard)) { vdpau_release_back_frames( this_gen ); /* empty past frames array */ printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); @@ -1186,6 +1190,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; this->video_mixer_height = mix_h; + this->color_standard = color_standard; vdpau_set_deinterlace( this_gen ); vdpau_set_inverse_telecine( this_gen ); vdpau_update_noise( this ); @@ -1907,6 +1912,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } + this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; this->video_mixer_chroma = chroma; this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h index 99cea4568..92a46e46f 100644 --- a/src/xine-engine/accel_vdpau.h +++ b/src/xine-engine/accel_vdpau.h @@ -49,6 +49,8 @@ typedef struct { VdpVideoSurface surface; VdpChromaType chroma; + VdpColorStandard color_standard; + int vdp_runtime_nr; /* this is used to keep in sync on preemptions */ int *current_vdp_runtime_nr; -- cgit v1.2.3 From bb85753bac351eadf6e8735403f250f000464611 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 25 Jan 2009 16:45:12 +0000 Subject: fFix ref pic marking process on frame_num wraps. --- src/libvdpau/h264_parser.c | 35 ++++++++++++++++++----------------- src/libvdpau/nal.h | 1 + src/libvdpau/vdpau_h264.c | 5 +++-- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 043ca3818..916c40c1a 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -799,10 +799,13 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) slc->bottom_field_flag = 0; } - if (slc->field_pic_flag == 0) + if (slc->field_pic_flag == 0) { + nal->max_pic_num = 1 << (sps->log2_max_frame_num_minus4+4); nal->curr_pic_num = slc->frame_num; - else + } else { nal->curr_pic_num = 2 * slc->frame_num + 1; + nal->max_pic_num = 2 * (1 << (sps->log2_max_frame_num_minus4+4)); + } if (nal->nal_unit_type == NAL_SLICE_IDR) slc->idr_pic_id = read_exp_golomb(buf); @@ -986,10 +989,10 @@ void decode_ref_pic_marking(struct nal_unit *nal, if (memory_management_control_operation == 1) { // short-term -> unused for reference - uint32_t pic_num_x = nal->curr_pic_num - - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1); - struct decoded_picture* pic = dpb_get_picture(dpb, pic_num_x); - if (pic != NULL) { + uint32_t pic_num_x = (nal->curr_pic_num + - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1))%nal->max_pic_num; + struct decoded_picture* pic = NULL; + if ((pic = dpb_get_picture(dpb, pic_num_x)) != NULL) { if (pic->nal->slc->field_pic_flag == 0) { printf("Set %d as unused for ref\n", pic_num_x); dpb_set_unused_ref_picture_a(dpb, pic); @@ -1001,9 +1004,9 @@ void decode_ref_pic_marking(struct nal_unit *nal, //printf("FIXME: We might need do delete more from the DPB...\n"); // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120 } - } - } - else if (memory_management_control_operation == 2) { + } else + printf("Can't set %d as unused for ref\n", pic_num_x); + } else if (memory_management_control_operation == 2) { // long-term -> unused for reference struct decoded_picture* pic = dpb_get_picture_by_ltpn(dpb, slc->dec_ref_pic_marking[marking_nr].long_term_pic_num); @@ -1017,8 +1020,7 @@ void decode_ref_pic_marking(struct nal_unit *nal, printf("FIXME: We might need do delete more from the DPB...\n"); } } - } - else if (memory_management_control_operation == 3) { + } else if (memory_management_control_operation == 3) { // short-term -> long-term, set long-term frame index uint32_t pic_num_x = nal->curr_pic_num - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1); @@ -1042,8 +1044,7 @@ void decode_ref_pic_marking(struct nal_unit *nal, printf("memory_management_control_operation: 3 failed. No such picture.\n"); } - } - else if (memory_management_control_operation == 4) { + } else if (memory_management_control_operation == 4) { // set max-long-term frame index, // mark all long-term pictures with long-term frame idx // greater max-long-term farme idx as unused for ref @@ -1052,8 +1053,7 @@ void decode_ref_pic_marking(struct nal_unit *nal, else dpb_set_unused_ref_picture_lidx_gt(dpb, slc->dec_ref_pic_marking[marking_nr].max_long_term_frame_idx_plus1 - 1); - } - else if (memory_management_control_operation == 5) { + } else if (memory_management_control_operation == 5) { // mark all ref pics as unused for reference, // set max-long-term frame index = no long-term frame idxs dpb_flush(dpb); @@ -1061,8 +1061,7 @@ void decode_ref_pic_marking(struct nal_unit *nal, parser->pic_order_cnt_msb = 0; parser->prev_pic_order_cnt_lsb = 0; parser->prev_pic_order_cnt_msb = 0; - } - else if (memory_management_control_operation == 6) { + } else if (memory_management_control_operation == 6) { // mark current picture as used for long-term ref, // assing long-term frame idx to it struct decoded_picture* pic = dpb_get_picture_by_ltidx(dpb, @@ -1079,6 +1078,7 @@ void decode_ref_pic_marking(struct nal_unit *nal, else printf("FIXME: BY Set frame to long-term ref\n"); } + /* FIXME: Do we need to care about MMC=0? */ } void parse_dec_ref_pic_marking(struct buf_reader *buf, @@ -1252,6 +1252,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, i, parser); } + if (parser->last_nal->slc != NULL) parser->prev_pic_order_cnt_lsb = parser->last_nal->slc->pic_order_cnt_lsb; diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index f892e1a3a..e03a69242 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -439,6 +439,7 @@ struct nal_unit uint8_t nal_ref_idc; // 0x03 uint8_t nal_unit_type; // 0x1f + uint32_t max_pic_num; uint32_t curr_pic_num; uint8_t used_for_long_term_ref; uint32_t long_term_pic_num; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index de3cf5d81..906c65f4c 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -247,7 +247,7 @@ static void fill_vdpau_pictureinfo_h264(video_decoder_t *this_gen, uint32_t slic pic->frame_num = slc->frame_num; pic->field_pic_flag = slc->field_pic_flag; pic->bottom_field_flag = slc->bottom_field_flag; - //pic->num_ref_frames = sps->num_ref_frames; + pic->num_ref_frames = sps->num_ref_frames; pic->mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; pic->constrained_intra_pred_flag = pps->constrained_intra_pred_flag; pic->weighted_pred_flag = pps->weighted_pred_flag; @@ -274,7 +274,8 @@ static void fill_vdpau_pictureinfo_h264(video_decoder_t *this_gen, uint32_t slic /* set num_ref_frames to the number of actually available reference frames, * if this is not set generation 3 decoders will fail. */ - pic->num_ref_frames = fill_vdpau_reference_list(&(this->nal_parser->dpb), pic->referenceFrames); + /*pic->num_ref_frames =*/ + fill_vdpau_reference_list(&(this->nal_parser->dpb), pic->referenceFrames); } -- cgit v1.2.3 From cfdf89b5aa5f0cc2953723c48d7b56f9b1b79600 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 25 Jan 2009 16:58:47 +0000 Subject: Remove some printfs. --- src/libvdpau/h264_parser.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 916c40c1a..f19383f8a 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -994,7 +994,6 @@ void decode_ref_pic_marking(struct nal_unit *nal, struct decoded_picture* pic = NULL; if ((pic = dpb_get_picture(dpb, pic_num_x)) != NULL) { if (pic->nal->slc->field_pic_flag == 0) { - printf("Set %d as unused for ref\n", pic_num_x); dpb_set_unused_ref_picture_a(dpb, pic); } else { if(!pic->top_is_reference) @@ -1004,8 +1003,7 @@ void decode_ref_pic_marking(struct nal_unit *nal, //printf("FIXME: We might need do delete more from the DPB...\n"); // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120 } - } else - printf("Can't set %d as unused for ref\n", pic_num_x); + } } else if (memory_management_control_operation == 2) { // long-term -> unused for reference struct decoded_picture* pic = dpb_get_picture_by_ltpn(dpb, -- cgit v1.2.3 From a1b2e519be60481831eaad8280427ac1115b15c3 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 25 Jan 2009 17:09:23 +0000 Subject: Switch back to default color standard when necessary. --- src/libvdpau/vdpau_h264.c | 20 +++++++++++++------- src/video_out/video_out_vdpau.c | 9 +++++++-- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 906c65f4c..988c6c676 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -67,6 +67,7 @@ typedef struct vdpau_h264_decoder_s { VdpDecoder decoder; int decoder_started; + VdpColorStandard color_standard; VdpDecoderProfile profile; vdpau_accel_t *vdpau_accel; @@ -490,16 +491,18 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(sps->vui_parameters.colour_description_present) { switch (sps->vui_parameters.colour_primaries) { case 1: - this->vdpau_accel->color_standard = VDP_COLOR_STANDARD_ITUR_BT_709; + this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_709; break; case 5: case 6: default: - this->vdpau_accel->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; + this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; break; } } + this->vdpau_accel->color_standard = this->color_standard; + struct decoded_picture *decoded_pic = NULL; if(pic.is_reference) { if(!slc->field_pic_flag || !this->wait_for_bottom_field) { @@ -672,6 +675,13 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { } free_parser(this->nal_parser); + + this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; + this->wait_for_bottom_field = 0; + this->video_step = 0; + this->curr_pts = 0; + this->next_pts = 0; + this->nal_parser = init_parser(); if(this->codec_private_len > 0) { parse_codec_private(this->nal_parser, this->codec_private, this->codec_private_len); @@ -683,11 +693,6 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->wait_for_frame_start = this->have_frame_boundary_marks; } - this->wait_for_bottom_field = 0; - this->video_step = 0; - this->curr_pts = 0; - this->next_pts = 0; - if (this->dangling_img) { this->dangling_img->free(this->dangling_img); this->dangling_img = NULL; @@ -757,6 +762,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->decoder = VDP_INVALID_HANDLE; this->vdp_runtime_nr = 1; + this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; this->nal_parser = init_parser(); diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index fe387e02f..780a308e9 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -898,6 +898,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ //printf("vo_vdpau: allocated_surfaces=%d\n", this->allocated_surfaces ); + frame->vdpau_accel_data.color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; frame->ratio = ratio; frame->vo_frame.future_frame = NULL; } @@ -1176,7 +1177,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) return; } - if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma) || (color_standard != this->color_standard)) { + if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma)) { vdpau_release_back_frames( this_gen ); /* empty past frames array */ printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); @@ -1190,11 +1191,15 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; this->video_mixer_height = mix_h; - this->color_standard = color_standard; vdpau_set_deinterlace( this_gen ); vdpau_set_inverse_telecine( this_gen ); vdpau_update_noise( this ); vdpau_update_sharpness( this ); + } + + if (color_standard != this->color_standard) { + printf("vo_vdpau: update color_standard: %d\n", color_standard); + this->color_standard = color_standard; vdpau_update_csc( this ); } -- cgit v1.2.3 From a3d246f8ff6bfc1748e5fdfbf24999a06b682960 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 27 Jan 2009 15:09:08 +0000 Subject: Fall back to software decode when no free vdpau decoder. Logging fixups. --- src/libvdpau/vdpau_h264.c | 13 +++++++++++++ src/libvdpau/vdpau_mpeg12.c | 27 +++++++++++++++++++-------- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 988c6c676..ea9c3187c 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -748,6 +748,19 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_H264) ) return NULL; + /* now check if vdpau has free decoder resource */ + vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); + vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + img->free(img); + VdpDecoder decoder; + VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_H264_MAIN, 1920, 1080, 16, &decoder ); + if ( st!=VDP_STATUS_OK ) { + lprintf( "can't create vdpau decoder.\n" ); + return NULL; + } + + accel->vdp_decoder_destroy( decoder ); + this = (vdpau_h264_decoder_t *) calloc(1, sizeof(vdpau_h264_decoder_t)); this->video_decoder.decode_data = vdpau_h264_decode_data; diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 3087868d1..e72341841 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -21,7 +21,7 @@ * */ -//#define LOG +/*#define LOG*/ #define LOG_MODULE "vdpau_mpeg12" @@ -39,8 +39,6 @@ #include - - #define sequence_header_code 0xb3 #define sequence_error_code 0xb4 #define sequence_end_code 0xb7 @@ -809,7 +807,7 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; - printf( "vdpau_mpeg12: vdpau_mpeg12_flush\n" ); + lprintf( "vdpau_mpeg12_flush\n" ); // incorrect: see libmpeg2, mpeg2_flush() // reset_sequence( &this->sequence ); } @@ -820,7 +818,7 @@ static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { static void vdpau_mpeg12_reset (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; - printf( "vdpau_mpeg12: vdpau_mpeg12_reset\n" ); + lprintf( "vdpau_mpeg12_reset\n" ); reset_sequence( &this->sequence ); //this->size = 0; @@ -832,7 +830,7 @@ static void vdpau_mpeg12_reset (video_decoder_t *this_gen) { static void vdpau_mpeg12_discontinuity (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; - printf( "vdpau_mpeg12: vdpau_mpeg12_discontinuity\n" ); + lprintf( "vdpau_mpeg12_discontinuity\n" ); reset_sequence( &this->sequence ); } @@ -844,7 +842,7 @@ static void vdpau_mpeg12_dispose (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; - printf( "vdpau_mpeg12: vdpau_mpeg12_dispose\n" ); + lprintf( "vdpau_mpeg12_dispose\n" ); if ( this->decoder!=VDP_INVALID_HANDLE && this->sequence.accel_vdpau ) { this->sequence.accel_vdpau->vdp_decoder_destroy( this->decoder ); @@ -868,11 +866,24 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre vdpau_mpeg12_decoder_t *this ; + lprintf( "open_plugin\n" ); + /* the videoout must be vdpau-capable to support this decoder */ if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_MPEG12) ) return NULL; - printf( "vdpau_mpeg12: open_plugin\n" ); + /* now check if vdpau has free decoder resource */ + vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); + vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + img->free(img); + VdpDecoder decoder; + VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, 1920, 1080, 2, &decoder ); + if ( st!=VDP_STATUS_OK ) { + lprintf( "can't create vdpau decoder.\n" ); + return NULL; + } + + accel->vdp_decoder_destroy( decoder ); this = (vdpau_mpeg12_decoder_t *) calloc(1, sizeof(vdpau_mpeg12_decoder_t)); -- cgit v1.2.3 From 1b324731e2105519a22f8e37a315d0883a997a70 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 27 Jan 2009 16:52:55 +0000 Subject: Fix pre-emption reinit in case an OSD was shown. --- src/libvdpau/vdpau_h264.c | 3 ++- src/video_out/video_out_vdpau.c | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ea9c3187c..16d8e3fb9 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -446,7 +446,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v this->decoder = VDP_INVALID_HANDLE; vdpau_h264_reset(this_gen); this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; - this->last_img = NULL; + img->free(img); + img = this->last_img = NULL; return 0; } diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 780a308e9..241143bb9 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -788,6 +788,11 @@ static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *origin return; } + if(orig->vdpau_accel_data.vdp_runtime_nr != this->vdpau_accel_data.vdp_runtime_nr) { + fprintf(stderr, "vdpau_duplicate_frame_data: called with invalid frame\n"); + return; + } + if (!(orig->flags & VO_CHROMA_422)) { this->vo_frame.pitches[0] = 8*((orig->vo_frame.width + 7) / 8); this->vo_frame.pitches[1] = 8*((orig->vo_frame.width + 15) / 16); @@ -1623,6 +1628,19 @@ static void vdpau_reinit( vo_driver_t *this_gen ) return; } + // osd overlays need to be recreated + this->overlay_output = VDP_INVALID_HANDLE; + this->overlay_output_width = this->overlay_output_height = 0; + this->overlay_unscaled = VDP_INVALID_HANDLE; + this->overlay_unscaled_width = this->overlay_unscaled_height = 0; + this->ovl_changed = 0; + this->has_overlay = 0; + this->has_unscaled = 0; + + this->argb_overlay = VDP_INVALID_HANDLE; + this->argb_overlay_width = this->argb_overlay_height = 0; + this->has_argb_overlay = 0; + this->video_mixer_chroma = chroma; VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; @@ -1639,10 +1657,10 @@ static void vdpau_reinit( vo_driver_t *this_gen ) vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this); - XUnlockDisplay(guarded_display); - printf("vo_vdpau: Reinit done.\n"); this->vdp_runtime_nr++; this->reinit_needed = 0; + XUnlockDisplay(guarded_display); + printf("vo_vdpau: Reinit done.\n"); } -- cgit v1.2.3 From fbbbd1709643e728166f04df54cc7dc851f146b6 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 29 Jan 2009 14:18:44 +0000 Subject: Clip yuv2rgb values. --- src/video_out/video_out_vdpau.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 241143bb9..5f1857362 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -444,10 +444,15 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) rlelen = rle->len; clr = rle->color; for ( i=0; i Date: Thu, 29 Jan 2009 14:18:44 +0000 Subject: Blend types list termination. --- src/video_out/video_out_vdpau.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 5f1857362..58a775b5a 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -60,15 +60,14 @@ const char *vdpau_deinterlace_methods[] = { NULL }; - - VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, - VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE , + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, - VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD }; + VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, + 0 }; -- cgit v1.2.3 From e8c9517c396f161b752c85a8b048c7cdde8c9496 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 30 Jan 2009 17:32:06 +0000 Subject: Initial VC1 commit. --- src/libvdpau/Makefile.am | 7 +- src/libvdpau/vdpau_vc1.c | 618 ++++++++++++++++++++++++++++++++++++++++++++ src/xine-engine/video_out.h | 1 + 3 files changed, 625 insertions(+), 1 deletion(-) create mode 100644 src/libvdpau/vdpau_vc1.c diff --git a/src/libvdpau/Makefile.am b/src/libvdpau/Makefile.am index dc7ace0a7..140168483 100644 --- a/src/libvdpau/Makefile.am +++ b/src/libvdpau/Makefile.am @@ -8,9 +8,11 @@ vdpau_h264_module = xineplug_decode_vdpau_h264.la VDPAU_CFLAGS = -D_ISOC99_SOURCE vdpau_mpeg12_module = xineplug_decode_vdpau_mpeg12.la + +vdpau_vc1_module = xineplug_decode_vdpau_vc1.la endif -xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) +xineplug_LTLIBRARIES = $(vdpau_h264_module) $(vdpau_mpeg12_module) $(vdpau_vc1_module) xineplug_decode_vdpau_h264_la_SOURCES = nal.c dpb.c h264_parser.c vdpau_h264.c xineplug_decode_vdpau_h264_la_CFLAGS = $(AM_CFLAGS) $(VDPAU_CFLAGS) @@ -20,3 +22,6 @@ xineplug_decode_vdpau_mpeg12_la_SOURCES = vdpau_mpeg12.c xineplug_decode_vdpau_mpeg12_la_CFLAGS = $(AM_CFLAGS) xineplug_decode_vdpau_mpeg12_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) +xineplug_decode_vdpau_vc1_la_SOURCES = vdpau_vc1.c +xineplug_decode_vdpau_vc1_la_CFLAGS = $(AM_CFLAGS) +xineplug_decode_vdpau_vc1_la_LIBADD = $(XINE_LIB) $(DYNAMIC_LD_LIBS) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c new file mode 100644 index 000000000..74b70d8ff --- /dev/null +++ b/src/libvdpau/vdpau_vc1.c @@ -0,0 +1,618 @@ +/* + * Copyright (C) 2008 Christophe Thommeret + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + * + * vdpau_vc1.c, a vc1 video stream parser using VDPAU hardware decoder + * + */ + +#define LOG +#define LOG_MODULE "vdpau_vc1" + + +#include +#include +#include +#include +#include + +#include "xine_internal.h" +#include "video_out.h" +#include "buffer.h" +#include "xineutils.h" +#include "accel_vdpau.h" + +#include + +#define sequence_header_code 0x0f +#define sequence_end_code 0x0a +#define entry_point_code 0x0e +#define frame_start_code 0x0d +#define field_start_code 0x0c +#define slice_start_code 0x0b + +#define PICTURE_FRAME 0 +#define PICTURE_FRAME_INTERLACE 2 +#define PICTURE_FIELD_INTERLACE 3 + +#define WANT_HEADER 1 +#define WANT_EXT 2 +#define WANT_SLICE 3 + + + +typedef struct { + VdpPictureInfoVC1 vdp_infos; + + int progressive_frame; + int state; +} picture_t; + + + +typedef struct { + uint32_t coded_width; + uint32_t coded_height; + + uint64_t video_step; /* frame duration in pts units */ + double ratio; + VdpDecoderProfile profile; + + int have_header; + + uint8_t *buf; /* accumulate data */ + uint32_t bufsize; + uint32_t bufpos; + + picture_t picture; + vo_frame_t *forward_ref; + vo_frame_t *backward_ref; + + int64_t seq_pts; + int64_t cur_pts; + + vdpau_accel_t *accel_vdpau; + + int vdp_runtime_nr; + +} sequence_t; + + + +typedef struct { + video_decoder_class_t decoder_class; +} vdpau_vc1_class_t; + + + +typedef struct vdpau_vc1_decoder_s { + video_decoder_t video_decoder; /* parent video decoder structure */ + + vdpau_vc1_class_t *class; + xine_stream_t *stream; + + sequence_t sequence; + + VdpDecoder decoder; + VdpDecoderProfile decoder_profile; + uint32_t decoder_width; + uint32_t decoder_height; + +} vdpau_vc1_decoder_t; + + + +static void reset_picture( picture_t *pic ) +{ + lprintf( "reset_picture\n" ); + /*pic->vdp_infos.picture_structure = 0; + pic->vdp_infos2.intra_dc_precision = pic->vdp_infos.intra_dc_precision = 0; + pic->vdp_infos2.frame_pred_frame_dct = pic->vdp_infos.frame_pred_frame_dct = 1; + pic->vdp_infos2.concealment_motion_vectors = pic->vdp_infos.concealment_motion_vectors = 0; + pic->vdp_infos2.intra_vlc_format = pic->vdp_infos.intra_vlc_format = 0; + pic->vdp_infos2.alternate_scan = pic->vdp_infos.alternate_scan = 0; + pic->vdp_infos2.q_scale_type = pic->vdp_infos.q_scale_type = 0; + pic->vdp_infos2.top_field_first = pic->vdp_infos.top_field_first = 0; + pic->slices_count = 0; + pic->slices_count2 = 0; + pic->slices_pos = 0; + pic->slices_pos_top = 0; + pic->state = WANT_HEADER;*/ +} + + + +static void init_picture( picture_t *pic ) +{ + reset_picture( pic ); +} + + + +static void init_sequence( sequence_t *sequence ) +{ + lprintf( "init_sequence\n" ); + sequence->have_header = 0; + sequence->bufpos = 0; + sequence->seq_pts = sequence->cur_pts = 0; + sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; + sequence->ratio = 0; + sequence->video_step = 0; + if ( sequence->forward_ref ) + sequence->forward_ref->free( sequence->forward_ref ); + sequence->forward_ref = NULL; + if ( sequence->backward_ref ) + sequence->backward_ref->free( sequence->backward_ref ); + sequence->backward_ref = NULL; +} + + + +static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) +{ + int i, nbytes; + uint32_t ret = 0; + uint8_t *buf; + + buf = b+(offbits/8); + offbits %=8; + nbytes = (offbits+nbits)/8; + if ( ((offbits+nbits)%8)>0 ) + nbytes++; + for ( i=0; i>i)>>((nbytes*8)-nbits-offbits); + + return ret; +} + + + +static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ +} + + + +static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + + if ( len < 4 ) + return; + + lprintf( "sequence_header\n" ); + + switch ( get_bits(buf,0,2) ) { + case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; break; + case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; break; + case 3: return sequence_header_advanced( this_gen, buf, len ); break; + default: return; /* illegal value, broken header? */ + } + + sequence->picture.vdp_infos.loopfilter = get_bits(buf,12,1); + sequence->picture.vdp_infos.multires = get_bits(buf,14,1); + sequence->picture.vdp_infos.fastuvmc = get_bits(buf,16,1); + sequence->picture.vdp_infos.extended_mv = get_bits(buf,17,1); + sequence->picture.vdp_infos.dquant = get_bits(buf,18,2); + sequence->picture.vdp_infos.vstransform = get_bits(buf,20,1); + sequence->picture.vdp_infos.overlap = get_bits(buf,22,1); + sequence->picture.vdp_infos.syncmarker = get_bits(buf,23,1); + sequence->picture.vdp_infos.rangered = get_bits(buf,24,1); + sequence->picture.vdp_infos.maxbframes = get_bits(buf,25,3); + sequence->picture.vdp_infos.quantizer = get_bits(buf,28,2); + sequence->picture.vdp_infos.finterpflag = get_bits(buf,30,1); + + if ( !sequence->have_header ) { + sequence->have_header = 1; + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); + _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "VC1/WMV9 (vdpau)" ); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = this_gen->stream; + event.data = &data; + event.data_length = sizeof(data); + data.width = sequence->coded_width; + data.height = sequence->coded_height; + data.aspect = sequence->ratio; + xine_event_send( this_gen->stream, &event ); + } +} + + + +static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); + + int off=2; + + if ( info->finterpflag ) + ++off; + if ( info->rangered ) + ++off; + if ( !info->maxbframes ) + info->picture_type = get_bits( buf,off,1 ); + else { + int ptype = get_bits( buf,off,1 ); + if ( ptype ) { + info->picture_type = ptype; + ++off; + } + else { + info->picture_type = get_bits( buf,off,2 ); + off += 2; + } + } + +} + + + +static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel ) +{ + sequence_t *seq = (sequence_t*)&vd->sequence; + picture_t *pic = (picture_t*)&seq->picture; + + VdpStatus st; + if ( vd->decoder==VDP_INVALID_HANDLE || vd->decoder_profile!=seq->profile || vd->decoder_width!=seq->coded_width || vd->decoder_height!=seq->coded_height ) { + if ( vd->decoder!=VDP_INVALID_HANDLE ) { + accel->vdp_decoder_destroy( vd->decoder ); + vd->decoder = VDP_INVALID_HANDLE; + } + st = accel->vdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder); + if ( st!=VDP_STATUS_OK ) + lprintf( "failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); + else { + lprintf( "decoder created.\n" ); + vd->decoder_profile = seq->profile; + vd->decoder_width = seq->coded_width; + vd->decoder_height = seq->coded_height; + seq->vdp_runtime_nr = accel->vdp_runtime_nr; + } + } + + VdpBitstreamBuffer vbit; + vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit.bitstream = seq->buf; + vbit.bitstream_bytes = seq->bufpos; + st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); + if ( st!=VDP_STATUS_OK ) + lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); + else { + lprintf( "DECODER SUCCESS : slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", + pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + } +} + + + +static void decode_picture( vdpau_vc1_decoder_t *vd ) +{ + sequence_t *seq = (sequence_t*)&vd->sequence; + + seq->picture.vdp_infos.picture_type = 1; + VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); + info->forward_reference = VDP_INVALID_HANDLE; + info->backward_reference = VDP_INVALID_HANDLE; + printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + + vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, + seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); + vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + if ( !seq->accel_vdpau ) + seq->accel_vdpau = accel; + + if( seq->vdp_runtime_nr != *(seq->accel_vdpau->current_vdp_runtime_nr) ) { + seq->accel_vdpau = accel; + if ( seq->forward_ref ) + seq->forward_ref->free( seq->forward_ref ); + seq->forward_ref = NULL; + if ( seq->backward_ref ) + seq->backward_ref->free( seq->backward_ref ); + seq->backward_ref = NULL; + vd->decoder = VDP_INVALID_HANDLE; + } + + decode_render( vd, accel ); + + img->pts = seq->seq_pts; + img->draw( img, vd->stream ); + img->free( img ); +} + + + +/* + * This function receives a buffer of data from the demuxer layer and + * figures out how to handle it based on its header flags. + */ +static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf) +{ + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + sequence_t *seq = (sequence_t*)&this->sequence; + + /* a video decoder does not care about this flag (?) */ + if (buf->decoder_flags & BUF_FLAG_PREVIEW) { + lprintf("BUF_FLAG_PREVIEW\n"); + return; + } + + if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { + lprintf("BUF_FLAG_FRAMERATE=%d\n", buf->decoder_info[0]); + if ( buf->decoder_info[0] > 0 ) { + this->sequence.video_step = buf->decoder_info[0]; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->sequence.video_step); + } + } + + if (buf->decoder_flags & BUF_FLAG_HEADER) { + lprintf("BUF_FLAG_HEADER\n"); + } + + if (buf->decoder_flags & BUF_FLAG_ASPECT) { + lprintf("BUF_FLAG_ASPECT\n"); + seq->ratio = (double)buf->decoder_info[1]/(double)buf->decoder_info[2]; + lprintf("arx=%d ary=%d ratio=%f\n", buf->decoder_info[1], buf->decoder_info[2], seq->ratio); + } + + if (buf->decoder_flags & BUF_FLAG_FRAME_START) { + lprintf("BUF_FLAG_FRAME_START\n"); + seq->seq_pts = buf->pts; + } + + if ( !buf->size ) + return; + + //printf("vdpau_vc1_decode_data: new pts : %lld\n", buf->pts ); + seq->cur_pts = buf->pts; + + if (buf->decoder_flags & BUF_FLAG_STDHEADER) { + lprintf("BUF_FLAG_STDHEADER\n"); + xine_bmiheader *bih = (xine_bmiheader *) buf->content; + int bs = sizeof( xine_bmiheader ); + seq->coded_width = bih->biWidth; + seq->coded_height = bih->biHeight; + lprintf( "width=%d height=%d\n", bih->biWidth, bih->biHeight ); + if ( buf->size > bs ) { + sequence_header( this, buf->content+bs, buf->size-bs ); + } + int i; + for ( i=0; isize; ++i ) + printf("%02X ", buf->content[i] ); + printf("\n\n"); + return; + } + + int size = seq->bufpos+buf->size; + if ( seq->bufsize < size ) { + seq->bufsize = size+10000; + seq->buf = realloc( seq->buf, seq->bufsize ); + lprintf("sequence buffer realloced = %d\n", seq->bufsize ); + } + xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size ); + seq->bufpos += buf->size; + + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { + lprintf("BUF_FLAG_FRAME_END\n"); + seq->picture.vdp_infos.slice_count = 1; + decode_picture( this ); + seq->bufpos = 0; + } + + + /*int i; + for ( i=0; isize; ++i ) + printf("%02X ", buf->content[i] ); + printf("\n\n"); + + uint8_t *buffer = buf->content; + for ( i=0; isize-4; ++i ) { + if ( buffer[i]==0 && buffer[i+1]==0 && buffer[i+2]==1 ) + printf("start code\n"); + }*/ +} + + +/* + * This function is called when xine needs to flush the system. + */ +static void vdpau_vc1_flush (video_decoder_t *this_gen) { + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + + lprintf( "vdpau_vc1_flush\n" ); +} + +/* + * This function resets the video decoder. + */ +static void vdpau_vc1_reset (video_decoder_t *this_gen) { + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + + lprintf( "vdpau_vc1_reset\n" ); + init_sequence( &this->sequence ); + + //this->size = 0; +} + +/* + * The decoder should forget any stored pts values here. + */ +static void vdpau_vc1_discontinuity (video_decoder_t *this_gen) { + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + + lprintf( "vdpau_vc1_discontinuity\n" ); + init_sequence( &this->sequence ); + +} + +/* + * This function frees the video decoder instance allocated to the decoder. + */ +static void vdpau_vc1_dispose (video_decoder_t *this_gen) { + + vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; + + lprintf( "vdpau_vc1_dispose\n" ); + + if ( this->decoder!=VDP_INVALID_HANDLE && this->sequence.accel_vdpau ) { + this->sequence.accel_vdpau->vdp_decoder_destroy( this->decoder ); + this->decoder = VDP_INVALID_HANDLE; + } + + this->stream->video_out->close( this->stream->video_out, this->stream ); + + free( this->sequence.buf ); + free( this_gen ); +} + +/* + * This function allocates, initializes, and returns a private video + * decoder structure. + */ +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { + + vdpau_vc1_decoder_t *this ; + + lprintf( "open_plugin\n" ); + + /* the videoout must be vdpau-capable to support this decoder */ + if ( !(stream->video_driver->get_capabilities(stream->video_driver) & VO_CAP_VDPAU_VC1) ) + return NULL; + + /* now check if vdpau has free decoder resource */ + vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); + vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + img->free(img); + VdpDecoder decoder; + VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, 1920, 1080, 2, &decoder ); + if ( st!=VDP_STATUS_OK ) { + lprintf( "can't create vdpau decoder.\n" ); + return NULL; + } + + accel->vdp_decoder_destroy( decoder ); + + this = (vdpau_vc1_decoder_t *) calloc(1, sizeof(vdpau_vc1_decoder_t)); + + this->video_decoder.decode_data = vdpau_vc1_decode_data; + this->video_decoder.flush = vdpau_vc1_flush; + this->video_decoder.reset = vdpau_vc1_reset; + this->video_decoder.discontinuity = vdpau_vc1_discontinuity; + this->video_decoder.dispose = vdpau_vc1_dispose; + + this->stream = stream; + this->class = (vdpau_vc1_class_t *) class_gen; + + this->sequence.bufsize = 10000; + this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize); + this->sequence.forward_ref = 0; + this->sequence.backward_ref = 0; + this->sequence.vdp_runtime_nr = 1; + init_sequence( &this->sequence ); + + init_picture( &this->sequence.picture ); + + this->decoder = VDP_INVALID_HANDLE; + this->sequence.accel_vdpau = NULL; + + (stream->video_out->open)(stream->video_out, stream); + + return &this->video_decoder; +} + +/* + * This function returns a brief string that describes (usually with the + * decoder's most basic name) the video decoder plugin. + */ +static char *get_identifier (video_decoder_class_t *this) { + return "vdpau_vc1"; +} + +/* + * This function returns a slightly longer string describing the video + * decoder plugin. + */ +static char *get_description (video_decoder_class_t *this) { + return "vdpau_vc1: vc1 decoder plugin using VDPAU hardware decoding.\n" + "Must be used along with video_out_vdpau."; +} + +/* + * This function frees the video decoder class and any other memory that was + * allocated. + */ +static void dispose_class (video_decoder_class_t *this) { + free (this); +} + +/* + * This function allocates a private video decoder class and initializes + * the class's member functions. + */ +static void *init_plugin (xine_t *xine, void *data) { + + vdpau_vc1_class_t *this; + + this = (vdpau_vc1_class_t *) calloc(1, sizeof(vdpau_vc1_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; + + return this; +} + +/* + * This is a list of all of the internal xine video buffer types that + * this decoder is able to handle. Check src/xine-engine/buffer.h for a + * list of valid buffer types (and add a new one if the one you need does + * not exist). Terminate the list with a 0. + */ +static const uint32_t video_types[] = { + BUF_VIDEO_VC1, BUF_VIDEO_WMV9, + 0 +}; + +/* + * This data structure combines the list of supported xine buffer types and + * the priority that the plugin should be given with respect to other + * plugins that handle the same buffer type. A plugin with priority (n+1) + * will be used instead of a plugin with priority (n). + */ +static const decoder_info_t dec_info_video = { + video_types, /* supported types */ + 8 /* priority */ +}; + +/* + * The plugin catalog entry. This is the only information that this plugin + * will export to the public. + */ +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* { type, API, "name", version, special_info, init_function } */ + { PLUGIN_VIDEO_DECODER, 18, "vdpau_vc1", XINE_VERSION_CODE, &dec_info_video, init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index 845ab0079..bbf0dcc35 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -296,6 +296,7 @@ struct xine_video_port_s { #define VO_CAP_XXMC 0x00000040 /* driver can use extended XvMC */ #define VO_CAP_VDPAU_H264 0x00000080 /* driver can use VDPAU for H264 */ #define VO_CAP_VDPAU_MPEG12 0x00000100 /* driver can use VDPAU for mpeg1/2 */ +#define VO_CAP_VDPAU_VC1 0x00000200 /* driver can use VDPAU for mpeg1/2 */ #define VO_CAP_CUSTOM_EXTENT_OVERLAY 0x01000000 /* driver can blend custom extent overlay to output extent */ #define VO_CAP_ARGB_LAYER_OVERLAY 0x02000000 /* driver supports true color overlay */ -- cgit v1.2.3 From 52c4074834a75fd4aee00bcf9bce0ad341b4f36b Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 30 Jan 2009 17:36:50 +0000 Subject: Fix aspect ratio. --- src/libvdpau/vdpau_vc1.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 74b70d8ff..ce99f1a8e 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -151,7 +151,7 @@ static void init_sequence( sequence_t *sequence ) sequence->bufpos = 0; sequence->seq_pts = sequence->cur_pts = 0; sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; - sequence->ratio = 0; + //sequence->ratio = 0; sequence->video_step = 0; if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); @@ -312,7 +312,6 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) { sequence_t *seq = (sequence_t*)&vd->sequence; - seq->picture.vdp_infos.picture_type = 1; VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); info->forward_reference = VDP_INVALID_HANDLE; info->backward_reference = VDP_INVALID_HANDLE; -- cgit v1.2.3 From 71b549cef6216b400045de3d331e22adbe87e7cd Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sat, 31 Jan 2009 13:16:37 +0000 Subject: Code cleanup. --- src/libvdpau/dpb.c | 10 +++---- src/libvdpau/h264_parser.c | 66 +++++++++++++++++++++++----------------------- src/libvdpau/nal.h | 3 ++- src/libvdpau/vdpau_h264.c | 2 +- 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index acc3f0865..9aa2f4298 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -347,13 +347,11 @@ int fill_vdpau_reference_list(struct dpb *dpb, VdpReferenceFrameH264 *reflist) reflist[i].surface = pic->surface; reflist[i].is_long_term = pic->nal->used_for_long_term_ref; if(reflist[i].is_long_term) - reflist[i].frame_idx = pic->nal->slc->frame_num; //pic->nal->long_term_frame_idx; + reflist[i].frame_idx = pic->nal->slc->frame_num; else - reflist[i].frame_idx = pic->nal->slc->frame_num; //pic->nal->curr_pic_num; - reflist[i].top_is_reference = pic->top_is_reference; /*pic->nal->slc->field_pic_flag - ? (pic->nal->slc->bottom_field_flag ? 0 : 1) : 1;*/ - reflist[i].bottom_is_reference = pic->bottom_is_reference; /*pic->nal->slc->field_pic_flag - ? (pic->nal->slc->bottom_field_flag ? 1 : 0) : 1;*/ + reflist[i].frame_idx = pic->nal->slc->frame_num; + reflist[i].top_is_reference = pic->top_is_reference; + reflist[i].bottom_is_reference = pic->bottom_is_reference; reflist[i].field_order_cnt[0] = pic->nal->top_field_order_cnt; reflist[i].field_order_cnt[1] = pic->nal->bottom_field_order_cnt; i++; diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index f19383f8a..37ad1402b 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -442,11 +442,11 @@ static void pps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, struct uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) { struct seq_parameter_set_rbsp *sps = parser->current_nal->sps; - sps->profile_idc = buf->buf[0]; - sps->constraint_setN_flag = (buf->buf[1] >> 4) & 0x0f; - sps->level_idc = buf->buf[2]; + sps->profile_idc = read_bits(buf, 8); + sps->constraint_setN_flag = read_bits(buf, 4); + read_bits(buf, 4); + sps->level_idc = read_bits(buf, 8); - buf->cur_pos = buf->buf + 3; sps->seq_parameter_set_id = read_exp_golomb(buf); memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); @@ -455,7 +455,7 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) == 122 || sps->profile_idc == 144) { sps->chroma_format_idc = read_exp_golomb(buf); if (sps->chroma_format_idc == 3) { - sps->residual_colour_transform_flag = read_bits(buf, 1); + sps->separate_colour_plane_flag = read_bits(buf, 1); } sps->bit_depth_luma_minus8 = read_exp_golomb(buf); @@ -484,7 +484,7 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) sps->pic_order_cnt_type = read_exp_golomb(buf); if (!sps->pic_order_cnt_type) sps->log2_max_pic_order_cnt_lsb_minus4 = read_exp_golomb(buf); - else { + else if(sps->pic_order_cnt_type == 1) { sps->delta_pic_order_always_zero_flag = read_bits(buf, 1); sps->offset_for_non_ref_pic = read_exp_golomb_s(buf); sps->offset_for_top_to_bottom_field = read_exp_golomb_s(buf); @@ -661,7 +661,6 @@ void parse_vui_parameters(struct buf_reader *buf, sps->vui_parameters.log2_max_mv_length_vertical = read_exp_golomb(buf); sps->vui_parameters.num_reorder_frames = read_exp_golomb(buf); sps->vui_parameters.max_dec_frame_buffering = read_exp_golomb(buf); - printf("Max_dec_frame_buffering: %d\n", sps->vui_parameters.max_dec_frame_buffering); } } @@ -738,7 +737,6 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, memset(pps->scaling_lists_4x4, 16, sizeof(pps->scaling_lists_4x4)); memset(pps->scaling_lists_8x8, 16, sizeof(pps->scaling_lists_8x8)); if (bit_length-bit_read > 1) { - printf("Read transform 8x8\n"); pps->transform_8x8_mode_flag = read_bits(buf, 1); pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); if (pps->pic_scaling_matrix_present_flag) { @@ -786,6 +784,9 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) //print_slice_type(slc->slice_type); slc->pic_parameter_set_id = read_exp_golomb(buf); + if(sps->separate_colour_plane_flag) + slc->colour_plane_id = read_bits(buf, 2); + slc->frame_num = read_bits(buf, sps->log2_max_frame_num_minus4 + 4); if (!sps->frame_mbs_only_flag) { slc->field_pic_flag = read_bits(buf, 1); @@ -816,7 +817,8 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) if (pps->pic_order_present_flag && !slc->field_pic_flag) slc->delta_pic_order_cnt_bottom = read_exp_golomb_s(buf); } - else if (sps->pic_order_cnt_type == 1) { + + if (sps->pic_order_cnt_type == 1 && !sps->delta_pic_order_always_zero_flag) { slc->delta_pic_order_cnt[0] = read_exp_golomb_s(buf); if (pps->pic_order_present_flag && !slc->field_pic_flag) slc->delta_pic_order_cnt[1] = read_exp_golomb_s(buf); @@ -863,11 +865,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) void parse_ref_pic_list_reordering(struct buf_reader *buf, struct nal_unit *nal, struct nal_parser *parser) { - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; - if (!sps || !pps) - return; if (slc->slice_type != SLICE_I && slc->slice_type != SLICE_SI) { slc->ref_pic_list_reordering.ref_pic_list_reordering_flag_l0 = read_bits( @@ -922,7 +920,11 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) nal->slc->pred_weight_table.luma_log2_weight_denom = read_exp_golomb(buf); - if (sps->chroma_format_idc != 0) + uint32_t ChromaArrayType = sps->chroma_format_idc; + if(sps->separate_colour_plane_flag) + ChromaArrayType = 0; + + if (ChromaArrayType != 0) nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); int i; @@ -934,7 +936,7 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) nal->slc->pred_weight_table.luma_offset_l0[i] = read_exp_golomb_s(buf); } - if (sps->chroma_format_idc != 0) { + if (ChromaArrayType != 0) { uint8_t chroma_weight_l0_flag = read_bits(buf, 1); if (chroma_weight_l0_flag == 1) { @@ -958,7 +960,7 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) nal->slc->pred_weight_table.luma_offset_l1[i] = read_exp_golomb_s(buf); } - if (sps->chroma_format_idc != 0) { + if (ChromaArrayType != 0) { uint8_t chroma_weight_l1_flag = read_bits(buf, 1); if (chroma_weight_l1_flag == 1) { @@ -980,17 +982,15 @@ void decode_ref_pic_marking(struct nal_unit *nal, uint32_t marking_nr, struct nal_parser *parser) { - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; struct dpb *dpb = &parser->dpb; - if (!sps || !pps || !slc) + if (!slc) return; if (memory_management_control_operation == 1) { // short-term -> unused for reference uint32_t pic_num_x = (nal->curr_pic_num - - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1))%nal->max_pic_num; + - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1))%(nal->max_pic_num+1); struct decoded_picture* pic = NULL; if ((pic = dpb_get_picture(dpb, pic_num_x)) != NULL) { if (pic->nal->slc->field_pic_flag == 0) { @@ -1083,10 +1083,9 @@ void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_parser *parser) { struct nal_unit *nal = parser->current_nal; - struct seq_parameter_set_rbsp *sps = nal->sps; - struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; - if (!sps || !pps) + + if (!slc) return; slc->dec_ref_pic_marking_count = 0; @@ -1095,8 +1094,7 @@ void parse_dec_ref_pic_marking(struct buf_reader *buf, if (nal->nal_unit_type == NAL_SLICE_IDR) { slc->dec_ref_pic_marking[i].no_output_of_prior_pics_flag = read_bits(buf, 1); slc->dec_ref_pic_marking[i].long_term_reference_flag = read_bits(buf, 1); - } - else { + } else { slc->dec_ref_pic_marking[i].adaptive_ref_pic_marking_mode_flag = read_bits( buf, 1); @@ -1133,7 +1131,7 @@ void parse_dec_ref_pic_marking(struct buf_reader *buf, } } - slc->dec_ref_pic_marking_count = i; + slc->dec_ref_pic_marking_count = (i>0) ? (i-1) : 0; } /* ----------------- NAL parser ----------------- */ @@ -1238,17 +1236,19 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t *prebuf = parser->prebuf; if(parser->nal_size_length > 0) - start_seq_len = 4-parser->have_nal_size_length_buf; + start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; if(parser->last_nal_res == 1 && parser->current_nal && parser->current_nal->slc) { int i; for(i = 0; i < parser->current_nal->slc->dec_ref_pic_marking_count; i++) { - decode_ref_pic_marking( - parser->current_nal, - parser->current_nal->slc->dec_ref_pic_marking[i].memory_management_control_operation, - i, - parser); + if(parser->current_nal->slc->dec_ref_pic_marking[i].adaptive_ref_pic_marking_mode_flag) { + decode_ref_pic_marking( + parser->current_nal, + parser->current_nal->slc->dec_ref_pic_marking[i].memory_management_control_operation, + i, + parser); + } } if (parser->last_nal->slc != NULL) @@ -1260,7 +1260,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset, parser)) >= 0) { next_nal += search_offset; if(parser->nal_size_length > 0) - start_seq_len = 4-parser->have_nal_size_length_buf; + start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; if(parser->incomplete_nal || completed_nal || next_nal == 0 || parser->nal_size_length) { diff --git a/src/libvdpau/nal.h b/src/libvdpau/nal.h index e03a69242..4e039b8b8 100644 --- a/src/libvdpau/nal.h +++ b/src/libvdpau/nal.h @@ -164,7 +164,7 @@ struct seq_parameter_set_rbsp uint8_t level_idc; // 0xff uint32_t seq_parameter_set_id; uint32_t chroma_format_idc; - uint8_t residual_colour_transform_flag; // 0x01 + uint8_t separate_colour_plane_flag; // 0x01 uint32_t bit_depth_luma_minus8; uint32_t bit_depth_chroma_minus8; uint8_t qpprime_y_zero_transform_bypass_flag; @@ -350,6 +350,7 @@ struct slice_header uint32_t first_mb_in_slice; uint32_t slice_type; uint32_t pic_parameter_set_id; + uint8_t colour_plane_id; uint32_t frame_num; uint8_t field_pic_flag; uint8_t bottom_field_flag; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 16d8e3fb9..8197a936a 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -626,7 +626,7 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, while(len < buf->size && !(this->wait_for_frame_start && !(buf->decoder_flags & BUF_FLAG_FRAME_START))) { this->wait_for_frame_start = 0; len += parse_frame(this->nal_parser, buf->content + len, buf->size - len, - (void*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); + (uint8_t*)&vdp_buffer.bitstream, &vdp_buffer.bitstream_bytes, &slice_count); if(this->decoder == VDP_INVALID_HANDLE && this->nal_parser->current_nal->sps != NULL && -- cgit v1.2.3 From 96ad7c0f1317b2efb949f23a86645f839eab31dd Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 31 Jan 2009 17:07:59 +0000 Subject: VC1 update. --- src/libvdpau/vdpau_vc1.c | 114 +++++++++++++++++++++++++++++++++------- src/video_out/video_out_raw.c | 15 ++++-- src/video_out/video_out_vdpau.c | 4 +- 3 files changed, 105 insertions(+), 28 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index ce99f1a8e..1ee76d2c4 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -50,6 +50,10 @@ #define PICTURE_FRAME_INTERLACE 2 #define PICTURE_FIELD_INTERLACE 3 +#define I_FRAME 1 +#define P_FRAME 2 +#define B_FRAME 3 + #define WANT_HEADER 1 #define WANT_EXT 2 #define WANT_SLICE 3 @@ -58,9 +62,7 @@ typedef struct { VdpPictureInfoVC1 vdp_infos; - - int progressive_frame; - int state; + int type; } picture_t; @@ -144,15 +146,11 @@ static void init_picture( picture_t *pic ) -static void init_sequence( sequence_t *sequence ) +static void reset_sequence( sequence_t *sequence ) { - lprintf( "init_sequence\n" ); - sequence->have_header = 0; + lprintf( "reset_sequence\n" ); sequence->bufpos = 0; sequence->seq_pts = sequence->cur_pts = 0; - sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; - //sequence->ratio = 0; - sequence->video_step = 0; if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); sequence->forward_ref = NULL; @@ -163,6 +161,18 @@ static void init_sequence( sequence_t *sequence ) +static void init_sequence( sequence_t *sequence ) +{ + lprintf( "init_sequence\n" ); + sequence->have_header = 0; + sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; + sequence->ratio = 0; + sequence->video_step = 0; + reset_sequence( sequence ); +} + + + static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) { int i, nbytes; @@ -186,6 +196,7 @@ static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) { + lprintf( "sequence_header_advanced\n" ); } @@ -200,8 +211,8 @@ static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int le lprintf( "sequence_header\n" ); switch ( get_bits(buf,0,2) ) { - case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; break; - case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; break; + case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; lprintf("VDP_DECODER_PROFILE_VC1_SIMPLE\n"); break; + case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("VDP_DECODER_PROFILE_VC1_MAIN\n"); break; case 3: return sequence_header_advanced( this_gen, buf, len ); break; default: return; /* illegal value, broken header? */ } @@ -244,6 +255,7 @@ static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int le static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) { sequence_t *sequence = (sequence_t*)&this_gen->sequence; + picture_t *pic = (picture_t*)&sequence->picture; VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); int off=2; @@ -252,20 +264,29 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ++off; if ( info->rangered ) ++off; - if ( !info->maxbframes ) + if ( !info->maxbframes ) { info->picture_type = get_bits( buf,off,1 ); + if ( info->picture_type ) + pic->type = P_FRAME; + else + pic->type = I_FRAME; + } else { int ptype = get_bits( buf,off,1 ); if ( ptype ) { info->picture_type = ptype; + pic->type = P_FRAME; ++off; } else { info->picture_type = get_bits( buf,off,2 ); + if ( info->picture_type ) + pic->type = I_FRAME; + else + pic->type = B_FRAME; off += 2; } } - } @@ -311,11 +332,39 @@ static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel ) static void decode_picture( vdpau_vc1_decoder_t *vd ) { sequence_t *seq = (sequence_t*)&vd->sequence; + picture_t *pic = (picture_t*)&seq->picture; + vdpau_accel_t *ref_accel; + + picture_header( vd, seq->buf, seq->bufpos ); VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); - info->forward_reference = VDP_INVALID_HANDLE; - info->backward_reference = VDP_INVALID_HANDLE; - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, pic->type, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + + pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; + pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; + + if ( pic->type==P_FRAME ) { + if ( seq->backward_ref ) { + ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; + pic->vdp_infos.forward_reference = ref_accel->surface; + } + else + return; + } + else if ( pic->type==B_FRAME ) { + if ( seq->forward_ref ) { + ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; + pic->vdp_infos.forward_reference = ref_accel->surface; + } + else + return; + if ( seq->backward_ref ) { + ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; + pic->vdp_infos.backward_reference = ref_accel->surface; + } + else + return; + } vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); @@ -337,8 +386,31 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) decode_render( vd, accel ); img->pts = seq->seq_pts; - img->draw( img, vd->stream ); - img->free( img ); + img->bad_frame = 0; + img->duration = seq->video_step; + + if ( pic->type!=B_FRAME ) { + if ( pic->type==I_FRAME && !seq->backward_ref ) { + img->pts = 0; + img->draw( img, vd->stream ); + ++img->drawn; + } + if ( seq->forward_ref ) { + seq->forward_ref->drawn = 0; + seq->forward_ref->free( seq->forward_ref ); + } + seq->forward_ref = seq->backward_ref; + if ( seq->forward_ref && !seq->forward_ref->drawn ) { + seq->forward_ref->draw( seq->forward_ref, vd->stream ); + } + seq->backward_ref = img; + } + else { + img->draw( img, vd->stream ); + img->free( img ); + } + + seq->seq_pts +=seq->video_step; } @@ -450,7 +522,7 @@ static void vdpau_vc1_reset (video_decoder_t *this_gen) { vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; lprintf( "vdpau_vc1_reset\n" ); - init_sequence( &this->sequence ); + reset_sequence( &this->sequence ); //this->size = 0; } @@ -462,7 +534,7 @@ static void vdpau_vc1_discontinuity (video_decoder_t *this_gen) { vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; lprintf( "vdpau_vc1_discontinuity\n" ); - init_sequence( &this->sequence ); + //reset_sequence( &this->sequence ); } @@ -480,6 +552,8 @@ static void vdpau_vc1_dispose (video_decoder_t *this_gen) { this->decoder = VDP_INVALID_HANDLE; } + reset_sequence( &this->sequence ); + this->stream->video_out->close( this->stream->video_out, this->stream ); free( this->sequence.buf ); diff --git a/src/video_out/video_out_raw.c b/src/video_out/video_out_raw.c index f3afb4aaa..52b959985 100644 --- a/src/video_out/video_out_raw.c +++ b/src/video_out/video_out_raw.c @@ -163,11 +163,16 @@ static int raw_process_ovl( raw_driver_t *this_gen, vo_overlay_t *overlay ) clr = rle->color; alpha = trans[clr]; for ( i=0; icapabilities |= VO_CAP_VDPAU_H264; - /*st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, &ok, &ml, &mr, &mw, &mh ); + st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, &ok, &ml, &mr, &mw, &mh ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: getting vc1_supported failed! : %s\n", vdp_get_error_string( st ) ); else if ( !ok ) @@ -2010,8 +2010,6 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo else this->capabilities |= VO_CAP_VDPAU_VC1; - this->capabilities |= VO_CAP_VDPAU_VC1;*/ - st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, &ok, &ml, &mr, &mw, &mh ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: getting mpeg12_supported failed! : %s\n", vdp_get_error_string( st ) ); -- cgit v1.2.3 From af3278bde6c5c04a99bf8382dec87c8e235cda81 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 2 Feb 2009 11:42:32 +0000 Subject: Work around non-spec-compliant divx7 samples. --- src/libvdpau/h264_parser.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 37ad1402b..d088d21f9 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -105,14 +105,19 @@ static void decode_nal(uint8_t **ret, int *len_ret, uint8_t *buf, int buf_len) *len_ret = pos - *ret; } -static inline void dump_bits(uint32_t bits) +#if 0 +static inline void dump_bits(const char *label, const struct buf_reader *buf, int bits) { + struct buf_reader lbuf; + memcpy(&lbuf, buf, sizeof(struct buf_reader)); + int i; - printf("0b"); - for(i=0; i < 32; i++) - printf("%d", (bits >> (31-i)) & 0x01); + printf("%s: 0b", label); + for(i=0; i < bits; i++) + printf("%d", read_bits(&lbuf, 1)); printf("\n"); } +#endif static inline uint32_t bits_read(struct buf_reader *buf) { @@ -142,12 +147,10 @@ static inline uint32_t read_bits(struct buf_reader *buf, int len) buf->cur_pos++; buf->cur_offset = 8; } - //dump_bits(bits); return bits; } else { bits |= (*buf->cur_pos & i_mask[buf->cur_offset]) << -i_shr; - //dump_bits(bits); len -= buf->cur_offset; buf->cur_pos++; buf->cur_offset = 8; @@ -452,7 +455,8 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) memset(sps->scaling_lists_4x4, 16, sizeof(sps->scaling_lists_4x4)); memset(sps->scaling_lists_8x8, 16, sizeof(sps->scaling_lists_8x8)); if (sps->profile_idc == 100 || sps->profile_idc == 110 || sps->profile_idc - == 122 || sps->profile_idc == 144) { + == 122 || sps->profile_idc == 244 || sps->profile_idc == 44 || + sps->profile_idc == 83 || sps->profile_idc == 86) { sps->chroma_format_idc = read_exp_golomb(buf); if (sps->chroma_format_idc == 3) { sps->separate_colour_plane_flag = read_bits(buf, 1); @@ -928,7 +932,10 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); int i; - for (i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) { + /* FIXME: Being spec-compliant here and loop to num_ref_idx_l0_active_minus1 + * will break Divx7 files. Keep this in mind if any other streams are broken + */ + for (i = 0; i <= 1 /*pps->num_ref_idx_l0_active_minus1*/; i++) { uint8_t luma_weight_l0_flag = read_bits(buf, 1); if (luma_weight_l0_flag == 1) { @@ -952,7 +959,10 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) } if (slc->slice_type == SLICE_B) { - for (i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) { + /* FIXME: Being spec-compliant here and loop to num_ref_idx_l0_active_minus1 + * will break Divx7 files. Keep this in mind if any other streams are broken + */ + for (i = 0; i <= 1 /*pps->num_ref_idx_l1_active_minus1*/; i++) { uint8_t luma_weight_l1_flag = read_bits(buf, 1); if (luma_weight_l1_flag == 1) { -- cgit v1.2.3 From 63cdcee855ddceb0b1bb9bfb81d76593e82d6fdc Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 2 Feb 2009 12:31:14 +0000 Subject: Replace previous commit with a proper fix taking slc-specific num_ref_idx_*_active values into account. this finally fixes the perfectly standard compliant (c: divx7 samples. --- src/libvdpau/h264_parser.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index d088d21f9..141f0d43e 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -835,6 +835,10 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) if (slc->slice_type == SLICE_B) slc->direct_spatial_mv_pred_flag = read_bits(buf, 1); + /* take default values in case they are not set here */ + slc->num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_active_minus1; + slc->num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_active_minus1; + if (slc->slice_type == SLICE_P || slc->slice_type == SLICE_SP || slc->slice_type == SLICE_B) { slc->num_ref_idx_active_override_flag = read_bits(buf, 1); @@ -932,10 +936,7 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); int i; - /* FIXME: Being spec-compliant here and loop to num_ref_idx_l0_active_minus1 - * will break Divx7 files. Keep this in mind if any other streams are broken - */ - for (i = 0; i <= 1 /*pps->num_ref_idx_l0_active_minus1*/; i++) { + for (i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) { uint8_t luma_weight_l0_flag = read_bits(buf, 1); if (luma_weight_l0_flag == 1) { @@ -962,7 +963,7 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) /* FIXME: Being spec-compliant here and loop to num_ref_idx_l0_active_minus1 * will break Divx7 files. Keep this in mind if any other streams are broken */ - for (i = 0; i <= 1 /*pps->num_ref_idx_l1_active_minus1*/; i++) { + for (i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) { uint8_t luma_weight_l1_flag = read_bits(buf, 1); if (luma_weight_l1_flag == 1) { -- cgit v1.2.3 From e8e043e68f413c16d5757645185d716b048ecf01 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 3 Feb 2009 00:39:46 +0000 Subject: More VC1. --- src/libvdpau/vdpau_vc1.c | 174 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 152 insertions(+), 22 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 1ee76d2c4..85f28e76d 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -21,7 +21,7 @@ * */ -#define LOG +//#define LOG #define LOG_MODULE "vdpau_vc1" @@ -62,6 +62,8 @@ typedef struct { VdpPictureInfoVC1 vdp_infos; + int hrd_param_flag; + int hrd_num_leaky_buckets; int type; } picture_t; @@ -168,6 +170,7 @@ static void init_sequence( sequence_t *sequence ) sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; sequence->ratio = 0; sequence->video_step = 0; + sequence->picture.hrd_param_flag = 0; reset_sequence( sequence ); } @@ -194,22 +197,97 @@ static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) +static void update_metadata( vdpau_vc1_decoder_t *this_gen ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + + if ( !sequence->have_header ) { + sequence->have_header = 1; + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); + _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); + _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "VC1/WMV9 (vdpau)" ); + xine_event_t event; + xine_format_change_data_t data; + event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; + event.stream = this_gen->stream; + event.data = &data; + event.data_length = sizeof(data); + data.width = sequence->coded_width; + data.height = sequence->coded_height; + data.aspect = sequence->ratio; + xine_event_send( this_gen->stream, &event ); + } +} + + + static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) { lprintf( "sequence_header_advanced\n" ); + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + + if ( len < 5 ) + return; + + sequence->profile = VDP_DECODER_PROFILE_VC1_ADVANCED; + lprintf("VDP_DECODER_PROFILE_VC1_ADVANCED\n"); + int off = 15; + sequence->picture.vdp_infos.postprocflag = get_bits(buf,off++,1); + sequence->coded_width = (get_bits(buf,off,12)+1)<<1; + off += 12; + sequence->coded_height = (get_bits(buf,off,12)+1)<<1; + off += 12; + ++off; + sequence->picture.vdp_infos.interlace = get_bits(buf,off++,1); + sequence->picture.vdp_infos.tfcntrflag = get_bits(buf,off++,1); + sequence->picture.vdp_infos.finterpflag = get_bits(buf,off++,1); + ++off; + sequence->picture.vdp_infos.psf = get_bits(buf,off++,1); + sequence->picture.vdp_infos.maxbframes = 7; + if ( get_bits(buf,off++,1) ) { + int w, h, ar=0; + w = get_bits(buf,off,14)+1; + off += 14; + h = get_bits(buf,off,14)+1; + off += 14; + if ( get_bits(buf,off++,1) ) { + ar = get_bits(buf,off,4); + off += 4; + } + if ( ar==15 ) { + w = get_bits(buf,off,8); + off += 8; + h = get_bits(buf,off,8); + off += 8; + } + if ( get_bits(buf,off++,1) ) { + if ( get_bits(buf,off++,1) ) + off += 16; + else + off += 12; + } + if ( get_bits(buf,off++,1) ) + off += 24; + } + sequence->picture.hrd_param_flag = get_bits(buf,off++,1); + if ( sequence->picture.hrd_param_flag ) + sequence->picture.hrd_num_leaky_buckets = get_bits(buf,off,5); + + update_metadata( this_gen ); } static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) { + lprintf( "sequence_header\n" ); sequence_t *sequence = (sequence_t*)&this_gen->sequence; if ( len < 4 ) return; - lprintf( "sequence_header\n" ); - switch ( get_bits(buf,0,2) ) { case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; lprintf("VDP_DECODER_PROFILE_VC1_SIMPLE\n"); break; case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("VDP_DECODER_PROFILE_VC1_MAIN\n"); break; @@ -230,23 +308,54 @@ static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int le sequence->picture.vdp_infos.quantizer = get_bits(buf,28,2); sequence->picture.vdp_infos.finterpflag = get_bits(buf,30,1); - if ( !sequence->have_header ) { - sequence->have_header = 1; - _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_WIDTH, sequence->coded_width ); - _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, sequence->coded_height ); - _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_VIDEO_RATIO, ((double)10000*sequence->ratio) ); - _x_stream_info_set( this_gen->stream, XINE_STREAM_INFO_FRAME_DURATION, sequence->video_step ); - _x_meta_info_set_utf8( this_gen->stream, XINE_META_INFO_VIDEOCODEC, "VC1/WMV9 (vdpau)" ); - xine_event_t event; - xine_format_change_data_t data; - event.type = XINE_EVENT_FRAME_FORMAT_CHANGE; - event.stream = this_gen->stream; - event.data = &data; - event.data_length = sizeof(data); - data.width = sequence->coded_width; - data.height = sequence->coded_height; - data.aspect = sequence->ratio; - xine_event_send( this_gen->stream, &event ); + update_metadata( this_gen ); +} + + + +static void entry_point( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + lprintf( "entry_point\n" ); + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + int off=2; + + sequence->picture.vdp_infos.panscan_flag = get_bits(buf,off++,1); + sequence->picture.vdp_infos.refdist_flag = get_bits(buf,off++,1); + sequence->picture.vdp_infos.loopfilter = get_bits(buf,off++,1); + sequence->picture.vdp_infos.fastuvmc = get_bits(buf,off++,1); + sequence->picture.vdp_infos.extended_mv = get_bits(buf,off++,1); + sequence->picture.vdp_infos.dquant = get_bits(buf,off,2); + off += 2; + sequence->picture.vdp_infos.vstransform = get_bits(buf,off++,1); + sequence->picture.vdp_infos.overlap = get_bits(buf,off++,1); + sequence->picture.vdp_infos.quantizer = get_bits(buf,off,2); + off += 2; + + if ( sequence->picture.hrd_param_flag ) { + int i; + for ( i=0; ipicture.hrd_num_leaky_buckets; ++i ) + off += 8; + } + + if ( get_bits(buf,off++,1) ) { + sequence->coded_width = (get_bits(buf,off,12)+1)<<1; + off += 12; + sequence->coded_height = (get_bits(buf,off,12)+1)<<1; + off += 12; + } + + if ( sequence->picture.vdp_infos.extended_mv ) + sequence->picture.vdp_infos.extended_dmv = get_bits(buf,off++,1); + + sequence->picture.vdp_infos.range_mapy_flag = get_bits(buf,off++,1); + if ( sequence->picture.vdp_infos.range_mapy_flag ) { + sequence->picture.vdp_infos.range_mapy = get_bits(buf,off,3); + off += 3; + } + sequence->picture.vdp_infos.range_mapuv_flag = get_bits(buf,off++,1); + if ( sequence->picture.vdp_infos.range_mapuv_flag ) { + sequence->picture.vdp_infos.range_mapuv = get_bits(buf,off,3); + off += 3; } } @@ -291,6 +400,27 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len +static void parse_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + int off=0; + + while ( off < (len-4) ) { + uint8_t *buffer = buf+off; + if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) { + switch ( buffer[3] ) { + case sequence_header_code: sequence_header( this_gen, buf+off+4, len-off-4 ); break; + case entry_point_code: entry_point( this_gen, buf+off+4, len-off-4 ); break; + } + } + ++off; + } + if ( !sequence->have_header ) + sequence_header( this_gen, buf, len ); +} + + + static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel ) { sequence_t *seq = (sequence_t*)&vd->sequence; @@ -338,7 +468,7 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) picture_header( vd, seq->buf, seq->bufpos ); VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, pic->type, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; @@ -467,7 +597,7 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf seq->coded_height = bih->biHeight; lprintf( "width=%d height=%d\n", bih->biWidth, bih->biHeight ); if ( buf->size > bs ) { - sequence_header( this, buf->content+bs, buf->size-bs ); + parse_header( this, buf->content+bs, buf->size-bs ); } int i; for ( i=0; isize; ++i ) -- cgit v1.2.3 From c2b8a783356a3705fe398686225056d3d5be1ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Tue, 3 Feb 2009 10:28:30 +0000 Subject: Allow multiple ARGB overlays. --- src/video_out/video_out_vdpau.c | 192 ++++++++++++++++++++++++++-------------- 1 file changed, 127 insertions(+), 65 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 13ce1b41b..07d73a764 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -190,6 +190,15 @@ typedef struct { } vdpau_overlay_t; +typedef struct { + int x; + int y; + int w; + int h; +} +argb_ovl_data_t; + + typedef struct { vo_frame_t vo_frame; @@ -230,10 +239,10 @@ typedef struct { uint32_t argb_overlay_width; uint32_t argb_overlay_height; int has_argb_overlay; - int argb_osd_x; - int argb_osd_y; - int argb_osd_w; - int argb_osd_h; + int argb_ovl_count; + vo_overlay_t *argb_ovl[XINE_VORAW_MAX_OVL]; + int argb_ovl_data_count; + argb_ovl_data_t argb_ovl_data[XINE_VORAW_MAX_OVL]; VdpVideoSurface soft_surface; uint32_t soft_surface_width; @@ -308,80 +317,124 @@ static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *over -static int vdpau_process_argb_ovl( vdpau_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay ) +static void vdpau_process_argb_ovls(vdpau_driver_t *this_gen, vo_frame_t *frame_gen) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + int i, k; - if(overlay->argb_layer == NULL) - return 0; + vo_overlay_t *ovl[XINE_VORAW_MAX_OVL]; + argb_ovl_data_t ovl_data[XINE_VORAW_MAX_OVL]; + int ovl_data_count = 0; + + int total_extent_width = 0, total_extent_height = 0; - pthread_mutex_lock(&overlay->argb_layer->mutex); + /* lock layers while processing and determine extent */ + for (i = 0; i < this->argb_ovl_count; i++) { + pthread_mutex_lock(&this->argb_ovl[i]->argb_layer->mutex); - if (overlay->argb_layer->buffer != NULL) { - int extent_width = overlay->extent_width; - int extent_height = overlay->extent_height; - if (extent_width <= 0 || extent_height <= 0) { - extent_width = frame_gen->width; - extent_height = frame_gen->height; + if (this->argb_ovl[i]->argb_layer->buffer != NULL) { + int extent_width = this->argb_ovl[i]->extent_width; + int extent_height = this->argb_ovl[i]->extent_height; + if (extent_width <= 0 || extent_height <= 0) { + extent_width = frame_gen->width; + extent_height = frame_gen->height; + } + if (extent_width > 0 && extent_height > 0) { + if (total_extent_width < extent_width) + total_extent_width = extent_width; + if (total_extent_height < extent_height) + total_extent_height = extent_height; + ovl_data[ovl_data_count].x = this->argb_ovl[i]->x; + ovl_data[ovl_data_count].y = this->argb_ovl[i]->y; + ovl_data[ovl_data_count].w = this->argb_ovl[i]->width; + ovl_data[ovl_data_count].h = this->argb_ovl[i]->height; + ovl[ovl_data_count++] = this->argb_ovl[i]; + } } + } - if (extent_width > 0 && extent_height > 0) { - if ( (this->argb_overlay_width != extent_width ) || (this->argb_overlay_height != extent_height) || (this->argb_overlay == VDP_INVALID_HANDLE) ) { - if (this->argb_overlay != VDP_INVALID_HANDLE) { - vdp_output_surface_destroy( this->argb_overlay ); - } - VdpStatus st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, extent_width, extent_height, &this->argb_overlay ); - if ( st != VDP_STATUS_OK ) { - printf( "vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); - } - this->argb_overlay_width = extent_width; - this->argb_overlay_height = extent_height; - - /* set stored osd location to extent as any smaller osd requires to clear the surface first */ - this->argb_osd_x = 0; - this->argb_osd_y = 0; - this->argb_osd_w = extent_width; - this->argb_osd_h = extent_height; + /* adjust surface */ + if (total_extent_width > 0 && total_extent_height > 0) { + if (this->argb_overlay_width != total_extent_width || this->argb_overlay_height != total_extent_height || this->argb_overlay == VDP_INVALID_HANDLE) { + if (this->argb_overlay != VDP_INVALID_HANDLE) + vdp_output_surface_destroy(this->argb_overlay); + + VdpStatus st = vdp_output_surface_create(vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, total_extent_width, total_extent_height, &this->argb_overlay); + if (st != VDP_STATUS_OK) + printf("vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st)); + + this->argb_overlay_width = total_extent_width; + this->argb_overlay_height = total_extent_height; + + /* change argb_ovl_data to wipe complete surface */ + this->argb_ovl_data_count = 1; + this->argb_ovl_data[0].x = 0; + this->argb_ovl_data[0].y = 0; + this->argb_ovl_data[0].w = total_extent_width; + this->argb_ovl_data[0].h = total_extent_height; + + /* extend dirty areas to maximum for filling wiped surface */ + for (i = 0; i < ovl_data_count; i++) { + ovl[i]->argb_layer->x1 = 0; + ovl[i]->argb_layer->y1 = 0; + ovl[i]->argb_layer->x2 = ovl[i]->width; + ovl[i]->argb_layer->y2 = ovl[i]->height; } + } + } - /* wipe surface if osd layout changed */ - if (overlay->x != this->argb_osd_x || overlay->y != this->argb_osd_y || overlay->width != this->argb_osd_w || overlay->height != this->argb_osd_h) { - this->argb_osd_x = overlay->x; - this->argb_osd_y = overlay->y; - this->argb_osd_w = overlay->width; - this->argb_osd_h = overlay->height; - - uint32_t *zeros = calloc(4 * extent_width, extent_height); - if (zeros) { - uint32_t pitch = extent_width * 4; - VdpRect dest = { 0, 0, extent_width, extent_height }; - VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(zeros), &pitch, &dest ); - if ( st != VDP_STATUS_OK ) - printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) ); - free(zeros); + /* wipe surface for gone overlays */ + if (this->argb_overlay != VDP_INVALID_HANDLE) { + uint32_t *zeros = NULL; + for (i = 0; i < this->argb_ovl_data_count; i++) { + argb_ovl_data_t *curr_ovl_data = &this->argb_ovl_data[i]; + int ovl_gone = 1; + for (k = 0; k < ovl_data_count; k++) { + if (0 == memcmp(curr_ovl_data, &ovl_data[k], sizeof (*curr_ovl_data))) { + ovl_gone = 0; + break; } } + if (!ovl_gone) + continue; + if (!zeros) + zeros = calloc(4, this->argb_overlay_width * this->argb_overlay_height); + if (zeros) { + uint32_t pitch = curr_ovl_data->w * 4; + VdpRect dest = { curr_ovl_data->x, curr_ovl_data->y, curr_ovl_data->x + curr_ovl_data->w, curr_ovl_data->y + curr_ovl_data->h }; + VdpStatus st = vdp_output_surface_put_bits(this->argb_overlay, (void *)&zeros, &pitch, &dest); + if (st != VDP_STATUS_OK) + printf("vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st)); + this->has_argb_overlay = 1; + } + } + free(zeros); + } - /* set destination area according to dirty area of argb layer and reset dirty area */ - uint32_t pitch = overlay->width * 4; - uint32_t *buffer_start = overlay->argb_layer->buffer + overlay->argb_layer->y1 * overlay->width + overlay->argb_layer->x1; - VdpRect dest = { overlay->x + overlay->argb_layer->x1, overlay->y + overlay->argb_layer->y1, overlay->x + overlay->argb_layer->x2, overlay->y + overlay->argb_layer->y2 }; - overlay->argb_layer->x1 = overlay->width; - overlay->argb_layer->y1 = overlay->height; - overlay->argb_layer->x2 = 0; - overlay->argb_layer->y2 = 0; + /* set destination area according to dirty area of argb layer and reset dirty area */ + for (i = 0; i < ovl_data_count; i++) { + uint32_t pitch = ovl[i]->width * 4; + uint32_t *buffer_start = ovl[i]->argb_layer->buffer + ovl[i]->argb_layer->y1 * ovl[i]->width + ovl[i]->argb_layer->x1; + VdpRect dest = { ovl[i]->x + ovl[i]->argb_layer->x1, ovl[i]->y + ovl[i]->argb_layer->y1, ovl[i]->x + ovl[i]->argb_layer->x2, ovl[i]->y + ovl[i]->argb_layer->y2 }; + ovl[i]->argb_layer->x1 = ovl[i]->width; + ovl[i]->argb_layer->y1 = ovl[i]->height; + ovl[i]->argb_layer->x2 = 0; + ovl[i]->argb_layer->y2 = 0; - VdpStatus st = vdp_output_surface_put_bits( this->argb_overlay, (void*)&(buffer_start), &pitch, &dest ); - if ( st != VDP_STATUS_OK ) { - printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st) ); - } else - this->has_argb_overlay = 1; - } + VdpStatus st = vdp_output_surface_put_bits(this->argb_overlay, (void *)&buffer_start, &pitch, &dest); + if (st != VDP_STATUS_OK) + printf( "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st)); + else + this->has_argb_overlay = 1; } - pthread_mutex_unlock(&overlay->argb_layer->mutex); + /* store ovl_data */ + memcpy(this->argb_ovl_data, ovl_data, sizeof (ovl_data)); + this->argb_ovl_data_count = ovl_data_count; - return 1; + /* unlock layers */ + for (i = 0; i < this->argb_ovl_count; i++) + pthread_mutex_unlock(&this->argb_ovl[i]->argb_layer->mutex); } @@ -480,6 +533,7 @@ static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, i this->has_overlay = this->has_unscaled = 0; this->has_argb_overlay = 0; + this->argb_ovl_count = 0; ++this->ovl_changed; } @@ -490,18 +544,23 @@ static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, v vdpau_driver_t *this = (vdpau_driver_t *) this_gen; vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; - if ( !this->ovl_changed || this->ovl_changed>XINE_VORAW_MAX_OVL ) + if (!this->ovl_changed) return; if (overlay->rle) { + if (this->ovl_changed >= XINE_VORAW_MAX_OVL) + return; if (!overlay->rgb_clut || !overlay->hili_rgb_clut) vdpau_overlay_clut_yuv2rgb (this, overlay, frame); if ( vdpau_process_ovl( this, overlay ) ) ++this->ovl_changed; } - if(overlay->argb_layer) - vdpau_process_argb_ovl( this, frame_gen, overlay ); + if (overlay->argb_layer) { + if (this->argb_ovl_count >= XINE_VORAW_MAX_OVL) + return; + this->argb_ovl[this->argb_ovl_count++] = overlay; + } } @@ -515,6 +574,9 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) if ( !this->ovl_changed ) return; + if (this->argb_ovl_count || this->argb_ovl_data_count) + vdpau_process_argb_ovls(this, frame); + if ( !(this->ovl_changed-1) ) { this->ovl_changed = 0; this->has_overlay = 0; -- cgit v1.2.3 From 9839d82d6edce0192c8de2588d5bac62f1f13a57 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 3 Feb 2009 23:57:32 +0000 Subject: More VC1. --- src/libvdpau/vdpau_vc1.c | 56 +++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 85f28e76d..baad30df3 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -21,7 +21,7 @@ * */ -//#define LOG +#define LOG #define LOG_MODULE "vdpau_vc1" @@ -50,9 +50,10 @@ #define PICTURE_FRAME_INTERLACE 2 #define PICTURE_FIELD_INTERLACE 3 -#define I_FRAME 1 -#define P_FRAME 2 +#define I_FRAME 0 +#define P_FRAME 1 #define B_FRAME 3 +#define BI_FRAME 4 #define WANT_HEADER 1 #define WANT_EXT 2 @@ -64,7 +65,6 @@ typedef struct { VdpPictureInfoVC1 vdp_infos; int hrd_param_flag; int hrd_num_leaky_buckets; - int type; } picture_t; @@ -239,7 +239,7 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu off += 12; sequence->coded_height = (get_bits(buf,off,12)+1)<<1; off += 12; - ++off; + sequence->picture.vdp_infos.pulldown = get_bits(buf,off++,1); sequence->picture.vdp_infos.interlace = get_bits(buf,off++,1); sequence->picture.vdp_infos.tfcntrflag = get_bits(buf,off++,1); sequence->picture.vdp_infos.finterpflag = get_bits(buf,off++,1); @@ -368,34 +368,42 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); int off=2; + int tmp; if ( info->finterpflag ) ++off; if ( info->rangered ) ++off; if ( !info->maxbframes ) { - info->picture_type = get_bits( buf,off,1 ); - if ( info->picture_type ) - pic->type = P_FRAME; + if ( get_bits( buf,off++,1 ) ) + info->picture_type = P_FRAME; else - pic->type = I_FRAME; + info->picture_type = I_FRAME; } else { - int ptype = get_bits( buf,off,1 ); - if ( ptype ) { - info->picture_type = ptype; - pic->type = P_FRAME; - ++off; - } + if ( get_bits( buf,off++,1 ) ) + info->picture_type = P_FRAME; else { - info->picture_type = get_bits( buf,off,2 ); - if ( info->picture_type ) - pic->type = I_FRAME; + if ( get_bits( buf,off++,1 ) ) + info->picture_type = I_FRAME; else - pic->type = B_FRAME; - off += 2; + info->picture_type = B_FRAME; } } + if ( info->picture_type == B_FRAME ) { + tmp = get_bits(buf,off,3); + if ( tmp==7 ) { + tmp = get_bits(buf,off,7); + off += 7; + if ( tmp==127 ) + info->picture_type = BI_FRAME; + } + else + off += 3; + } + if ( info->picture_type==I_FRAME || info->picture_type==BI_FRAME ) + off += 7; + tmp = get_bits(buf,off,5); } @@ -473,7 +481,7 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; - if ( pic->type==P_FRAME ) { + if ( pic->vdp_infos.picture_type==P_FRAME ) { if ( seq->backward_ref ) { ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; pic->vdp_infos.forward_reference = ref_accel->surface; @@ -481,7 +489,7 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) else return; } - else if ( pic->type==B_FRAME ) { + else if ( pic->vdp_infos.picture_type>=B_FRAME ) { if ( seq->forward_ref ) { ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; pic->vdp_infos.forward_reference = ref_accel->surface; @@ -519,8 +527,8 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) img->bad_frame = 0; img->duration = seq->video_step; - if ( pic->type!=B_FRAME ) { - if ( pic->type==I_FRAME && !seq->backward_ref ) { + if ( pic->vdp_infos.picture_typevdp_infos.picture_type==I_FRAME && !seq->backward_ref ) { img->pts = 0; img->draw( img, vd->stream ); ++img->drawn; -- cgit v1.2.3 From 07b831a6cfaea761f309fb82b4e81a877ed564d3 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 4 Feb 2009 00:41:00 +0000 Subject: Initial advanced_profile support. --- src/libvdpau/vdpau_vc1.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index baad30df3..391eba04d 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -366,9 +366,9 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len sequence_t *sequence = (sequence_t*)&this_gen->sequence; picture_t *pic = (picture_t*)&sequence->picture; VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); + int tmp; int off=2; - int tmp; if ( info->finterpflag ) ++off; @@ -408,6 +408,35 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len +static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + picture_t *pic = (picture_t*)&sequence->picture; + VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); + int off=0; + + if ( info->interlace ) + return; // not yet supported + if ( !get_bits(buf,off++,1) ) + info->picture_type = P_FRAME; + else { + if ( !get_bits(buf,off++,1) ) + info->picture_type = B_FRAME; + else { + if ( !get_bits(buf,off++,1) ) + info->picture_type = I_FRAME; + else { + if ( !get_bits(buf,off++,1) ) + info->picture_type = BI_FRAME; + else + info->picture_type = P_FRAME; // TODO: skipped frame + } + } + } +} + + + static void parse_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) { sequence_t *sequence = (sequence_t*)&this_gen->sequence; @@ -473,7 +502,10 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) picture_t *pic = (picture_t*)&seq->picture; vdpau_accel_t *ref_accel; - picture_header( vd, seq->buf, seq->bufpos ); + if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) + picture_header_advanced( vd, seq->buf, seq->bufpos ); + else + picture_header( vd, seq->buf, seq->bufpos ); VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); -- cgit v1.2.3 From 409cc2850fc6cf5b5d5b2322feb10699743a8962 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 4 Feb 2009 17:49:39 +0000 Subject: Skipped frames. --- src/libvdpau/vdpau_vc1.c | 56 ++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 391eba04d..22a03d1ff 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -65,6 +65,7 @@ typedef struct { VdpPictureInfoVC1 vdp_infos; int hrd_param_flag; int hrd_num_leaky_buckets; + int skipped; } picture_t; @@ -121,29 +122,9 @@ typedef struct vdpau_vc1_decoder_s { -static void reset_picture( picture_t *pic ) -{ - lprintf( "reset_picture\n" ); - /*pic->vdp_infos.picture_structure = 0; - pic->vdp_infos2.intra_dc_precision = pic->vdp_infos.intra_dc_precision = 0; - pic->vdp_infos2.frame_pred_frame_dct = pic->vdp_infos.frame_pred_frame_dct = 1; - pic->vdp_infos2.concealment_motion_vectors = pic->vdp_infos.concealment_motion_vectors = 0; - pic->vdp_infos2.intra_vlc_format = pic->vdp_infos.intra_vlc_format = 0; - pic->vdp_infos2.alternate_scan = pic->vdp_infos.alternate_scan = 0; - pic->vdp_infos2.q_scale_type = pic->vdp_infos.q_scale_type = 0; - pic->vdp_infos2.top_field_first = pic->vdp_infos.top_field_first = 0; - pic->slices_count = 0; - pic->slices_count2 = 0; - pic->slices_pos = 0; - pic->slices_pos_top = 0; - pic->state = WANT_HEADER;*/ -} - - - static void init_picture( picture_t *pic ) { - reset_picture( pic ); + memset( pic, 0, sizeof( picture_t ) ); } @@ -401,9 +382,9 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len else off += 3; } - if ( info->picture_type==I_FRAME || info->picture_type==BI_FRAME ) + /*if ( info->picture_type==I_FRAME || info->picture_type==BI_FRAME ) off += 7; - tmp = get_bits(buf,off,5); + tmp = get_bits(buf,off,5);*/ } @@ -428,8 +409,10 @@ static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf else { if ( !get_bits(buf,off++,1) ) info->picture_type = BI_FRAME; - else - info->picture_type = P_FRAME; // TODO: skipped frame + else { + info->picture_type = P_FRAME; + pic->skipped = 1; + } } } } @@ -458,6 +441,19 @@ static void parse_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +static void duplicate_image( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, vo_frame_t *dst ) +{ + sequence_t *seq = (sequence_t*)&vd->sequence; + picture_t *pic = (picture_t*)&seq->picture; + + if ( !seq->backward_ref ) // Should not happen! + return; + + dst->proc_duplicate_frame_data( dst, seq->backward_ref ); +} + + + static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel ) { sequence_t *seq = (sequence_t*)&vd->sequence; @@ -502,11 +498,16 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) picture_t *pic = (picture_t*)&seq->picture; vdpau_accel_t *ref_accel; + pic->skipped = 0; + if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) picture_header_advanced( vd, seq->buf, seq->bufpos ); else picture_header( vd, seq->buf, seq->bufpos ); + if ( seq->bufpos<2 ) + pic->skipped = 1; + VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); @@ -553,7 +554,10 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) vd->decoder = VDP_INVALID_HANDLE; } - decode_render( vd, accel ); + if ( pic->skipped ) + duplicate_image( vd, accel, img ); + else + decode_render( vd, accel ); img->pts = seq->seq_pts; img->bad_frame = 0; -- cgit v1.2.3 From f81bb95b4d74684d2bb0caa1454db56389dce0c4 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 4 Feb 2009 19:01:11 +0000 Subject: Aspect ratio. --- src/libvdpau/vdpau_vc1.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 22a03d1ff..13cec7717 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -21,7 +21,7 @@ * */ -#define LOG +//#define LOG #define LOG_MODULE "vdpau_vc1" @@ -61,6 +61,25 @@ +const double aspect_ratio[] = { + 0.0, + 1.0, + 12./11., + 10./11., + 16./11., + 40./33., + 24./11., + 20./11., + 32./11., + 80./33., + 18./11., + 15./11., + 64./33., + 160./99. +}; + + + typedef struct { VdpPictureInfoVC1 vdp_infos; int hrd_param_flag; @@ -243,6 +262,9 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu h = get_bits(buf,off,8); off += 8; } + else if ( ar && ar<14 ) + sequence->ratio = aspect_ratio[ar]; + if ( get_bits(buf,off++,1) ) { if ( get_bits(buf,off++,1) ) off += 16; @@ -509,7 +531,7 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) pic->skipped = 1; VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); - printf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; -- cgit v1.2.3 From 19b4b913d0b173ae11a443530b34732b52119c16 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 6 Feb 2009 01:04:07 +0000 Subject: Update csc at mixer_create. --- src/video_out/video_out_vdpau.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 07d73a764..490002bb1 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1266,6 +1266,8 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_set_inverse_telecine( this_gen ); vdpau_update_noise( this ); vdpau_update_sharpness( this ); + this->color_standard = color_standard; + vdpau_update_csc( this ); } if (color_standard != this->color_standard) { -- cgit v1.2.3 From 52f3df4fd835c3e7601d30d74a5ea954db10f018 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 6 Feb 2009 20:37:54 +0000 Subject: Fix ref_pic_marking progress regression (i.e. simulhd). --- src/libvdpau/h264_parser.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 141f0d43e..ea043ca70 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -936,7 +936,7 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) nal->slc->pred_weight_table.chroma_log2_weight_denom = read_exp_golomb(buf); int i; - for (i = 0; i <= pps->num_ref_idx_l0_active_minus1; i++) { + for (i = 0; i <= slc->num_ref_idx_l0_active_minus1; i++) { uint8_t luma_weight_l0_flag = read_bits(buf, 1); if (luma_weight_l0_flag == 1) { @@ -963,7 +963,7 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) /* FIXME: Being spec-compliant here and loop to num_ref_idx_l0_active_minus1 * will break Divx7 files. Keep this in mind if any other streams are broken */ - for (i = 0; i <= pps->num_ref_idx_l1_active_minus1; i++) { + for (i = 0; i <= slc->num_ref_idx_l1_active_minus1; i++) { uint8_t luma_weight_l1_flag = read_bits(buf, 1); if (luma_weight_l1_flag == 1) { @@ -1001,7 +1001,7 @@ void decode_ref_pic_marking(struct nal_unit *nal, if (memory_management_control_operation == 1) { // short-term -> unused for reference uint32_t pic_num_x = (nal->curr_pic_num - - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1))%(nal->max_pic_num+1); + - (slc->dec_ref_pic_marking[marking_nr].difference_of_pic_nums_minus1 + 1))%nal->max_pic_num; struct decoded_picture* pic = NULL; if ((pic = dpb_get_picture(dpb, pic_num_x)) != NULL) { if (pic->nal->slc->field_pic_flag == 0) { @@ -1094,9 +1094,10 @@ void parse_dec_ref_pic_marking(struct buf_reader *buf, struct nal_parser *parser) { struct nal_unit *nal = parser->current_nal; + struct pic_parameter_set_rbsp *pps = parser->current_nal->pps; struct slice_header *slc = nal->slc; - if (!slc) + if (!slc || !pps) return; slc->dec_ref_pic_marking_count = 0; @@ -1253,13 +1254,11 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->current_nal->slc) { int i; for(i = 0; i < parser->current_nal->slc->dec_ref_pic_marking_count; i++) { - if(parser->current_nal->slc->dec_ref_pic_marking[i].adaptive_ref_pic_marking_mode_flag) { - decode_ref_pic_marking( - parser->current_nal, - parser->current_nal->slc->dec_ref_pic_marking[i].memory_management_control_operation, - i, - parser); - } + decode_ref_pic_marking( + parser->current_nal, + parser->current_nal->slc->dec_ref_pic_marking[i].memory_management_control_operation, + i, + parser); } if (parser->last_nal->slc != NULL) -- cgit v1.2.3 From e1f2db6c16e44fe3da9e0462b74dee26b96853cc Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 7 Feb 2009 10:30:43 +0000 Subject: Quick hack for .evo files. --- src/demuxers/demux_mpeg.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index 388be2140..026d2a88e 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -246,6 +246,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) len = read_bytes(this, 2); + //printf( "parse_mpeg2_packet: stream_id=%X\n", stream_id); + if (stream_id==0xbd) { int track; @@ -467,7 +469,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) } - } else if ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) { + } else if ( ((stream_id >= 0xbc) && ((stream_id & 0xf0) == 0xe0)) || stream_id==0xfd ) { w = read_bytes(this, 1); flags = read_bytes(this, 1); @@ -516,7 +518,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) return; } - buf->type = BUF_VIDEO_MPEG; + buf->type = (stream_id==0xfd) ? BUF_VIDEO_VC1 : BUF_VIDEO_MPEG; buf->pts = pts; buf->decoder_info[0] = pts - dts; check_newpts( this, pts, PTS_VIDEO ); -- cgit v1.2.3 From 3fb7d03899d6863b4a49896a649d18395810e128 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 7 Feb 2009 10:33:36 +0000 Subject: VC1 in hd-dvd initial support. --- src/libvdpau/vdpau_h264.c | 2 +- src/libvdpau/vdpau_mpeg12.c | 6 +- src/libvdpau/vdpau_vc1.c | 247 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 208 insertions(+), 47 deletions(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 8197a936a..7e57d405a 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -757,7 +757,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_H264_MAIN, 1920, 1080, 16, &decoder ); if ( st!=VDP_STATUS_OK ) { lprintf( "can't create vdpau decoder.\n" ); - return NULL; + return 1; } accel->vdp_decoder_destroy( decoder ); diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index e72341841..3ccc7f60c 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -769,8 +769,8 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * seq->bufpos += buf->size; while ( seq->bufseek <= seq->bufpos-4 ) { - uint8_t *buf = seq->buf+seq->bufseek; - if ( buf[0]==0 && buf[1]==0 && buf[2]==1 ) { + uint8_t *buffer = seq->buf+seq->bufseek; + if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) { if ( seq->start<0 ) { seq->start = seq->bufseek; } @@ -880,7 +880,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, 1920, 1080, 2, &decoder ); if ( st!=VDP_STATUS_OK ) { lprintf( "can't create vdpau decoder.\n" ); - return NULL; + return 1; } accel->vdp_decoder_destroy( decoder ); diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 13cec7717..05fb112f5 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -21,7 +21,7 @@ * */ -//#define LOG +#define LOG #define LOG_MODULE "vdpau_vc1" @@ -55,9 +55,8 @@ #define B_FRAME 3 #define BI_FRAME 4 -#define WANT_HEADER 1 -#define WANT_EXT 2 -#define WANT_SLICE 3 +#define MODE_STARTCODE 0 +#define MODE_FRAME 1 @@ -84,6 +83,8 @@ typedef struct { VdpPictureInfoVC1 vdp_infos; int hrd_param_flag; int hrd_num_leaky_buckets; + int repeat_first_field; + int top_field_first; int skipped; } picture_t; @@ -97,9 +98,13 @@ typedef struct { double ratio; VdpDecoderProfile profile; + int mode; int have_header; uint8_t *buf; /* accumulate data */ + int bufseek; + int start; + int code_start; uint32_t bufsize; uint32_t bufpos; @@ -148,10 +153,19 @@ static void init_picture( picture_t *pic ) +static void reset_picture( picture_t *pic ) +{ +} + + + static void reset_sequence( sequence_t *sequence ) { lprintf( "reset_sequence\n" ); sequence->bufpos = 0; + sequence->bufseek = 0; + sequence->start = -1; + sequence->code_start = 0; sequence->seq_pts = sequence->cur_pts = 0; if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); @@ -159,6 +173,7 @@ static void reset_sequence( sequence_t *sequence ) if ( sequence->backward_ref ) sequence->backward_ref->free( sequence->backward_ref ); sequence->backward_ref = NULL; + reset_picture( &sequence->picture ); } @@ -247,10 +262,13 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu sequence->picture.vdp_infos.psf = get_bits(buf,off++,1); sequence->picture.vdp_infos.maxbframes = 7; if ( get_bits(buf,off++,1) ) { - int w, h, ar=0; + double w, h; + int ar=0; w = get_bits(buf,off,14)+1; + lprintf("width=%fd\n", w); off += 14; h = get_bits(buf,off,14)+1; + lprintf("height=%f\n", h); off += 14; if ( get_bits(buf,off++,1) ) { ar = get_bits(buf,off,4); @@ -261,15 +279,40 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu off += 8; h = get_bits(buf,off,8); off += 8; + sequence->ratio = w/h; + lprintf("aspect_ratio (w/h) = %f\n", sequence->ratio); + } + else if ( ar && ar<14 ) { + sequence->ratio = w*aspect_ratio[ar]/h; + lprintf("aspect_ratio = %f\n", sequence->ratio); } - else if ( ar && ar<14 ) - sequence->ratio = aspect_ratio[ar]; if ( get_bits(buf,off++,1) ) { - if ( get_bits(buf,off++,1) ) + if ( get_bits(buf,off++,1) ) { + int exp = get_bits(buf,off,16); + lprintf("framerate exp = %d\n", exp); off += 16; - else - off += 12; + } + else { + int nr = get_bits(buf,off,8); + switch (nr) { + case 1: nr = 24000; break; + case 2: nr = 25000; break; + case 3: nr = 30000; break; + case 4: nr = 50000; break; + case 5: nr = 60000; break; + default: nr = 0; + } + off += 8; + int dr = get_bits(buf,off,4); + switch (dr) { + case 2: dr = 1001; break; + default: dr = 1000; + } + off += 4; + sequence->video_step = 90000/(nr/dr); + lprintf("framerate = %d video_step = %d\n", nr/dr, sequence->video_step); + } } if ( get_bits(buf,off++,1) ) off += 24; @@ -294,6 +337,7 @@ static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int le switch ( get_bits(buf,0,2) ) { case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; lprintf("VDP_DECODER_PROFILE_VC1_SIMPLE\n"); break; case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("VDP_DECODER_PROFILE_VC1_MAIN\n"); break; + case 2: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("vc1_complex profile not supported by vdpau, trying vc1_main.\n"); break; case 3: return sequence_header_advanced( this_gen, buf, len ); break; default: return; /* illegal value, broken header? */ } @@ -371,6 +415,8 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); int tmp; + lprintf("picture_header\n"); + int off=2; if ( info->finterpflag ) @@ -418,8 +464,25 @@ static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); int off=0; - if ( info->interlace ) - return; // not yet supported + lprintf("picture_header_advanced\n"); + + if ( info->interlace ) { + lprintf("frame->interlace=1\n"); + if ( !get_bits(buf,off++,1) ) { + lprintf("progressive frame\n"); + info->frame_coding_mode = 0; + } + else { + if ( !get_bits(buf,off++,1) ) { + lprintf("frame interlaced\n"); + info->frame_coding_mode = 2; + } + else { + lprintf("field interlaced\n"); + info->frame_coding_mode = 3; + } + } + } if ( !get_bits(buf,off++,1) ) info->picture_type = P_FRAME; else { @@ -438,6 +501,12 @@ static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf } } } + if ( info->tfcntrflag ) + off += 8; + if ( info->pulldown && info->interlace ) { + pic->top_field_first = get_bits(buf,off++,1); + pic->repeat_first_field = get_bits(buf,off++,1); + } } @@ -463,7 +532,44 @@ static void parse_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) -static void duplicate_image( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, vo_frame_t *dst ) +static int parse_code( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +{ + sequence_t *sequence = (sequence_t*)&this_gen->sequence; + + if ( !sequence->have_header && buf[3]!=sequence_header_code ) + return 0; + + if ( sequence->code_start == frame_start_code ) + return 1; /* frame complete, decode */ + + switch ( buf[3] ) { + case sequence_header_code: + lprintf("sequence_header_code\n"); + sequence_header( this_gen, buf+4, len-4 ); + break; + case entry_point_code: + lprintf("entry_point_code\n"); + entry_point( this_gen, buf+4, len-4 ); + break; + case sequence_end_code: + lprintf("sequence_end_code\n"); + break; + case frame_start_code: + lprintf("frame_start_code\n"); + break; + case field_start_code: + lprintf("field_start_code\n"); + break; + case slice_start_code: + lprintf("slice_start_code\n"); + break; + } + return 0; +} + + + +static void duplicate_image( vdpau_vc1_decoder_t *vd, vo_frame_t *dst ) { sequence_t *seq = (sequence_t*)&vd->sequence; picture_t *pic = (picture_t*)&seq->picture; @@ -476,7 +582,7 @@ static void duplicate_image( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, vo_f -static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel ) +static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, uint8_t *buf, int len ) { sequence_t *seq = (sequence_t*)&vd->sequence; picture_t *pic = (picture_t*)&seq->picture; @@ -501,8 +607,8 @@ static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel ) VdpBitstreamBuffer vbit; vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; - vbit.bitstream = seq->buf; - vbit.bitstream_bytes = seq->bufpos; + vbit.bitstream = buf; + vbit.bitstream_bytes = len; st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); if ( st!=VDP_STATUS_OK ) lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); @@ -520,19 +626,43 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) picture_t *pic = (picture_t*)&seq->picture; vdpau_accel_t *ref_accel; + uint8_t *buf; + int len; + pic->skipped = 0; - if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) - picture_header_advanced( vd, seq->buf, seq->bufpos ); - else - picture_header( vd, seq->buf, seq->bufpos ); + if ( seq->mode == MODE_FRAME ) { + buf = seq->buf; + len = seq->bufpos; + if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) + picture_header_advanced( vd, seq->buf, seq->bufpos ); + else + picture_header( vd, seq->buf, seq->bufpos ); + + if ( seq->bufpos<2 ) + pic->skipped = 1; + } + else { + seq->picture.vdp_infos.slice_count = 1; + buf = seq->buf+seq->start+4; + len = seq->bufseek-seq->start-4; + if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) + picture_header_advanced( vd, seq->buf+seq->start+4, seq->bufseek-seq->start-4 ); + else + picture_header( vd, seq->buf+seq->start+4, seq->bufseek-seq->start-4 ); - if ( seq->bufpos<2 ) - pic->skipped = 1; + if ( (seq->bufseek-seq->start-4) < 2 ) + pic->skipped = 1; + } VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + int i; + for ( i=0; i<22; ++i ) + printf("%02X ", buf[i-4] ); + printf("\n\n"); + pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; @@ -577,10 +707,18 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) } if ( pic->skipped ) - duplicate_image( vd, accel, img ); + duplicate_image( vd, img ); else - decode_render( vd, accel ); + decode_render( vd, accel, buf, len ); + if ( pic->vdp_infos.interlace && pic->vdp_infos.frame_coding_mode ) { + img->progressive_frame = 0; + img->top_field_first = pic->top_field_first; + } + else { + img->progressive_frame = 1; + img->top_field_first = 1; + } img->pts = seq->seq_pts; img->bad_frame = 0; img->duration = seq->video_step; @@ -623,7 +761,6 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf /* a video decoder does not care about this flag (?) */ if (buf->decoder_flags & BUF_FLAG_PREVIEW) { lprintf("BUF_FLAG_PREVIEW\n"); - return; } if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { @@ -663,6 +800,7 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf seq->coded_height = bih->biHeight; lprintf( "width=%d height=%d\n", bih->biWidth, bih->biHeight ); if ( buf->size > bs ) { + seq->mode = MODE_FRAME; parse_header( this, buf->content+bs, buf->size-bs ); } int i; @@ -681,27 +819,49 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size ); seq->bufpos += buf->size; - if (buf->decoder_flags & BUF_FLAG_FRAME_END) { - lprintf("BUF_FLAG_FRAME_END\n"); - seq->picture.vdp_infos.slice_count = 1; - decode_picture( this ); - seq->bufpos = 0; + if ( seq->mode == MODE_FRAME ) { + if (buf->decoder_flags & BUF_FLAG_FRAME_END) { + lprintf("BUF_FLAG_FRAME_END\n"); + seq->picture.vdp_infos.slice_count = 1; + decode_picture( this ); + seq->bufpos = 0; + } + } + else { + while ( seq->bufseek <= seq->bufpos-4 ) { + uint8_t *buffer = seq->buf+seq->bufseek; + if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) { + if ( seq->start<0 ) { + seq->start = seq->bufseek; + seq->code_start = buffer[3]; + if ( seq->cur_pts ) + seq->seq_pts = seq->cur_pts; + } + else { + if ( parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ) ) { + decode_picture( this ); + parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ); + } + uint8_t *tmp = (uint8_t*)malloc(seq->bufsize); + xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek ); + seq->bufpos -= seq->bufseek; + seq->start = -1; + seq->bufseek = -1; + free( seq->buf ); + seq->buf = tmp; + } + } + ++seq->bufseek; + } + /*int i; + for ( i=0; isize; ++i ) + printf("%02X ", buf->content[i] ); + printf("\n\n");*/ } - - - /*int i; - for ( i=0; isize; ++i ) - printf("%02X ", buf->content[i] ); - printf("\n\n"); - - uint8_t *buffer = buf->content; - for ( i=0; isize-4; ++i ) { - if ( buffer[i]==0 && buffer[i+1]==0 && buffer[i+2]==1 ) - printf("start code\n"); - }*/ } + /* * This function is called when xine needs to flush the system. */ @@ -778,7 +938,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, 1920, 1080, 2, &decoder ); if ( st!=VDP_STATUS_OK ) { lprintf( "can't create vdpau decoder.\n" ); - return NULL; + return 1; } accel->vdp_decoder_destroy( decoder ); @@ -805,6 +965,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->decoder = VDP_INVALID_HANDLE; this->sequence.accel_vdpau = NULL; + this->sequence.mode = MODE_STARTCODE; (stream->video_out->open)(stream->video_out, stream); -- cgit v1.2.3 From c65baeabb4c0d31faabb8f1af1b8e7a923dec292 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 7 Feb 2009 10:34:36 +0000 Subject: Don't remove vdpau decoders from catalogue if failed to open. It could be because of no free decoder (it should be tried again later). --- src/xine-engine/load_plugins.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 4f7492c65..f0e33ceed 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -1959,7 +1959,13 @@ video_decoder_t *_x_get_video_decoder (xine_stream_t *stream, uint8_t stream_typ vd = ((video_decoder_class_t *)node->plugin_class)->open_plugin(node->plugin_class, stream); - if (vd) { + if (vd == 1) { + /* HACK: plugin failed to instantiate because required resources are unavailable at that time, + but may be available later, so don't remove this plugin from catalog. */ + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, + "load_plugins: plugin %s failed to instantiate, resources temporarily unavailable.\n", node->info->id); + } + else if (vd) { inc_node_ref(node); vd->node = node; xprintf(stream->xine, XINE_VERBOSITY_DEBUG, -- cgit v1.2.3 From e49970b2aae305a9f521fba5f7931a7e102e93d1 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 7 Feb 2009 15:06:57 +0000 Subject: Set 709 color_standard. --- src/libvdpau/vdpau_vc1.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 05fb112f5..f91e94e75 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -265,10 +265,8 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu double w, h; int ar=0; w = get_bits(buf,off,14)+1; - lprintf("width=%fd\n", w); off += 14; h = get_bits(buf,off,14)+1; - lprintf("height=%f\n", h); off += 14; if ( get_bits(buf,off++,1) ) { ar = get_bits(buf,off,4); @@ -283,7 +281,7 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu lprintf("aspect_ratio (w/h) = %f\n", sequence->ratio); } else if ( ar && ar<14 ) { - sequence->ratio = w*aspect_ratio[ar]/h; + sequence->ratio = sequence->coded_width*aspect_ratio[ar]/sequence->coded_height; lprintf("aspect_ratio = %f\n", sequence->ratio); } @@ -294,8 +292,8 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu off += 16; } else { - int nr = get_bits(buf,off,8); - switch (nr) { + double nr = get_bits(buf,off,8); + switch ((int)nr) { case 1: nr = 24000; break; case 2: nr = 25000; break; case 3: nr = 30000; break; @@ -304,18 +302,20 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu default: nr = 0; } off += 8; - int dr = get_bits(buf,off,4); - switch (dr) { + double dr = get_bits(buf,off,4); + switch ((int)dr) { case 2: dr = 1001; break; default: dr = 1000; } off += 4; sequence->video_step = 90000/(nr/dr); - lprintf("framerate = %d video_step = %d\n", nr/dr, sequence->video_step); + lprintf("framerate = %f video_step = %d\n", nr/dr, sequence->video_step); } } - if ( get_bits(buf,off++,1) ) + if ( get_bits(buf,off++,1) ) { + lprintf("color_standard = %d\n", get_bits(buf,off,8)); off += 24; + } } sequence->picture.hrd_param_flag = get_bits(buf,off++,1); if ( sequence->picture.hrd_param_flag ) @@ -658,11 +658,6 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); - int i; - for ( i=0; i<22; ++i ) - printf("%02X ", buf[i-4] ); - printf("\n\n"); - pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; @@ -722,6 +717,7 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) img->pts = seq->seq_pts; img->bad_frame = 0; img->duration = seq->video_step; + accel->color_standard = VDP_COLOR_STANDARD_ITUR_BT_709; if ( pic->vdp_infos.picture_typevdp_infos.picture_type==I_FRAME && !seq->backward_ref ) { -- cgit v1.2.3 From 74e9c411c7f77968df7eed956f198f096a742df9 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 10 Feb 2009 04:36:47 +0000 Subject: Fix color_standard & deinterlace. --- src/video_out/video_out_vdpau.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 490002bb1..735dc43d7 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -53,7 +53,7 @@ -const char *vdpau_deinterlace_methods[] = { +char *vdpau_deinterlace_methods[] = { "bob", "temporal", "temporal_spatial", @@ -881,6 +881,8 @@ static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *origin if (st != VDP_STATUS_OK) printf("vo_vdpau: failed to put surface bits !! %s\n", vdp_get_error_string(st)); + this->vdpau_accel_data.color_standard = orig->vdpau_accel_data.color_standard; + if (this->chunk[0]) free(this->chunk[0]); if (this->chunk[1]) @@ -1290,9 +1292,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height }; - //printf( "vid_src = %d %d %d %d - out_dest = %d %d %d %d - vid_dest = %d %d %d %d\n", - //vid_source.x0, vid_source.y0, vid_source.x1, vid_source.y1, out_dest.x0, out_dest.y0, out_dest.x1, out_dest.y1, vid_dest.x0, vid_dest.y0, vid_dest.x1, vid_dest.y1 ); - /* prepare field delay calculation to not run into a deadlock while display locked */ stream_speed = frame->vo_frame.stream ? xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) : 0; if (stream_speed != 0) { @@ -1336,7 +1335,8 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } int non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive; - if ( stream_speed && frame->vo_frame.duration>2500 && this->deinterlace && non_progressive && frame->format==XINE_IMGFMT_VDPAU ) { + int frame_duration = (frame->vo_frame.duration>0) ? frame->vo_frame.duration : 3000; /* unknown frame duration should not lead to no deint! */ + if ( stream_speed && frame_duration>2500 && this->deinterlace && non_progressive && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; VdpVideoSurface future[1]; -- cgit v1.2.3 From 91d4b0c438be1366e7426458d7988f9acad10e2b Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 10 Feb 2009 17:06:33 +0000 Subject: Cleanups. --- src/libvdpau/vdpau_mpeg12.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 3ccc7f60c..99be61cf4 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -209,7 +209,6 @@ static void reset_sequence( sequence_t *sequence ) sequence->seq_pts = sequence->cur_pts = 0; sequence->profile = VDP_DECODER_PROFILE_MPEG1; sequence->chroma = 0; - //sequence->ratio = 1.0; sequence->video_step = 3600; if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); @@ -533,7 +532,6 @@ static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) break; case sequence_display_ext_sc: lprintf( " ----------- sequence_display_extension_start_code\n" ); - //sequence_display_extension( sequence, buf+4, len-4 ); break; } break; @@ -546,7 +544,6 @@ static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) break; case picture_start_code: lprintf( " ----------- picture_start_code\n" ); - //slice_count = 0; picture_header( sequence, buf+4, len-4 ); break; case sequence_error_code: @@ -604,7 +601,6 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) pic->vdp_infos2.backward_reference = VDP_INVALID_HANDLE; pic->vdp_infos2.forward_reference = VDP_INVALID_HANDLE; if ( pic->vdp_infos2.picture_coding_type==P_FRAME ) { - pic->vdp_infos2.backward_reference = VDP_INVALID_HANDLE; if ( pic->vdp_infos.picture_coding_type==I_FRAME ) pic->vdp_infos2.forward_reference = accel->surface; else @@ -624,8 +620,6 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos2.picture_coding_type, pic->vdp_infos2.slice_count, accel->surface, pic->vdp_infos2.forward_reference, pic->vdp_infos2.backward_reference, seq->seq_pts ); } - - //printf( "vdpau_meg12: forwref:%d, backref:%d\n", seq->forward_ref, seq->backward_ref ); } @@ -670,7 +664,6 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) return; } - //printf("vdpau_mpeg12: get image ..\n"); vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, seq->ratio, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS|seq->chroma ); vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; @@ -688,11 +681,9 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) vd->decoder = VDP_INVALID_HANDLE; } - img->drawn = 0; - //printf("vdpau_mpeg12: .. got image %d\n", img); - decode_render( vd, accel ); + img->drawn = 0; img->pts = seq->seq_pts; img->bad_frame = 0; img->duration = seq->video_step; @@ -701,7 +692,9 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) else img->top_field_first = 0; - // progressive_frame is unreliable with most mpeg2 streams //img->progressive_frame = pic->progressive_frame; + /* progressive_frame is unreliable with most mpeg2 streams + img->progressive_frame = pic->progressive_frame;*/ + img->progressive_frame = 0; if ( pic->vdp_infos.picture_coding_type!=B_FRAME ) { if ( pic->vdp_infos.picture_coding_type==I_FRAME && !seq->backward_ref ) { @@ -712,21 +705,16 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) if ( seq->forward_ref ) { seq->forward_ref->drawn = 0; seq->forward_ref->free( seq->forward_ref ); - //printf("vdpau_mpeg12: freed image %d\n", seq->forward_ref ); } seq->forward_ref = seq->backward_ref; if ( seq->forward_ref && !seq->forward_ref->drawn ) { - //seq->forward_ref->pts = seq->seq_pts; seq->forward_ref->draw( seq->forward_ref, vd->stream ); - //printf( "vdpau_mpeg12: drawn reference image with pts=%lld\n", seq->forward_ref->pts ); } seq->backward_ref = img; } else { img->draw( img, vd->stream ); - //printf( "vdpau_mpeg12: drawn image with pts=%lld\n", img->pts ); img->free( img ); - //printf("vdpau_mpeg12: freed B image %d\n", img ); } seq->seq_pts +=seq->video_step; @@ -743,27 +731,20 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; sequence_t *seq = (sequence_t*)&this->sequence; - /* a video decoder does not care about this flag (?) */ - if (buf->decoder_flags & BUF_FLAG_PREVIEW) { - return; - } - if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { - //this->video_step = buf->decoder_info[0]; - //_x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); + this->video_step = buf->decoder_info[0]; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); } if ( !buf->size ) return; seq->cur_pts = buf->pts; - //printf("vdpau_mpeg12_decode_data: new pts : %lld\n", buf->pts ); int size = seq->bufpos+buf->size; if ( seq->bufsize < size ) { seq->bufsize = size+1024; seq->buf = realloc( seq->buf, seq->bufsize ); - //printf("sequence buffer realloced = %d\n", seq->bufsize ); } xine_fast_memcpy( seq->buf+seq->bufpos, buf->content, buf->size ); seq->bufpos += buf->size; @@ -808,8 +789,6 @@ static void vdpau_mpeg12_flush (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; lprintf( "vdpau_mpeg12_flush\n" ); -// incorrect: see libmpeg2, mpeg2_flush() -// reset_sequence( &this->sequence ); } /* @@ -820,8 +799,6 @@ static void vdpau_mpeg12_reset (video_decoder_t *this_gen) { lprintf( "vdpau_mpeg12_reset\n" ); reset_sequence( &this->sequence ); - - //this->size = 0; } /* @@ -902,6 +879,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->sequence.backward_ref = 0; this->sequence.vdp_runtime_nr = 1; reset_sequence( &this->sequence ); + this->sequence.ratio = 1; init_picture( &this->sequence.picture ); -- cgit v1.2.3 From fb733aa58d90dd35760b51c1f1c915184a26938e Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 10 Feb 2009 17:07:17 +0000 Subject: Interlaced support. --- src/libvdpau/vdpau_vc1.c | 162 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 126 insertions(+), 36 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index f91e94e75..989e0c899 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -50,13 +50,22 @@ #define PICTURE_FRAME_INTERLACE 2 #define PICTURE_FIELD_INTERLACE 3 -#define I_FRAME 0 -#define P_FRAME 1 -#define B_FRAME 3 -#define BI_FRAME 4 +#define I_FRAME 0 +#define P_FRAME 1 +#define B_FRAME 3 +#define BI_FRAME 4 -#define MODE_STARTCODE 0 -#define MODE_FRAME 1 +#define FIELDS_I_I 0 +#define FIELDS_I_P 1 +#define FIELDS_P_I 2 +#define FIELDS_P_P 3 +#define FIELDS_B_B 4 +#define FIELDS_B_BI 5 +#define FIELDS_BI_B 6 +#define FIELDS_BI_BI 7 + +#define MODE_STARTCODE 0 +#define MODE_FRAME 1 @@ -81,6 +90,9 @@ const double aspect_ratio[] = { typedef struct { VdpPictureInfoVC1 vdp_infos; + int fptype; + int field; + int header_size; int hrd_param_flag; int hrd_num_leaky_buckets; int repeat_first_field; @@ -450,9 +462,6 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len else off += 3; } - /*if ( info->picture_type==I_FRAME || info->picture_type==BI_FRAME ) - off += 7; - tmp = get_bits(buf,off,5);*/ } @@ -470,39 +479,60 @@ static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf lprintf("frame->interlace=1\n"); if ( !get_bits(buf,off++,1) ) { lprintf("progressive frame\n"); - info->frame_coding_mode = 0; + info->frame_coding_mode = PICTURE_FRAME; } else { if ( !get_bits(buf,off++,1) ) { lprintf("frame interlaced\n"); - info->frame_coding_mode = 2; + info->frame_coding_mode = PICTURE_FRAME_INTERLACE; } else { lprintf("field interlaced\n"); - info->frame_coding_mode = 3; + info->frame_coding_mode = PICTURE_FIELD_INTERLACE; } } } - if ( !get_bits(buf,off++,1) ) - info->picture_type = P_FRAME; + if ( info->frame_coding_mode == PICTURE_FIELD_INTERLACE ) { + pic->fptype = get_bits(buf,off,3); + switch ( pic->fptype ) { + case FIELDS_I_I: + case FIELDS_I_P: + info->picture_type = I_FRAME; break; + case FIELDS_P_I: + case FIELDS_P_P: + info->picture_type = P_FRAME; break; + case FIELDS_B_B: + case FIELDS_B_BI: + info->picture_type = B_FRAME; break; + default: + info->picture_type = BI_FRAME; + } + off += 3; + } else { if ( !get_bits(buf,off++,1) ) - info->picture_type = B_FRAME; + info->picture_type = P_FRAME; else { if ( !get_bits(buf,off++,1) ) - info->picture_type = I_FRAME; + info->picture_type = B_FRAME; else { if ( !get_bits(buf,off++,1) ) - info->picture_type = BI_FRAME; + info->picture_type = I_FRAME; else { - info->picture_type = P_FRAME; - pic->skipped = 1; + if ( !get_bits(buf,off++,1) ) + info->picture_type = BI_FRAME; + else { + info->picture_type = P_FRAME; + pic->skipped = 1; + } } } } } - if ( info->tfcntrflag ) + if ( info->tfcntrflag ) { + lprintf("tfcntrflag=1\n"); off += 8; + } if ( info->pulldown && info->interlace ) { pic->top_field_first = get_bits(buf,off++,1); pic->repeat_first_field = get_bits(buf,off++,1); @@ -574,7 +604,7 @@ static void duplicate_image( vdpau_vc1_decoder_t *vd, vo_frame_t *dst ) sequence_t *seq = (sequence_t*)&vd->sequence; picture_t *pic = (picture_t*)&seq->picture; - if ( !seq->backward_ref ) // Should not happen! + if ( !seq->backward_ref ) /* Should not happen! */ return; dst->proc_duplicate_frame_data( dst, seq->backward_ref ); @@ -609,13 +639,73 @@ static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, uint8_ vbit.struct_version = VDP_BITSTREAM_BUFFER_VERSION; vbit.bitstream = buf; vbit.bitstream_bytes = len; + if ( pic->field ) + vbit.bitstream_bytes = pic->field; st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); if ( st!=VDP_STATUS_OK ) lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else { lprintf( "DECODER SUCCESS : slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + int i; + for ( i=0; i<20; ++i ) + printf("%02X ", buf[i]); + printf("\n"); } + + if ( pic->field ) { + int old_type = pic->vdp_infos.picture_type; + switch ( pic->fptype ) { + case FIELDS_I_I: + case FIELDS_P_I: + pic->vdp_infos.picture_type = I_FRAME; + pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; + pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; + break; + case FIELDS_I_P: + case FIELDS_P_P: + pic->vdp_infos.forward_reference = accel->surface; + pic->vdp_infos.picture_type = P_FRAME; break; + case FIELDS_B_B: + case FIELDS_BI_B: + pic->vdp_infos.picture_type = B_FRAME; + break; + default: + pic->vdp_infos.picture_type = BI_FRAME; + } + vbit.bitstream = buf+pic->field+4; + vbit.bitstream_bytes = len-pic->field-4; + st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); + if ( st!=VDP_STATUS_OK ) + lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); + else { + lprintf( "DECODER SUCCESS : slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", + pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + int i; + for ( i=0; i<20; ++i ) + printf("%02X ", buf[pic->field+4+i] ); + printf("\n"); + } + VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); + lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + + pic->vdp_infos.picture_type = old_type; + } +} + + + +static int search_field( vdpau_vc1_decoder_t *vd, uint8_t *buf, int len ) +{ + int i; + lprintf("search_fields, len=%d\n", len); + for ( i=0; isequence; picture_t *pic = (picture_t*)&seq->picture; vdpau_accel_t *ref_accel; + int field; uint8_t *buf; int len; pic->skipped = 0; + pic->field = 0; if ( seq->mode == MODE_FRAME ) { buf = seq->buf; len = seq->bufpos; if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) - picture_header_advanced( vd, seq->buf, seq->bufpos ); + picture_header_advanced( vd, buf, len ); else - picture_header( vd, seq->buf, seq->bufpos ); + picture_header( vd, buf, len ); - if ( seq->bufpos<2 ) + if ( len < 2 ) pic->skipped = 1; + + if ( pic->vdp_infos.interlace && pic->vdp_infos.frame_coding_mode == PICTURE_FIELD_INTERLACE ) { + if ( !(field = search_field( vd, buf, len )) ) + lprintf("error, no fields found!\n"); + else + pic->field = field; + } } else { seq->picture.vdp_infos.slice_count = 1; buf = seq->buf+seq->start+4; len = seq->bufseek-seq->start-4; if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) - picture_header_advanced( vd, seq->buf+seq->start+4, seq->bufseek-seq->start-4 ); + picture_header_advanced( vd, buf, len ); else - picture_header( vd, seq->buf+seq->start+4, seq->bufseek-seq->start-4 ); + picture_header( vd, buf, len ); - if ( (seq->bufseek-seq->start-4) < 2 ) + if ( len < 2 ) pic->skipped = 1; } @@ -785,7 +884,6 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf if ( !buf->size ) return; - //printf("vdpau_vc1_decode_data: new pts : %lld\n", buf->pts ); seq->cur_pts = buf->pts; if (buf->decoder_flags & BUF_FLAG_STDHEADER) { @@ -849,10 +947,6 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf } ++seq->bufseek; } - /*int i; - for ( i=0; isize; ++i ) - printf("%02X ", buf->content[i] ); - printf("\n\n");*/ } } @@ -875,8 +969,6 @@ static void vdpau_vc1_reset (video_decoder_t *this_gen) { lprintf( "vdpau_vc1_reset\n" ); reset_sequence( &this->sequence ); - - //this->size = 0; } /* @@ -886,8 +978,6 @@ static void vdpau_vc1_discontinuity (video_decoder_t *this_gen) { vdpau_vc1_decoder_t *this = (vdpau_vc1_decoder_t *) this_gen; lprintf( "vdpau_vc1_discontinuity\n" ); - //reset_sequence( &this->sequence ); - } /* -- cgit v1.2.3 From 424733ab41f30ba1c59913b84172439b8293c833 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 10 Feb 2009 17:08:03 +0000 Subject: Cleanups. --- src/video_out/video_out_vdpau.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 735dc43d7..3831a0c2a 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -60,6 +60,7 @@ char *vdpau_deinterlace_methods[] = { NULL }; + VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, @@ -144,9 +145,9 @@ static VdpStatus guarded_vdp_video_surface_create(VdpDevice device, VdpChromaTyp static VdpStatus guarded_vdp_video_surface_destroy(VdpVideoSurface surface) { VdpStatus r; -// XLockDisplay(guarded_display); + /*XLockDisplay(guarded_display);*/ r = orig_vdp_video_surface_destroy(surface); -// XUnlockDisplay(guarded_display); + /*XUnlockDisplay(guarded_display);*/ return r; } @@ -905,7 +906,6 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ /* Check frame size and format and reallocate if necessary */ if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) || (frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr)) { - //printf("vo_vdpau: updating frame to %d x %d (ratio=%g, format=%08X)\n", width, height, ratio, format); /* (re-) allocate render space */ if ( frame->chunk[0] ) @@ -969,8 +969,6 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ vdpau_frame_field ((vo_frame_t *)frame, flags); } - //printf("vo_vdpau: allocated_surfaces=%d\n", this->allocated_surfaces ); - frame->vdpau_accel_data.color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; frame->ratio = ratio; frame->vo_frame.future_frame = NULL; @@ -1207,7 +1205,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_redraw_needed( this_gen ); if ( (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) ) { - //printf( "vo_vdpau: got a yuv image -------------\n" ); chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; if ( (frame->width > this->soft_surface_width) || (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { printf( "vo_vdpau: soft_surface size update\n" ); @@ -1236,7 +1233,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) mix_h = this->soft_surface_height; } else if (frame->format == XINE_IMGFMT_VDPAU) { - //printf( "vo_vdpau: got a vdpau image -------------\n" ); surface = frame->vdpau_accel_data.surface; mix_w = frame->width; mix_h = frame->height; @@ -1297,7 +1293,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if (stream_speed != 0) { int vo_bufs_in_fifo = 0; _x_query_buffer_usage(frame->vo_frame.stream, NULL, NULL, &vo_bufs_in_fifo, NULL); - //fprintf(stderr, "vo_bufs: %d\n", vo_bufs_in_fifo); + /* fprintf(stderr, "vo_bufs: %d\n", vo_bufs_in_fifo); */ if (vo_bufs_in_fifo <= 0) stream_speed = 0; /* still image -> no delay */ } @@ -1313,13 +1309,11 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpLayer layer[3]; VdpRect layersrc, unscaledsrc; if ( this->has_overlay ) { - //printf("vdpau_display_frame: overlay should be visible !\n"); layer_count = 2; layersrc.x0 = 0; layersrc.y0 = 0; layersrc.x1 = this->overlay_output_width; layersrc.y1 = this->overlay_output_height; layer[0].struct_version = VDP_LAYER_VERSION; layer[0].source_surface = this->overlay_output; layer[0].source_rect = &layersrc; layer[0].destination_rect = &vid_dest; unscaledsrc.x0 = 0; unscaledsrc.y0 = 0; unscaledsrc.x1 = this->overlay_unscaled_width; unscaledsrc.y1 = this->overlay_unscaled_height; layer[1].struct_version = VDP_LAYER_VERSION; layer[1].source_surface = this->overlay_unscaled; layer[1].source_rect = &unscaledsrc; layer[1].destination_rect = &unscaledsrc; - //printf( "layersrc = %d %d %d %d \n", layersrc.x0, layersrc.y0, layersrc.x1, layersrc.y1 ); } else { layer_count = 0; @@ -1350,8 +1344,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - //else - //printf( "vo_vdpau: vdp_video_mixer_render: top_field, past1=%d, past0=%d, current=%d, future=%d\n", past[1], past[0], surface, future[0] ); vdp_queue_get_time( vdp_queue, ¤t_time ); vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); @@ -1384,8 +1376,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); if ( st != VDP_STATUS_OK ) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - //else - //printf( "vo_vdpau: vdp_video_mixer_render: bottom_field, past1=%d, past0=%d, current=%d, future=%d\n", past[1], past[0], surface, future[0] ); /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */ if (stream_speed > 0) @@ -1696,7 +1686,7 @@ static void vdpau_reinit( vo_driver_t *this_gen ) return; } - // osd overlays need to be recreated + /* osd overlays need to be recreated */ this->overlay_output = VDP_INVALID_HANDLE; this->overlay_output_width = this->overlay_output_height = 0; this->overlay_unscaled = VDP_INVALID_HANDLE; -- cgit v1.2.3 From 5760073f495f7143b1a39e88e8dfa2a977acdf57 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 11 Feb 2009 06:57:03 +0000 Subject: Compile fix. --- src/libvdpau/vdpau_mpeg12.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 99be61cf4..d3c2436f9 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -732,8 +732,8 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * sequence_t *seq = (sequence_t*)&this->sequence; if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { - this->video_step = buf->decoder_info[0]; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, this->video_step); + seq->video_step = buf->decoder_info[0]; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, seq->video_step); } if ( !buf->size ) -- cgit v1.2.3 From b48689cb87d8147753001325527bfc5b743ced32 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 11 Feb 2009 23:42:57 +0000 Subject: vo_vdpau: try to get frame duration from previous img->pts when frame->duration is 0. --- src/video_out/video_out_vdpau.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 3831a0c2a..ff1c4893e 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1328,8 +1328,14 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) layer[layer_count-1].struct_version = VDP_LAYER_VERSION; } + /* try to get frame duration from previous img->pts when frame->duration is 0 */ + int frame_duration = frame->vo_frame.duration; + if ( !frame_duration && this->back_frame[0] ) { + int duration = frame->vo_frame.pts - this->back_frame[0]->vo_frame.pts; + if ( duration>0 && duration<4000 ) + frame_duration = duration; + } int non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive; - int frame_duration = (frame->vo_frame.duration>0) ? frame->vo_frame.duration : 3000; /* unknown frame duration should not lead to no deint! */ if ( stream_speed && frame_duration>2500 && this->deinterlace && non_progressive && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; -- cgit v1.2.3 From 91f2c78995297c5e6c8d1374fb766fc40285cdf2 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 15 Feb 2009 03:42:29 +0000 Subject: VC1 interlaced fixes. --- src/libvdpau/vdpau_mpeg12.c | 4 +- src/libvdpau/vdpau_vc1.c | 94 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 76 insertions(+), 22 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index d3c2436f9..c97c7cf9a 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -732,8 +732,8 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * sequence_t *seq = (sequence_t*)&this->sequence; if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { - seq->video_step = buf->decoder_info[0]; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, seq->video_step); + /*seq->video_step = buf->decoder_info[0]; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, seq->video_step);*/ } if ( !buf->size ) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 989e0c899..fca537d2d 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -562,6 +562,40 @@ static void parse_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) +static void remove_emulation_prevention( uint8_t *src, uint8_t *dst, int src_len, int *dst_len ) +{ + int i; + int len = 0; + int removed = 0; + + for ( i=0; isequence; @@ -569,17 +603,28 @@ static int parse_code( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) if ( !sequence->have_header && buf[3]!=sequence_header_code ) return 0; - if ( sequence->code_start == frame_start_code ) + if ( sequence->code_start == frame_start_code ) { + if ( buf[3]==field_start_code || buf[3]==slice_start_code ) + return -1; return 1; /* frame complete, decode */ + } switch ( buf[3] ) { + int dst_len; + uint8_t *tmp; case sequence_header_code: lprintf("sequence_header_code\n"); - sequence_header( this_gen, buf+4, len-4 ); + tmp = malloc( len ); + remove_emulation_prevention( buf, tmp, len, &dst_len ); + sequence_header( this_gen, tmp+4, dst_len-4 ); + free( tmp ); break; case entry_point_code: lprintf("entry_point_code\n"); - entry_point( this_gen, buf+4, len-4 ); + tmp = malloc( len ); + remove_emulation_prevention( buf, tmp, len, &dst_len ); + entry_point( this_gen, tmp+4, dst_len-4 ); + free( tmp ); break; case sequence_end_code: lprintf("sequence_end_code\n"); @@ -733,20 +778,18 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) if ( len < 2 ) pic->skipped = 1; - - if ( pic->vdp_infos.interlace && pic->vdp_infos.frame_coding_mode == PICTURE_FIELD_INTERLACE ) { - if ( !(field = search_field( vd, buf, len )) ) - lprintf("error, no fields found!\n"); - else - pic->field = field; - } } else { seq->picture.vdp_infos.slice_count = 1; buf = seq->buf+seq->start+4; len = seq->bufseek-seq->start-4; - if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) - picture_header_advanced( vd, buf, len ); + if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) { + int tmplen = (len>50) ? 50 : len; + uint8_t *tmp = malloc( tmplen ); + remove_emulation_prevention( buf, tmp, tmplen, &tmplen ); + picture_header_advanced( vd, tmp, tmplen ); + free( tmp ); + } else picture_header( vd, buf, len ); @@ -754,6 +797,13 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) pic->skipped = 1; } + if ( pic->vdp_infos.interlace && pic->vdp_infos.frame_coding_mode == PICTURE_FIELD_INTERLACE ) { + if ( !(field = search_field( vd, buf, len )) ) + lprintf("error, no fields found!\n"); + else + pic->field = field; + } + VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); @@ -922,6 +972,7 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf } } else { + int res; while ( seq->bufseek <= seq->bufpos-4 ) { uint8_t *buffer = seq->buf+seq->bufseek; if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) { @@ -932,17 +983,20 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf seq->seq_pts = seq->cur_pts; } else { - if ( parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ) ) { + res = parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ); + if ( res==1 ) { decode_picture( this ); parse_code( this, seq->buf+seq->start, seq->bufseek-seq->start ); } - uint8_t *tmp = (uint8_t*)malloc(seq->bufsize); - xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek ); - seq->bufpos -= seq->bufseek; - seq->start = -1; - seq->bufseek = -1; - free( seq->buf ); - seq->buf = tmp; + if ( res!=-1 ) { + uint8_t *tmp = (uint8_t*)malloc(seq->bufsize); + xine_fast_memcpy( tmp, seq->buf+seq->bufseek, seq->bufpos-seq->bufseek ); + seq->bufpos -= seq->bufseek; + seq->start = -1; + seq->bufseek = -1; + free( seq->buf ); + seq->buf = tmp; + } } } ++seq->bufseek; -- cgit v1.2.3 From 91bbcee4cf1f45d43e15b95a50bc8d59775c40ec Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 15 Feb 2009 03:43:48 +0000 Subject: New demuxer: demux_vc1es. --- src/demuxers/Makefile.am | 6 +- src/demuxers/demux_vc1es.c | 452 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 457 insertions(+), 1 deletion(-) create mode 100644 src/demuxers/demux_vc1es.c diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index 2c4b38e4a..0875672b2 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -48,7 +48,8 @@ xineplug_LTLIBRARIES = $(ogg_module) $(asf_module) $(mng_module) $(image_module) xineplug_dmx_nsv.la \ xineplug_dmx_matroska.la \ xineplug_dmx_iff.la \ - xineplug_dmx_flv.la + xineplug_dmx_flv.la \ + xineplug_dmx_vc1_es.la xineplug_dmx_ogg_la_SOURCES = demux_ogg.c xineplug_dmx_ogg_la_LIBADD = $(XINE_LIB) $(VORBIS_LIBS) $(SPEEX_LIBS) $(THEORA_LIBS) $(OGG_LIBS) $(LTLIBINTL) @@ -66,6 +67,9 @@ xineplug_dmx_mpeg_la_LIBADD = $(XINE_LIB) xineplug_dmx_mpeg_elem_la_SOURCES = demux_elem.c xineplug_dmx_mpeg_elem_la_LIBADD = $(XINE_LIB) +xineplug_dmx_vc1_es_la_SOURCES = demux_vc1es.c +xineplug_dmx_vc1_es_la_LIBADD = $(XINE_LIB) + xineplug_dmx_mpeg_pes_la_SOURCES = demux_mpeg_pes.c xineplug_dmx_mpeg_pes_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) diff --git a/src/demuxers/demux_vc1es.c b/src/demuxers/demux_vc1es.c new file mode 100644 index 000000000..1e970f72c --- /dev/null +++ b/src/demuxers/demux_vc1es.c @@ -0,0 +1,452 @@ +/* + * Copyright (C) 2008 Christophe Thommeret + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + */ + +/* + * demultiplexer for wmv9/vc1 elementary streams + * + * + * SMP (.rcv) format: + * + * ** header *** + * le24 number of frames + * C5 04 00 00 00 + * 4 bytes sequence header + * le32 height + * le32 width + * 0C 00 00 00 + * 8 bytes unknown + * le32 fps + * ************ + * le24 frame_size + * 80 + * le32 pts (ms) + * frame_size bytes of picture data + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +/* #define LOG */ +#define LOG_MODULE "demux_vc1es" +#define LOG_VERBOSE + +#include "xine_internal.h" +#include "xineutils.h" +#include "compat.h" +#include "demux.h" + +#define SCRATCH_SIZE 36 +#define PRIVATE_SIZE 44 + +#define MODE_SMP 1 +#define MODE_AP 2 + + + +typedef struct { + demux_plugin_t demux_plugin; + + xine_stream_t *stream; + fifo_buffer_t *video_fifo; + fifo_buffer_t *audio_fifo; + input_plugin_t *input; + int status; + int mode; + int first_chunk; + uint8_t private[PRIVATE_SIZE]; + uint32_t video_step; + + uint32_t blocksize; +} demux_vc1_es_t ; + + + +typedef struct { + demux_class_t demux_class; +} demux_vc1_es_class_t; + + + +static int demux_vc1_es_next_smp( demux_vc1_es_t *this ) +{ + buf_element_t *buf; + uint32_t pts=0, frame_size=0; + off_t done; + uint8_t head[SCRATCH_SIZE]; + int start_flag = 1; + + if ( this->first_chunk ) { + this->input->read( this->input, head, SCRATCH_SIZE ); + this->first_chunk = 0; + } + + done = this->input->read( this->input, head, 8 ); + frame_size = head[2]<<16 | head[1]<<8 | head[0]; + pts = head[7]<<24 | head[6]<<16 | head[5]<<8 | head[4]; + + done = 0; + while ( frame_size>0 ) { + buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); + off_t read = (frame_size>buf->max_size) ? buf->max_size : frame_size; + done = this->input->read( this->input, buf->mem, read ); + if ( done<=0 ) { + buf->free_buffer( buf ); + this->status = DEMUX_FINISHED; + return 0; + } + buf->size = done; + buf->content = buf->mem; + buf->type = BUF_VIDEO_WMV9; + buf->pts = pts*90; + frame_size -= done; + if ( start_flag ) { + buf->decoder_flags = BUF_FLAG_FRAME_START; + start_flag = 0; + } + if ( !(frame_size>0) ) + buf->decoder_flags = BUF_FLAG_FRAME_END; + this->video_fifo->put(this->video_fifo, buf); + } + + return 1; +} + + + +static int demux_vc1_es_next_ap( demux_vc1_es_t *this ) +{ + buf_element_t *buf; + uint32_t blocksize; + off_t done; + + buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); + blocksize = (this->blocksize ? this->blocksize : buf->max_size); + done = this->input->read(this->input, buf->mem, blocksize); + + if (done <= 0) { + buf->free_buffer (buf); + this->status = DEMUX_FINISHED; + return 0; + } + + buf->size = done; + buf->content = buf->mem; + buf->pts = 0; + buf->type = BUF_VIDEO_VC1; + + if( this->input->get_length (this->input) ) + buf->extra_info->input_normpos = (int)( (double)this->input->get_current_pos( this->input )*65535/this->input->get_length( this->input ) ); + + this->video_fifo->put(this->video_fifo, buf); + + return 1; +} + + + +static int demux_vc1_es_send_chunk( demux_plugin_t *this_gen ) +{ + demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen; + //printf ("demux_vc1_es_send_chunk\n"); + + if ( this->mode==MODE_SMP ) { + if (!demux_vc1_es_next_smp(this)) + this->status = DEMUX_FINISHED; + return this->status; + } + + if (!demux_vc1_es_next_ap(this)) + this->status = DEMUX_FINISHED; + return this->status; +} + + + +static int demux_vc1_es_get_status( demux_plugin_t *this_gen ) +{ + demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen; + + return this->status; +} + + + +static void demux_vc1_es_send_headers( demux_plugin_t *this_gen ) +{ + demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen; + + this->video_fifo = this->stream->video_fifo; + this->audio_fifo = this->stream->audio_fifo; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 0); + _x_demux_control_start(this->stream); + this->blocksize = this->input->get_blocksize(this->input); + this->status = DEMUX_OK; + + if ( this->mode==MODE_SMP ) { + buf_element_t *buf; + buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); + xine_fast_memcpy( buf->mem, this->private, PRIVATE_SIZE ); + buf->size = PRIVATE_SIZE; + buf->content = buf->mem; + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; + if ( this->video_step ) { + buf->decoder_flags |= BUF_FLAG_FRAMERATE; + buf->decoder_info[0] = 90000/this->video_step; + } + buf->type = BUF_VIDEO_WMV9; + this->video_fifo->put(this->video_fifo, buf); + } +} + + + +static int demux_vc1_es_seek( demux_plugin_t *this_gen, off_t start_pos, int start_time, int playing ) +{ + demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen; + + if ( this->mode==MODE_SMP ) { + this->status = DEMUX_OK; + return this->status; + } + + start_pos = (off_t) ( (double) start_pos / 65535 * + this->input->get_length (this->input) ); + + this->status = DEMUX_OK; + + if (playing) + _x_demux_flush_engine(this->stream); + + if (INPUT_IS_SEEKABLE(this->input)) { + + /* FIXME: implement time seek */ + + if (start_pos != this->input->seek (this->input, start_pos, SEEK_SET)) { + this->status = DEMUX_FINISHED; + return this->status; + } + lprintf ("seeking to %"PRId64"\n", start_pos); + } + + /* + * now start demuxing + */ + this->status = DEMUX_OK; + + return this->status; +} + + + +static void demux_vc1_es_dispose( demux_plugin_t *this ) +{ + free (this); +} + + + +static int demux_vc1_es_get_stream_length( demux_plugin_t *this_gen ) +{ + return 0 ; /*FIXME: implement */ +} + + + +static uint32_t demux_vc1_es_get_capabilities( demux_plugin_t *this_gen ) +{ + return DEMUX_CAP_NOCAP; +} + + + +static int demux_vc1_es_get_optional_data( demux_plugin_t *this_gen, void *data, int data_type ) +{ + return DEMUX_OPTIONAL_UNSUPPORTED; +} + + + +static demux_plugin_t *open_plugin( demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input ) +{ + + demux_vc1_es_t *this; + uint8_t scratch[SCRATCH_SIZE]; + int i, read, found=0; + + switch (stream->content_detection_method) { + + case METHOD_BY_CONTENT: { + read = _x_demux_read_header(input, scratch, SCRATCH_SIZE); + if (!read) + return NULL; + lprintf("read size =%d\n",read); + + /* simple and main profiles */ + if ( read>=SCRATCH_SIZE ) { + lprintf("searching for rcv format..\n"); + if ( scratch[3]==0xc5 && scratch[4]==4 && scratch[5]==0 && scratch[6]==0 && scratch[7]==0 && scratch[20]==0x0c && scratch[21]==0 && scratch[22]==0 && scratch[23]==0 ) { + lprintf("rcv format found\n"); + found = MODE_SMP; + } + } + + if ( found==0 ) { + /* advanced profile */ + for (i = 0; i < read-4; i++) { + lprintf ("%02x %02x %02x %02x\n", scratch[i], scratch[i+1], scratch[i+2], scratch[i+3]); + if ((scratch[i] == 0x00) && (scratch[i+1] == 0x00) && (scratch[i+2] == 0x01)) { + if (scratch[i+3] == 0x0f) { + found = MODE_AP; + lprintf ("found header at offset 0x%x\n", i); + break; + } + } + } + } + + if (found == 0) + return NULL; + lprintf ("input accepted.\n"); + } + break; + + case METHOD_BY_EXTENSION: { + const char *extensions, *mrl; + + mrl = input->get_mrl (input); + extensions = class_gen->get_extensions (class_gen); + + if (!_x_demux_check_extension (mrl, extensions)) + return NULL; + } + break; + + case METHOD_EXPLICIT: + break; + + default: + return NULL; + } + + this = calloc(1, sizeof(demux_vc1_es_t)); + this->mode = found; + this->first_chunk = 1; + if ( found==MODE_SMP ) { + xine_fast_memcpy( this->private+8, scratch+12, 4 ); /* height */ + xine_fast_memcpy( this->private+4, scratch+16, 4 ); /* width */ + xine_fast_memcpy( this->private+40, scratch+8, 4 ); /* sequence header */ + } + this->video_step = scratch[35]<<24 | scratch[34]<<16 | scratch[33]<<8 | scratch[32]; + this->stream = stream; + this->input = input; + + this->demux_plugin.send_headers = demux_vc1_es_send_headers; + this->demux_plugin.send_chunk = demux_vc1_es_send_chunk; + this->demux_plugin.seek = demux_vc1_es_seek; + this->demux_plugin.dispose = demux_vc1_es_dispose; + this->demux_plugin.get_status = demux_vc1_es_get_status; + this->demux_plugin.get_stream_length = demux_vc1_es_get_stream_length; + this->demux_plugin.get_capabilities = demux_vc1_es_get_capabilities; + this->demux_plugin.get_optional_data = demux_vc1_es_get_optional_data; + this->demux_plugin.demux_class = class_gen; + + this->status = DEMUX_FINISHED; + + return &this->demux_plugin; +} + + + +static const char *get_description( demux_class_t *this_gen ) +{ + return "VC1 elementary stream demux plugin"; +} + + + +static const char *get_identifier( demux_class_t *this_gen ) +{ + return "VC1_ES"; +} + + + +static const char *get_extensions( demux_class_t *this_gen ) +{ + return ""; +} + + + +static const char *get_mimetypes( demux_class_t *this_gen ) +{ + return NULL; +} + + + +static void class_dispose( demux_class_t *this_gen ) +{ + demux_vc1_es_class_t *this = (demux_vc1_es_class_t *) this_gen; + + free (this); +} + + + +static void *init_plugin( xine_t *xine, void *data ) +{ + demux_vc1_es_class_t *this; + + this = calloc(1, sizeof(demux_vc1_es_class_t)); + + this->demux_class.open_plugin = open_plugin; + this->demux_class.get_description = get_description; + this->demux_class.get_identifier = get_identifier; + this->demux_class.get_mimetypes = get_mimetypes; + this->demux_class.get_extensions = get_extensions; + this->demux_class.dispose = class_dispose; + + return this; +} + + +/* + * exported plugin catalog entry + */ +static const demuxer_info_t demux_info_vc1es = { + 0 /* priority */ +}; + + + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_DEMUX, 26, "vc1es", XINE_VERSION_CODE, &demux_info_vc1es, init_plugin }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; -- cgit v1.2.3 From 4086f48eeff9d5b4989bf2e43f6255002faa77be Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 17 Feb 2009 05:53:16 +0000 Subject: Endianness cleanup. --- src/demuxers/demux_vc1es.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/demuxers/demux_vc1es.c b/src/demuxers/demux_vc1es.c index 1e970f72c..8f5e2b4bd 100644 --- a/src/demuxers/demux_vc1es.c +++ b/src/demuxers/demux_vc1es.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 the xine project * Copyright (C) 2008 Christophe Thommeret * * This file is part of xine, a free video player. @@ -57,6 +58,7 @@ #include "xine_internal.h" #include "xineutils.h" #include "compat.h" +#include "bswap.h" #include "demux.h" #define SCRATCH_SIZE 36 @@ -105,8 +107,8 @@ static int demux_vc1_es_next_smp( demux_vc1_es_t *this ) } done = this->input->read( this->input, head, 8 ); - frame_size = head[2]<<16 | head[1]<<8 | head[0]; - pts = head[7]<<24 | head[6]<<16 | head[5]<<8 | head[4]; + frame_size = _X_LE_24( head ); + pts = _X_LE_32( head+4 ); done = 0; while ( frame_size>0 ) { @@ -361,7 +363,7 @@ static demux_plugin_t *open_plugin( demux_class_t *class_gen, xine_stream_t *str xine_fast_memcpy( this->private+4, scratch+16, 4 ); /* width */ xine_fast_memcpy( this->private+40, scratch+8, 4 ); /* sequence header */ } - this->video_step = scratch[35]<<24 | scratch[34]<<16 | scratch[33]<<8 | scratch[32]; + this->video_step = _X_LE_32( scratch+32 ); this->stream = stream; this->input = input; -- cgit v1.2.3 From cd46d8edb40c79520e7a0908a3e9727433479199 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 18 Feb 2009 15:08:06 +0000 Subject: Minor fix. --- src/demuxers/demux_vc1es.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/demuxers/demux_vc1es.c b/src/demuxers/demux_vc1es.c index 8f5e2b4bd..820993609 100644 --- a/src/demuxers/demux_vc1es.c +++ b/src/demuxers/demux_vc1es.c @@ -173,7 +173,6 @@ static int demux_vc1_es_next_ap( demux_vc1_es_t *this ) static int demux_vc1_es_send_chunk( demux_plugin_t *this_gen ) { demux_vc1_es_t *this = (demux_vc1_es_t *) this_gen; - //printf ("demux_vc1_es_send_chunk\n"); if ( this->mode==MODE_SMP ) { if (!demux_vc1_es_next_smp(this)) @@ -362,8 +361,8 @@ static demux_plugin_t *open_plugin( demux_class_t *class_gen, xine_stream_t *str xine_fast_memcpy( this->private+8, scratch+12, 4 ); /* height */ xine_fast_memcpy( this->private+4, scratch+16, 4 ); /* width */ xine_fast_memcpy( this->private+40, scratch+8, 4 ); /* sequence header */ + this->video_step = _X_LE_32( scratch+32 ); } - this->video_step = _X_LE_32( scratch+32 ); this->stream = stream; this->input = input; -- cgit v1.2.3 From 2cc870f8270dfd550d621e46bf4c7a75e9c90f78 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 19 Feb 2009 18:05:38 +0000 Subject: Top/bottom fix. --- src/video_out/video_out_vdpau.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index ff1c4893e..ac4dcd1a8 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 the xine project * Copyright (C) 2008 Christophe Thommeret * * This file is part of xine, a free video player. @@ -1303,8 +1304,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( this->init_queue>1 ) vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); - XLockDisplay( this->display ); - uint32_t layer_count; VdpLayer layer[3]; VdpRect layersrc, unscaledsrc; @@ -1336,6 +1335,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) frame_duration = duration; } int non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive; + + XLockDisplay( this->display ); + if ( stream_speed && frame_duration>2500 && this->deinterlace && non_progressive && frame->format==XINE_IMGFMT_VDPAU ) { VdpTime current_time = 0; VdpVideoSurface past[2]; @@ -1376,7 +1378,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; else future[0] = VDP_INVALID_HANDLE; - picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; + picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD; st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); -- cgit v1.2.3 From 55491cbc1b742aa6afde58c6c994efb59a5bf160 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 19 Feb 2009 23:33:10 +0000 Subject: Fix overlays recreation after pre-emption. --- src/video_out/video_out_vdpau.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index ac4dcd1a8..8b4923266 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1695,6 +1695,13 @@ static void vdpau_reinit( vo_driver_t *this_gen ) } /* osd overlays need to be recreated */ + + int i; + for ( i=0; ioverlays[i].ovl_bitmap = VDP_INVALID_HANDLE; + this->overlays[i].bitmap_width = 0; + this->overlays[i].bitmap_height = 0; + } this->overlay_output = VDP_INVALID_HANDLE; this->overlay_output_width = this->overlay_output_height = 0; this->overlay_unscaled = VDP_INVALID_HANDLE; -- cgit v1.2.3 From 384743ff9ccb078750de9563d82a46e63b97f74f Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 19 Feb 2009 23:45:14 +0000 Subject: Fix pre-emption reinit. --- src/libvdpau/vdpau_h264.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 7e57d405a..8a88dde13 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -752,6 +752,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre /* now check if vdpau has free decoder resource */ vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + int runtime_nr = accel->vdp_runtime_nr; img->free(img); VdpDecoder decoder; VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_H264_MAIN, 1920, 1080, 16, &decoder ); @@ -775,7 +776,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->class = (vdpau_h264_class_t *) class_gen; this->decoder = VDP_INVALID_HANDLE; - this->vdp_runtime_nr = 1; + this->vdp_runtime_nr = runtime_nr; this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; this->nal_parser = init_parser(); -- cgit v1.2.3 From 27069809bf3dd57ab1006dda6ffdd10a7ae86687 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 19 Feb 2009 23:45:58 +0000 Subject: Fix mpeg progressive flag. --- src/libvdpau/vdpau_mpeg12.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index c97c7cf9a..dbcc77783 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 the xine project * Copyright (C) 2008 Christophe Thommeret * * This file is part of xine, a free video player. @@ -185,6 +186,7 @@ static void reset_picture( picture_t *pic ) pic->slices_count2 = 0; pic->slices_pos = 0; pic->slices_pos_top = 0; + pic->progressive_frame = 0; pic->state = WANT_HEADER; } @@ -692,9 +694,11 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) else img->top_field_first = 0; - /* progressive_frame is unreliable with most mpeg2 streams - img->progressive_frame = pic->progressive_frame;*/ - img->progressive_frame = 0; + /* progressive_frame is unreliable with most mpeg2 streams */ + if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME ) + img->progressive_frame = 0; + else + img->progressive_frame = pic->progressive_frame; if ( pic->vdp_infos.picture_coding_type!=B_FRAME ) { if ( pic->vdp_infos.picture_coding_type==I_FRAME && !seq->backward_ref ) { @@ -731,11 +735,6 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; sequence_t *seq = (sequence_t*)&this->sequence; - if (buf->decoder_flags & BUF_FLAG_FRAMERATE) { - /*seq->video_step = buf->decoder_info[0]; - _x_stream_info_set(this->stream, XINE_STREAM_INFO_FRAME_DURATION, seq->video_step);*/ - } - if ( !buf->size ) return; -- cgit v1.2.3 From 88e51a20a8054d24abf2fe2e27ca35bc1adefdda Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 19 Feb 2009 23:48:50 +0000 Subject: Fix pre-emption reinit. --- src/libvdpau/vdpau_mpeg12.c | 3 ++- src/libvdpau/vdpau_vc1.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index dbcc77783..8141a202d 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -851,6 +851,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre /* now check if vdpau has free decoder resource */ vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + int runtime_nr = accel->vdp_runtime_nr; img->free(img); VdpDecoder decoder; VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_MPEG2_MAIN, 1920, 1080, 2, &decoder ); @@ -876,7 +877,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize); this->sequence.forward_ref = 0; this->sequence.backward_ref = 0; - this->sequence.vdp_runtime_nr = 1; + this->sequence.vdp_runtime_nr = runtime_nr; reset_sequence( &this->sequence ); this->sequence.ratio = 1; diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index fca537d2d..137b03d03 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -1073,6 +1073,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre /* now check if vdpau has free decoder resource */ vo_frame_t *img = stream->video_out->get_frame( stream->video_out, 1920, 1080, 1, XINE_IMGFMT_VDPAU, VO_BOTH_FIELDS ); vdpau_accel_t *accel = (vdpau_accel_t*)img->accel_data; + int runtime_nr = accel->vdp_runtime_nr; img->free(img); VdpDecoder decoder; VdpStatus st = accel->vdp_decoder_create( accel->vdp_device, VDP_DECODER_PROFILE_VC1_MAIN, 1920, 1080, 2, &decoder ); @@ -1098,7 +1099,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->sequence.buf = (uint8_t*)malloc(this->sequence.bufsize); this->sequence.forward_ref = 0; this->sequence.backward_ref = 0; - this->sequence.vdp_runtime_nr = 1; + this->sequence.vdp_runtime_nr = runtime_nr; init_sequence( &this->sequence ); init_picture( &this->sequence.picture ); -- cgit v1.2.3 From 09c12deddb69c61f7aa8a3dbe67eacf9392ed8e1 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 20 Feb 2009 00:01:16 +0000 Subject: Set background color after pre-emption. --- src/video_out/video_out_vdpau.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 8b4923266..1cdd61fee 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1673,6 +1673,7 @@ static void vdpau_reinit( vo_driver_t *this_gen ) st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); if ( vdpau_reinit_error( st, "Can't create presentation queue !!" ) ) return; + vdp_queue_set_background_color( vdp_queue, &this->back_color ); VdpChromaType chroma = VDP_CHROMA_TYPE_420; -- cgit v1.2.3 From bc5c244b04c756001720060c8b7a695d3f4a5d3d Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 21 Feb 2009 02:43:24 +0000 Subject: Top/bottom fix. --- src/video_out/video_out_vdpau.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 1cdd61fee..f58215a57 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1093,6 +1093,7 @@ static void vdpau_honor_progressive_flag( void *this_gen, xine_cfg_entry_t *entr vdpau_driver_t *this = (vdpau_driver_t *) this_gen; this->honor_progressive = entry->num_value; + printf( "vo_vdpau: honor_progressive=%d\n", this->honor_progressive ); } @@ -1378,7 +1379,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; else future[0] = VDP_INVALID_HANDLE; - picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD; + picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); -- cgit v1.2.3 From 48450216ea572bdba3d34aa9e4ccd64db16a2d31 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 23 Feb 2009 16:03:44 +0000 Subject: Fix TFF/BFF. --- src/libvdpau/vdpau_mpeg12.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 8141a202d..175091130 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -181,7 +181,7 @@ static void reset_picture( picture_t *pic ) pic->vdp_infos2.intra_vlc_format = pic->vdp_infos.intra_vlc_format = 0; pic->vdp_infos2.alternate_scan = pic->vdp_infos.alternate_scan = 0; pic->vdp_infos2.q_scale_type = pic->vdp_infos.q_scale_type = 0; - pic->vdp_infos2.top_field_first = pic->vdp_infos.top_field_first = 0; + pic->vdp_infos2.top_field_first = pic->vdp_infos.top_field_first = 1; pic->slices_count = 0; pic->slices_count2 = 0; pic->slices_pos = 0; @@ -689,10 +689,7 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) img->pts = seq->seq_pts; img->bad_frame = 0; img->duration = seq->video_step; - if ( pic->vdp_infos.top_field_first || pic->vdp_infos.picture_structure==PICTURE_FRAME ) - img->top_field_first = 1; - else - img->top_field_first = 0; + img->top_field_first = pic->vdp_infos.top_field_first; /* progressive_frame is unreliable with most mpeg2 streams */ if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME ) -- cgit v1.2.3 From c6f739dec2813c077d9f94f09c113d9ecb0a7b54 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 25 Feb 2009 02:37:51 +0000 Subject: Add skip_chroma_deinterlace option. --- src/video_out/video_out_vdpau.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index f58215a57..2671a1d1c 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -188,7 +188,7 @@ typedef struct { int ovl_x, ovl_y; /* overlay's top-left display position */ int unscaled; int expected_overlay_width; /*if >0 scale to video width*/ - int expected_overlay_height; /* if >0 sccale to video height */ + int expected_overlay_height; /* if >0 scale to video height */ } vdpau_overlay_t; @@ -280,6 +280,7 @@ typedef struct { int deinterlace_method; int enable_inverse_telecine; int honor_progressive; + int skip_chroma; int vdp_runtime_nr; int reinit_needed; @@ -1176,6 +1177,28 @@ static void vdpau_update_csc( vdpau_driver_t *this_gen ) +static void vdpau_update_skip_chroma( vdpau_driver_t *this_gen ) +{ + VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE }; + void* attribute_values[] = { &(this_gen->skip_chroma) }; + VdpStatus st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: error, can't set skip_chroma !!\n" ); + else + printf( "vo_vdpau: skip_chroma = %d\n", this_gen->skip_chroma ); +} + + + +static void vdpau_set_skip_chroma( void *this_gen, xine_cfg_entry_t *entry ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + this->skip_chroma = entry->num_value; + vdpau_update_skip_chroma( this ); +} + + + static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -1268,6 +1291,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_update_sharpness( this ); this->color_standard = color_standard; vdpau_update_csc( this ); + vdpau_update_skip_chroma( this ); } if (color_standard != this->color_standard) { @@ -2003,7 +2027,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdp_video_surface_destroy( this->soft_surface ); return NULL; } - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[1] ); + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[1], this->output_surface_height[1], &this->output_surface[1] ); if ( vdpau_init_error( st, "Can't create second output surface !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); vdp_output_surface_destroy( this->output_surface[0] ); @@ -2049,6 +2073,11 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo "This flag is not always reliable.\n\n"), 10, vdpau_honor_progressive_flag, this ); + this->skip_chroma = config->register_bool( config, "video.output.vdpau_skip_chroma_deinterlace", 0, + _("vdpau: disable advanced deinterlacers chroma filter"), + _("Setting to true may help if your video card isn't able to run advanced deinterlacers.\n\n"), + 10, vdpau_set_skip_chroma, this ); + /* number of video frames from config - register it with the default value. */ int frame_num = config->register_num (config, "engine.buffers.video_num_frames", 15, /* default */ _("default number of video frames"), -- cgit v1.2.3 From 6fc581dce7666c8b9d48a96ecbce0d5711338f0e Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 25 Feb 2009 02:43:48 +0000 Subject: Set rangeredfrm in rangered's bit 1. --- src/libvdpau/vdpau_vc1.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 137b03d03..db99c538b 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -433,8 +433,10 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len if ( info->finterpflag ) ++off; - if ( info->rangered ) - ++off; + if ( info->rangered ) { + info->rangered &= ~2; + info->rangered |= get_bits( buf,off++,1 ) << 1; + } if ( !info->maxbframes ) { if ( get_bits( buf,off++,1 ) ) info->picture_type = P_FRAME; -- cgit v1.2.3 From 262b4fc5ff0f87525c1ea626324154ab48f4a7c5 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 25 Feb 2009 02:43:48 +0000 Subject: Cleanup. --- src/libvdpau/vdpau_vc1.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index db99c538b..2004de063 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -21,7 +21,7 @@ * */ -#define LOG +/*#define LOG*/ #define LOG_MODULE "vdpau_vc1" @@ -570,9 +570,9 @@ static void remove_emulation_prevention( uint8_t *src, uint8_t *dst, int src_len int len = 0; int removed = 0; - for ( i=0; ivdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); int i; - for ( i=0; i<20; ++i ) + /*for ( i=0; i<20; ++i ) printf("%02X ", buf[i]); - printf("\n"); + printf("\n");*/ } if ( pic->field ) { @@ -729,9 +729,9 @@ static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, uint8_ lprintf( "DECODER SUCCESS : slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); int i; - for ( i=0; i<20; ++i ) + /*for ( i=0; i<20; ++i ) printf("%02X ", buf[pic->field+4+i] ); - printf("\n"); + printf("\n");*/ } VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); @@ -950,9 +950,9 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf parse_header( this, buf->content+bs, buf->size-bs ); } int i; - for ( i=0; isize; ++i ) + /*for ( i=0; isize; ++i ) printf("%02X ", buf->content[i] ); - printf("\n\n"); + printf("\n\n");*/ return; } -- cgit v1.2.3 From d7c21ec548ef36aae4962d346a14e9fb3d4d23d7 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 2 Mar 2009 10:33:50 +0000 Subject: Fix recreation of broken nal start sequences when they were split across buffers. --- src/libvdpau/h264_parser.c | 50 +++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index ea043ca70..562f735f3 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1245,7 +1245,31 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, int start_seq_len = 3; uint8_t completed_nal = 0; - uint8_t *prebuf = parser->prebuf; + /* seek for nal start sequences split across buffer boundaries */ + if(!parser->nal_size_length) { + if(parser->prebuf_len >= 2 && inbuf_len >= 1 && + parser->prebuf[parser->prebuf_len-2] == 0x00 && + parser->prebuf[parser->prebuf_len-1] == 0x00 && + inbuf[0] == 0x01) { + parsed_len = 1; + } else if (parser->prebuf_len >= 1 && inbuf_len >= 1 && + parser->prebuf[parser->prebuf_len-1] == 0x00 && + inbuf[0] == 0x00 && + inbuf[1] == 0x01) { + parsed_len = 2; + } + + /* in case a start seq was splitted call ourself with just a start + * sequences and strip incomplete start seq parts from the buffer + * before. + */ + if(parsed_len > 0) { + static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + parser->prebuf_len -= start_seq_len - parsed_len; + parse_frame(parser, start_seq, start_seq_len, ret_buf, ret_len, ret_slice_cnt); + return parsed_len; + } + } if(parser->nal_size_length > 0) start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; @@ -1289,7 +1313,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parsed_len += next_nal; inbuf += next_nal; - parser->last_nal_res = parse_nal(prebuf+start_seq_len, parser->prebuf_len-start_seq_len, parser); + parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, parser->prebuf_len-start_seq_len, parser); if (parser->last_nal_res == 1 && parser->buf_len > 0) { //printf("Frame complete: %d bytes\n", parser->buf_len); @@ -1304,7 +1328,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, /* this is a SLICE, keep it in the buffer */ //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); if(parser->nal_size_length > 0) { - uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; xine_fast_memcpy(parser->buf, start_seq, 3); parser->buf_len += 3; } @@ -1312,8 +1336,8 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, int offset = 0; if(parser->nal_size_length > 0) offset = start_seq_len; - xine_fast_memcpy(parser->buf+parser->buf_len, prebuf+offset, parser->prebuf_len-offset); - parser->buf_len += parser->prebuf_len-offset; + xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, parser->prebuf_len-offset); + parser->buf_len += (parser->prebuf_len-offset); parser->prebuf_len = 0; parser->incomplete_nal = 0; @@ -1332,7 +1356,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); /* this is a SLICE, keep it in the buffer */ if(parser->nal_size_length > 0) { - uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; xine_fast_memcpy(parser->buf + parser->buf_len, start_seq, 3); parser->buf_len += 3; } @@ -1341,7 +1365,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, if(parser->nal_size_length > 0) offset = start_seq_len; - xine_fast_memcpy(parser->buf + parser->buf_len, prebuf+offset, parser->prebuf_len-offset); + xine_fast_memcpy(parser->buf + parser->buf_len, parser->prebuf+offset, parser->prebuf_len-offset); parser->buf_len += (parser->prebuf_len-offset); } @@ -1372,22 +1396,12 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, *ret_buf = NULL; return parsed_len; } + parser->incomplete_nal = 1; xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len-parsed_len); parser->prebuf_len += inbuf_len-parsed_len; parsed_len += inbuf_len-parsed_len; inbuf += inbuf_len-parsed_len; - - /* now check if prebuf contains a second slice header - * this might happen if the nal start sequence is split - * over the buf-boundary - if this is the case we - */ - if(!parser->nal_size_length && parsed_len > 2 && - (next_nal = seek_for_nal(prebuf+start_seq_len, parser->prebuf_len, parser)) >= 0) { - inbuf -= parser->prebuf_len-next_nal-start_seq_len; - parsed_len -= parser->prebuf_len-next_nal-start_seq_len; - parser->prebuf_len = next_nal+start_seq_len; - } } *ret_len = 0; -- cgit v1.2.3 From b612a4aec4fb8c0bedee4fa47585614fe031524f Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 2 Mar 2009 11:05:44 +0000 Subject: Fix split nal start sequences again. this is for the case where the split nal sequences is on the 2nd nal in a new frame. --- src/libvdpau/h264_parser.c | 51 ++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 562f735f3..ed186d383 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1245,6 +1245,26 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, int start_seq_len = 3; uint8_t completed_nal = 0; + if(parser->nal_size_length > 0) + start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; + + if(parser->last_nal_res == 1 && parser->current_nal && + parser->current_nal->slc) { + int i; + for(i = 0; i < parser->current_nal->slc->dec_ref_pic_marking_count; i++) { + decode_ref_pic_marking( + parser->current_nal, + parser->current_nal->slc->dec_ref_pic_marking[i].memory_management_control_operation, + i, + parser); + } + + if (parser->last_nal->slc != NULL) + parser->prev_pic_order_cnt_lsb + = parser->last_nal->slc->pic_order_cnt_lsb; + parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; + } + /* seek for nal start sequences split across buffer boundaries */ if(!parser->nal_size_length) { if(parser->prebuf_len >= 2 && inbuf_len >= 1 && @@ -1252,7 +1272,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->prebuf[parser->prebuf_len-1] == 0x00 && inbuf[0] == 0x01) { parsed_len = 1; - } else if (parser->prebuf_len >= 1 && inbuf_len >= 1 && + } else if (parser->prebuf_len >= 1 && inbuf_len >= 2 && parser->prebuf[parser->prebuf_len-1] == 0x00 && inbuf[0] == 0x00 && inbuf[1] == 0x01) { @@ -1266,29 +1286,16 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, if(parsed_len > 0) { static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; parser->prebuf_len -= start_seq_len - parsed_len; - parse_frame(parser, start_seq, start_seq_len, ret_buf, ret_len, ret_slice_cnt); - return parsed_len; - } - } - - if(parser->nal_size_length > 0) - start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; - if(parser->last_nal_res == 1 && parser->current_nal && - parser->current_nal->slc) { - int i; - for(i = 0; i < parser->current_nal->slc->dec_ref_pic_marking_count; i++) { - decode_ref_pic_marking( - parser->current_nal, - parser->current_nal->slc->dec_ref_pic_marking[i].memory_management_control_operation, - i, - parser); + /* loop this until the start_seq was really parsed, else it might + * be dropped in case we are just at a frame boundary + */ + int int_parsed = 0; + do { + int_parsed += parse_frame(parser, start_seq, start_seq_len, ret_buf, ret_len, ret_slice_cnt); + } while(int_parsed < 3); + return parsed_len; } - - if (parser->last_nal->slc != NULL) - parser->prev_pic_order_cnt_lsb - = parser->last_nal->slc->pic_order_cnt_lsb; - parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; } while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset, parser)) >= 0) { -- cgit v1.2.3 From 66475e7901d34d42a32930b649383e99cc56cf33 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Thu, 5 Mar 2009 17:43:41 +0000 Subject: Fix mmc operation parsing. It has to be done after decoding the frame, but before adding the decoded frame to dpb. --- src/libvdpau/h264_parser.c | 31 +++++++++++++++++-------------- src/libvdpau/h264_parser.h | 5 +++++ src/libvdpau/vdpau_h264.c | 2 ++ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index ed186d383..d7c268fcc 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1011,6 +1011,7 @@ void decode_ref_pic_marking(struct nal_unit *nal, dpb_set_unused_ref_picture_a(dpb, pic); else pic->top_is_reference = 0; + //printf("FIXME: We might need do delete more from the DPB...\n"); // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120 } @@ -1235,21 +1236,10 @@ void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_le printf("done parsing extradata\n"); } - -int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, - uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) +void process_mmc_operations(struct nal_parser *parser) { - int32_t next_nal = 0; - int parsed_len = 0; - int search_offset = 0; - int start_seq_len = 3; - uint8_t completed_nal = 0; - - if(parser->nal_size_length > 0) - start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; - if(parser->last_nal_res == 1 && parser->current_nal && - parser->current_nal->slc) { + parser->current_nal->slc) { int i; for(i = 0; i < parser->current_nal->slc->dec_ref_pic_marking_count; i++) { decode_ref_pic_marking( @@ -1264,6 +1254,19 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, = parser->last_nal->slc->pic_order_cnt_lsb; parser->prev_pic_order_cnt_msb = parser->pic_order_cnt_msb; } +} + +int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, + uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) +{ + int32_t next_nal = 0; + int parsed_len = 0; + int search_offset = 0; + int start_seq_len = 3; + uint8_t completed_nal = 0; + + if(parser->nal_size_length > 0) + start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; /* seek for nal start sequences split across buffer boundaries */ if(!parser->nal_size_length) { @@ -1407,8 +1410,8 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->incomplete_nal = 1; xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len-parsed_len); parser->prebuf_len += inbuf_len-parsed_len; - parsed_len += inbuf_len-parsed_len; inbuf += inbuf_len-parsed_len; + parsed_len += inbuf_len-parsed_len; } *ret_len = 0; diff --git a/src/libvdpau/h264_parser.h b/src/libvdpau/h264_parser.h index c726f7b90..bf3d34100 100644 --- a/src/libvdpau/h264_parser.h +++ b/src/libvdpau/h264_parser.h @@ -88,6 +88,11 @@ void free_parser(struct nal_parser *parser); int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt); +/* this has to be called after decoding the frame delivered by parse_frame, + * but before adding a decoded frame to the dpb. + */ +void process_mmc_operations(struct nal_parser *parser); + void parse_codec_private(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len); #endif diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 8a88dde13..a8d4093d9 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -466,6 +466,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v this->curr_pts = this->next_pts; this->next_pts = 0; + process_mmc_operations(this->nal_parser); + if(status != VDP_STATUS_OK) { xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); -- cgit v1.2.3 From 3dfbff7382ba723343c5206c8a730a23498168bd Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 6 Mar 2009 09:57:12 +0000 Subject: Fix deinterlacing settings after a pre-emption. --- src/video_out/video_out_vdpau.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 2671a1d1c..a5082bdd7 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1754,6 +1754,7 @@ static void vdpau_reinit( vo_driver_t *this_gen ) return; } + vdpau_set_deinterlace(this_gen); vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this); this->vdp_runtime_nr++; -- cgit v1.2.3 From 26d9ad1dde5b85defcfda971b7746d49e2f9e316 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 7 Mar 2009 13:13:59 +0000 Subject: Some cleanups. --- src/libvdpau/vdpau_vc1.c | 47 +++++++++++++++++------------------------------ 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 2004de063..d5e5e265c 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2008 the xine project * Copyright (C) 2008 Christophe Thommeret * * This file is part of xine, a free video player. @@ -434,8 +435,9 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len if ( info->finterpflag ) ++off; if ( info->rangered ) { - info->rangered &= ~2; - info->rangered |= get_bits( buf,off++,1 ) << 1; + /*info->rangered &= ~2; + info->rangered |= get_bits( buf,off++,1 ) << 1;*/ + info->rangered = (get_bits( buf,off++,1 ) << 1) +1; } if ( !info->maxbframes ) { if ( get_bits( buf,off++,1 ) ) @@ -494,7 +496,7 @@ static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf } } } - if ( info->frame_coding_mode == PICTURE_FIELD_INTERLACE ) { + if ( info->interlace && info->frame_coding_mode == PICTURE_FIELD_INTERLACE ) { pic->fptype = get_bits(buf,off,3); switch ( pic->fptype ) { case FIELDS_I_I: @@ -570,10 +572,6 @@ static void remove_emulation_prevention( uint8_t *src, uint8_t *dst, int src_len int len = 0; int removed = 0; - /*for ( i=0; ivdp_decoder_create( accel->vdp_device, seq->profile, seq->coded_width, seq->coded_height, 2, &vd->decoder); if ( st!=VDP_STATUS_OK ) - lprintf( "failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); + printf( "vdpau_vc1: failed to create decoder !! %s\n", accel->vdp_get_error_string( st ) ); else { lprintf( "decoder created.\n" ); vd->decoder_profile = seq->profile; @@ -690,15 +684,16 @@ static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, uint8_ vbit.bitstream_bytes = pic->field; st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); if ( st!=VDP_STATUS_OK ) - lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); + printf( "vdpau_vc1: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else { lprintf( "DECODER SUCCESS : slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); - int i; - /*for ( i=0; i<20; ++i ) - printf("%02X ", buf[i]); - printf("\n");*/ } + VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); + lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", info->slice_count, info->picture_type, info->frame_coding_mode, + info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, + info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, + info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); if ( pic->field ) { int old_type = pic->vdp_infos.picture_type; @@ -726,15 +721,14 @@ static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, uint8_ if ( st!=VDP_STATUS_OK ) lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else { - lprintf( "DECODER SUCCESS : slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", + lprintf( "DECODER SUCCESS (second field): slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); - int i; - /*for ( i=0; i<20; ++i ) - printf("%02X ", buf[pic->field+4+i] ); - printf("\n");*/ } VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); - lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); + lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n", info->slice_count, info->picture_type, info->frame_coding_mode, + info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, + info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, + info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); pic->vdp_infos.picture_type = old_type; } @@ -806,9 +800,6 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) pic->field = field; } - VdpPictureInfoVC1 *info = &(seq->picture.vdp_infos); - lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n\n", info->slice_count, info->picture_type, info->frame_coding_mode, info->postprocflag, info->pulldown, info->interlace, info->tfcntrflag, info->finterpflag, info->psf, info->dquant, info->panscan_flag, info->refdist_flag, info->quantizer, info->extended_mv, info->extended_dmv, info->overlap, info->vstransform, info->loopfilter, info->fastuvmc, info->range_mapy_flag, info->range_mapy, info->range_mapuv_flag, info->range_mapuv, info->multires, info->syncmarker, info->rangered, info->maxbframes, info->deblockEnable, info->pquant ); - pic->vdp_infos.forward_reference = VDP_INVALID_HANDLE; pic->vdp_infos.backward_reference = VDP_INVALID_HANDLE; @@ -949,10 +940,6 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf seq->mode = MODE_FRAME; parse_header( this, buf->content+bs, buf->size-bs ); } - int i; - /*for ( i=0; isize; ++i ) - printf("%02X ", buf->content[i] ); - printf("\n\n");*/ return; } -- cgit v1.2.3 From 7cf13672ddbcef1cb03704960408d1e21f3ad060 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 7 Mar 2009 13:15:19 +0000 Subject: Debug fix. --- src/libvdpau/vdpau_vc1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index d5e5e265c..dde011293 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -719,7 +719,7 @@ static void decode_render( vdpau_vc1_decoder_t *vd, vdpau_accel_t *accel, uint8_ vbit.bitstream_bytes = len-pic->field-4; st = accel->vdp_decoder_render( vd->decoder, accel->surface, (VdpPictureInfo*)&pic->vdp_infos, 1, &vbit ); if ( st!=VDP_STATUS_OK ) - lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); + printf( "vdpau_vc1: decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else { lprintf( "DECODER SUCCESS (second field): slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); -- cgit v1.2.3 From 11eda00ea06b7de8b0c7daa1df763684f5171201 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 8 Mar 2009 10:22:02 +0000 Subject: Fix mixer attributes after pre-emption. --- src/video_out/video_out_vdpau.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index a5082bdd7..6b25b28c3 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1740,7 +1740,6 @@ static void vdpau_reinit( vo_driver_t *this_gen ) this->argb_overlay_width = this->argb_overlay_height = 0; this->has_argb_overlay = 0; - this->video_mixer_chroma = chroma; VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; @@ -1753,8 +1752,14 @@ static void vdpau_reinit( vo_driver_t *this_gen ) vdp_output_surface_destroy( this->output_surface[1] ); return; } + this->video_mixer_chroma = chroma; + vdpau_set_deinterlace( this_gen ); + vdpau_set_inverse_telecine( this_gen ); + vdpau_update_noise( this ); + vdpau_update_sharpness( this ); + vdpau_update_csc( this ); + vdpau_update_skip_chroma( this ); - vdpau_set_deinterlace(this_gen); vdp_preemption_callback_register(vdp_device, &vdp_preemption_callback, (void*)this); this->vdp_runtime_nr++; -- cgit v1.2.3 From dad0229ab95b40e83ad8368bf00c33f1aa73b4ad Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 19 Mar 2009 10:24:11 +0000 Subject: Don't decode preview buffers; fix discontinuity. --- src/libvdpau/vdpau_mpeg12.c | 46 ++++++++++++++++++++++++++++++++------------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 175091130..2e3288957 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -201,17 +201,20 @@ static void init_picture( picture_t *pic ) -static void reset_sequence( sequence_t *sequence ) +static void reset_sequence( sequence_t *sequence, int free_refs ) { - lprintf( "reset_sequence\n" ); - sequence->have_header = 0; sequence->bufpos = 0; sequence->bufseek = 0; sequence->start = -1; - sequence->seq_pts = sequence->cur_pts = 0; - sequence->profile = VDP_DECODER_PROFILE_MPEG1; - sequence->chroma = 0; - sequence->video_step = 3600; + sequence->seq_pts = sequence->cur_pts = 0; + if ( sequence->forward_ref ) + sequence->forward_ref->pts = 0; + if ( sequence->backward_ref ) + sequence->backward_ref->pts = 0; + + if ( !free_refs ) + return; + if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); sequence->forward_ref = NULL; @@ -222,6 +225,18 @@ static void reset_sequence( sequence_t *sequence ) +static void free_sequence( sequence_t *sequence ) +{ + lprintf( "init_sequence\n" ); + sequence->have_header = 0; + sequence->profile = VDP_DECODER_PROFILE_MPEG1; + sequence->chroma = 0; + sequence->video_step = 3600; + reset_sequence( sequence, 1 ); +} + + + static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) { int i, nbytes; @@ -496,8 +511,10 @@ static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) { sequence_t *sequence = (sequence_t*)&this_gen->sequence; - if ( !sequence->have_header && buf[3]!=sequence_header_code ) + if ( !sequence->have_header && buf[3]!=sequence_header_code ) { + lprintf( " ----------- no sequence header yet.\n" ); return 0; + } if ( (buf[3] >= begin_slice_start_code) && (buf[3] <= end_slice_start_code) ) { lprintf( " ----------- slice_start_code\n" ); @@ -732,6 +749,10 @@ static void vdpau_mpeg12_decode_data (video_decoder_t *this_gen, buf_element_t * vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; sequence_t *seq = (sequence_t*)&this->sequence; + /* preview buffers shall not be decoded and drawn -- use them only to supply stream information */ + if (buf->decoder_flags & BUF_FLAG_PREVIEW) + return; + if ( !buf->size ) return; @@ -794,7 +815,7 @@ static void vdpau_mpeg12_reset (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; lprintf( "vdpau_mpeg12_reset\n" ); - reset_sequence( &this->sequence ); + reset_sequence( &this->sequence, 1 ); } /* @@ -804,8 +825,7 @@ static void vdpau_mpeg12_discontinuity (video_decoder_t *this_gen) { vdpau_mpeg12_decoder_t *this = (vdpau_mpeg12_decoder_t *) this_gen; lprintf( "vdpau_mpeg12_discontinuity\n" ); - reset_sequence( &this->sequence ); - + reset_sequence( &this->sequence, 0 ); } /* @@ -822,7 +842,7 @@ static void vdpau_mpeg12_dispose (video_decoder_t *this_gen) { this->decoder = VDP_INVALID_HANDLE; } - reset_sequence( &this->sequence ); + free_sequence( &this->sequence ); this->stream->video_out->close( this->stream->video_out, this->stream ); @@ -875,7 +895,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre this->sequence.forward_ref = 0; this->sequence.backward_ref = 0; this->sequence.vdp_runtime_nr = runtime_nr; - reset_sequence( &this->sequence ); + free_sequence( &this->sequence ); this->sequence.ratio = 1; init_picture( &this->sequence.picture ); -- cgit v1.2.3 From 6b74e1ea780e2f1f20aa45f5a130ca20151a12fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Mon, 23 Mar 2009 11:18:27 +0000 Subject: Allow interception of vdpau frame type by post plugins; fix dpb issues on broken streams (missing or doubled images in dpb). --- src/libvdpau/dpb.c | 31 ++++++++++++++++++++++++++++++ src/libvdpau/vdpau_h264.c | 22 ++++++++++++++------- src/video_out/video_out_vdpau.c | 42 ++++++++++++++++++++++++++++++++++++++++- src/xine-engine/accel_vdpau.h | 4 ++++ 4 files changed, 91 insertions(+), 8 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 9aa2f4298..01f147639 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -240,6 +240,31 @@ int dpb_remove_picture(struct dpb *dpb, struct decoded_picture *rempic) return -1; } +static int dpb_remove_picture_by_img(struct dpb *dpb, vo_frame_t *remimg) +{ + struct decoded_picture *pic = dpb->pictures; + struct decoded_picture *last_pic = NULL; + + if (pic != NULL) + do { + if (pic->img == remimg) { + // FIXME: free the picture.... + + if (last_pic != NULL) + last_pic->next = pic->next; + else + dpb->pictures = pic->next; + free_decoded_picture(pic); + dpb->used--; + return 0; + } + + last_pic = pic; + } while ((pic = pic->next) != NULL); + + return -1; +} + int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum) { struct decoded_picture *pic = dpb->pictures; @@ -259,6 +284,12 @@ int dpb_remove_picture_by_picnum(struct dpb *dpb, uint32_t picnum) int dpb_add_picture(struct dpb *dpb, struct decoded_picture *pic, uint32_t num_ref_frames) { + pic->img->lock(pic->img); + if (0 == dpb_remove_picture_by_img(dpb, pic->img)) + fprintf(stderr, "broken stream: current img was already in dpb -- freed it\n"); + else + pic->img->free(pic->img); + int i = 0; struct decoded_picture *last_pic = dpb->pictures; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index a8d4093d9..90dc15d67 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -353,6 +353,13 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) img->duration = this->video_step; img->pts = this->curr_pts; + if (this->dangling_img) { + fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!"); + this->dangling_img->free(this->dangling_img); + } + this->dangling_img = img; + this->last_img = img; + this->vdpau_accel = (vdpau_accel_t*)img->accel_data; /*VdpBool is_supported; @@ -370,9 +377,6 @@ static int vdpau_decoder_init(video_decoder_t *this_gen) return 0; } } - this->last_img = img; - this->dangling_img = img; - return 1; } @@ -438,6 +442,10 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v img->duration = this->video_step; img->pts = this->curr_pts; + if (this->dangling_img) { + fprintf(stderr, "broken stream: current img wasn't processed -- freeing it\n!"); + this->dangling_img->free(this->dangling_img); + } this->dangling_img = img; } @@ -446,8 +454,6 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v this->decoder = VDP_INVALID_HANDLE; vdpau_h264_reset(this_gen); this->vdp_runtime_nr = this->vdpau_accel->vdp_runtime_nr; - img->free(img); - img = this->last_img = NULL; return 0; } @@ -471,7 +477,8 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(status != VDP_STATUS_OK) { xprintf(this->xine, XINE_VERBOSITY_LOG, "vdpau_h264: Decoder failure: %s\n", this->vdpau_accel->vdp_get_error_string(status)); - img->free(img); + if (this->dangling_img) + this->dangling_img->free(this->dangling_img); img = this->last_img = this->dangling_img = NULL; } else { @@ -700,6 +707,8 @@ static void vdpau_h264_reset (video_decoder_t *this_gen) { this->dangling_img->free(this->dangling_img); this->dangling_img = NULL; } + + this->last_img = NULL; } /* @@ -725,7 +734,6 @@ static void vdpau_h264_dispose (video_decoder_t *this_gen) { this->dangling_img = NULL; } - dpb_free_all( &(this->nal_parser->dpb) ); if (this->decoder != VDP_INVALID_HANDLE) { diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 6b25b28c3..af7c33c3b 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -754,6 +754,7 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) frame->vo_frame.dispose = vdpau_frame_dispose; frame->vo_frame.driver = this_gen; + frame->vdpau_accel_data.vo_frame = &frame->vo_frame; frame->vdpau_accel_data.vdp_device = vdp_device; frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; frame->vdpau_accel_data.chroma = VDP_CHROMA_TYPE_420; @@ -901,10 +902,19 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ uint32_t width, uint32_t height, double ratio, int format, int flags) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; + vdpau_frame_t *frame = VDPAU_FRAME(frame_gen); VdpChromaType chroma = (flags & VO_CHROMA_422) ? VDP_CHROMA_TYPE_422 : VDP_CHROMA_TYPE_420; + vo_frame_t orig_frame_content; + if (format == XINE_IMGFMT_VDPAU) { + if (frame_gen != &frame->vo_frame) { + /* this is an intercepted frame, so we need to detect and propagate any + * changes on the original vo_frame to all the intercepted frames */ + xine_fast_memcpy(&orig_frame_content, &frame->vo_frame, sizeof (vo_frame_t)); + } + } + /* Check frame size and format and reallocate if necessary */ if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) || (frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr)) { @@ -974,6 +984,36 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ frame->vdpau_accel_data.color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; frame->ratio = ratio; frame->vo_frame.future_frame = NULL; + + if (format == XINE_IMGFMT_VDPAU) { + if (frame_gen != &frame->vo_frame) { + /* this is an intercepted frame, so we need to detect and propagate any + * changes on the original vo_frame to all the intercepted frames */ + unsigned char *p0 = (unsigned char *)&orig_frame_content; + unsigned char *p1 = (unsigned char *)&frame->vo_frame; + int i; + for (i = 0; i < sizeof (vo_frame_t); i++) { + if (*p0 != *p1) { + /* propagate the change */ + vo_frame_t *f = frame_gen; + while (f->next) { + /* serveral restrictions apply when intercepting VDPAU frames. So let's check + * the intercepted frames before modifing them and fail otherwise. */ + unsigned char *p = (unsigned char *)f + i; + if (*p != *p0) { + xprintf(this->xine, XINE_VERBOSITY_DEBUG, "vdpau_update_frame_format: a post plugin violates the restrictions on intercepting VDPAU frames\n"); + _x_abort(); + } + + *p = *p1; + f = f->next; + } + } + p0++; + p1++; + } + } + } } diff --git a/src/xine-engine/accel_vdpau.h b/src/xine-engine/accel_vdpau.h index 92a46e46f..7ddc5e21f 100644 --- a/src/xine-engine/accel_vdpau.h +++ b/src/xine-engine/accel_vdpau.h @@ -38,6 +38,7 @@ extern "C" { typedef struct { + vo_frame_t *vo_frame; VdpDevice vdp_device; @@ -56,6 +57,9 @@ typedef struct { } vdpau_accel_t; +#define VDPAU_DATA(frame_gen) ((frame_gen) ? (vdpau_accel_t *)(frame_gen)->accel_data : (vdpau_accel_t *)0) +#define VDPAU_FRAME(frame_gen) ((frame_gen) ? (vdpau_accel_t *)VDPAU_DATA(frame_gen)->vo_frame : (vdpau_frame_t *)0) + #ifdef __cplusplus } #endif -- cgit v1.2.3 From 0edcaa5cbcf431bc3c3029aecb2dcc810ef67a82 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 23 Mar 2009 15:18:56 +0000 Subject: Fix Sky Sports HD samples. pic_order_cnt calculation was broken in some cases. --- src/libvdpau/h264_parser.c | 11 ++++++----- src/libvdpau/vdpau_h264.c | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index d7c268fcc..14e1b735a 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -303,12 +303,13 @@ void calculate_pic_order(struct nal_parser *parser) if(!slc->field_pic_flag || !slc->bottom_field_flag) nal->top_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; + nal->bottom_field_order_cnt = 0; + if(!slc->field_pic_flag) nal->bottom_field_order_cnt = nal->top_field_order_cnt + slc->delta_pic_order_cnt_bottom; - else + else if(slc->bottom_field_flag) nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; - } else if (sps->pic_order_cnt_type == 2) { uint32_t prev_frame_num = parser->last_nal->slc->frame_num; uint32_t prev_frame_num_offset = parser->frame_num_offset; @@ -1007,10 +1008,10 @@ void decode_ref_pic_marking(struct nal_unit *nal, if (pic->nal->slc->field_pic_flag == 0) { dpb_set_unused_ref_picture_a(dpb, pic); } else { - if(!pic->top_is_reference) + //if(!pic->top_is_reference) dpb_set_unused_ref_picture_a(dpb, pic); - else - pic->top_is_reference = 0; + /*else + pic->top_is_reference = 0;*/ //printf("FIXME: We might need do delete more from the DPB...\n"); // FIXME: some more handling needed here?! See 8.2.5.4.1, p. 120 diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 90dc15d67..6ae22d3bc 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -249,7 +249,7 @@ static void fill_vdpau_pictureinfo_h264(video_decoder_t *this_gen, uint32_t slic pic->field_pic_flag = slc->field_pic_flag; pic->bottom_field_flag = slc->bottom_field_flag; pic->num_ref_frames = sps->num_ref_frames; - pic->mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag; + pic->mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag && !slc->field_pic_flag; pic->constrained_intra_pred_flag = pps->constrained_intra_pred_flag; pic->weighted_pred_flag = pps->weighted_pred_flag; pic->weighted_bipred_idc = pps->weighted_bipred_idc; -- cgit v1.2.3 From a31ee4e35b7a67deb5d2158ab07fce98c33ec35f Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 23 Mar 2009 18:03:45 +0000 Subject: Another fix for split nal boundaries. --- src/libvdpau/h264_parser.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 14e1b735a..c5dfbb373 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1287,17 +1287,24 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, * sequences and strip incomplete start seq parts from the buffer * before. */ + if(parsed_len > 0) { static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; parser->prebuf_len -= start_seq_len - parsed_len; - /* loop this until the start_seq was really parsed, else it might - * be dropped in case we are just at a frame boundary + /* if we are just at a frame boundary the sequence wouldn't + * be taken over but we would just be notified about a new + * completed frame. + * so in this case we have to send the start sequence another + * time to get it into the prebuf again. */ - int int_parsed = 0; - do { - int_parsed += parse_frame(parser, start_seq, start_seq_len, ret_buf, ret_len, ret_slice_cnt); - } while(int_parsed < 3); + uint8_t *tmp_ret_buf; + uint32_t tmp_ret_len; + uint32_t tmp_slice_cnt; + + if(parse_frame(parser, start_seq, start_seq_len, ret_buf, ret_len, ret_slice_cnt) == 0) + parse_frame(parser, start_seq, start_seq_len, &tmp_ret_buf, &tmp_ret_len, &tmp_slice_cnt); + return parsed_len; } } -- cgit v1.2.3 From 81cf18adbe584702c6ff9926a52d31cf0a2685f8 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 3 Apr 2009 20:09:54 +0100 Subject: PTS fix. --- src/libvdpau/vdpau_mpeg12.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 2e3288957..fa25c1261 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -137,8 +137,7 @@ typedef struct { vo_frame_t *forward_ref; vo_frame_t *backward_ref; - int64_t seq_pts; - int64_t cur_pts; + int64_t cur_pts; vdpau_accel_t *accel_vdpau; @@ -206,7 +205,7 @@ static void reset_sequence( sequence_t *sequence, int free_refs ) sequence->bufpos = 0; sequence->bufseek = 0; sequence->start = -1; - sequence->seq_pts = sequence->cur_pts = 0; + sequence->cur_pts = 0; if ( sequence->forward_ref ) sequence->forward_ref->pts = 0; if ( sequence->backward_ref ) @@ -263,9 +262,7 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int sequence_t *sequence = (sequence_t*)&this_gen->sequence; int i, j, off=0; - if ( sequence->cur_pts ) { - sequence->seq_pts = sequence->cur_pts; - } + sequence->coded_width = get_bits( buf,0,12 ); lprintf( "coded_width: %d\n", get_bits( buf,0,12 ) ); sequence->coded_height = get_bits( buf,12,12 ); @@ -346,10 +343,6 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) if ( sequence->picture.state!=WANT_HEADER ) return; - if ( sequence->cur_pts ) { - sequence->seq_pts = sequence->cur_pts; - } - if ( sequence->profile==VDP_DECODER_PROFILE_MPEG1 ) sequence->picture.vdp_infos.picture_structure = PICTURE_FRAME; @@ -611,7 +604,7 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else { lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, slices_bytes=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", - pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->seq_pts ); + pic->vdp_infos.picture_coding_type, pic->vdp_infos.slice_count, vbit.bitstream_bytes, accel->surface, pic->vdp_infos.forward_reference, pic->vdp_infos.backward_reference, seq->cur_pts ); VdpPictureInfoMPEG1Or2 *info = &pic->vdp_infos; lprintf("%d %d %d %d %d %d %d %d %d %d %d %d %d\n", info->intra_dc_precision, info->frame_pred_frame_dct, info->concealment_motion_vectors, info->intra_vlc_format, info->alternate_scan, info->q_scale_type, info->top_field_first, info->full_pel_forward_vector, info->full_pel_backward_vector, info->f_code[0][0], info->f_code[0][1], info->f_code[1][0], info->f_code[1][1] ); } @@ -637,7 +630,7 @@ static void decode_render( vdpau_mpeg12_decoder_t *vd, vdpau_accel_t *accel ) lprintf( "decoder failed : %d!! %s\n", st, accel->vdp_get_error_string( st ) ); else lprintf( "DECODER SUCCESS : frame_type:%d, slices=%d, current=%d, forwref:%d, backref:%d, pts:%lld\n", - pic->vdp_infos2.picture_coding_type, pic->vdp_infos2.slice_count, accel->surface, pic->vdp_infos2.forward_reference, pic->vdp_infos2.backward_reference, seq->seq_pts ); + pic->vdp_infos2.picture_coding_type, pic->vdp_infos2.slice_count, accel->surface, pic->vdp_infos2.forward_reference, pic->vdp_infos2.backward_reference, seq->cur_pts ); } } @@ -703,7 +696,7 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) decode_render( vd, accel ); img->drawn = 0; - img->pts = seq->seq_pts; + img->pts = seq->cur_pts; img->bad_frame = 0; img->duration = seq->video_step; img->top_field_first = pic->vdp_infos.top_field_first; @@ -734,8 +727,6 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) img->draw( img, vd->stream ); img->free( img ); } - - seq->seq_pts +=seq->video_step; } -- cgit v1.2.3 From 9ae63c46d0228999e6fc1f2343cfdca46f3a6815 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 3 Apr 2009 21:25:26 +0100 Subject: PTS fix. --- src/libvdpau/vdpau_mpeg12.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index fa25c1261..8443403c7 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -137,7 +137,7 @@ typedef struct { vo_frame_t *forward_ref; vo_frame_t *backward_ref; - int64_t cur_pts; + int64_t cur_pts, seq_pts; vdpau_accel_t *accel_vdpau; @@ -205,7 +205,7 @@ static void reset_sequence( sequence_t *sequence, int free_refs ) sequence->bufpos = 0; sequence->bufseek = 0; sequence->start = -1; - sequence->cur_pts = 0; + sequence->cur_pts = sequence->seq_pts = 0; if ( sequence->forward_ref ) sequence->forward_ref->pts = 0; if ( sequence->backward_ref ) @@ -263,6 +263,10 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int int i, j, off=0; + if ( sequence->cur_pts ) { + sequence->seq_pts = sequence->cur_pts; + } + sequence->coded_width = get_bits( buf,0,12 ); lprintf( "coded_width: %d\n", get_bits( buf,0,12 ) ); sequence->coded_height = get_bits( buf,12,12 ); @@ -343,6 +347,10 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) if ( sequence->picture.state!=WANT_HEADER ) return; + if ( sequence->cur_pts ) { + sequence->seq_pts = sequence->cur_pts; + } + if ( sequence->profile==VDP_DECODER_PROFILE_MPEG1 ) sequence->picture.vdp_infos.picture_structure = PICTURE_FRAME; @@ -696,7 +704,7 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) decode_render( vd, accel ); img->drawn = 0; - img->pts = seq->cur_pts; + img->pts = (pic->vdp_infos.picture_coding_type==I_FRAME) ? seq->seq_pts : 0; img->bad_frame = 0; img->duration = seq->video_step; img->top_field_first = pic->vdp_infos.top_field_first; -- cgit v1.2.3 From fcf7369327ce8a1362e49bb289b72dc832e78969 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 4 Apr 2009 20:09:40 +0100 Subject: Pts fix (match libmpeg2). --- src/libvdpau/vdpau_mpeg12.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 8443403c7..89b42bb0e 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -704,7 +704,8 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) decode_render( vd, accel ); img->drawn = 0; - img->pts = (pic->vdp_infos.picture_coding_type==I_FRAME) ? seq->seq_pts : 0; + img->pts = seq->seq_pts; + seq->seq_pts = 0; /* reset */ img->bad_frame = 0; img->duration = seq->video_step; img->top_field_first = pic->vdp_infos.top_field_first; -- cgit v1.2.3 From 51c7cb7e55307dbccb93bcb63a984920148a6202 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 5 Apr 2009 21:58:25 +0100 Subject: Fix PTS discontinuity. --- src/libvdpau/vdpau_mpeg12.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 89b42bb0e..be912b22a 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -202,9 +202,6 @@ static void init_picture( picture_t *pic ) static void reset_sequence( sequence_t *sequence, int free_refs ) { - sequence->bufpos = 0; - sequence->bufseek = 0; - sequence->start = -1; sequence->cur_pts = sequence->seq_pts = 0; if ( sequence->forward_ref ) sequence->forward_ref->pts = 0; @@ -214,6 +211,9 @@ static void reset_sequence( sequence_t *sequence, int free_refs ) if ( !free_refs ) return; + sequence->bufpos = 0; + sequence->bufseek = 0; + sequence->start = -1; if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); sequence->forward_ref = NULL; -- cgit v1.2.3 From 2a2999364b7909e9bf251e97987032c01fc2db2a Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Sun, 12 Apr 2009 20:55:41 +0100 Subject: Rework the buffering code. --- src/libvdpau/h264_parser.c | 252 +++++++++++++++------------------------------ src/libvdpau/vdpau_h264.c | 9 +- 2 files changed, 88 insertions(+), 173 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index c5dfbb373..154c99c0a 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -310,6 +310,9 @@ void calculate_pic_order(struct nal_parser *parser) else if(slc->bottom_field_flag) nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; + /*if(slc->bottom_field_flag) + nal->top_field_order_cnt = parser->last_nal->top_field_order_cnt;*/ + } else if (sps->pic_order_cnt_type == 2) { uint32_t prev_frame_num = parser->last_nal->slc->frame_num; uint32_t prev_frame_num_offset = parser->frame_num_offset; @@ -1261,172 +1264,106 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, uint8_t **ret_buf, uint32_t *ret_len, uint32_t *ret_slice_cnt) { int32_t next_nal = 0; - int parsed_len = 0; - int search_offset = 0; + int32_t offset = 0; int start_seq_len = 3; - uint8_t completed_nal = 0; if(parser->nal_size_length > 0) - start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; - - /* seek for nal start sequences split across buffer boundaries */ - if(!parser->nal_size_length) { - if(parser->prebuf_len >= 2 && inbuf_len >= 1 && - parser->prebuf[parser->prebuf_len-2] == 0x00 && - parser->prebuf[parser->prebuf_len-1] == 0x00 && - inbuf[0] == 0x01) { - parsed_len = 1; - } else if (parser->prebuf_len >= 1 && inbuf_len >= 2 && - parser->prebuf[parser->prebuf_len-1] == 0x00 && - inbuf[0] == 0x00 && - inbuf[1] == 0x01) { - parsed_len = 2; - } + start_seq_len = offset = parser->nal_size_length; + + if (parser->prebuf_len + inbuf_len > MAX_FRAME_SIZE) { + printf("buf underrun!!\n"); + *ret_len = 0; + *ret_buf = NULL; + parser->prebuf_len = 0; + return inbuf_len; + } - /* in case a start seq was splitted call ourself with just a start - * sequences and strip incomplete start seq parts from the buffer - * before. - */ + /* copy the whole inbuf to the prebuf, + * then search for a nal-start sequence in the prebuf, + * if it's in there, parse the nal and append to parser->buf + * or return a frame */ - if(parsed_len > 0) { - static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; - parser->prebuf_len -= start_seq_len - parsed_len; + xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len); + parser->prebuf_len += inbuf_len; - /* if we are just at a frame boundary the sequence wouldn't - * be taken over but we would just be notified about a new - * completed frame. - * so in this case we have to send the start sequence another - * time to get it into the prebuf again. - */ - uint8_t *tmp_ret_buf; - uint32_t tmp_ret_len; - uint32_t tmp_slice_cnt; + while((next_nal = seek_for_nal(parser->prebuf+start_seq_len-offset, parser->prebuf_len-2*start_seq_len+(2*offset), parser)) > 0) { - if(parse_frame(parser, start_seq, start_seq_len, ret_buf, ret_len, ret_slice_cnt) == 0) - parse_frame(parser, start_seq, start_seq_len, &tmp_ret_buf, &tmp_ret_len, &tmp_slice_cnt); + if(!parser->nal_size_length && + (parser->prebuf[0] != 0x00 || parser->prebuf[1] != 0x00 || parser->prebuf[2] != 0x01)) { + printf("Broken NAL, skip it.\n"); + parser->last_nal_res = 2; + } else + parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, next_nal, parser); - return parsed_len; - } - } + if (parser->last_nal_res == 1 && parser->buf_len > 0) { - while ((next_nal = seek_for_nal(inbuf+search_offset, inbuf_len-parsed_len-search_offset, parser)) >= 0) { - next_nal += search_offset; - if(parser->nal_size_length > 0) - start_seq_len = parser->nal_size_length-parser->have_nal_size_length_buf; + //printf("Frame complete: %d bytes\n", parser->buf_len); + *ret_len = parser->buf_len; + *ret_buf = malloc(*ret_len); + xine_fast_memcpy(*ret_buf, parser->buf, parser->buf_len); + *ret_slice_cnt = parser->slice_cnt; - if(parser->incomplete_nal || completed_nal || next_nal == 0 || - parser->nal_size_length) { + parser->slice_cnt = 1; + parser->buf_len = 0; - if (parser->prebuf_len + next_nal > MAX_FRAME_SIZE) { - printf("buf underrun!!\n"); - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; - } + /* this is a SLICE, keep it in the buffer */ - xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, next_nal); - parser->prebuf_len += next_nal; - parser->incomplete_nal = 0; + if(parser->nal_size_length > 0) { + static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + xine_fast_memcpy(parser->buf, start_seq, 3); + parser->buf_len += 3; + } - parsed_len += next_nal; - inbuf += next_nal; + xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset); + parser->buf_len += next_nal+start_seq_len-2*offset; - parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, parser->prebuf_len-start_seq_len, parser); - if (parser->last_nal_res == 1 && parser->buf_len > 0) { + memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); + parser->prebuf_len -= next_nal+start_seq_len-offset; - //printf("Frame complete: %d bytes\n", parser->buf_len); - *ret_len = parser->buf_len; - *ret_buf = malloc(*ret_len); - xine_fast_memcpy(*ret_buf, parser->buf, *ret_len); - *ret_slice_cnt = parser->slice_cnt; + return inbuf_len; + } - parser->slice_cnt = 1; + /* got a new nal, which is part of the current + * coded picture. add it to buf + */ + if (parser->last_nal_res != 2) { + if (parser->buf_len + next_nal+start_seq_len-offset > MAX_FRAME_SIZE) { + printf("buf underrun 1!!\n"); parser->buf_len = 0; - - /* this is a SLICE, keep it in the buffer */ - //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); - if(parser->nal_size_length > 0) { - static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; - xine_fast_memcpy(parser->buf, start_seq, 3); - parser->buf_len += 3; - } - - int offset = 0; - if(parser->nal_size_length > 0) - offset = start_seq_len; - xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, parser->prebuf_len-offset); - parser->buf_len += (parser->prebuf_len-offset); - parser->prebuf_len = 0; - parser->incomplete_nal = 0; - - return parsed_len; + *ret_len = 0; + *ret_buf = NULL; + return inbuf_len; } - if (parser->last_nal_res != 2) { - if (parser->buf_len + parser->prebuf_len > MAX_FRAME_SIZE) { - printf("buf underrun 1!!\n"); - parser->buf_len = 0; - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; - } - - //printf("slice %d size: %d\n", parser->slice_cnt-1, parser->prebuf_len); - /* this is a SLICE, keep it in the buffer */ - if(parser->nal_size_length > 0) { - static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; - xine_fast_memcpy(parser->buf + parser->buf_len, start_seq, 3); - parser->buf_len += 3; - } - - int offset = 0; - if(parser->nal_size_length > 0) - offset = start_seq_len; - - xine_fast_memcpy(parser->buf + parser->buf_len, parser->prebuf+offset, parser->prebuf_len-offset); - parser->buf_len += (parser->prebuf_len-offset); + if(parser->nal_size_length > 0) { + static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + xine_fast_memcpy(parser->buf, start_seq, 3); + parser->buf_len += 3; } - parser->prebuf_len = 0; - completed_nal = 1; + xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset); + parser->buf_len += next_nal+start_seq_len-2*offset; + memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); + parser->prebuf_len -= next_nal+start_seq_len-offset; } else { - /* most likely we are at the beginning of the stream here - * which starts not with a nal-boundardy but with some garbage - * -> throw it away - */ - parsed_len += next_nal; - inbuf += next_nal; - } - - if(!parser->nal_size_length) - search_offset = start_seq_len; - } - - /* if inbuf does not end with the start of a new nal - * copy the left data into prebuf - */ - if(parsed_len < inbuf_len) { - if (inbuf_len-parsed_len + parser->prebuf_len > MAX_FRAME_SIZE) { - printf("buf underrun 0!!\n"); - parser->prebuf_len = 0; - *ret_len = 0; - *ret_buf = NULL; - return parsed_len; + /* got a non-relevant nal, just remove it */ + memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); + parser->prebuf_len -= next_nal+start_seq_len-offset; } - - parser->incomplete_nal = 1; - xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len-parsed_len); - parser->prebuf_len += inbuf_len-parsed_len; - inbuf += inbuf_len-parsed_len; - parsed_len += inbuf_len-parsed_len; } - *ret_len = 0; *ret_buf = NULL; - return parsed_len; + *ret_len = 0; + return inbuf_len; } + +/** + * @return 0: NAL is part of coded picture + * 2: NAL is not part of coded picture + * 1: NAL is the beginning of a new coded picture + */ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { struct buf_reader bufr; @@ -1561,49 +1498,24 @@ int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { if(parser->nal_size_length > 0) { if(buf_len <= 0 || - (buf_len < parser->nal_size_length && - (parser->next_nal_position == 0 || - parser->next_nal_position > buf_len))) { - /* if we have less than nal_size_length bytes - * left in the buffer we need to store them, so - * that the next length calculation will be correct - */ - if(!parser->next_nal_position) { - memcpy(parser->nal_size_length_buf, buf, buf_len); - parser->have_nal_size_length_buf = buf_len; - } + buf_len < parser->nal_size_length) { return -1; } uint32_t next_nal = parser->next_nal_position; if(!next_nal) { - if(parser->have_nal_size_length_buf > 0) { - memcpy(parser->nal_size_length_buf+parser->have_nal_size_length_buf, buf, parser->nal_size_length-parser->have_nal_size_length_buf); - - struct buf_reader bufr; + struct buf_reader bufr; - bufr.buf = parser->nal_size_length_buf; - bufr.cur_pos = parser->nal_size_length_buf; - bufr.cur_offset = 8; - bufr.len = parser->nal_size_length; + bufr.buf = buf; + bufr.cur_pos = buf; + bufr.cur_offset = 8; + bufr.len = buf_len; - next_nal = read_bits(&bufr, parser->nal_size_length*8)+4-parser->have_nal_size_length_buf; - - parser->have_nal_size_length_buf = 0; - } else { - struct buf_reader bufr; - - bufr.buf = buf; - bufr.cur_pos = buf; - bufr.cur_offset = 8; - bufr.len = buf_len; - - next_nal = read_bits(&bufr, parser->nal_size_length*8)+4; - } + next_nal = read_bits(&bufr, parser->nal_size_length*8)+parser->nal_size_length; } if(next_nal > buf_len) { - parser->next_nal_position = next_nal-buf_len; + parser->next_nal_position = next_nal; return -1; } else parser->next_nal_position = 0; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 6ae22d3bc..ad0a77b9b 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -533,15 +533,18 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v if(!slc->field_pic_flag || (slc->field_pic_flag && slc->bottom_field_flag && this->wait_for_bottom_field)) { + if(!decoded_pic) { decoded_pic = init_decoded_picture(this->nal_parser->current_nal, surface, img); - decoded_pic->delayed_output = 1; + //decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; dpb_add_picture(&(this->nal_parser->dpb), decoded_pic, sps->num_ref_frames); this->dangling_img = NULL; + if(decoded_pic->nal->slc->bottom_field_flag) decoded_pic->nal->top_field_order_cnt = this->last_top_field_order_cnt; - } else - decoded_pic->delayed_output = 1; + } + + decoded_pic->delayed_output = 1; if(this->wait_for_bottom_field && slc->bottom_field_flag) decoded_pic->nal->bottom_field_order_cnt = this->nal_parser->current_nal->bottom_field_order_cnt; -- cgit v1.2.3 From 3fa3377b8390478732b72fc03d95ced445e4bb1c Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Mon, 13 Apr 2009 18:28:19 +0100 Subject: Fix(?!) some broken streams. --- src/libvdpau/h264_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 154c99c0a..6507a577a 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -307,7 +307,7 @@ void calculate_pic_order(struct nal_parser *parser) if(!slc->field_pic_flag) nal->bottom_field_order_cnt = nal->top_field_order_cnt + slc->delta_pic_order_cnt_bottom; - else if(slc->bottom_field_flag) + else //if(slc->bottom_field_flag) TODO: this is not spec compliant, but works... nal->bottom_field_order_cnt = parser->pic_order_cnt_msb + slc->pic_order_cnt_lsb; /*if(slc->bottom_field_flag) -- cgit v1.2.3 From c52ce94d57dab4d67f0689d785ad373f92b60a90 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 14 Apr 2009 09:37:35 +0100 Subject: Add H.264 still frame support. --- src/libvdpau/dpb.c | 4 ++-- src/libvdpau/dpb.h | 2 +- src/libvdpau/h264_parser.c | 53 ++++++++++++++++++++++++++++++++-------------- src/libvdpau/vdpau_h264.c | 18 +++++++++++++++- 4 files changed, 57 insertions(+), 20 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index 01f147639..d82a2e16d 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -51,12 +51,12 @@ void free_decoded_picture(struct decoded_picture *pic) free(pic); } -struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb) +struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb, int do_flush) { struct decoded_picture *pic = dpb->pictures; struct decoded_picture *outpic = NULL; - if(dpb->used < MAX_DPB_SIZE) + if(!do_flush && dpb->used < MAX_DPB_SIZE) return NULL; if (pic != NULL) diff --git a/src/libvdpau/dpb.h b/src/libvdpau/dpb.h index 6578aa42f..6be2acec8 100644 --- a/src/libvdpau/dpb.h +++ b/src/libvdpau/dpb.h @@ -55,7 +55,7 @@ struct decoded_picture* init_decoded_picture(struct nal_unit *src_nal, VdpVideoSurface surface, vo_frame_t *img); void free_decoded_picture(struct decoded_picture *pic); -struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb); +struct decoded_picture* dpb_get_next_out_picture(struct dpb *dpb, int do_flush); struct decoded_picture* dpb_get_picture(struct dpb *dpb, uint32_t picnum); struct decoded_picture* dpb_get_picture_by_ltpn(struct dpb *dpb, uint32_t longterm_picnum); diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 6507a577a..f97176859 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1286,7 +1286,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, xine_fast_memcpy(parser->prebuf + parser->prebuf_len, inbuf, inbuf_len); parser->prebuf_len += inbuf_len; - while((next_nal = seek_for_nal(parser->prebuf+start_seq_len-offset, parser->prebuf_len-2*start_seq_len+(2*offset), parser)) > 0) { + while((next_nal = seek_for_nal(parser->prebuf+start_seq_len-offset, parser->prebuf_len-start_seq_len+offset, parser)) > 0) { if(!parser->nal_size_length && (parser->prebuf[0] != 0x00 || parser->prebuf[1] != 0x00 || parser->prebuf[2] != 0x01)) { @@ -1295,7 +1295,8 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, } else parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, next_nal, parser); - if (parser->last_nal_res == 1 && parser->buf_len > 0) { + printf("nal res: %d\n", parser->last_nal_res); + if ((parser->last_nal_res == 1 || parser->last_nal_res == 3) && parser->buf_len > 0) { //printf("Frame complete: %d bytes\n", parser->buf_len); *ret_len = parser->buf_len; @@ -1308,15 +1309,18 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, /* this is a SLICE, keep it in the buffer */ - if(parser->nal_size_length > 0) { - static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; - xine_fast_memcpy(parser->buf, start_seq, 3); - parser->buf_len += 3; - } + if(parser->last_nal_res != 3) { + if(parser->nal_size_length > 0) { + static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; + xine_fast_memcpy(parser->buf, start_seq, 3); + parser->buf_len += 3; + } - xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset); - parser->buf_len += next_nal+start_seq_len-2*offset; + xine_fast_memcpy(parser->buf+parser->buf_len, parser->prebuf+offset, next_nal+start_seq_len-2*offset); + parser->buf_len += next_nal+start_seq_len-2*offset; + } + printf("move %d bytes\n", parser->prebuf_len-(next_nal+start_seq_len-offset)); memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); parser->prebuf_len -= next_nal+start_seq_len-offset; @@ -1326,7 +1330,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, /* got a new nal, which is part of the current * coded picture. add it to buf */ - if (parser->last_nal_res != 2) { + if (parser->last_nal_res < 2) { if (parser->buf_len + next_nal+start_seq_len-offset > MAX_FRAME_SIZE) { printf("buf underrun 1!!\n"); parser->buf_len = 0; @@ -1348,6 +1352,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->prebuf_len -= next_nal+start_seq_len-offset; } else { /* got a non-relevant nal, just remove it */ + printf("move: %d bytes\n", parser->prebuf_len-(next_nal+start_seq_len-offset)); memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); parser->prebuf_len -= next_nal+start_seq_len-offset; } @@ -1363,6 +1368,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, * @return 0: NAL is part of coded picture * 2: NAL is not part of coded picture * 1: NAL is the beginning of a new coded picture + * 3: NAL is marked as END_OF_SEQUENCE */ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { @@ -1483,11 +1489,20 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) parser->slice_cnt++; return ret; - } - else if (res == NAL_PPS || res == NAL_SPS) { + } else if (res == NAL_PPS || res == NAL_SPS) { return 2; - } - else if (res >= NAL_SEI) { + } else if (res == NAL_END_OF_SEQUENCE) { + if (parser->current_nal == parser->nal0) { + parser->current_nal = parser->nal1; + parser->last_nal = parser->nal0; + } + else { + parser->current_nal = parser->nal0; + parser->last_nal = parser->nal1; + } + + return 3; + } else if (res >= NAL_SEI) { return 2; } @@ -1496,9 +1511,11 @@ int parse_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) { + if(buf_len <= 0) + return -1; + if(parser->nal_size_length > 0) { - if(buf_len <= 0 || - buf_len < parser->nal_size_length) { + if(buf_len < parser->nal_size_length) { return -1; } @@ -1523,6 +1540,10 @@ int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) return next_nal; } + /* NAL_END_OF_SEQUENCE */ + if(buf[0] == 0x0a) + return 1; + int i; for (i = 0; i < buf_len - 2; i++) { if (buf[i] == 0x00 && buf[i + 1] == 0x00 && buf[i + 2] == 0x01) { diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index ad0a77b9b..82a18af64 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -87,6 +87,7 @@ typedef struct vdpau_h264_decoder_s { } vdpau_h264_decoder_t; static void vdpau_h264_reset (video_decoder_t *this_gen); +static void vdpau_h264_flush (video_decoder_t *this_gen); /************************************************************************** * vdpau_h264 specific decode functions @@ -552,7 +553,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v this->last_img = img = NULL; /* now retrieve the next output frame */ - if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb))) != NULL) { + if ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 0)) != NULL) { decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); //printf("draw pts: %lld\n", decoded_pic->img->pts); decoded_pic->img->draw(decoded_pic->img, this->stream); @@ -654,6 +655,12 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, this->nal_parser->current_nal->pps != NULL) { vdpau_decoder_render(this_gen, &vdp_buffer, slice_count); } + + /* in case the last nal was detected as END_OF_SEQUENCE + * we will flush the dpb, so that all pictures get drawn + */ + if(this->nal_parser->last_nal_res == 3) + vdpau_h264_flush(this_gen); } if(buf->pts != 0 && buf->pts != this->next_pts) { @@ -670,6 +677,15 @@ static void vdpau_h264_decode_data (video_decoder_t *this_gen, * This function is called when xine needs to flush the system. */ static void vdpau_h264_flush (video_decoder_t *this_gen) { + vdpau_h264_decoder_t *this = (vdpau_h264_decoder_t*) this_gen; + struct decoded_picture *decoded_pic = NULL; + + while ((decoded_pic = dpb_get_next_out_picture(&(this->nal_parser->dpb), 1)) != NULL) { + decoded_pic->img->top_field_first = (decoded_pic->nal->top_field_order_cnt <= decoded_pic->nal->bottom_field_order_cnt); + printf("FLUSH draw pts: %lld\n", decoded_pic->img->pts); + decoded_pic->img->draw(decoded_pic->img, this->stream); + dpb_set_output_picture(&(this->nal_parser->dpb), decoded_pic); + } } /* -- cgit v1.2.3 From ab3f5fb441a3d368595154c36339b71a7e05e85c Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 14 Apr 2009 09:41:10 +0100 Subject: Remove some debug output. --- src/libvdpau/h264_parser.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index f97176859..c5af54077 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1295,7 +1295,6 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, } else parser->last_nal_res = parse_nal(parser->prebuf+start_seq_len, next_nal, parser); - printf("nal res: %d\n", parser->last_nal_res); if ((parser->last_nal_res == 1 || parser->last_nal_res == 3) && parser->buf_len > 0) { //printf("Frame complete: %d bytes\n", parser->buf_len); @@ -1320,7 +1319,6 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->buf_len += next_nal+start_seq_len-2*offset; } - printf("move %d bytes\n", parser->prebuf_len-(next_nal+start_seq_len-offset)); memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); parser->prebuf_len -= next_nal+start_seq_len-offset; @@ -1352,7 +1350,6 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, parser->prebuf_len -= next_nal+start_seq_len-offset; } else { /* got a non-relevant nal, just remove it */ - printf("move: %d bytes\n", parser->prebuf_len-(next_nal+start_seq_len-offset)); memmove(parser->prebuf, parser->prebuf+(next_nal+start_seq_len-offset), parser->prebuf_len-(next_nal+start_seq_len-offset)); parser->prebuf_len -= next_nal+start_seq_len-offset; } -- cgit v1.2.3 From 6b55016151b3fdca4ac0341bb061b2b867584b82 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Tue, 14 Apr 2009 12:00:03 +0100 Subject: Fix mov cotainers. --- src/libvdpau/h264_parser.c | 7 ++++--- src/libvdpau/vdpau_h264.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index c5af54077..951195caf 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -1339,7 +1339,7 @@ int parse_frame(struct nal_parser *parser, uint8_t *inbuf, int inbuf_len, if(parser->nal_size_length > 0) { static const uint8_t start_seq[3] = { 0x00, 0x00, 0x01 }; - xine_fast_memcpy(parser->buf, start_seq, 3); + xine_fast_memcpy(parser->buf+parser->buf_len, start_seq, 3); parser->buf_len += 3; } @@ -1537,8 +1537,9 @@ int seek_for_nal(uint8_t *buf, int buf_len, struct nal_parser *parser) return next_nal; } - /* NAL_END_OF_SEQUENCE */ - if(buf[0] == 0x0a) + /* NAL_END_OF_SEQUENCE has only 1 byte, so + * we do not need to search for the next start sequence */ + if(buf[0] == NAL_END_OF_SEQUENCE) return 1; int i; diff --git a/src/libvdpau/vdpau_h264.c b/src/libvdpau/vdpau_h264.c index 82a18af64..40ae04059 100644 --- a/src/libvdpau/vdpau_h264.c +++ b/src/libvdpau/vdpau_h264.c @@ -460,7 +460,7 @@ static int vdpau_decoder_render(video_decoder_t *this_gen, VdpBitstreamBuffer *v VdpVideoSurface surface = this->vdpau_accel->surface; - //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer.bitstream_bytes, this->curr_pts); + //printf("Decode: NUM: %d, REF: %d, BYTES: %d, PTS: %lld\n", pic.frame_num, pic.is_reference, vdp_buffer->bitstream_bytes, this->curr_pts); VdpStatus status = this->vdpau_accel->vdp_decoder_render(this->decoder, surface, (VdpPictureInfo*)&pic, 1, vdp_buffer); -- cgit v1.2.3 From 017cc60ffd3a12c35a5dc6775e509aa98193d9ae Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 21 Apr 2009 14:40:51 +0100 Subject: Fix display_queue timestamps & bad scaling of overlay with zoom. --- src/video_out/video_out_vdpau.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index af7c33c3b..9f9b5db72 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1371,11 +1371,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) uint32_t layer_count; VdpLayer layer[3]; - VdpRect layersrc, unscaledsrc; + VdpRect unscaledsrc; if ( this->has_overlay ) { layer_count = 2; - layersrc.x0 = 0; layersrc.y0 = 0; layersrc.x1 = this->overlay_output_width; layersrc.y1 = this->overlay_output_height; - layer[0].struct_version = VDP_LAYER_VERSION; layer[0].source_surface = this->overlay_output; layer[0].source_rect = &layersrc; layer[0].destination_rect = &vid_dest; + layer[0].struct_version = VDP_LAYER_VERSION; layer[0].source_surface = this->overlay_output; layer[0].source_rect = &vid_source; layer[0].destination_rect = &vid_dest; unscaledsrc.x0 = 0; unscaledsrc.y0 = 0; unscaledsrc.x1 = this->overlay_unscaled_width; unscaledsrc.y1 = this->overlay_unscaled_height; layer[1].struct_version = VDP_LAYER_VERSION; layer[1].source_surface = this->overlay_unscaled; layer[1].source_rect = &unscaledsrc; layer[1].destination_rect = &unscaledsrc; } @@ -1403,7 +1402,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) XLockDisplay( this->display ); - if ( stream_speed && frame_duration>2500 && this->deinterlace && non_progressive && frame->format==XINE_IMGFMT_VDPAU ) { + if ( frame->format==XINE_IMGFMT_VDPAU && this->deinterlace && non_progressive && stream_speed && frame_duration>2500 ) { VdpTime current_time = 0; VdpVideoSurface past[2]; VdpVideoSurface future[1]; @@ -1419,7 +1418,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); vdp_queue_get_time( vdp_queue, ¤t_time ); - vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); + vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); /* display _now_ */ if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; if ( this->init_queue>1 ) { @@ -1439,7 +1438,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } past[0] = surface; - if ( frame->vo_frame.future_frame!=NULL ) + if ( frame->vo_frame.future_frame!=NULL && ((vdpau_frame_t*)(frame->vo_frame.future_frame))->format==XINE_IMGFMT_VDPAU ) future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; else future[0] = VDP_INVALID_HANDLE; -- cgit v1.2.3 From 9d894422d8473865342c55c38aa7b28bc9aff0e9 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 12 May 2009 14:24:41 +0100 Subject: Fix sliced decoding. --- src/libvdpau/vdpau_vc1.c | 62 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 9 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index dde011293..67a453870 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -68,6 +68,12 @@ #define MODE_STARTCODE 0 #define MODE_FRAME 1 +/*#define MAKE_DAT*/ /*do NOT define this, unless you know what you do */ +#ifdef MAKE_DAT +static int nframes; +static FILE *outfile; +#endif + const double aspect_ratio[] = { @@ -91,6 +97,7 @@ const double aspect_ratio[] = { typedef struct { VdpPictureInfoVC1 vdp_infos; + int slices; int fptype; int field; int header_size; @@ -117,7 +124,7 @@ typedef struct { uint8_t *buf; /* accumulate data */ int bufseek; int start; - int code_start; + int code_start, current_code; uint32_t bufsize; uint32_t bufpos; @@ -168,6 +175,7 @@ static void init_picture( picture_t *pic ) static void reset_picture( picture_t *pic ) { + pic->slices = 1; } @@ -178,7 +186,7 @@ static void reset_sequence( sequence_t *sequence ) sequence->bufpos = 0; sequence->bufseek = 0; sequence->start = -1; - sequence->code_start = 0; + sequence->code_start = sequence->current_code = 0; sequence->seq_pts = sequence->cur_pts = 0; if ( sequence->forward_ref ) sequence->forward_ref->free( sequence->forward_ref ); @@ -600,8 +608,10 @@ static int parse_code( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) return 0; if ( sequence->code_start == frame_start_code ) { - if ( buf[3]==field_start_code || buf[3]==slice_start_code ) + if ( sequence->current_code==field_start_code || sequence->current_code==slice_start_code ) { + sequence->picture.slices++; return -1; + } return 1; /* frame complete, decode */ } @@ -626,13 +636,13 @@ static int parse_code( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) lprintf("sequence_end_code\n"); break; case frame_start_code: - lprintf("frame_start_code\n"); + lprintf("frame_start_code, len=%d\n", len); break; case field_start_code: lprintf("field_start_code\n"); break; case slice_start_code: - lprintf("slice_start_code\n"); + lprintf("slice_start_code, len=%d\n", len); break; } return 0; @@ -642,6 +652,7 @@ static int parse_code( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) static void duplicate_image( vdpau_vc1_decoder_t *vd, vo_frame_t *dst ) { + lprintf("duplicate_image\n"); sequence_t *seq = (sequence_t*)&vd->sequence; picture_t *pic = (picture_t*)&seq->picture; @@ -776,7 +787,7 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) pic->skipped = 1; } else { - seq->picture.vdp_infos.slice_count = 1; + seq->picture.vdp_infos.slice_count = seq->picture.slices; buf = seq->buf+seq->start+4; len = seq->bufseek-seq->start-4; if ( seq->profile==VDP_DECODER_PROFILE_VC1_ADVANCED ) { @@ -808,22 +819,28 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; pic->vdp_infos.forward_reference = ref_accel->surface; } - else + else { + reset_picture( &seq->picture ); return; + } } else if ( pic->vdp_infos.picture_type>=B_FRAME ) { if ( seq->forward_ref ) { ref_accel = (vdpau_accel_t*)seq->forward_ref->accel_data; pic->vdp_infos.forward_reference = ref_accel->surface; } - else + else { + reset_picture( &seq->picture ); return; + } if ( seq->backward_ref ) { ref_accel = (vdpau_accel_t*)seq->backward_ref->accel_data; pic->vdp_infos.backward_reference = ref_accel->surface; } - else + else { + reset_picture( &seq->picture ); return; + } } vo_frame_t *img = vd->stream->video_out->get_frame( vd->stream->video_out, seq->coded_width, seq->coded_height, @@ -848,6 +865,23 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) else decode_render( vd, accel, buf, len ); + +#ifdef MAKE_DAT + if ( nframes==0 ) { + fwrite( &seq->coded_width, 1, sizeof(seq->coded_width), outfile ); + fwrite( &seq->coded_height, 1, sizeof(seq->coded_height), outfile ); + fwrite( &seq->ratio, 1, sizeof(seq->ratio), outfile ); + fwrite( &seq->profile, 1, sizeof(seq->profile), outfile ); + } + + if ( nframes++ < 25 ) { + fwrite( &pic->vdp_infos, 1, sizeof(pic->vdp_infos), outfile ); + fwrite( &len, 1, sizeof(len), outfile ); + fwrite( buf, 1, len, outfile ); + printf( "picture_type = %d\n", pic->vdp_infos.picture_type); + } +#endif + if ( pic->vdp_infos.interlace && pic->vdp_infos.frame_coding_mode ) { img->progressive_frame = 0; img->top_field_first = pic->top_field_first; @@ -883,6 +917,8 @@ static void decode_picture( vdpau_vc1_decoder_t *vd ) } seq->seq_pts +=seq->video_step; + + reset_picture( &seq->picture ); } @@ -965,9 +1001,12 @@ static void vdpau_vc1_decode_data (video_decoder_t *this_gen, buf_element_t *buf while ( seq->bufseek <= seq->bufpos-4 ) { uint8_t *buffer = seq->buf+seq->bufseek; if ( buffer[0]==0 && buffer[1]==0 && buffer[2]==1 ) { + seq->current_code = buffer[3]; + lprintf("current_code = %d\n", seq->current_code); if ( seq->start<0 ) { seq->start = seq->bufseek; seq->code_start = buffer[3]; + lprintf("code_start = %d\n", seq->code_start); if ( seq->cur_pts ) seq->seq_pts = seq->cur_pts; } @@ -1099,6 +1138,11 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre (stream->video_out->open)(stream->video_out, stream); +#ifdef MAKE_DAT + outfile = fopen( "/home/cris/qvdpautest/mpg.dat","w"); + nframes = 0; +#endif + return &this->video_decoder; } -- cgit v1.2.3 From 16dff702fb2b4d807c465b0a30afeb862b49e9a1 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 10 Jun 2009 17:07:38 +0100 Subject: Add half-rate deinterlacers; make XLock/UnlockDisplay compilation conditionnal --- src/video_out/video_out_vdpau.c | 117 +++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 32 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 9f9b5db72..7f4956e97 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -52,10 +52,14 @@ #define NUM_FRAMES_BACK 1 +/*#define LOCKDISPLAY*/ /*define this if you have a buggy libX11/libX11xcb*/ + char *vdpau_deinterlace_methods[] = { "bob", + "half temporal", + "half temporal_spatial", "temporal", "temporal_spatial", NULL @@ -137,9 +141,13 @@ static Display *guarded_display; static VdpStatus guarded_vdp_video_surface_create(VdpDevice device, VdpChromaType chroma_type, uint32_t width, uint32_t height,VdpVideoSurface *surface) { VdpStatus r; +#ifdef LOCKDISPLAY XLockDisplay(guarded_display); +#endif r = orig_vdp_video_surface_create(device, chroma_type, width, height, surface); +#ifdef LOCKDISPLAY XUnlockDisplay(guarded_display); +#endif return r; } @@ -155,27 +163,39 @@ static VdpStatus guarded_vdp_video_surface_destroy(VdpVideoSurface surface) static VdpStatus guarded_vdp_decoder_create(VdpDevice device, VdpDecoderProfile profile, uint32_t width, uint32_t height, uint32_t max_references, VdpDecoder *decoder) { VdpStatus r; +#ifdef LOCKDISPLAY XLockDisplay(guarded_display); +#endif r = orig_vdp_decoder_create(device, profile, width, height, max_references, decoder); +#ifdef LOCKDISPLAY XUnlockDisplay(guarded_display); +#endif return r; } static VdpStatus guarded_vdp_decoder_destroy(VdpDecoder decoder) { VdpStatus r; +#ifdef LOCKDISPLAY XLockDisplay(guarded_display); +#endif r = orig_vdp_decoder_destroy(decoder); +#ifdef LOCKDISPLAY XUnlockDisplay(guarded_display); +#endif return r; } static VdpStatus guarded_vdp_decoder_render(VdpDecoder decoder, VdpVideoSurface target, VdpPictureInfo const *picture_info, uint32_t bitstream_buffer_count, VdpBitstreamBuffer const *bitstream_buffers) { VdpStatus r; +#ifdef LOCKDISPLAY XLockDisplay(guarded_display); +#endif r = orig_vdp_decoder_render(decoder, target, picture_info, bitstream_buffer_count, bitstream_buffers); +#ifdef LOCKDISPLAY XUnlockDisplay(guarded_display); +#endif return r; } @@ -846,6 +866,8 @@ static void vdpau_provide_standard_frame_data (vo_frame_t *this_gen, xine_curren } } + + static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original) { vdpau_frame_t *this = (vdpau_frame_t *)this_gen; @@ -1074,8 +1096,10 @@ static void vdpau_set_deinterlace( vo_driver_t *this_gen ) else { switch ( this->deinterlace_method ) { case 0: feature_enables[0] = feature_enables[1] = 0; break; /* bob */ - case 1: feature_enables[0] = 1; feature_enables[1] = 0; break; /* temporal */ - case 2: feature_enables[0] = feature_enables[1] = 1; break; /* temporal_spatial */ + case 1: + case 3: feature_enables[0] = 1; feature_enables[1] = 0; break; /* temporal */ + case 2: + case 4: feature_enables[0] = feature_enables[1] = 1; break; /* temporal_spatial */ } } } @@ -1400,7 +1424,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } int non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive; +#ifdef LOCKDISPLAY XLockDisplay( this->display ); +#endif if ( frame->format==XINE_IMGFMT_VDPAU && this->deinterlace && non_progressive && stream_speed && frame_duration>2500 ) { VdpTime current_time = 0; @@ -1421,43 +1447,50 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); /* display _now_ */ if ( this->init_queue<2 ) ++this->init_queue; this->current_output_surface ^= 1; - if ( this->init_queue>1 ) { - XUnlockDisplay(this->display); - vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); - XLockDisplay(this->display); + + if ( (this->deinterlace_method != 1) && (this->deinterlace_method != 2) ) { /* process second field */ + if ( this->init_queue>1 ) { +#ifdef LOCKDISPLAY + XUnlockDisplay(this->display); +#endif + vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); +#ifdef LOCKDISPLAY + XLockDisplay(this->display); +#endif } - if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { - /* recreate output surface to match window size */ - printf( "vo_vdpau: output_surface size update\n" ); - this->output_surface_width[this->current_output_surface] = this->sc.gui_width; - this->output_surface_height[this->current_output_surface] = this->sc.gui_height; + if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { + /* recreate output surface to match window size */ + printf( "vo_vdpau: output_surface size update\n" ); + this->output_surface_width[this->current_output_surface] = this->sc.gui_width; + this->output_surface_height[this->current_output_surface] = this->sc.gui_height; - vdp_output_surface_destroy( this->output_surface[this->current_output_surface] ); - vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); - } + vdp_output_surface_destroy( this->output_surface[this->current_output_surface] ); + vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); + } - past[0] = surface; - if ( frame->vo_frame.future_frame!=NULL && ((vdpau_frame_t*)(frame->vo_frame.future_frame))->format==XINE_IMGFMT_VDPAU ) - future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; - else - future[0] = VDP_INVALID_HANDLE; - picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; + past[0] = surface; + if ( frame->vo_frame.future_frame!=NULL && ((vdpau_frame_t*)(frame->vo_frame.future_frame))->format==XINE_IMGFMT_VDPAU ) + future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; + else + future[0] = VDP_INVALID_HANDLE; + picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; - st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, + st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); - if ( st != VDP_STATUS_OK ) - printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + if ( st != VDP_STATUS_OK ) + printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); - /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */ - if (stream_speed > 0) - current_time += frame->vo_frame.duration * 100000ull * XINE_FINE_SPEED_NORMAL / (18 * stream_speed); - else - current_time = 0; /* immediately i. e. no delay */ + /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */ + if (stream_speed > 0) + current_time += frame->vo_frame.duration * 100000ull * XINE_FINE_SPEED_NORMAL / (18 * stream_speed); + else + current_time = 0; /* immediately i. e. no delay */ - vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); - if ( this->init_queue<2 ) ++this->init_queue; - this->current_output_surface ^= 1; + vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); + if ( this->init_queue<2 ) ++this->init_queue; + this->current_output_surface ^= 1; + } } else { st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, @@ -1470,7 +1503,9 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->current_output_surface ^= 1; } +#ifdef LOCKDISPLAY XUnlockDisplay( this->display ); +#endif vdpau_backup_frame( this_gen, frame_gen ); } @@ -1601,34 +1636,46 @@ static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void * case XINE_GUI_SEND_EXPOSE_EVENT: { if ( this->init_queue ) { +#ifdef LOCKDISPLAY XLockDisplay( this->display ); +#endif int previous = this->current_output_surface ^ 1; vdp_queue_display( vdp_queue, this->output_surface[previous], 0, 0, 0 ); +#ifdef LOCKDISPLAY XUnlockDisplay( this->display ); +#endif } break; } case XINE_GUI_SEND_DRAWABLE_CHANGED: { VdpStatus st; +#ifdef LOCKDISPLAY XLockDisplay( this->display ); +#endif this->drawable = (Drawable) data; vdp_queue_destroy( vdp_queue ); vdp_queue_target_destroy( vdp_queue_target ); st = vdp_queue_target_create_x11( vdp_device, this->drawable, &vdp_queue_target ); if ( st != VDP_STATUS_OK ) { printf( "vo_vdpau: FATAL !! Can't recreate presentation queue target after drawable change !!\n" ); +#ifdef LOCKDISPLAY XUnlockDisplay( this->display ); +#endif break; } st = vdp_queue_create( vdp_device, vdp_queue_target, &vdp_queue ); if ( st != VDP_STATUS_OK ) { printf( "vo_vdpau: FATAL !! Can't recreate presentation queue after drawable change !!\n" ); +#ifdef LOCKDISPLAY XUnlockDisplay( this->display ); +#endif break; } vdp_queue_set_background_color( vdp_queue, &this->back_color ); +#ifdef LOCKDISPLAY XUnlockDisplay( this->display ); +#endif this->sc.force_redraw = 1; break; } @@ -1717,7 +1764,9 @@ static void vdpau_reinit( vo_driver_t *this_gen ) printf("vo_vdpau: VDPAU was pre-empted. Reinit.\n"); vdpau_driver_t *this = (vdpau_driver_t *)this_gen; +#ifdef LOCKDISPLAY XLockDisplay(guarded_display); +#endif vdpau_release_back_frames(this_gen); VdpStatus st = vdp_device_create_x11( this->display, this->screen, &vdp_device, &vdp_get_proc_address ); @@ -1803,7 +1852,9 @@ static void vdpau_reinit( vo_driver_t *this_gen ) this->vdp_runtime_nr++; this->reinit_needed = 0; +#ifdef LOCKDISPLAY XUnlockDisplay(guarded_display); +#endif printf("vo_vdpau: Reinit done.\n"); } @@ -2096,10 +2147,12 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } - this->deinterlace_method = config->register_enum( config, "video.output.vdpau_deinterlace_method", 1, + this->deinterlace_method = config->register_enum( config, "video.output.vdpau_deinterlace_method", 3, vdpau_deinterlace_methods, _("vdpau: HD deinterlace method"), _("bob\n" "Basic deinterlacing, doing 50i->50p.\n\n" + "half temporal, half temporal_spatial\n" + "Displays first field only, doing 50i->25p\n\n" "temporal\n" "Very good, 50i->50p\n\n" "temporal_spatial\n" -- cgit v1.2.3 From 152bbca94ab1e298c68a7b810222a5ae6f5a8808 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 11 Jun 2009 01:06:33 +0100 Subject: video_window_overlay + vdpau_dispose fixes. --- include/xine.h.in | 8 ++++ src/video_out/video_out_vdpau.c | 83 ++++++++++++++++++++++++++++++++-------- src/xine-engine/osd.c | 26 +++++++++++++ src/xine-engine/osd.h | 11 ++++++ src/xine-engine/video_out.c | 14 +++++++ src/xine-engine/video_out.h | 7 ++++ src/xine-engine/xine_interface.c | 4 ++ 7 files changed, 138 insertions(+), 15 deletions(-) diff --git a/include/xine.h.in b/include/xine.h.in index a2a658611..854474de3 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -2139,6 +2139,7 @@ void xine_event_send (xine_stream_t *stream, const xine_event_t *event) XINE_PRO #define XINE_OSD_CAP_UNSCALED 0x0002 /* unscaled overlays supp. by vo drv */ #define XINE_OSD_CAP_CUSTOM_EXTENT 0x0004 /* hardware scaled to match video output window */ #define XINE_OSD_CAP_ARGB_LAYER 0x0008 /* supports separate true color layer */ +#define XINE_OSD_CAP_VIDEO_WINDOW 0x0010 /* can scale video to an area within osd extent */ typedef struct xine_osd_s xine_osd_t; @@ -2225,6 +2226,13 @@ void xine_osd_set_argb_buffer(xine_osd_t *self, uint32_t *argb_buffer, */ void xine_osd_set_extent(xine_osd_t *self, int extent_width, int extent_height) XINE_PROTECTED; +/* + * define area within osd extent to output + * video to while osd is on screen + * see also XINE_OSD_CAP_VIDEO_WINDOW + */ +void xine_osd_set_video_window(xine_osd_t *self, int window_x, int window_y, int window_width, int window_height) XINE_PROTECTED; + /* * close osd rendering engine * loaded fonts are unloaded diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 7f4956e97..c7d3daa02 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -81,6 +81,8 @@ VdpDevice vdp_device; VdpPresentationQueue vdp_queue; VdpPresentationQueueTarget vdp_queue_target; +VdpDeviceDestroy *vdp_device_destroy; + VdpGetProcAddress *vdp_get_proc_address; VdpGetApiVersion *vdp_get_api_version; @@ -266,6 +268,11 @@ typedef struct { int argb_ovl_data_count; argb_ovl_data_t argb_ovl_data[XINE_VORAW_MAX_OVL]; + int32_t video_window_x; + int32_t video_window_y; + int32_t video_window_width; + int32_t video_window_height; + VdpVideoSurface soft_surface; uint32_t soft_surface_width; uint32_t soft_surface_height; @@ -350,6 +357,10 @@ static void vdpau_process_argb_ovls(vdpau_driver_t *this_gen, vo_frame_t *frame_ int ovl_data_count = 0; int total_extent_width = 0, total_extent_height = 0; + this->video_window_x = 0; + this->video_window_y = 0; + this->video_window_width = 0; + this->video_window_height = 0; /* lock layers while processing and determine extent */ for (i = 0; i < this->argb_ovl_count; i++) { @@ -373,6 +384,14 @@ static void vdpau_process_argb_ovls(vdpau_driver_t *this_gen, vo_frame_t *frame_ ovl_data[ovl_data_count].h = this->argb_ovl[i]->height; ovl[ovl_data_count++] = this->argb_ovl[i]; } + if (this->argb_ovl[i]->video_window_width > 0 + && this->argb_ovl[i]->video_window_height > 0) { + /* last one wins */ + this->video_window_x = this->argb_ovl[i]->video_window_x; + this->video_window_y = this->argb_ovl[i]->video_window_y; + this->video_window_width = this->argb_ovl[i]->video_window_width; + this->video_window_height = this->argb_ovl[i]->video_window_height; + } } } @@ -428,7 +447,6 @@ static void vdpau_process_argb_ovls(vdpau_driver_t *this_gen, vo_frame_t *frame_ VdpStatus st = vdp_output_surface_put_bits(this->argb_overlay, (void *)&zeros, &pitch, &dest); if (st != VDP_STATUS_OK) printf("vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st)); - this->has_argb_overlay = 1; } } free(zeros); @@ -1406,13 +1424,23 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) layer_count = 0; } - VdpRect argb_rect = {0, 0, this->argb_overlay_width, this->argb_overlay_height }; + VdpRect argb_dest; + VdpRect argb_rect = { 0, 0, this->argb_overlay_width, this->argb_overlay_height }; if( this->has_argb_overlay ) { layer_count++; - layer[layer_count-1].destination_rect = &vid_dest; + memcpy(&argb_dest, &vid_dest, sizeof (vid_dest)); + layer[layer_count-1].destination_rect = &argb_dest; layer[layer_count-1].source_rect = &argb_rect; layer[layer_count-1].source_surface = this->argb_overlay; layer[layer_count-1].struct_version = VDP_LAYER_VERSION; + /* recalculate video destination window to match osd's specified video window */ + if (this->video_window_width > 0 && this->video_window_height > 0) { + VdpRect win_rect = { this->video_window_x, this->video_window_y, this->video_window_x + this->video_window_width, this->video_window_y + this->video_window_height }; + vid_dest.x0 = ((win_rect.x0 - argb_rect.x0) * (argb_dest.x1 - argb_dest.x0) + argb_dest.x0 * (argb_rect.x1 - argb_rect.x0)) / (argb_rect.x1 - argb_rect.x0); + vid_dest.y0 = ((win_rect.y0 - argb_rect.y0) * (argb_dest.y1 - argb_dest.y0) + argb_dest.y0 * (argb_rect.y1 - argb_rect.y0)) / (argb_rect.y1 - argb_rect.y0); + vid_dest.x1 = ((win_rect.x1 - argb_rect.x0) * (argb_dest.x1 - argb_dest.x0) + argb_dest.x0 * (argb_rect.x1 - argb_rect.x0)) / (argb_rect.x1 - argb_rect.x0); + vid_dest.y1 = ((win_rect.y1 - argb_rect.y0) * (argb_dest.y1 - argb_dest.y0) + argb_dest.y0 * (argb_rect.y1 - argb_rect.y0)) / (argb_rect.y1 - argb_rect.y0); + } } /* try to get frame duration from previous img->pts when frame->duration is 0 */ @@ -1457,7 +1485,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) #ifdef LOCKDISPLAY XLockDisplay(this->display); #endif - } + } if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { /* recreate output surface to match window size */ @@ -1726,18 +1754,29 @@ static void vdpau_dispose (vo_driver_t *this_gen) if ( this->video_mixer!=VDP_INVALID_HANDLE ) vdp_video_mixer_destroy( this->video_mixer ); - if ( this->overlay_unscaled!=VDP_INVALID_HANDLE ) - vdp_output_surface_destroy( this->overlay_unscaled ); - if ( this->overlay_output!=VDP_INVALID_HANDLE ) - vdp_output_surface_destroy( this->overlay_output ); - if ( this->output_surface[0]!=VDP_INVALID_HANDLE ) - vdp_output_surface_destroy( this->output_surface[0] ); - if ( this->output_surface[1]!=VDP_INVALID_HANDLE ) - vdp_output_surface_destroy( this->output_surface[1] ); if ( this->soft_surface != VDP_INVALID_HANDLE ) vdp_video_surface_destroy( this->soft_surface ); - vdp_queue_destroy( vdp_queue ); - vdp_queue_target_destroy( vdp_queue_target ); + + if ( vdp_output_surface_destroy ) { + if (this->argb_overlay != VDP_INVALID_HANDLE) + vdp_output_surface_destroy(this->argb_overlay); + if ( this->overlay_unscaled!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->overlay_unscaled ); + if ( this->overlay_output!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->overlay_output ); + if ( this->output_surface[0]!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->output_surface[0] ); + if ( this->output_surface[1]!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->output_surface[1] ); + } + + if ( vdp_queue != VDP_INVALID_HANDLE ) + vdp_queue_destroy( vdp_queue ); + if ( vdp_queue_target != VDP_INVALID_HANDLE ) + vdp_queue_target_destroy( vdp_queue_target ); + + if ( (vdp_device != VDP_INVALID_HANDLE) && vdp_device_destroy ) + vdp_device_destroy( vdp_device ); for ( i=0; iback_frame[i] ) @@ -1927,6 +1966,17 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->vo_driver.dispose = vdpau_dispose; this->vo_driver.redraw_needed = vdpau_redraw_needed; + this->video_mixer = VDP_INVALID_HANDLE; + this->output_surface[0] = VDP_INVALID_HANDLE; + this->output_surface[1] = VDP_INVALID_HANDLE; + this->soft_surface = VDP_INVALID_HANDLE; + vdp_queue = VDP_INVALID_HANDLE; + vdp_queue_target = VDP_INVALID_HANDLE; + vdp_device = VDP_INVALID_HANDLE; + + vdp_output_surface_destroy = NULL, + vdp_device_destroy = NULL; + for ( i=0; ioverlays[i].ovl_w = this->overlays[i].ovl_h = 0; this->overlays[i].bitmap_width = this->overlays[i].bitmap_height = 0; @@ -1994,6 +2044,9 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdpau_dispose( &this->vo_driver ); return NULL; } + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DEVICE_DESTROY , (void*)&vdp_device_destroy ); + if ( vdpau_init_error( st, "Can't get DEVICE_DESTROY proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_CREATE , (void*)&orig_vdp_video_surface_create ); vdp_video_surface_create = guarded_vdp_video_surface_create; if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -2189,7 +2242,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if(frame_num < 22) config->update_num(config,"engine.buffers.video_num_frames",22); - this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY; + this->capabilities = VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_CROP | VO_CAP_UNSCALED_OVERLAY | VO_CAP_CUSTOM_EXTENT_OVERLAY | VO_CAP_ARGB_LAYER_OVERLAY | VO_CAP_VIDEO_WINDOW_OVERLAY; ok = 0; uint32_t mw, mh, ml, mr; st = vdp_decoder_query_capabilities( vdp_device, VDP_DECODER_PROFILE_H264_MAIN, &ok, &ml, &mr, &mw, &mh ); diff --git a/src/xine-engine/osd.c b/src/xine-engine/osd.c index 7f4e6aefb..73470be1f 100644 --- a/src/xine-engine/osd.c +++ b/src/xine-engine/osd.c @@ -143,6 +143,10 @@ static osd_object_t *XINE_MALLOC osd_new_object (osd_renderer_t *this, int width osd->next = this->osds; this->osds = osd; + osd->video_window_x = 0; + osd->video_window_y = 0; + osd->video_window_width = 0; + osd->video_window_height = 0; osd->extent_width = 0; osd->extent_height = 0; osd->width = width; @@ -186,6 +190,19 @@ static void osd_set_extent (osd_object_t *osd, int extent_width, int extent_heig osd->extent_height = extent_height; } +/* + * osd video window defines an area withing osd extent where the + * video shall be scaled to while an osd is displayed on screen. + * both width and height must be > 0 to take effect. + */ +static void osd_set_video_window (osd_object_t *osd, int window_x, int window_y, int window_width, int window_height) { + + osd->video_window_x = window_x; + osd->video_window_y = window_y; + osd->video_window_width = window_width; + osd->video_window_height = window_height; +} + /* @@ -254,6 +271,11 @@ static int _osd_show (osd_object_t *osd, int64_t vpts, int unscaled ) { this->event.object.overlay->width = osd->x2 - osd->x1; this->event.object.overlay->height = osd->y2 - osd->y1; + this->event.object.overlay->video_window_x = osd->video_window_x; + this->event.object.overlay->video_window_y = osd->video_window_y; + this->event.object.overlay->video_window_width = osd->video_window_width; + this->event.object.overlay->video_window_height = osd->video_window_height; + this->event.object.overlay->extent_width = osd->extent_width; this->event.object.overlay->extent_height = osd->extent_height; @@ -1627,6 +1649,9 @@ static uint32_t osd_get_capabilities (osd_object_t *osd) { if (vo_capabilities & VO_CAP_ARGB_LAYER_OVERLAY) capabilities |= XINE_OSD_CAP_ARGB_LAYER; + if (vo_capabilities & VO_CAP_VIDEO_WINDOW_OVERLAY) + capabilities |= XINE_OSD_CAP_VIDEO_WINDOW; + return capabilities; } @@ -1691,6 +1716,7 @@ osd_renderer_t *_x_osd_renderer_init( xine_stream_t *stream ) { this->show_unscaled = osd_show_unscaled; this->get_capabilities = osd_get_capabilities; this->set_extent = osd_set_extent; + this->set_video_window = osd_set_video_window; return this; } diff --git a/src/xine-engine/osd.h b/src/xine-engine/osd.h index 36e6fc0ae..be5e2218c 100644 --- a/src/xine-engine/osd.h +++ b/src/xine-engine/osd.h @@ -50,6 +50,10 @@ struct osd_object_s { int area_touched; /* work area was used for painting */ int display_x,display_y; /* where to display it in screen */ + /* video output area within osd extent */ + int video_window_x, video_window_y; + int video_window_width, video_window_height; + /* extent of reference coordinate system */ int extent_width, extent_height; @@ -243,6 +247,13 @@ struct osd_renderer_s { void (*set_argb_buffer) (osd_object_t *osd, uint32_t *argb_buffer, int dirty_x, int dirty_y, int dirty_width, int dirty_height); + /* + * osd video window defines an area withing osd extent where the + * video shall be scaled to while an osd is displayed on screen. + * both width and height must be > 0 to take effect. + */ + void (*set_video_window) (osd_object_t *osd, + int window_x, int window_y, int window_width, int window_height); /* private stuff */ diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 171190bc5..152f0878a 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -437,6 +437,20 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { int frames_to_skip; int duration; + /*if (1) { + static int64_t pts = 0; + fprintf(stderr, "img->pts: %lld, pts: %lld, img->duration: %d", img->pts, pts, img->duration); + if (img->pts) { + if (pts != img->pts) + fprintf(stderr, " ERROR: %12ld", img->pts - pts); + pts = img->pts + img->duration; + } + else { + pts += img->duration; + } + fprintf(stderr, "\n"); + }*/ + /* handle anonymous streams like NULL for easy checking */ if (stream == XINE_ANON_STREAM) stream = NULL; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index bbf0dcc35..480c1c8f2 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -299,6 +299,7 @@ struct xine_video_port_s { #define VO_CAP_VDPAU_VC1 0x00000200 /* driver can use VDPAU for mpeg1/2 */ #define VO_CAP_CUSTOM_EXTENT_OVERLAY 0x01000000 /* driver can blend custom extent overlay to output extent */ #define VO_CAP_ARGB_LAYER_OVERLAY 0x02000000 /* driver supports true color overlay */ +#define VO_CAP_VIDEO_WINDOW_OVERLAY 0x04000000 /* driver can scale video to an area within overlay */ /* @@ -429,6 +430,12 @@ struct vo_overlay_s { int width; /* width of subpicture area */ int height; /* height of subpicture area */ + /* area within osd extent to scale video to */ + int video_window_x; + int video_window_y; + int video_window_width; + int video_window_height; + /* extent of reference coordinate system */ int extent_width; int extent_height; diff --git a/src/xine-engine/xine_interface.c b/src/xine-engine/xine_interface.c index 20101b436..8301414cd 100644 --- a/src/xine-engine/xine_interface.c +++ b/src/xine-engine/xine_interface.c @@ -868,6 +868,10 @@ void xine_osd_set_extent(xine_osd_t *this, int extent_width, int extent_height) this->osd.renderer->set_extent(&this->osd, extent_width, extent_height); } +void xine_osd_set_video_window(xine_osd_t *this, int window_x, int window_y, int window_width, int window_height) { + this->osd.renderer->set_video_window(&this->osd, window_x, window_y, window_width, window_height); +} + const char *const *xine_post_list_inputs(xine_post_t *this_gen) { post_plugin_t *this = (post_plugin_t *)this_gen; -- cgit v1.2.3 From 2daed669573c55bcd621153bdfffa251758e0f83 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 11 Jun 2009 13:07:37 +0100 Subject: Cleanup. --- src/xine-engine/video_out.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index 152f0878a..171190bc5 100644 --- a/src/xine-engine/video_out.c +++ b/src/xine-engine/video_out.c @@ -437,20 +437,6 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { int frames_to_skip; int duration; - /*if (1) { - static int64_t pts = 0; - fprintf(stderr, "img->pts: %lld, pts: %lld, img->duration: %d", img->pts, pts, img->duration); - if (img->pts) { - if (pts != img->pts) - fprintf(stderr, " ERROR: %12ld", img->pts - pts); - pts = img->pts + img->duration; - } - else { - pts += img->duration; - } - fprintf(stderr, "\n"); - }*/ - /* handle anonymous streams like NULL for easy checking */ if (stream == XINE_ANON_STREAM) stream = NULL; -- cgit v1.2.3 From e2d0dde5f0435f2942961e6ae5f1778516555798 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Thu, 11 Jun 2009 17:27:15 +0100 Subject: Fix chroma_format_idc default to be 1, like the spec expects it to be. Minor cleanups. --- src/libvdpau/dpb.c | 1 + src/libvdpau/h264_parser.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/dpb.c b/src/libvdpau/dpb.c index d82a2e16d..31677e51c 100644 --- a/src/libvdpau/dpb.c +++ b/src/libvdpau/dpb.c @@ -169,6 +169,7 @@ int dpb_set_unused_ref_picture_bylidx(struct dpb *dpb, uint32_t longterm_idx) if (pic != NULL) do { if (pic->nal->long_term_frame_idx == longterm_idx) { + pic->nal->used_for_long_term_ref = 0; pic->used_for_reference = 0; if(!pic->delayed_output) dpb_remove_picture(dpb, pic); diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 951195caf..c489d3544 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -210,6 +210,7 @@ int parse_nal_header(struct buf_reader *buf, struct nal_parser *parser) struct nal_unit *nal = parser->current_nal; + memset(nal, 0x00, sizeof(struct nal_unit) - sizeof(struct seq_parameter_set_rbsp*) - sizeof(struct pic_parameter_set_rbsp*) - sizeof(struct slice_header*)); nal->nal_ref_idc = (buf->buf[0] >> 5) & 0x03; nal->nal_unit_type = buf->buf[0] & 0x1f; @@ -485,7 +486,8 @@ uint8_t parse_sps(struct buf_reader *buf, struct nal_parser *parser) } } } - } + } else + sps->chroma_format_idc = 1; sps->log2_max_frame_num_minus4 = read_exp_golomb(buf); @@ -783,6 +785,7 @@ uint8_t parse_slice_header(struct buf_reader *buf, struct nal_parser *parser) struct seq_parameter_set_rbsp *sps = nal->sps; struct pic_parameter_set_rbsp *pps = nal->pps; struct slice_header *slc = nal->slc; + memset(slc, 0x00, sizeof(struct slice_header)); if (!sps || !pps) return -1; @@ -963,7 +966,7 @@ void parse_pred_weight_table(struct buf_reader *buf, struct nal_unit *nal) } } - if (slc->slice_type == SLICE_B) { + if ((slc->slice_type % 5) == SLICE_B) { /* FIXME: Being spec-compliant here and loop to num_ref_idx_l0_active_minus1 * will break Divx7 files. Keep this in mind if any other streams are broken */ -- cgit v1.2.3 From 458e2ab2b14b0bfed69abf382abe6981065380df Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 12 Jun 2009 00:05:16 +0100 Subject: Query features and enable accordingly; cleanup. --- src/video_out/video_out_vdpau.c | 299 ++++++++++++++++++++++++++++++++-------- 1 file changed, 238 insertions(+), 61 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index c7d3daa02..c4d0b1535 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -55,8 +55,15 @@ /*#define LOCKDISPLAY*/ /*define this if you have a buggy libX11/libX11xcb*/ +#define DEINT_BOB 1 +#define DEINT_HALF_TEMPORAL 2 +#define DEINT_HALF_TEMPORAL_SPATIAL 3 +#define DEINT_TEMPORAL 4 +#define DEINT_TEMPORAL_SPATIAL 5 -char *vdpau_deinterlace_methods[] = { +#define NUMBER_OF_DEINTERLACERS 5 + +char *vdpau_deinterlacer_name[] = { "bob", "half temporal", "half temporal_spatial", @@ -65,6 +72,15 @@ char *vdpau_deinterlace_methods[] = { NULL }; +char* vdpau_deinterlacer_description [] = { + "bob\nBasic deinterlacing, doing 50i->50p.\n\n", + "half temporal\nDisplays first field only, doing 50i->25p\n\n", + "half temporal_spatial\nDisplays first field only, doing 50i->25p\n\n", + "temporal\nVery good, 50i->50p\n\n", + "temporal_spatial\nThe best, but very GPU intensive.\n\n", + NULL +}; + VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, @@ -106,6 +122,11 @@ VdpVideoMixerRender *vdp_video_mixer_render; VdpVideoMixerSetAttributeValues *vdp_video_mixer_set_attribute_values; VdpVideoMixerSetFeatureEnables *vdp_video_mixer_set_feature_enables; VdpVideoMixerGetFeatureEnables *vdp_video_mixer_get_feature_enables; +VdpVideoMixerQueryFeatureSupport *vdp_video_mixer_query_feature_support; +VdpVideoMixerQueryParameterSupport *vdp_video_mixer_query_parameter_support; +VdpVideoMixerQueryAttributeSupport *vdp_video_mixer_query_attribute_support; +VdpVideoMixerQueryParameterValueRange *vdp_video_mixer_query_parameter_value_range; +VdpVideoMixerQueryAttributeValueRange *vdp_video_mixer_query_attribute_value_range; VdpGenerateCSCMatrix *vdp_generate_csc_matrix; @@ -128,6 +149,7 @@ VdpDecoderDestroy *vdp_decoder_destroy; VdpDecoderRender *vdp_decoder_render; VdpPreemptionCallbackRegister *vdp_preemption_callback_register; + static void vdp_preemption_callback( VdpDevice device, void *context ); static void vdpau_reinit( vo_driver_t *this_gen ); @@ -289,6 +311,15 @@ typedef struct { uint32_t video_mixer_width; uint32_t video_mixer_height; VdpColorStandard color_standard; + VdpBool temporal_spatial_is_supported; + VdpBool temporal_is_supported; + VdpBool noise_reduction_is_supported; + VdpBool sharpness_is_supported; + VdpBool inverse_telecine_is_supported; + VdpBool skip_chroma_is_supported; + + char* deinterlacers_name[NUMBER_OF_DEINTERLACERS+1]; + int deinterlacers_method[NUMBER_OF_DEINTERLACERS]; VdpColor back_color; @@ -716,7 +747,7 @@ static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) double rx = (double)this->overlay_output_width/(double)this->overlays[i].expected_overlay_width; double ry = (double)this->overlay_output_height/(double)this->overlays[i].expected_overlay_height; dest.x0 *= rx; dest.y0 *= ry; dest.x1 *=rx; dest.y1 *= ry; - printf( "vdpau_overlay_end: overlay_width=%d overlay_height=%d rx=%f ry=%f\n", this->overlay_output_width, this->overlay_output_height, rx, ry ); + lprintf( "vdpau_overlay_end: overlay_width=%d overlay_height=%d rx=%f ry=%f\n", this->overlay_output_width, this->overlay_output_height, rx, ry ); } VdpRect src = { 0, 0, this->overlays[i].ovl_w, this->overlays[i].ovl_h }; surface = (this->overlays[i].unscaled) ? &this->overlay_unscaled : &this->overlay_output; @@ -768,7 +799,7 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen) vdpau_frame_t *frame; vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - printf( "vo_vdpau: vdpau_alloc_frame\n" ); + lprintf( "vo_vdpau: vdpau_alloc_frame\n" ); frame = (vdpau_frame_t *) calloc(1, sizeof(vdpau_frame_t)); @@ -992,7 +1023,7 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ if ( frame->vdpau_accel_data.surface != VDP_INVALID_HANDLE ) { if ( (frame->width != width) || (frame->height != height) || (format != XINE_IMGFMT_VDPAU) || frame->vdpau_accel_data.chroma != chroma ) { - printf("vo_vdpau: update_frame - destroy surface\n"); + lprintf("vo_vdpau: update_frame - destroy surface\n"); vdp_video_surface_destroy( frame->vdpau_accel_data.surface ); frame->vdpau_accel_data.surface = VDP_INVALID_HANDLE; --this->allocated_surfaces; @@ -1112,12 +1143,15 @@ static void vdpau_set_deinterlace( vo_driver_t *this_gen ) if ( this->video_mixer_width<800 ) feature_enables[0] = feature_enables[1] = 1; else { - switch ( this->deinterlace_method ) { - case 0: feature_enables[0] = feature_enables[1] = 0; break; /* bob */ - case 1: - case 3: feature_enables[0] = 1; feature_enables[1] = 0; break; /* temporal */ - case 2: - case 4: feature_enables[0] = feature_enables[1] = 1; break; /* temporal_spatial */ + switch ( this->deinterlacers_method[this->deinterlace_method] ) { + case DEINT_BOB: + feature_enables[0] = feature_enables[1] = 0; break; /* bob */ + case DEINT_HALF_TEMPORAL: + case DEINT_TEMPORAL: + feature_enables[0] = 1; feature_enables[1] = 0; break; /* temporal */ + case DEINT_HALF_TEMPORAL_SPATIAL: + case DEINT_TEMPORAL_SPATIAL: + feature_enables[0] = feature_enables[1] = 1; break; /* temporal_spatial */ } } } @@ -1135,6 +1169,9 @@ static void vdpau_set_inverse_telecine( vo_driver_t *this_gen ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + if ( !this->inverse_telecine_is_supported ) + return; + VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE }; VdpBool feature_enables[1]; if ( this->deinterlace && this->enable_inverse_telecine ) @@ -1183,6 +1220,9 @@ static void vdpau_honor_progressive_flag( void *this_gen, xine_cfg_entry_t *entr static void vdpau_update_noise( vdpau_driver_t *this_gen ) { + if ( !this_gen->noise_reduction_is_supported ) + return; + float value = this_gen->noise/100.0; if ( value==0 ) { VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION }; @@ -1209,6 +1249,9 @@ static void vdpau_update_noise( vdpau_driver_t *this_gen ) static void vdpau_update_sharpness( vdpau_driver_t *this_gen ) { + if ( !this_gen->sharpness_is_supported ) + return; + float value = this_gen->sharpness/100.0; if ( value==0 ) { VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS }; @@ -1261,6 +1304,9 @@ static void vdpau_update_csc( vdpau_driver_t *this_gen ) static void vdpau_update_skip_chroma( vdpau_driver_t *this_gen ) { + if ( !this_gen->skip_chroma_is_supported ) + return; + VdpVideoMixerAttribute attributes [] = { VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE }; void* attribute_values[] = { &(this_gen->skip_chroma) }; VdpStatus st = vdp_video_mixer_set_attribute_values( this_gen->video_mixer, 1, attributes, attribute_values ); @@ -1281,6 +1327,34 @@ static void vdpau_set_skip_chroma( void *this_gen, xine_cfg_entry_t *entry ) +static void vdpau_shift_queue( vo_driver_t *this_gen ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + if ( this->init_queue<2 ) + ++this->init_queue; + this->current_output_surface ^= 1; +} + + + +static void vdpau_check_output_size( vo_driver_t *this_gen ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { + /* recreate output surface to match window size */ + lprintf( "vo_vdpau: output_surface size update\n" ); + this->output_surface_width[this->current_output_surface] = this->sc.gui_width; + this->output_surface_height[this->current_output_surface] = this->sc.gui_height; + + vdp_output_surface_destroy( this->output_surface[this->current_output_surface] ); + vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); + } +} + + + static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -1314,7 +1388,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) ) { chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; if ( (frame->width > this->soft_surface_width) || (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { - printf( "vo_vdpau: soft_surface size update\n" ); + lprintf( "vo_vdpau: soft_surface size update\n" ); /* recreate surface to match frame changes */ this->soft_surface_width = frame->width; this->soft_surface_height = frame->height; @@ -1355,15 +1429,35 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( (mix_w != this->video_mixer_width) || (mix_h != this->video_mixer_height) || (chroma != this->video_mixer_chroma)) { vdpau_release_back_frames( this_gen ); /* empty past frames array */ - printf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); + lprintf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, - VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerFeature features[5]; + int features_count = 0; + if ( this->noise_reduction_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; + ++features_count; + } + if ( this->sharpness_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; + ++features_count; + } + if ( this->temporal_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; + ++features_count; + } + if ( this->temporal_spatial_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; + ++features_count; + } + if ( this->inverse_telecine_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; + ++features_count; + } VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; - vdp_video_mixer_create( vdp_device, 4, features, 4, params, param_values, &this->video_mixer ); + vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); this->video_mixer_chroma = chroma; this->video_mixer_width = mix_w; this->video_mixer_height = mix_h; @@ -1377,20 +1471,12 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) } if (color_standard != this->color_standard) { - printf("vo_vdpau: update color_standard: %d\n", color_standard); + lprintf("vo_vdpau: update color_standard: %d\n", color_standard); this->color_standard = color_standard; vdpau_update_csc( this ); } - if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { - /* recreate output surface to match window size */ - printf( "vo_vdpau: output_surface size update\n" ); - this->output_surface_width[this->current_output_surface] = this->sc.gui_width; - this->output_surface_height[this->current_output_surface] = this->sc.gui_height; - - vdp_output_surface_destroy( this->output_surface[this->current_output_surface] ); - vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); - } + vdpau_check_output_size( this_gen ); VdpRect vid_source = { this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width+this->sc.displayed_xoffset, this->sc.displayed_height+this->sc.displayed_yoffset }; VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; @@ -1473,8 +1559,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_get_time( vdp_queue, ¤t_time ); vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); /* display _now_ */ - if ( this->init_queue<2 ) ++this->init_queue; - this->current_output_surface ^= 1; + vdpau_shift_queue( this_gen ); if ( (this->deinterlace_method != 1) && (this->deinterlace_method != 2) ) { /* process second field */ if ( this->init_queue>1 ) { @@ -1487,15 +1572,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) #endif } - if ( (this->sc.gui_width > this->output_surface_width[this->current_output_surface]) || (this->sc.gui_height > this->output_surface_height[this->current_output_surface]) ) { - /* recreate output surface to match window size */ - printf( "vo_vdpau: output_surface size update\n" ); - this->output_surface_width[this->current_output_surface] = this->sc.gui_width; - this->output_surface_height[this->current_output_surface] = this->sc.gui_height; - - vdp_output_surface_destroy( this->output_surface[this->current_output_surface] ); - vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[this->current_output_surface], this->output_surface_height[this->current_output_surface], &this->output_surface[this->current_output_surface] ); - } + vdpau_check_output_size( this_gen ); past[0] = surface; if ( frame->vo_frame.future_frame!=NULL && ((vdpau_frame_t*)(frame->vo_frame.future_frame))->format==XINE_IMGFMT_VDPAU ) @@ -1516,8 +1593,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) current_time = 0; /* immediately i. e. no delay */ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); - if ( this->init_queue<2 ) ++this->init_queue; - this->current_output_surface ^= 1; + vdpau_shift_queue( this_gen ); } } else { @@ -1527,8 +1603,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) printf( "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); - if ( this->init_queue<2 ) ++this->init_queue; - this->current_output_surface ^= 1; + vdpau_shift_queue( this_gen ); } #ifdef LOCKDISPLAY @@ -1867,12 +1942,32 @@ static void vdpau_reinit( vo_driver_t *this_gen ) this->argb_overlay_width = this->argb_overlay_height = 0; this->has_argb_overlay = 0; - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, - VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerFeature features[5]; + int features_count = 0; + if ( this->noise_reduction_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; + ++features_count; + } + if ( this->sharpness_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; + ++features_count; + } + if ( this->temporal_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; + ++features_count; + } + if ( this->temporal_spatial_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; + ++features_count; + } + if ( this->inverse_telecine_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; + ++features_count; + } VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; - st = vdp_video_mixer_create( vdp_device, 4, features, 4, params, param_values, &this->video_mixer ); + st = vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_reinit_error( st, "Can't create video mixer !!" ) ) { orig_vdp_video_surface_destroy( this->soft_surface ); vdp_output_surface_destroy( this->output_surface[0] ); @@ -1977,6 +2072,13 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdp_output_surface_destroy = NULL, vdp_device_destroy = NULL; + this->sharpness_is_supported = 0; + this->noise_reduction_is_supported = 0; + this->temporal_is_supported = 0; + this->temporal_spatial_is_supported = 0; + this->inverse_telecine_is_supported = 0; + this->skip_chroma_is_supported = 0; + for ( i=0; ioverlays[i].ovl_w = this->overlays[i].ovl_h = 0; this->overlays[i].bitmap_width = this->overlays[i].bitmap_height = 0; @@ -2089,6 +2191,21 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES , (void*)&vdp_video_mixer_get_feature_enables ); if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_GET_FEATURE_ENABLES proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT , (void*)&vdp_video_mixer_query_feature_support ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_FEATURE_SUPPORT proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT , (void*)&vdp_video_mixer_query_parameter_support ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_PARAMETER_SUPPORT proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT , (void*)&vdp_video_mixer_query_attribute_support ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE , (void*)&vdp_video_mixer_query_parameter_value_range ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE , (void*)&vdp_video_mixer_query_attribute_value_range ); + if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_GENERATE_CSC_MATRIX , (void*)&vdp_generate_csc_matrix ); if ( vdpau_init_error( st, "Can't get GENERATE_CSC_MATRIX proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -2183,16 +2300,44 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } + vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, &this->temporal_is_supported ); + vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, &this->temporal_spatial_is_supported ); + vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, &this->noise_reduction_is_supported ); + vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, &this->sharpness_is_supported ); + vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE, &this->inverse_telecine_is_supported ); + vdp_video_mixer_query_attribute_support( vdp_device, VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE, &this->skip_chroma_is_supported ); + this->color_standard = VDP_COLOR_STANDARD_ITUR_BT_601; this->video_mixer_chroma = chroma; this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, VDP_VIDEO_MIXER_FEATURE_SHARPNESS, - VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; - VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; + VdpVideoMixerFeature features[5]; + int features_count = 0; + if ( this->noise_reduction_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; + ++features_count; + } + if ( this->sharpness_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; + ++features_count; + } + if ( this->temporal_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; + ++features_count; + } + if ( this->temporal_spatial_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; + ++features_count; + } + if ( this->inverse_telecine_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; + ++features_count; + } + VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, + VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; - st = vdp_video_mixer_create( vdp_device, 4, features, 4, params, param_values, &this->video_mixer ); + st = vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); vdp_output_surface_destroy( this->output_surface[0] ); @@ -2200,23 +2345,53 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } - this->deinterlace_method = config->register_enum( config, "video.output.vdpau_deinterlace_method", 3, - vdpau_deinterlace_methods, _("vdpau: HD deinterlace method"), - _("bob\n" - "Basic deinterlacing, doing 50i->50p.\n\n" - "half temporal, half temporal_spatial\n" - "Displays first field only, doing 50i->25p\n\n" - "temporal\n" - "Very good, 50i->50p\n\n" - "temporal_spatial\n" - "The best, but very GPU intensive.\n\n"), - 10, vdpau_update_deinterlace_method, this ); - - this->enable_inverse_telecine = config->register_bool( config, "video.output.vdpau_enable_inverse_telecine", 1, + char deinterlacers_description[1024]; + memset( deinterlacers_description, 0, 1024 ); + int deint_count = 0; + int deint_default = 0; + this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[0]; + this->deinterlacers_method[deint_count] = DEINT_BOB; + strcat( deinterlacers_description, vdpau_deinterlacer_description[0] ); + ++deint_count; + if ( this->temporal_is_supported ) { + this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[1]; + this->deinterlacers_method[deint_count] = DEINT_HALF_TEMPORAL; + strcat( deinterlacers_description, vdpau_deinterlacer_description[1] ); + ++deint_count; + } + if ( this->temporal_spatial_is_supported ) { + this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[2]; + this->deinterlacers_method[deint_count] = DEINT_HALF_TEMPORAL_SPATIAL; + strcat( deinterlacers_description, vdpau_deinterlacer_description[2] ); + ++deint_count; + } + if ( this->temporal_is_supported ) { + this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[3]; + this->deinterlacers_method[deint_count] = DEINT_TEMPORAL; + strcat( deinterlacers_description, vdpau_deinterlacer_description[3] ); + deint_default = deint_count; + ++deint_count; + } + if ( this->temporal_spatial_is_supported ) { + this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[4]; + this->deinterlacers_method[deint_count] = DEINT_TEMPORAL_SPATIAL; + strcat( deinterlacers_description, vdpau_deinterlacer_description[4] ); + ++deint_count; + } + this->deinterlacers_name[deint_count] = NULL; + + this->deinterlace_method = config->register_enum( config, "video.output.vdpau_deinterlace_method", deint_default, + this->deinterlacers_name, _("vdpau: HD deinterlace method"), + deinterlacers_description, + 10, vdpau_update_deinterlace_method, this ); + + if ( this->inverse_telecine_is_supported ) { + this->enable_inverse_telecine = config->register_bool( config, "video.output.vdpau_enable_inverse_telecine", 1, _("vdpau: Try to recreate progressive frames from pulldown material"), _("Enable this to detect bad-flagged progressive content to which\n" "a 2:2 or 3:2 pulldown was applied.\n\n"), 10, vdpau_update_enable_inverse_telecine, this ); + } this->honor_progressive = config->register_bool( config, "video.output.vdpau_honor_progressive", 0, _("vdpau: disable deinterlacing when progressive_frame flag is set"), @@ -2224,10 +2399,12 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo "This flag is not always reliable.\n\n"), 10, vdpau_honor_progressive_flag, this ); - this->skip_chroma = config->register_bool( config, "video.output.vdpau_skip_chroma_deinterlace", 0, + if ( this->skip_chroma_is_supported ) { + this->skip_chroma = config->register_bool( config, "video.output.vdpau_skip_chroma_deinterlace", 0, _("vdpau: disable advanced deinterlacers chroma filter"), _("Setting to true may help if your video card isn't able to run advanced deinterlacers.\n\n"), 10, vdpau_set_skip_chroma, this ); + } /* number of video frames from config - register it with the default value. */ int frame_num = config->register_num (config, "engine.buffers.video_num_frames", 15, /* default */ -- cgit v1.2.3 From c318c39dc1d87cba1dd2a62a3c2ecd6e663d55fa Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 12 Jun 2009 12:00:43 +0100 Subject: Fix color shifting due to missing second_chroma_qp_index_offset default. --- src/libvdpau/h264_parser.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index c489d3544..b164fea49 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -766,7 +766,8 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, } pps->second_chroma_qp_index_offset = read_exp_golomb_s(buf); - } + } else + pps->second_chroma_qp_index_offset = pps->chroma_qp_index_offset; if (!pps->pic_scaling_matrix_present_flag && sps != NULL) { memcpy(pps->scaling_lists_4x4, sps->scaling_lists_4x4, -- cgit v1.2.3 From 663a226aeebc06cbdc6b952400c2d9c7bc80cff8 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 12 Jun 2009 12:30:39 +0100 Subject: Fix default scaling lists, to use zigzag encoding. --- src/libvdpau/h264_parser.c | 74 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index b164fea49..5d671ce7f 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -382,45 +382,78 @@ void parse_scaling_list(struct buf_reader *buf, uint8_t *scaling_list, switch (index) { case 0: case 1: - case 2: - memcpy(scaling_list, default_4x4_intra, sizeof(default_4x4_intra)); + case 2: { + for(i = 0; i < sizeof(default_4x4_intra); i++) { + scaling_list[zigzag_4x4[i]] = default_4x4_intra[i]; + } + //memcpy(scaling_list, default_4x4_intra, sizeof(default_4x4_intra)); break; + } case 3: case 4: - case 5: - memcpy(scaling_list, default_4x4_inter, sizeof(default_4x4_inter)); + case 5: { + for(i = 0; i < sizeof(default_4x4_inter); i++) { + scaling_list[zigzag_4x4[i]] = default_4x4_inter[i]; + } + //memcpy(scaling_list, default_4x4_inter, sizeof(default_4x4_inter)); break; - case 6: - memcpy(scaling_list, default_8x8_intra, sizeof(default_8x8_intra)); + } + case 6: { + for(i = 0; i < sizeof(default_8x8_intra); i++) { + scaling_list[zigzag_8x8[i]] = default_8x8_intra[i]; + } + //memcpy(scaling_list, default_8x8_intra, sizeof(default_8x8_intra)); break; - case 7: - memcpy(scaling_list, default_8x8_inter, sizeof(default_8x8_inter)); + } + case 7: { + for(i = 0; i < sizeof(default_8x8_inter); i++) { + scaling_list[zigzag_8x8[i]] = default_8x8_inter[i]; + } + //memcpy(scaling_list, default_8x8_inter, sizeof(default_8x8_inter)); break; + } } } } static void sps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, int i) { + int j; switch (i) { - case 0: - memcpy(sps->scaling_lists_4x4[i], default_4x4_intra, sizeof(sps->scaling_lists_4x4[i])); + case 0: { + for(j = 0; j < sizeof(default_4x4_intra); j++) { + sps->scaling_lists_4x4[i][zigzag_4x4[j]] = default_4x4_intra[j]; + } + //memcpy(sps->scaling_lists_4x4[i], default_4x4_intra, sizeof(sps->scaling_lists_4x4[i])); break; - case 3: - memcpy(sps->scaling_lists_4x4[i], default_4x4_inter, sizeof(sps->scaling_lists_4x4[i])); + } + case 3: { + for(j = 0; j < sizeof(default_4x4_inter); j++) { + sps->scaling_lists_4x4[i][zigzag_4x4[j]] = default_4x4_inter[j]; + } + //memcpy(sps->scaling_lists_4x4[i], default_4x4_inter, sizeof(sps->scaling_lists_4x4[i])); break; + } case 1: case 2: case 4: case 5: memcpy(sps->scaling_lists_4x4[i], sps->scaling_lists_4x4[i-1], sizeof(sps->scaling_lists_4x4[i])); break; - case 6: - memcpy(sps->scaling_lists_8x8[i-6], default_8x8_intra, sizeof(sps->scaling_lists_8x8[i-6])); + case 6: { + for(j = 0; j < sizeof(default_8x8_intra); j++) { + sps->scaling_lists_8x8[i-6][zigzag_8x8[j]] = default_8x8_intra[j]; + } + //memcpy(sps->scaling_lists_8x8[i-6], default_8x8_intra, sizeof(sps->scaling_lists_8x8[i-6])); break; - case 7: - memcpy(sps->scaling_lists_8x8[i-6], default_8x8_inter, sizeof(sps->scaling_lists_8x8[i-6])); + } + case 7: { + for(j = 0; j < sizeof(default_8x8_inter); j++) { + sps->scaling_lists_8x8[i-6][zigzag_8x8[j]] = default_8x8_inter[j]; + } + //memcpy(sps->scaling_lists_8x8[i-6], default_8x8_inter, sizeof(sps->scaling_lists_8x8[i-6])); break; + } } } @@ -436,7 +469,7 @@ static void pps_scaling_list_fallback(struct seq_parameter_set_rbsp *sps, struct case 2: case 4: case 5: - memcpy(pps->scaling_lists_4x4[i], pps->scaling_lists_4x4[i-1], sizeof(sps->scaling_lists_4x4[i])); + memcpy(pps->scaling_lists_4x4[i], pps->scaling_lists_4x4[i-1], sizeof(pps->scaling_lists_4x4[i])); break; case 6: case 7: @@ -751,8 +784,11 @@ uint8_t parse_pps(struct buf_reader *buf, struct pic_parameter_set_rbsp *pps, pps->pic_scaling_matrix_present_flag = read_bits(buf, 1); if (pps->pic_scaling_matrix_present_flag) { int i; - for (i = 0; i < 6 + 2 * pps->transform_8x8_mode_flag; i++) { - pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); + for (i = 0; i < 8; i++) { + if(i < 6 || pps->transform_8x8_mode_flag) + pps->pic_scaling_list_present_flag[i] = read_bits(buf, 1); + else + pps->pic_scaling_list_present_flag[i] = 0; if (pps->pic_scaling_list_present_flag[i]) { if (i < 6) -- cgit v1.2.3 From 1fd0871ae50c1891ec619bd0ccb4746d43f0c700 Mon Sep 17 00:00:00 2001 From: Julian Scheel Date: Fri, 12 Jun 2009 13:39:42 +0100 Subject: Fix a typo in the default_8x8_intra scaling matrix. --- src/libvdpau/h264_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/h264_parser.c b/src/libvdpau/h264_parser.c index 5d671ce7f..fffa1389e 100644 --- a/src/libvdpau/h264_parser.c +++ b/src/libvdpau/h264_parser.c @@ -35,7 +35,7 @@ uint8_t default_4x4_inter[16] = { 10, 14, 14, 20, 20, 20, 24, 24, 24, 24, 27, 27, 27, 30, 30, 34 }; uint8_t default_8x8_intra[64] = { 6, 10, 10, 13, 11, 13, 16, 16, 16, 16, 18, - 18, 18, 18, 18, 32, 23, 23, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 27, 27, + 18, 18, 18, 18, 23, 23, 23, 23, 23, 23, 25, 25, 25, 25, 25, 25, 25, 27, 27, 27, 27, 27, 27, 27, 27, 29, 29, 29, 29, 29, 29, 29, 31, 31, 31, 31, 31, 31, 33, 33, 33, 33, 33, 36, 36, 36, 36, 38, 38, 38, 40, 40, 42 }; -- cgit v1.2.3 From 0029750b60b8f0bf10efd5e34b450d7b49eafdf9 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sat, 13 Jun 2009 15:49:44 +0100 Subject: Minor deinterlace fix. --- src/video_out/video_out_vdpau.c | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index c4d0b1535..fc3a01d24 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -52,7 +52,7 @@ #define NUM_FRAMES_BACK 1 -/*#define LOCKDISPLAY*/ /*define this if you have a buggy libX11/libX11xcb*/ +/*#define LOCKDISPLAY*/ /*define this if you have a buggy libX11/xcb*/ #define DEINT_BOB 1 @@ -1137,30 +1137,42 @@ static void vdpau_set_deinterlace( vo_driver_t *this_gen ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL }; + VdpVideoMixerFeature features[2]; VdpBool feature_enables[2]; + int features_count = 0; + if ( this->temporal_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; + ++features_count; + } + if ( this->temporal_spatial_is_supported ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; + ++features_count; + } + + if ( !features_count ) + return; + if ( this->deinterlace ) { - if ( this->video_mixer_width<800 ) + if ( this->video_mixer_width<800 ) { feature_enables[0] = feature_enables[1] = 1; + } else { switch ( this->deinterlacers_method[this->deinterlace_method] ) { case DEINT_BOB: - feature_enables[0] = feature_enables[1] = 0; break; /* bob */ + feature_enables[0] = feature_enables[1] = 0; break; /* bob */ case DEINT_HALF_TEMPORAL: - case DEINT_TEMPORAL: - feature_enables[0] = 1; feature_enables[1] = 0; break; /* temporal */ + case DEINT_TEMPORAL: + feature_enables[0] = 1; feature_enables[1] = 0; break; /* temporal */ case DEINT_HALF_TEMPORAL_SPATIAL: - case DEINT_TEMPORAL_SPATIAL: - feature_enables[0] = feature_enables[1] = 1; break; /* temporal_spatial */ + case DEINT_TEMPORAL_SPATIAL: + feature_enables[0] = feature_enables[1] = 1; break; /* temporal_spatial */ } } } else feature_enables[0] = feature_enables[1] = 0; - vdp_video_mixer_set_feature_enables( this->video_mixer, 2, features, feature_enables ); - vdp_video_mixer_get_feature_enables( this->video_mixer, 2, features, feature_enables ); - printf("vo_vdpau: enabled features: temporal=%d, temporal_spatial=%d\n", feature_enables[0], feature_enables[1] ); + vdp_video_mixer_set_feature_enables( this->video_mixer, features_count, features, feature_enables ); } @@ -1561,7 +1573,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); /* display _now_ */ vdpau_shift_queue( this_gen ); - if ( (this->deinterlace_method != 1) && (this->deinterlace_method != 2) ) { /* process second field */ + if ( (this->deinterlacers_method[this->deinterlace_method] != DEINT_HALF_TEMPORAL) && (this->deinterlacers_method[this->deinterlace_method] != DEINT_HALF_TEMPORAL_SPATIAL) ) { /* process second field */ if ( this->init_queue>1 ) { #ifdef LOCKDISPLAY XUnlockDisplay(this->display); -- cgit v1.2.3 From 055b6e0685a1d961b0c29f0d8606d3a955d9194f Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 18 Jun 2009 14:45:50 +0100 Subject: Fix soft_surface size update. --- src/video_out/video_out_vdpau.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index fc3a01d24..e2137dfe6 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1399,13 +1399,14 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) if ( (frame->format == XINE_IMGFMT_YV12) || (frame->format == XINE_IMGFMT_YUY2) ) { chroma = ( frame->format==XINE_IMGFMT_YV12 )? VDP_CHROMA_TYPE_420 : VDP_CHROMA_TYPE_422; - if ( (frame->width > this->soft_surface_width) || (frame->height > this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { + if ( (frame->width != this->soft_surface_width) || (frame->height != this->soft_surface_height) || (frame->format != this->soft_surface_format) ) { lprintf( "vo_vdpau: soft_surface size update\n" ); /* recreate surface to match frame changes */ this->soft_surface_width = frame->width; this->soft_surface_height = frame->height; this->soft_surface_format = frame->format; vdp_video_surface_destroy( this->soft_surface ); + this->soft_surface = VDP_INVALID_HANDLE; vdp_video_surface_create( vdp_device, chroma, this->soft_surface_width, this->soft_surface_height, &this->soft_surface ); } /* FIXME: have to swap U and V planes to get correct colors !! */ @@ -2327,11 +2328,11 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo int features_count = 0; if ( this->noise_reduction_is_supported ) { features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; - ++features_count; + ++features_count; } if ( this->sharpness_is_supported ) { features[features_count] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; - ++features_count; + ++features_count; } if ( this->temporal_is_supported ) { features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; @@ -2368,34 +2369,34 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if ( this->temporal_is_supported ) { this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[1]; this->deinterlacers_method[deint_count] = DEINT_HALF_TEMPORAL; - strcat( deinterlacers_description, vdpau_deinterlacer_description[1] ); - ++deint_count; + strcat( deinterlacers_description, vdpau_deinterlacer_description[1] ); + ++deint_count; } if ( this->temporal_spatial_is_supported ) { this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[2]; this->deinterlacers_method[deint_count] = DEINT_HALF_TEMPORAL_SPATIAL; - strcat( deinterlacers_description, vdpau_deinterlacer_description[2] ); - ++deint_count; + strcat( deinterlacers_description, vdpau_deinterlacer_description[2] ); + ++deint_count; } if ( this->temporal_is_supported ) { this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[3]; this->deinterlacers_method[deint_count] = DEINT_TEMPORAL; - strcat( deinterlacers_description, vdpau_deinterlacer_description[3] ); - deint_default = deint_count; - ++deint_count; + strcat( deinterlacers_description, vdpau_deinterlacer_description[3] ); + deint_default = deint_count; + ++deint_count; } if ( this->temporal_spatial_is_supported ) { this->deinterlacers_name[deint_count] = vdpau_deinterlacer_name[4]; this->deinterlacers_method[deint_count] = DEINT_TEMPORAL_SPATIAL; - strcat( deinterlacers_description, vdpau_deinterlacer_description[4] ); - ++deint_count; + strcat( deinterlacers_description, vdpau_deinterlacer_description[4] ); + ++deint_count; } this->deinterlacers_name[deint_count] = NULL; this->deinterlace_method = config->register_enum( config, "video.output.vdpau_deinterlace_method", deint_default, this->deinterlacers_name, _("vdpau: HD deinterlace method"), deinterlacers_description, - 10, vdpau_update_deinterlace_method, this ); + 10, vdpau_update_deinterlace_method, this ); if ( this->inverse_telecine_is_supported ) { this->enable_inverse_telecine = config->register_bool( config, "video.output.vdpau_enable_inverse_telecine", 1, -- cgit v1.2.3 From 0a0b0f61cca62f786a6d84e1b4e70d3f8999b18b Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 18 Jun 2009 21:55:04 +0100 Subject: Destroy all surfaces before device_destroy. --- src/video_out/video_out_vdpau.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index e2137dfe6..b78316567 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -19,7 +19,8 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * - * video_out_vdpau.c, a video output plugin using VDPAU (Video Decode and Presentation Api for Unix) + * video_out_vdpau.c, a video output plugin + * using VDPAU (Video Decode and Presentation Api for Unix) * * */ @@ -82,14 +83,16 @@ char* vdpau_deinterlacer_description [] = { }; -VdpOutputSurfaceRenderBlendState blend = { VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, - VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, - VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, - VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, - VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, - VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, - 0 }; +VdpOutputSurfaceRenderBlendState blend = { + VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION, + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE, + VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, + VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD, + 0 +}; @@ -521,6 +524,7 @@ static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) if ( (ovl->bitmap_width < overlay->width ) || (ovl->bitmap_height < overlay->height) || (ovl->ovl_bitmap == VDP_INVALID_HANDLE) ) { if (ovl->ovl_bitmap != VDP_INVALID_HANDLE) { vdp_bitmap_destroy( ovl->ovl_bitmap ); + ovl->ovl_bitmap = VDP_INVALID_HANDLE; } VdpStatus st = vdp_bitmap_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, overlay->width, overlay->height, 0, &ovl->ovl_bitmap ); if ( st != VDP_STATUS_OK ) { @@ -1444,15 +1448,16 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_release_back_frames( this_gen ); /* empty past frames array */ lprintf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); - VdpVideoMixerFeature features[5]; + this->video_mixer = VDP_INVALID_HANDLE; + VdpVideoMixerFeature features[5]; int features_count = 0; if ( this->noise_reduction_is_supported ) { features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; - ++features_count; + ++features_count; } if ( this->sharpness_is_supported ) { features[features_count] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; - ++features_count; + ++features_count; } if ( this->temporal_is_supported ) { features[features_count] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; @@ -1574,7 +1579,8 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); /* display _now_ */ vdpau_shift_queue( this_gen ); - if ( (this->deinterlacers_method[this->deinterlace_method] != DEINT_HALF_TEMPORAL) && (this->deinterlacers_method[this->deinterlace_method] != DEINT_HALF_TEMPORAL_SPATIAL) ) { /* process second field */ + int dm = this->deinterlacers_method[this->deinterlace_method]; + if ( (dm != DEINT_HALF_TEMPORAL) && (dm != DEINT_HALF_TEMPORAL_SPATIAL) ) { /* process second field */ if ( this->init_queue>1 ) { #ifdef LOCKDISPLAY XUnlockDisplay(this->display); @@ -1863,13 +1869,13 @@ static void vdpau_dispose (vo_driver_t *this_gen) if ( vdp_queue_target != VDP_INVALID_HANDLE ) vdp_queue_target_destroy( vdp_queue_target ); - if ( (vdp_device != VDP_INVALID_HANDLE) && vdp_device_destroy ) - vdp_device_destroy( vdp_device ); - for ( i=0; iback_frame[i] ) this->back_frame[i]->vo_frame.dispose( &this->back_frame[i]->vo_frame ); + if ( (vdp_device != VDP_INVALID_HANDLE) && vdp_device_destroy ) + vdp_device_destroy( vdp_device ); + free (this); } -- cgit v1.2.3 From d109d20c07176bee7ab2069972d8552f74fdbf5b Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 8 Jul 2009 17:00:04 +0100 Subject: Don't process second field if no future_frame. --- src/video_out/video_out_vdpau.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index b78316567..01ddc83d9 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1580,7 +1580,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_shift_queue( this_gen ); int dm = this->deinterlacers_method[this->deinterlace_method]; - if ( (dm != DEINT_HALF_TEMPORAL) && (dm != DEINT_HALF_TEMPORAL_SPATIAL) ) { /* process second field */ + if ( (dm != DEINT_HALF_TEMPORAL) && (dm != DEINT_HALF_TEMPORAL_SPATIAL) && frame->vo_frame.future_frame ) { /* process second field */ if ( this->init_queue>1 ) { #ifdef LOCKDISPLAY XUnlockDisplay(this->display); @@ -1593,12 +1593,12 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_check_output_size( this_gen ); + picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; past[0] = surface; if ( frame->vo_frame.future_frame!=NULL && ((vdpau_frame_t*)(frame->vo_frame.future_frame))->format==XINE_IMGFMT_VDPAU ) future[0] = ((vdpau_frame_t*)(frame->vo_frame.future_frame))->vdpau_accel_data.surface; else future[0] = VDP_INVALID_HANDLE; - picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD; st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, picture_structure, 2, past, surface, 1, future, &vid_source, this->output_surface[this->current_output_surface], &out_dest, &vid_dest, layer_count, layer_count?layer:NULL ); @@ -1613,7 +1613,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); vdpau_shift_queue( this_gen ); - } + } } else { st = vdp_video_mixer_render( this->video_mixer, VDP_INVALID_HANDLE, 0, VDP_VIDEO_MIXER_PICTURE_STRUCTURE_FRAME, @@ -2088,7 +2088,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo vdp_queue_target = VDP_INVALID_HANDLE; vdp_device = VDP_INVALID_HANDLE; - vdp_output_surface_destroy = NULL, + vdp_output_surface_destroy = NULL; vdp_device_destroy = NULL; this->sharpness_is_supported = 0; -- cgit v1.2.3 From a645069fe04f733217992fd59a9c1fb4e561500d Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Thu, 6 Aug 2009 13:12:53 +0100 Subject: Better deinterlacer logging. --- src/video_out/video_out_vdpau.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 01ddc83d9..883f6c6c0 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1159,22 +1159,44 @@ static void vdpau_set_deinterlace( vo_driver_t *this_gen ) if ( this->deinterlace ) { if ( this->video_mixer_width<800 ) { feature_enables[0] = feature_enables[1] = 1; + if ( this->temporal_is_supported ) { + if ( this->temporal_spatial_is_supported ) + printf("vo_vdpau: deinterlace: temporal_spatial\n" ); + else + printf("vo_vdpau: deinterlace: temporal\n" ); + } + else + printf("vo_vdpau: deinterlace: bob\n" ); } else { switch ( this->deinterlacers_method[this->deinterlace_method] ) { case DEINT_BOB: - feature_enables[0] = feature_enables[1] = 0; break; /* bob */ + feature_enables[0] = feature_enables[1] = 0; + printf("vo_vdpau: deinterlace: bob\n" ); + break; case DEINT_HALF_TEMPORAL: + feature_enables[0] = 1; feature_enables[1] = 0; + printf("vo_vdpau: deinterlace: half_temporal\n" ); + break; case DEINT_TEMPORAL: - feature_enables[0] = 1; feature_enables[1] = 0; break; /* temporal */ + feature_enables[0] = 1; feature_enables[1] = 0; + printf("vo_vdpau: deinterlace: temporal\n" ); + break; case DEINT_HALF_TEMPORAL_SPATIAL: + feature_enables[0] = feature_enables[1] = 1; + printf("vo_vdpau: deinterlace: half_temporal_spatial\n" ); + break; case DEINT_TEMPORAL_SPATIAL: - feature_enables[0] = feature_enables[1] = 1; break; /* temporal_spatial */ + feature_enables[0] = feature_enables[1] = 1; + printf("vo_vdpau: deinterlace: temporal_spatial\n" ); + break; } } } - else + else { feature_enables[0] = feature_enables[1] = 0; + printf("vo_vdpau: deinterlace: none\n" ); + } vdp_video_mixer_set_feature_enables( this->video_mixer, features_count, features, feature_enables ); } -- cgit v1.2.3 From 4a3ea58e686bfc2bbeeca059a946253798d4d17e Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 9 Aug 2009 00:57:19 +0100 Subject: Switch to bits_reader. --- src/libvdpau/bits_reader.h | 36 +++++++ src/libvdpau/vdpau_mpeg12.c | 226 +++++++++++++++++++++++++------------------- src/libvdpau/vdpau_vc1.c | 197 ++++++++++++++++++-------------------- 3 files changed, 260 insertions(+), 199 deletions(-) create mode 100644 src/libvdpau/bits_reader.h diff --git a/src/libvdpau/bits_reader.h b/src/libvdpau/bits_reader.h new file mode 100644 index 000000000..9563c9d3b --- /dev/null +++ b/src/libvdpau/bits_reader.h @@ -0,0 +1,36 @@ +#include + + + +typedef struct { + uint8_t *buffer; + int offbits; +} bits_reader_t; + +static void bits_reader_set( bits_reader_t *br, uint8_t *buf ) +{ + br->buffer = buf; + br->offbits = 0; +} + +static uint32_t read_bits( bits_reader_t *br, int nbits ) +{ + int i, nbytes; + uint32_t ret = 0; + uint8_t *buf; + + buf = br->buffer; + nbytes = (br->offbits + nbits)/8; + if ( ((br->offbits + nbits) %8 ) > 0 ) + nbytes++; + for ( i=0; ioffbits; + ret = ((ret<>i)>>((nbytes*8)-nbits-br->offbits); + + br->offbits += nbits; + br->buffer += br->offbits / 8; + br->offbits %= 8; + + return ret; +} diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index be912b22a..4ef1f5c30 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -37,6 +37,7 @@ #include "buffer.h" #include "xineutils.h" #include "accel_vdpau.h" +#include "bits_reader.h" #include @@ -67,6 +68,12 @@ #define WANT_EXT 2 #define WANT_SLICE 3 +/*#define MAKE_DAT*/ /*do NOT define this, unless you know what you do */ +#ifdef MAKE_DAT +static int nframes; +static FILE *outfile; +#endif + /* default intra quant matrix, in zig-zag order */ @@ -141,6 +148,8 @@ typedef struct { vdpau_accel_t *accel_vdpau; + bits_reader_t br; + int vdp_runtime_nr; } sequence_t; @@ -236,50 +245,32 @@ static void free_sequence( sequence_t *sequence ) -static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) -{ - int i, nbytes; - uint32_t ret = 0; - uint8_t *buf; - - buf = b+(offbits/8); - offbits %=8; - nbytes = (offbits+nbits)/8; - if ( ((offbits+nbits)%8)>0 ) - nbytes++; - for ( i=0; i>i)>>((nbytes*8)-nbits-offbits); - - return ret; -} - - - static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) { sequence_t *sequence = (sequence_t*)&this_gen->sequence; - int i, j, off=0; + int i, j; if ( sequence->cur_pts ) { sequence->seq_pts = sequence->cur_pts; } - sequence->coded_width = get_bits( buf,0,12 ); - lprintf( "coded_width: %d\n", get_bits( buf,0,12 ) ); - sequence->coded_height = get_bits( buf,12,12 ); - lprintf( "coded_height: %d\n", get_bits( buf,12,12 ) ); - switch ( get_bits( buf+3,0,4 ) ) { + bits_reader_set( &sequence->br, buf ); + sequence->coded_width = read_bits( &sequence->br, 12 ); + lprintf( "coded_width: %d\n", sequence->coded_width ); + sequence->coded_height = read_bits( &sequence->br, 12 ); + lprintf( "coded_height: %d\n", sequence->coded_height ); + int rt = read_bits( &sequence->br, 4 ); + switch ( rt ) { case 1: sequence->ratio = 1.0; break; case 2: sequence->ratio = 4.0/3.0; break; case 3: sequence->ratio = 16.0/9.0; break; case 4: sequence->ratio = 2.21; break; default: sequence->ratio = (double)sequence->coded_width/(double)sequence->coded_height; } - lprintf( "ratio: %d\n", get_bits( buf+3,0,4 ) ); - switch ( get_bits( buf+3,4,4 ) ) { + lprintf( "ratio: %d\n", rt ); + int fr = read_bits( &sequence->br, 4 ); + switch ( fr ) { case 1: sequence->video_step = 3913; break; /* 23.976.. */ case 2: sequence->video_step = 3750; break; /* 24 */ case 3: sequence->video_step = 3600; break; /* 25 */ @@ -289,18 +280,22 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int case 7: sequence->video_step = 1525; break; /* 59.94.. */ case 8: sequence->video_step = 1509; break; /* 60 */ } - lprintf( "frame_rate: %d\n", get_bits( buf+3,4,4 ) ); - lprintf( "bit_rate_value: %d\n", get_bits( buf+4,0,18 ) ); - lprintf( "marker_bit: %d\n", get_bits( buf+6,2,1 ) ); - lprintf( "vbv_buffer_size_value: %d\n", get_bits( buf+6,3,10 ) ); - lprintf( "constrained_parameters_flag: %d\n", get_bits( buf+7,5,1 ) ); - i = get_bits( buf+7,6,1 ); + lprintf( "frame_rate: %d\n", fr ); + int tmp; + tmp = read_bits( &sequence->br, 18 ); + lprintf( "bit_rate_value: %d\n", tmp ); + tmp = read_bits( &sequence->br, 1 ); + lprintf( "marker_bit: %d\n", tmp ); + tmp = read_bits( &sequence->br, 10 ); + lprintf( "vbv_buffer_size_value: %d\n", tmp ); + tmp = read_bits( &sequence->br, 1 ); + lprintf( "constrained_parameters_flag: %d\n", tmp ); + i = read_bits( &sequence->br, 1 ); lprintf( "load_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+7+j,7,8 ); + sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = read_bits( &sequence->br, 8 ); } - off = 64; } else { for ( j=0; j<64; ++j ) { @@ -308,11 +303,11 @@ static void sequence_header( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int } } - i = get_bits( buf+7+off,7,1 ); + i = read_bits( &sequence->br, 1 ); lprintf( "load_non_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->picture.vdp_infos2.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+8+off+j,0,8 ); + sequence->picture.vdp_infos2.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = read_bits( &sequence->br, 8 ); } } else { @@ -366,17 +361,20 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) infos = &sequence->picture.vdp_infos2; } - lprintf( "temporal_reference: %d\n", get_bits( buf,0,10 ) ); - infos->picture_coding_type = get_bits( buf,10,3 ); - lprintf( "picture_coding_type: %d\n", get_bits( buf,10,3 ) ); + bits_reader_set( &sequence->br, buf ); + int tmp = read_bits( &sequence->br, 10 ); + lprintf( "temporal_reference: %d\n", tmp ); + infos->picture_coding_type = read_bits( &sequence->br, 3 ); + lprintf( "picture_coding_type: %d\n", infos->picture_coding_type ); infos->forward_reference = VDP_INVALID_HANDLE; infos->backward_reference = VDP_INVALID_HANDLE; + read_bits( &sequence->br, 16 ); if ( infos->picture_coding_type > I_FRAME ) { - infos->full_pel_forward_vector = get_bits( buf+2,13,1 ); - infos->f_code[0][0] = infos->f_code[0][1] = get_bits( buf+2,14,3 ); + infos->full_pel_forward_vector = read_bits( &sequence->br, 1 ); + infos->f_code[0][0] = infos->f_code[0][1] = read_bits( &sequence->br, 3 ); if ( infos->picture_coding_type==B_FRAME ) { - infos->full_pel_backward_vector = get_bits( buf+2,17,1 ); - infos->f_code[1][0] = infos->f_code[1][1] = get_bits( buf+2,18,3 ); + infos->full_pel_backward_vector = read_bits( &sequence->br, 1 ); + infos->f_code[1][0] = infos->f_code[1][1] = read_bits( &sequence->br, 3 ); } } else { @@ -393,24 +391,35 @@ static void picture_header( sequence_t *sequence, uint8_t *buf, int len ) static void sequence_extension( sequence_t *sequence, uint8_t *buf, int len ) { - lprintf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); - switch ( get_bits( buf,5,3 ) ) { + bits_reader_set( &sequence->br, buf ); + int tmp = read_bits( &sequence->br, 4 ); + lprintf( "extension_start_code_identifier: %d\n", tmp ); + read_bits( &sequence->br, 1 ); + switch ( read_bits( &sequence->br, 3 ) ) { case 5: sequence->profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; break; default: sequence->profile = VDP_DECODER_PROFILE_MPEG2_MAIN; } - lprintf( "profile_and_level_indication: %d\n", get_bits( buf,4,8 ) ); - lprintf( "progressive_sequence: %d\n", get_bits( buf,12,1 ) ); - if ( get_bits( buf,13,2 )==2 ) + read_bits( &sequence->br, 4 ); + tmp = read_bits( &sequence->br, 1 ); + lprintf( "progressive_sequence: %d\n", tmp ); + if ( read_bits( &sequence->br, 2 ) == 2 ) sequence->chroma = VO_CHROMA_422; - lprintf( "chroma_format: %d\n", get_bits( buf,13,2 ) ); - lprintf( "horizontal_size_extension: %d\n", get_bits( buf,15,2 ) ); - lprintf( "vertical_size_extension: %d\n", get_bits( buf,17,2 ) ); - lprintf( "bit_rate_extension: %d\n", get_bits( buf,19,12 ) ); - lprintf( "marker_bit: %d\n", get_bits( buf,31,1 ) ); - lprintf( "vbv_buffer_size_extension: %d\n", get_bits( buf+4,0,8 ) ); - lprintf( "low_delay: %d\n", get_bits( buf+5,0,1 ) ); - lprintf( "frame_rate_extension_n: %d\n", get_bits( buf+5,1,2 ) ); - lprintf( "frame_rate_extension_d: %d\n", get_bits( buf+5,3,5 ) ); + tmp = read_bits( &sequence->br, 2 ); + lprintf( "horizontal_size_extension: %d\n", tmp ); + tmp = read_bits( &sequence->br, 2 ); + lprintf( "vertical_size_extension: %d\n", tmp ); + tmp = read_bits( &sequence->br, 12 ); + lprintf( "bit_rate_extension: %d\n", tmp ); + tmp = read_bits( &sequence->br, 1 ); + lprintf( "marker_bit: %d\n", tmp ); + tmp = read_bits( &sequence->br, 8 ); + lprintf( "vbv_buffer_size_extension: %d\n", tmp ); + tmp = read_bits( &sequence->br, 1 ); + lprintf( "low_delay: %d\n", tmp ); + tmp = read_bits( &sequence->br, 2 ); + lprintf( "frame_rate_extension_n: %d\n", tmp ); + tmp = read_bits( &sequence->br, 5 ); + lprintf( "frame_rate_extension_d: %d\n", tmp ); } @@ -424,35 +433,39 @@ static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int le if ( infos->picture_structure && infos->picture_structure!=PICTURE_FRAME ) infos = &sequence->picture.vdp_infos2; - infos->f_code[0][0] = get_bits( buf,4,4 ); - infos->f_code[0][1] = get_bits( buf,8,4 ); - infos->f_code[1][0] = get_bits( buf,12,4 ); - infos->f_code[1][1] = get_bits( buf,16,4 ); - lprintf( "extension_start_code_identifier: %d\n", get_bits( buf,0,4 ) ); - lprintf( "f_code_0_0: %d\n", get_bits( buf,4,4 ) ); - lprintf( "f_code_0_1: %d\n", get_bits( buf,8,4 ) ); - lprintf( "f_code_1_0: %d\n", get_bits( buf,12,4 ) ); - lprintf( "f_code_1_1: %d\n", get_bits( buf,16,4 ) ); - infos->intra_dc_precision = get_bits( buf,20,2 ); - lprintf( "intra_dc_precision: %d\n", get_bits( buf,20,2 ) ); - infos->picture_structure = get_bits( buf,22,2 ); - lprintf( "picture_structure: %d\n", get_bits( buf,22,2 ) ); - infos->top_field_first = get_bits( buf,24,1 ); - lprintf( "top_field_first: %d\n", get_bits( buf,24,1 ) ); - infos->frame_pred_frame_dct = get_bits( buf,25,1 ); - lprintf( "frame_pred_frame_dct: %d\n", get_bits( buf,25,1 ) ); - infos->concealment_motion_vectors = get_bits( buf,26,1 ); - lprintf( "concealment_motion_vectors: %d\n", get_bits( buf,26,1 ) ); - infos->q_scale_type = get_bits( buf,27,1 ); - lprintf( "q_scale_type: %d\n", get_bits( buf,27,1 ) ); - infos->intra_vlc_format = get_bits( buf,28,1 ); - lprintf( "intra_vlc_format: %d\n", get_bits( buf,28,1 ) ); - infos->alternate_scan = get_bits( buf,29,1 ); - lprintf( "alternate_scan: %d\n", get_bits( buf,29,1 ) ); - lprintf( "repeat_first_field: %d\n", get_bits( buf,30,1 ) ); - lprintf( "chroma_420_type: %d\n", get_bits( buf,31,1 ) ); - sequence->picture.progressive_frame = get_bits( buf,32,1 ); - lprintf( "progressive_frame: %d\n", get_bits( buf,32,1 ) ); + bits_reader_set( &sequence->br, buf ); + int tmp = read_bits( &sequence->br, 4 ); + lprintf( "extension_start_code_identifier: %d\n", tmp ); + infos->f_code[0][0] = read_bits( &sequence->br, 4 ); + infos->f_code[0][1] = read_bits( &sequence->br, 4 ); + infos->f_code[1][0] = read_bits( &sequence->br, 4 ); + infos->f_code[1][1] = read_bits( &sequence->br, 4 ); + lprintf( "f_code_0_0: %d\n", infos->f_code[0][0] ); + lprintf( "f_code_0_1: %d\n", infos->f_code[0][1] ); + lprintf( "f_code_1_0: %d\n", infos->f_code[1][0] ); + lprintf( "f_code_1_1: %d\n", infos->f_code[1][1] ); + infos->intra_dc_precision = read_bits( &sequence->br, 2 ); + lprintf( "intra_dc_precision: %d\n", infos->intra_dc_precision ); + infos->picture_structure = read_bits( &sequence->br, 2 ); + lprintf( "picture_structure: %d\n", infos->picture_structure ); + infos->top_field_first = read_bits( &sequence->br, 1 ); + lprintf( "top_field_first: %d\n", infos->top_field_first ); + infos->frame_pred_frame_dct = read_bits( &sequence->br, 1 ); + lprintf( "frame_pred_frame_dct: %d\n", infos->frame_pred_frame_dct ); + infos->concealment_motion_vectors = read_bits( &sequence->br, 1 ); + lprintf( "concealment_motion_vectors: %d\n", infos->concealment_motion_vectors ); + infos->q_scale_type = read_bits( &sequence->br, 1 ); + lprintf( "q_scale_type: %d\n", infos->q_scale_type ); + infos->intra_vlc_format = read_bits( &sequence->br, 1 ); + lprintf( "intra_vlc_format: %d\n", infos->intra_vlc_format ); + infos->alternate_scan = read_bits( &sequence->br, 1 ); + lprintf( "alternate_scan: %d\n", infos->alternate_scan ); + tmp = read_bits( &sequence->br, 1 ); + lprintf( "repeat_first_field: %d\n", tmp ); + tmp = read_bits( &sequence->br, 1 ); + lprintf( "chroma_420_type: %d\n", tmp ); + sequence->picture.progressive_frame = read_bits( &sequence->br, 1 ); + lprintf( "progressive_frame: %d\n", sequence->picture.progressive_frame ); sequence->picture.state = WANT_SLICE; } @@ -460,15 +473,16 @@ static void picture_coding_extension( sequence_t *sequence, uint8_t *buf, int le static void quant_matrix_extension( sequence_t *sequence, uint8_t *buf, int len ) { - int i, j, off=0; + int i, j; - i = get_bits( buf,4,1 ); + bits_reader_set( &sequence->br, buf ); + read_bits( &sequence->br, 4 ); + i = read_bits( &sequence->br, 1 ); lprintf( "load_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+j,5,8 ); + sequence->picture.vdp_infos2.intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.intra_quantizer_matrix[mpeg2_scan_norm[j]] = read_bits( &sequence->br, 8 ); } - off = 64; } else { for ( j=0; j<64; ++j ) { @@ -476,11 +490,11 @@ static void quant_matrix_extension( sequence_t *sequence, uint8_t *buf, int len } } - i = get_bits( buf+off,5,1 ); + i = read_bits( &sequence->br, 1 ); lprintf( "load_non_intra_quantizer_matrix: %d\n", i ); if ( i ) { for ( j=0; j<64; ++j ) { - sequence->picture.vdp_infos2.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = get_bits( buf+off+j,6,8 ); + sequence->picture.vdp_infos2.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = sequence->picture.vdp_infos.non_intra_quantizer_matrix[mpeg2_scan_norm[j]] = read_bits( &sequence->br, 8 ); } } else { @@ -537,7 +551,7 @@ static int parse_code( vdpau_mpeg12_decoder_t *this_gen, uint8_t *buf, int len ) sequence_header( this_gen, buf+4, len-4 ); break; case extension_start_code: { - switch ( get_bits( buf+4,0,4 ) ) { + switch ( buf[4]>>4 ) { case sequence_ext_sc: lprintf( " ----------- sequence_extension_start_code\n" ); sequence_extension( sequence, buf+4, len-4 ); @@ -703,6 +717,21 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) decode_render( vd, accel ); +#ifdef MAKE_DAT + if ( nframes==0 ) { + fwrite( &seq->coded_width, 1, sizeof(seq->coded_width), outfile ); + fwrite( &seq->coded_height, 1, sizeof(seq->coded_height), outfile ); + fwrite( &seq->ratio, 1, sizeof(seq->ratio), outfile ); + fwrite( &seq->profile, 1, sizeof(seq->profile), outfile ); + } + + if ( nframes++ < 25 ) { + fwrite( &pic->vdp_infos, 1, sizeof(pic->vdp_infos), outfile ); + fwrite( &pic->slices_pos, 1, sizeof(pic->slices_pos), outfile ); + fwrite( pic->slices, 1, pic->slices_pos, outfile ); + } +#endif + img->drawn = 0; img->pts = seq->seq_pts; seq->seq_pts = 0; /* reset */ @@ -905,6 +934,11 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre (stream->video_out->open)(stream->video_out, stream); +#ifdef MAKE_DAT + outfile = fopen( "/tmp/mpg.dat","w"); + nframes = 0; +#endif + return &this->video_decoder; } diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 67a453870..2ccc7e6b9 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -37,6 +37,7 @@ #include "buffer.h" #include "xineutils.h" #include "accel_vdpau.h" +#include "bits_reader.h" #include @@ -137,6 +138,8 @@ typedef struct { vdpau_accel_t *accel_vdpau; + bits_reader_t br; + int vdp_runtime_nr; } sequence_t; @@ -212,7 +215,7 @@ static void init_sequence( sequence_t *sequence ) -static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) +/*static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) { int i, nbytes; uint32_t ret = 0; @@ -229,7 +232,7 @@ static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) ret = ((ret<>i)>>((nbytes*8)-nbits-offbits); return ret; -} +}*/ @@ -269,35 +272,29 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu sequence->profile = VDP_DECODER_PROFILE_VC1_ADVANCED; lprintf("VDP_DECODER_PROFILE_VC1_ADVANCED\n"); - int off = 15; - sequence->picture.vdp_infos.postprocflag = get_bits(buf,off++,1); - sequence->coded_width = (get_bits(buf,off,12)+1)<<1; - off += 12; - sequence->coded_height = (get_bits(buf,off,12)+1)<<1; - off += 12; - sequence->picture.vdp_infos.pulldown = get_bits(buf,off++,1); - sequence->picture.vdp_infos.interlace = get_bits(buf,off++,1); - sequence->picture.vdp_infos.tfcntrflag = get_bits(buf,off++,1); - sequence->picture.vdp_infos.finterpflag = get_bits(buf,off++,1); - ++off; - sequence->picture.vdp_infos.psf = get_bits(buf,off++,1); + bits_reader_set( &sequence->br, buf ); + read_bits( &sequence->br, 15 ); + sequence->picture.vdp_infos.postprocflag = read_bits( &sequence->br, 1 ); + sequence->coded_width = read_bits( &sequence->br, 12 )<<1; + sequence->coded_height = (read_bits( &sequence->br, 12 )+1)<<1; + sequence->picture.vdp_infos.pulldown = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.interlace = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.tfcntrflag = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.finterpflag = read_bits( &sequence->br, 1 ); + read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.psf = read_bits( &sequence->br, 1 ); sequence->picture.vdp_infos.maxbframes = 7; - if ( get_bits(buf,off++,1) ) { + if ( read_bits( &sequence->br, 1 ) ) { double w, h; int ar=0; - w = get_bits(buf,off,14)+1; - off += 14; - h = get_bits(buf,off,14)+1; - off += 14; - if ( get_bits(buf,off++,1) ) { - ar = get_bits(buf,off,4); - off += 4; + w = read_bits( &sequence->br, 14 )+1; + h = read_bits( &sequence->br, 14 )+1; + if ( read_bits( &sequence->br, 1 ) ) { + ar = read_bits( &sequence->br, 4 ); } if ( ar==15 ) { - w = get_bits(buf,off,8); - off += 8; - h = get_bits(buf,off,8); - off += 8; + w = read_bits( &sequence->br, 8 ); + h = read_bits( &sequence->br, 8 ); sequence->ratio = w/h; lprintf("aspect_ratio (w/h) = %f\n", sequence->ratio); } @@ -306,14 +303,13 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu lprintf("aspect_ratio = %f\n", sequence->ratio); } - if ( get_bits(buf,off++,1) ) { - if ( get_bits(buf,off++,1) ) { - int exp = get_bits(buf,off,16); + if ( read_bits( &sequence->br, 1 ) ) { + if ( read_bits( &sequence->br, 1 ) ) { + int exp = read_bits( &sequence->br, 16 ); lprintf("framerate exp = %d\n", exp); - off += 16; } else { - double nr = get_bits(buf,off,8); + double nr = read_bits( &sequence->br, 8 ); switch ((int)nr) { case 1: nr = 24000; break; case 2: nr = 25000; break; @@ -322,25 +318,23 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu case 5: nr = 60000; break; default: nr = 0; } - off += 8; - double dr = get_bits(buf,off,4); + double dr = read_bits( &sequence->br, 4 ); switch ((int)dr) { case 2: dr = 1001; break; default: dr = 1000; } - off += 4; sequence->video_step = 90000/(nr/dr); lprintf("framerate = %f video_step = %d\n", nr/dr, sequence->video_step); } } - if ( get_bits(buf,off++,1) ) { - lprintf("color_standard = %d\n", get_bits(buf,off,8)); - off += 24; + if ( read_bits( &sequence->br, 1 ) ) { + lprintf("color_standard = %d\n", read_bits( &sequence->br, 8 )); + read_bits( &sequence->br, 16 ); } } - sequence->picture.hrd_param_flag = get_bits(buf,off++,1); + sequence->picture.hrd_param_flag = read_bits( &sequence->br, 1 ); if ( sequence->picture.hrd_param_flag ) - sequence->picture.hrd_num_leaky_buckets = get_bits(buf,off,5); + sequence->picture.hrd_num_leaky_buckets = read_bits( &sequence->br, 5 ); update_metadata( this_gen ); } @@ -355,26 +349,30 @@ static void sequence_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int le if ( len < 4 ) return; - switch ( get_bits(buf,0,2) ) { + bits_reader_set( &sequence->br, buf ); + switch ( read_bits( &sequence->br, 2 ) ) { case 0: sequence->profile = VDP_DECODER_PROFILE_VC1_SIMPLE; lprintf("VDP_DECODER_PROFILE_VC1_SIMPLE\n"); break; case 1: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("VDP_DECODER_PROFILE_VC1_MAIN\n"); break; case 2: sequence->profile = VDP_DECODER_PROFILE_VC1_MAIN; lprintf("vc1_complex profile not supported by vdpau, trying vc1_main.\n"); break; case 3: return sequence_header_advanced( this_gen, buf, len ); break; default: return; /* illegal value, broken header? */ } - - sequence->picture.vdp_infos.loopfilter = get_bits(buf,12,1); - sequence->picture.vdp_infos.multires = get_bits(buf,14,1); - sequence->picture.vdp_infos.fastuvmc = get_bits(buf,16,1); - sequence->picture.vdp_infos.extended_mv = get_bits(buf,17,1); - sequence->picture.vdp_infos.dquant = get_bits(buf,18,2); - sequence->picture.vdp_infos.vstransform = get_bits(buf,20,1); - sequence->picture.vdp_infos.overlap = get_bits(buf,22,1); - sequence->picture.vdp_infos.syncmarker = get_bits(buf,23,1); - sequence->picture.vdp_infos.rangered = get_bits(buf,24,1); - sequence->picture.vdp_infos.maxbframes = get_bits(buf,25,3); - sequence->picture.vdp_infos.quantizer = get_bits(buf,28,2); - sequence->picture.vdp_infos.finterpflag = get_bits(buf,30,1); + read_bits( &sequence->br, 10 ); + sequence->picture.vdp_infos.loopfilter = read_bits( &sequence->br, 1 ); + read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.multires = read_bits( &sequence->br, 1 ); + read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.fastuvmc = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.extended_mv = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.dquant = read_bits( &sequence->br, 2 ); + sequence->picture.vdp_infos.vstransform = read_bits( &sequence->br, 1 ); + read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.overlap = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.syncmarker = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.rangered = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.maxbframes = read_bits( &sequence->br, 3 ); + sequence->picture.vdp_infos.quantizer = read_bits( &sequence->br, 2 ); + sequence->picture.vdp_infos.finterpflag = read_bits( &sequence->br, 1 ); update_metadata( this_gen ); } @@ -385,45 +383,40 @@ static void entry_point( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len ) { lprintf( "entry_point\n" ); sequence_t *sequence = (sequence_t*)&this_gen->sequence; - int off=2; - - sequence->picture.vdp_infos.panscan_flag = get_bits(buf,off++,1); - sequence->picture.vdp_infos.refdist_flag = get_bits(buf,off++,1); - sequence->picture.vdp_infos.loopfilter = get_bits(buf,off++,1); - sequence->picture.vdp_infos.fastuvmc = get_bits(buf,off++,1); - sequence->picture.vdp_infos.extended_mv = get_bits(buf,off++,1); - sequence->picture.vdp_infos.dquant = get_bits(buf,off,2); - off += 2; - sequence->picture.vdp_infos.vstransform = get_bits(buf,off++,1); - sequence->picture.vdp_infos.overlap = get_bits(buf,off++,1); - sequence->picture.vdp_infos.quantizer = get_bits(buf,off,2); - off += 2; + + bits_reader_set( &sequence->br, buf ); + read_bits( &sequence->br, 2 ); + sequence->picture.vdp_infos.panscan_flag = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.refdist_flag = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.loopfilter = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.fastuvmc = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.extended_mv = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.dquant = read_bits( &sequence->br, 2 ); + sequence->picture.vdp_infos.vstransform = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.overlap = read_bits( &sequence->br, 1 ); + sequence->picture.vdp_infos.quantizer = read_bits( &sequence->br, 2 ); if ( sequence->picture.hrd_param_flag ) { int i; for ( i=0; ipicture.hrd_num_leaky_buckets; ++i ) - off += 8; + read_bits( &sequence->br, 8 ); } - if ( get_bits(buf,off++,1) ) { - sequence->coded_width = (get_bits(buf,off,12)+1)<<1; - off += 12; - sequence->coded_height = (get_bits(buf,off,12)+1)<<1; - off += 12; + if ( read_bits( &sequence->br, 1 ) ) { + sequence->coded_width = (read_bits( &sequence->br, 12 )+1)<<1; + sequence->coded_height = (read_bits( &sequence->br, 12 )+1)<<1; } if ( sequence->picture.vdp_infos.extended_mv ) - sequence->picture.vdp_infos.extended_dmv = get_bits(buf,off++,1); + sequence->picture.vdp_infos.extended_dmv = read_bits( &sequence->br, 1 ); - sequence->picture.vdp_infos.range_mapy_flag = get_bits(buf,off++,1); + sequence->picture.vdp_infos.range_mapy_flag = read_bits( &sequence->br, 1 ); if ( sequence->picture.vdp_infos.range_mapy_flag ) { - sequence->picture.vdp_infos.range_mapy = get_bits(buf,off,3); - off += 3; + sequence->picture.vdp_infos.range_mapy = read_bits( &sequence->br, 3 ); } - sequence->picture.vdp_infos.range_mapuv_flag = get_bits(buf,off++,1); + sequence->picture.vdp_infos.range_mapuv_flag = read_bits( &sequence->br, 1 ); if ( sequence->picture.vdp_infos.range_mapuv_flag ) { - sequence->picture.vdp_infos.range_mapuv = get_bits(buf,off,3); - off += 3; + sequence->picture.vdp_infos.range_mapuv = read_bits( &sequence->br, 3 ); } } @@ -438,41 +431,39 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len lprintf("picture_header\n"); - int off=2; + bits_reader_set( &sequence->br, buf ); + read_bits( &sequence->br, 2 ); if ( info->finterpflag ) - ++off; + read_bits( &sequence->br, 1 ); if ( info->rangered ) { /*info->rangered &= ~2; info->rangered |= get_bits( buf,off++,1 ) << 1;*/ - info->rangered = (get_bits( buf,off++,1 ) << 1) +1; + info->rangered = (read_bits( &sequence->br, 1 ) << 1) +1; } if ( !info->maxbframes ) { - if ( get_bits( buf,off++,1 ) ) + if ( read_bits( &sequence->br, 1 ) ) info->picture_type = P_FRAME; else info->picture_type = I_FRAME; } else { - if ( get_bits( buf,off++,1 ) ) + if ( read_bits( &sequence->br, 1 ) ) info->picture_type = P_FRAME; else { - if ( get_bits( buf,off++,1 ) ) + if ( read_bits( &sequence->br, 1 ) ) info->picture_type = I_FRAME; else info->picture_type = B_FRAME; } } if ( info->picture_type == B_FRAME ) { - tmp = get_bits(buf,off,3); + tmp = read_bits( &sequence->br, 3 ); if ( tmp==7 ) { - tmp = get_bits(buf,off,7); - off += 7; + tmp = read_bits( &sequence->br, 7 ); if ( tmp==127 ) info->picture_type = BI_FRAME; } - else - off += 3; } } @@ -483,18 +474,19 @@ static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf sequence_t *sequence = (sequence_t*)&this_gen->sequence; picture_t *pic = (picture_t*)&sequence->picture; VdpPictureInfoVC1 *info = &(sequence->picture.vdp_infos); - int off=0; lprintf("picture_header_advanced\n"); + bits_reader_set( &sequence->br, buf ); + if ( info->interlace ) { lprintf("frame->interlace=1\n"); - if ( !get_bits(buf,off++,1) ) { + if ( !read_bits( &sequence->br, 1 ) ) { lprintf("progressive frame\n"); info->frame_coding_mode = PICTURE_FRAME; } else { - if ( !get_bits(buf,off++,1) ) { + if ( !read_bits( &sequence->br, 1 ) ) { lprintf("frame interlaced\n"); info->frame_coding_mode = PICTURE_FRAME_INTERLACE; } @@ -505,7 +497,7 @@ static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf } } if ( info->interlace && info->frame_coding_mode == PICTURE_FIELD_INTERLACE ) { - pic->fptype = get_bits(buf,off,3); + pic->fptype = read_bits( &sequence->br, 3 ); switch ( pic->fptype ) { case FIELDS_I_I: case FIELDS_I_P: @@ -519,19 +511,18 @@ static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf default: info->picture_type = BI_FRAME; } - off += 3; } else { - if ( !get_bits(buf,off++,1) ) + if ( !read_bits( &sequence->br, 1 ) ) info->picture_type = P_FRAME; else { - if ( !get_bits(buf,off++,1) ) + if ( !read_bits( &sequence->br, 1 ) ) info->picture_type = B_FRAME; else { - if ( !get_bits(buf,off++,1) ) + if ( !read_bits( &sequence->br, 1 ) ) info->picture_type = I_FRAME; else { - if ( !get_bits(buf,off++,1) ) + if ( !read_bits( &sequence->br, 1 ) ) info->picture_type = BI_FRAME; else { info->picture_type = P_FRAME; @@ -543,11 +534,11 @@ static void picture_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *buf } if ( info->tfcntrflag ) { lprintf("tfcntrflag=1\n"); - off += 8; + read_bits( &sequence->br, 8 ); } if ( info->pulldown && info->interlace ) { - pic->top_field_first = get_bits(buf,off++,1); - pic->repeat_first_field = get_bits(buf,off++,1); + pic->top_field_first = read_bits( &sequence->br, 1 ); + pic->repeat_first_field = read_bits( &sequence->br, 1 ); } } @@ -1139,7 +1130,7 @@ static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stre (stream->video_out->open)(stream->video_out, stream); #ifdef MAKE_DAT - outfile = fopen( "/home/cris/qvdpautest/mpg.dat","w"); + outfile = fopen( "/tmp/vc1.dat","w"); nframes = 0; #endif -- cgit v1.2.3 From 3c777cd744227ad68813ffe7091d2ea413ecf602 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Sun, 9 Aug 2009 01:10:20 +0100 Subject: Cleanup. --- src/libvdpau/vdpau_vc1.c | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 2ccc7e6b9..9e17c605a 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -215,27 +215,6 @@ static void init_sequence( sequence_t *sequence ) -/*static uint32_t get_bits( uint8_t *b, int offbits, int nbits ) -{ - int i, nbytes; - uint32_t ret = 0; - uint8_t *buf; - - buf = b+(offbits/8); - offbits %=8; - nbytes = (offbits+nbits)/8; - if ( ((offbits+nbits)%8)>0 ) - nbytes++; - for ( i=0; i>i)>>((nbytes*8)-nbits-offbits); - - return ret; -}*/ - - - static void update_metadata( vdpau_vc1_decoder_t *this_gen ) { sequence_t *sequence = (sequence_t*)&this_gen->sequence; -- cgit v1.2.3 From deaea99f0ec02fbb2392e702c6c6c2f5ba3e27c2 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 14 Aug 2009 03:09:14 +0100 Subject: Better deint when paused. --- src/video_out/video_out_vdpau.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 883f6c6c0..11c22ff74 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -1582,7 +1582,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) XLockDisplay( this->display ); #endif - if ( frame->format==XINE_IMGFMT_VDPAU && this->deinterlace && non_progressive && stream_speed && frame_duration>2500 ) { + if ( frame->format==XINE_IMGFMT_VDPAU && this->deinterlace && non_progressive /*&& stream_speed*/ && frame_duration>2500 ) { VdpTime current_time = 0; VdpVideoSurface past[2]; VdpVideoSurface future[1]; @@ -1651,7 +1651,10 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) XUnlockDisplay( this->display ); #endif - vdpau_backup_frame( this_gen, frame_gen ); + if ( stream_speed ) /* do not release past frame if paused, it will be used for redrawing */ + vdpau_backup_frame( this_gen, frame_gen ); + else + frame->vo_frame.free( &frame->vo_frame ); } -- cgit v1.2.3 From 5f611996c86f98cb8fd46e67b7dd21e8f8b38038 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Fri, 14 Aug 2009 03:09:14 +0100 Subject: Default to LOCKDISPLAY atm. --- src/video_out/video_out_vdpau.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 11c22ff74..42ba9b982 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -53,7 +53,7 @@ #define NUM_FRAMES_BACK 1 -/*#define LOCKDISPLAY*/ /*define this if you have a buggy libX11/xcb*/ +#define LOCKDISPLAY /*define this if you have a buggy libX11/xcb*/ #define DEINT_BOB 1 -- cgit v1.2.3 From a6d4dfe992ebd4f67e4745b09654cf08df2b9205 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 7 Sep 2009 23:26:15 +0100 Subject: High Quality Scaling. --- src/video_out/video_out_vdpau.c | 89 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 42ba9b982..4b69f4ffc 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -324,6 +324,9 @@ typedef struct { char* deinterlacers_name[NUMBER_OF_DEINTERLACERS+1]; int deinterlacers_method[NUMBER_OF_DEINTERLACERS]; + int scaling_level_max; + int scaling_level_current; + VdpColor back_color; vdpau_frame_t *back_frame[ NUM_FRAMES_BACK ]; @@ -1235,6 +1238,42 @@ static void vdpau_update_deinterlace_method( void *this_gen, xine_cfg_entry_t *e +static void vdpau_set_scaling_level( vo_driver_t *this_gen ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + int i; + VdpVideoMixerFeature features[9]; + VdpBool feature_enables[9]; +#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + for ( i=0; iscaling_level_max; ++i ) { + features[i] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i; + feature_enables[i] = 0; + } + vdp_video_mixer_set_feature_enables( this->video_mixer, this->scaling_level_max, features, feature_enables ); + + if ( this->scaling_level_current ) { + features[0] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 - 1 + this->scaling_level_current; + feature_enables[0] = 1; + vdp_video_mixer_set_feature_enables( this->video_mixer, 1, features, feature_enables ); + } + + printf( "vo_vdpau: set_scaling_level=%d\n", this->scaling_level_current ); +#endif +} + + + +static void vdpau_update_scaling_level( void *this_gen, xine_cfg_entry_t *entry ) +{ + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; + + this->scaling_level_current = entry->num_value; + printf( "vo_vdpau: scaling_quality=%d\n", this->scaling_level_current ); + vdpau_set_scaling_level( (vo_driver_t*)this_gen ); +} + + + static void vdpau_update_enable_inverse_telecine( void *this_gen, xine_cfg_entry_t *entry ) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; @@ -1471,7 +1510,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) lprintf("vo_vdpau: recreate mixer to match frames: width=%d, height=%d, chroma=%d\n", mix_w, mix_h, chroma); vdp_video_mixer_destroy( this->video_mixer ); this->video_mixer = VDP_INVALID_HANDLE; - VdpVideoMixerFeature features[5]; + VdpVideoMixerFeature features[15]; int features_count = 0; if ( this->noise_reduction_is_supported ) { features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; @@ -1493,6 +1532,13 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) features[features_count] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; ++features_count; } + int i; +#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + for ( i=0; iscaling_level_max; ++i ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i; + ++features_count; + } +#endif VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; @@ -1502,6 +1548,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) this->video_mixer_width = mix_w; this->video_mixer_height = mix_h; vdpau_set_deinterlace( this_gen ); + vdpau_set_scaling_level( this_gen ); vdpau_set_inverse_telecine( this_gen ); vdpau_update_noise( this ); vdpau_update_sharpness( this ); @@ -1986,7 +2033,7 @@ static void vdpau_reinit( vo_driver_t *this_gen ) this->argb_overlay_width = this->argb_overlay_height = 0; this->has_argb_overlay = 0; - VdpVideoMixerFeature features[5]; + VdpVideoMixerFeature features[15]; int features_count = 0; if ( this->noise_reduction_is_supported ) { features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; @@ -2008,6 +2055,12 @@ static void vdpau_reinit( vo_driver_t *this_gen ) features[features_count] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; ++features_count; } +#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + for ( i=0; iscaling_level_max; ++i ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i; + ++features_count; + } +#endif VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; @@ -2020,6 +2073,7 @@ static void vdpau_reinit( vo_driver_t *this_gen ) } this->video_mixer_chroma = chroma; vdpau_set_deinterlace( this_gen ); + vdpau_set_scaling_level( this_gen ); vdpau_set_inverse_telecine( this_gen ); vdpau_update_noise( this ); vdpau_update_sharpness( this ); @@ -2344,6 +2398,22 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo return NULL; } + this->scaling_level_max = this->scaling_level_current = 0; +#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + VdpBool hqscaling; + for ( i=0; i<9; ++i ) { + st = vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i, &hqscaling ); + if ( ( st != VDP_STATUS_OK ) || !hqscaling ) { + //printf("unsupported scaling quality=%d\n", i); + break; + } + else { + //printf("supported scaling quality=%d\n", i); + ++this->scaling_level_max; + } + } +#endif + vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, &this->temporal_is_supported ); vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL, &this->temporal_spatial_is_supported ); vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION, &this->noise_reduction_is_supported ); @@ -2355,7 +2425,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->video_mixer_chroma = chroma; this->video_mixer_width = this->soft_surface_width; this->video_mixer_height = this->soft_surface_height; - VdpVideoMixerFeature features[5]; + VdpVideoMixerFeature features[15]; int features_count = 0; if ( this->noise_reduction_is_supported ) { features[features_count] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; @@ -2377,6 +2447,12 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo features[features_count] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE; ++features_count; } +#ifdef VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + for ( i=0; iscaling_level_max; ++i ) { + features[features_count] = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1 + i; + ++features_count; + } +#endif VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; int num_layers = 3; @@ -2424,6 +2500,13 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo } this->deinterlacers_name[deint_count] = NULL; + if ( this->scaling_level_max ) { + this->scaling_level_current = config->register_range( config, "video.output.vdpau_scaling_quality", 0, + 0, this->scaling_level_max, _("vdpau: Scaling Quality"), + _("Scaling Quality Level"), + 10, vdpau_update_scaling_level, this ); + } + this->deinterlace_method = config->register_enum( config, "video.output.vdpau_deinterlace_method", deint_default, this->deinterlacers_name, _("vdpau: HD deinterlace method"), deinterlacers_description, -- cgit v1.2.3 From 29150fd62b65fa758dc12b2304aed0211663fce2 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 28 Sep 2009 14:58:59 +0100 Subject: Fix consumed bits. --- src/libvdpau/vdpau_vc1.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index 9e17c605a..f0bc974a4 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -307,7 +307,8 @@ static void sequence_header_advanced( vdpau_vc1_decoder_t *this_gen, uint8_t *bu } } if ( read_bits( &sequence->br, 1 ) ) { - lprintf("color_standard = %d\n", read_bits( &sequence->br, 8 )); + int col = read_bits( &sequence->br, 8 ); + lprintf("color_standard = %d\n", col); read_bits( &sequence->br, 16 ); } } @@ -439,7 +440,7 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len if ( info->picture_type == B_FRAME ) { tmp = read_bits( &sequence->br, 3 ); if ( tmp==7 ) { - tmp = read_bits( &sequence->br, 7 ); + tmp = (tmp<<3) | read_bits( &sequence->br, 4 ); if ( tmp==127 ) info->picture_type = BI_FRAME; } -- cgit v1.2.3 From 9c38df222650505b673d70c5eedf7b51fc9f0b19 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 28 Sep 2009 15:00:51 +0100 Subject: Try to deal with buggy top_field_first. --- src/libvdpau/vdpau_mpeg12.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_mpeg12.c b/src/libvdpau/vdpau_mpeg12.c index 4ef1f5c30..f3ad9a03c 100644 --- a/src/libvdpau/vdpau_mpeg12.c +++ b/src/libvdpau/vdpau_mpeg12.c @@ -131,6 +131,7 @@ typedef struct { double ratio; VdpDecoderProfile profile; int chroma; + int top_field_first; int have_header; @@ -229,6 +230,7 @@ static void reset_sequence( sequence_t *sequence, int free_refs ) if ( sequence->backward_ref ) sequence->backward_ref->free( sequence->backward_ref ); sequence->backward_ref = NULL; + sequence->top_field_first = 0; } @@ -737,7 +739,14 @@ static void decode_picture( vdpau_mpeg12_decoder_t *vd ) seq->seq_pts = 0; /* reset */ img->bad_frame = 0; img->duration = seq->video_step; - img->top_field_first = pic->vdp_infos.top_field_first; + + /* trying to deal with (french) buggy streams that randomly set bottom_field_first + while stream is top_field_first. So we assume that when top_field_first + is set one time, the stream _is_ top_field_first. */ + //printf("pic->vdp_infos.top_field_first = %d\n", pic->vdp_infos.top_field_first); + if ( pic->vdp_infos.top_field_first ) + seq->top_field_first = 1; + img->top_field_first = seq->top_field_first; /* progressive_frame is unreliable with most mpeg2 streams */ if ( pic->vdp_infos.picture_structure!=PICTURE_FRAME ) -- cgit v1.2.3 From eeabd4c12859a1e5b27d48fb6f26d269dd2150b0 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Mon, 28 Sep 2009 15:04:35 +0100 Subject: Fix consumed bits. --- src/libvdpau/vdpau_vc1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libvdpau/vdpau_vc1.c b/src/libvdpau/vdpau_vc1.c index f0bc974a4..2ffd9a2e2 100644 --- a/src/libvdpau/vdpau_vc1.c +++ b/src/libvdpau/vdpau_vc1.c @@ -440,7 +440,7 @@ static void picture_header( vdpau_vc1_decoder_t *this_gen, uint8_t *buf, int len if ( info->picture_type == B_FRAME ) { tmp = read_bits( &sequence->br, 3 ); if ( tmp==7 ) { - tmp = (tmp<<3) | read_bits( &sequence->br, 4 ); + tmp = (tmp<<4) | read_bits( &sequence->br, 4 ); if ( tmp==127 ) info->picture_type = BI_FRAME; } -- cgit v1.2.3 From e18856000d2bd7d6447ab6c59d3eb8ee3d354dfc Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Wed, 21 Oct 2009 05:11:08 +0100 Subject: Cleanup. --- src/video_out/video_out_vdpau.c | 105 +++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 4b69f4ffc..8b4c645d6 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -141,6 +141,7 @@ VdpPresentationQueueDisplay *vdp_queue_display; VdpPresentationQueueBlockUntilSurfaceIdle *vdp_queue_block; VdpPresentationQueueSetBackgroundColor *vdp_queue_set_background_color; VdpPresentationQueueGetTime *vdp_queue_get_time; +VdpPresentationQueueQuerySurfaceStatus *vdp_queue_query_surface_status; VdpBitmapSurfacePutBitsNative *vdp_bitmap_put_bits; VdpBitmapSurfaceCreate *vdp_bitmap_create; @@ -303,10 +304,11 @@ typedef struct { uint32_t soft_surface_height; int soft_surface_format; - VdpOutputSurface output_surface[2]; +#define NOUTPUTSURFACE 2 + VdpOutputSurface output_surface[NOUTPUTSURFACE]; uint8_t current_output_surface; - uint32_t output_surface_width[2]; - uint32_t output_surface_height[2]; + uint32_t output_surface_width[NOUTPUTSURFACE]; + uint32_t output_surface_height[NOUTPUTSURFACE]; uint8_t init_queue; VdpVideoMixer video_mixer; @@ -1410,7 +1412,9 @@ static void vdpau_shift_queue( vo_driver_t *this_gen ) if ( this->init_queue<2 ) ++this->init_queue; - this->current_output_surface ^= 1; + ++this->current_output_surface; + if ( this->current_output_surface > (NOUTPUTSURFACE-1) ) + this->current_output_surface = 0; } @@ -1563,11 +1567,15 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) vdpau_update_csc( this ); } - vdpau_check_output_size( this_gen ); + VdpRect vid_source, out_dest, vid_dest; - VdpRect vid_source = { this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width+this->sc.displayed_xoffset, this->sc.displayed_height+this->sc.displayed_yoffset }; - VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height }; - VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height }; + vdpau_check_output_size( this_gen ); + vid_source.x0 = this->sc.displayed_xoffset; vid_source.y0 = this->sc.displayed_yoffset; + vid_source.x1 = this->sc.displayed_width+this->sc.displayed_xoffset; vid_source.y1 = this->sc.displayed_height+this->sc.displayed_yoffset; + out_dest.x0 = out_dest.y0 = 0; + out_dest.x1 = this->sc.gui_width; out_dest.y1 = this->sc.gui_height; + vid_dest.x0 = this->sc.output_xoffset; vid_dest.y0 = this->sc.output_yoffset; + vid_dest.x1 = this->sc.output_xoffset+this->sc.output_width; vid_dest.y1 = this->sc.output_yoffset+this->sc.output_height; /* prepare field delay calculation to not run into a deadlock while display locked */ stream_speed = frame->vo_frame.stream ? xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) : 0; @@ -1676,10 +1684,12 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */ if (stream_speed > 0) - current_time += frame->vo_frame.duration * 100000ull * XINE_FINE_SPEED_NORMAL / (18 * stream_speed); + current_time += frame->vo_frame.duration * 1000000ull * XINE_FINE_SPEED_NORMAL / (180 * stream_speed); else current_time = 0; /* immediately i. e. no delay */ + //current_time = 0; + //printf( "vo_vdpau: deint delay = %d\n", frame_duration *1ull * XINE_FINE_SPEED_NORMAL / (180 * stream_speed) ); vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, current_time ); vdpau_shift_queue( this_gen ); } @@ -1833,7 +1843,9 @@ static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void * #ifdef LOCKDISPLAY XLockDisplay( this->display ); #endif - int previous = this->current_output_surface ^ 1; + int previous = this->current_output_surface - 1; + if ( previous < 0 ) + previous = NOUTPUTSURFACE - 1; vdp_queue_display( vdp_queue, this->output_surface[previous], 0, 0, 0 ); #ifdef LOCKDISPLAY XUnlockDisplay( this->display ); @@ -1930,10 +1942,10 @@ static void vdpau_dispose (vo_driver_t *this_gen) vdp_output_surface_destroy( this->overlay_unscaled ); if ( this->overlay_output!=VDP_INVALID_HANDLE ) vdp_output_surface_destroy( this->overlay_output ); - if ( this->output_surface[0]!=VDP_INVALID_HANDLE ) - vdp_output_surface_destroy( this->output_surface[0] ); - if ( this->output_surface[1]!=VDP_INVALID_HANDLE ) - vdp_output_surface_destroy( this->output_surface[1] ); + for ( i=0; ioutput_surface[i]!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->output_surface[i] ); + } } if ( vdp_queue != VDP_INVALID_HANDLE ) @@ -2001,21 +2013,19 @@ static void vdpau_reinit( vo_driver_t *this_gen ) this->current_output_surface = 0; this->init_queue = 0; - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] ); - if ( vdpau_reinit_error( st, "Can't create first output surface !!" ) ) { - orig_vdp_video_surface_destroy( this->soft_surface ); - return; - } - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[1] ); - if ( vdpau_reinit_error( st, "Can't create second output surface !!" ) ) { - orig_vdp_video_surface_destroy( this->soft_surface ); - vdp_output_surface_destroy( this->output_surface[0] ); - return; + int i; + for ( i=0; ioutput_surface_width[i], this->output_surface_height[i], &this->output_surface[i] ); + if ( vdpau_reinit_error( st, "Can't create output surface !!" ) ) { + int j; + for ( j=0; joutput_surface[j] ); + vdp_video_surface_destroy( this->soft_surface ); + return; + } } /* osd overlays need to be recreated */ - - int i; for ( i=0; ioverlays[i].ovl_bitmap = VDP_INVALID_HANDLE; this->overlays[i].bitmap_width = 0; @@ -2067,8 +2077,8 @@ static void vdpau_reinit( vo_driver_t *this_gen ) st = vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_reinit_error( st, "Can't create video mixer !!" ) ) { orig_vdp_video_surface_destroy( this->soft_surface ); - vdp_output_surface_destroy( this->output_surface[0] ); - vdp_output_surface_destroy( this->output_surface[1] ); + for ( i=0; ioutput_surface[i] ); return; } this->video_mixer_chroma = chroma; @@ -2119,7 +2129,7 @@ static int vdpau_init_error( VdpStatus st, const char *msg, vo_driver_t *driver, static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) { vdpau_class_t *class = (vdpau_class_t *) class_gen; - x11_visual_t *visual = (x11_visual_t *) visual_gen; + x11_visual_t *visual = (x11_visual_t *) visual_gen; vdpau_driver_t *this; config_values_t *config = class->xine->config; int i; @@ -2139,6 +2149,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->sc.dest_size_cb = visual->dest_size_cb; this->sc.user_data = visual->user_data; this->sc.user_ratio = XINE_VO_ASPECT_AUTO; + this->zoom_x = 100; this->zoom_y = 100; @@ -2160,8 +2171,8 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->vo_driver.redraw_needed = vdpau_redraw_needed; this->video_mixer = VDP_INVALID_HANDLE; - this->output_surface[0] = VDP_INVALID_HANDLE; - this->output_surface[1] = VDP_INVALID_HANDLE; + for ( i=0; ioutput_surface[i] = VDP_INVALID_HANDLE; this->soft_surface = VDP_INVALID_HANDLE; vdp_queue = VDP_INVALID_HANDLE; vdp_queue_target = VDP_INVALID_HANDLE; @@ -2331,6 +2342,9 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME , (void*)&vdp_queue_get_time ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_GET_TIME proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS , (void*)&vdp_queue_query_surface_status ); + if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_QUERY_SURFACE_STATUS proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , (void*)&vdp_decoder_query_capabilities ); if ( vdpau_init_error( st, "Can't get DECODER_QUERY_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -2382,20 +2396,21 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) return NULL; - this->output_surface_width[0] = this->output_surface_width[1] = 320; - this->output_surface_height[0] = this->output_surface_height[1] = 240; + for ( i=0; ioutput_surface_width[i] = 320; + this->output_surface_height[i] = 240; + } this->current_output_surface = 0; this->init_queue = 0; - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] ); - if ( vdpau_init_error( st, "Can't create first output surface !!", &this->vo_driver, 1 ) ) { - vdp_video_surface_destroy( this->soft_surface ); - return NULL; - } - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[1], this->output_surface_height[1], &this->output_surface[1] ); - if ( vdpau_init_error( st, "Can't create second output surface !!", &this->vo_driver, 1 ) ) { - vdp_video_surface_destroy( this->soft_surface ); - vdp_output_surface_destroy( this->output_surface[0] ); - return NULL; + for ( i=0; ioutput_surface_width[i], this->output_surface_height[i], &this->output_surface[i] ); + if ( vdpau_init_error( st, "Can't create output surface !!", &this->vo_driver, 1 ) ) { + int j; + for ( j=0; joutput_surface[j] ); + vdp_video_surface_destroy( this->soft_surface ); + return NULL; + } } this->scaling_level_max = this->scaling_level_current = 0; @@ -2460,8 +2475,8 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { vdp_video_surface_destroy( this->soft_surface ); - vdp_output_surface_destroy( this->output_surface[0] ); - vdp_output_surface_destroy( this->output_surface[1] ); + for ( i=0; ioutput_surface[i] ); return NULL; } -- cgit v1.2.3