bool CVDPAU::CheckStatus(VdpStatus vdp_st, int line) { if (vdp_st == VDP_STATUS_HANDLE_DEVICE_MISMATCH || vdp_st == VDP_STATUS_DISPLAY_PREEMPTED) recover = true; // no need to log errors about this case, as it will happen on cleanup if (vdp_st == VDP_STATUS_INVALID_HANDLE && recover && vdpauConfigured) return false; if (vdp_st != VDP_STATUS_OK) { CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", vdp_get_error_string(vdp_st), vdp_st, __FILE__, line); recover = true; return true; } return false; }
bool CVDPAU::CheckStatus(VdpStatus vdp_st, int line) { if (vdp_st != VDP_STATUS_OK) { CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) at %s:%d\n", vdp_get_error_string(vdp_st), vdp_st, __FILE__, line); CExclusiveLock lock(m_DisplaySection); if(m_DisplayState == VDPAU_OPEN) { if (vdp_st == VDP_STATUS_DISPLAY_PREEMPTED) m_DisplayState = VDPAU_LOST; else m_DisplayState = VDPAU_ERROR; } return true; } return false; }
static vlc_vdp_video_field_t *CreateSurface(vlc_va_t *va) { vlc_va_sys_t *sys = va->sys; VdpVideoSurface surface; VdpStatus err; err = vdp_video_surface_create(sys->vdp, sys->device, sys->type, sys->width, sys->height, &surface); if (err != VDP_STATUS_OK) { msg_Err(va, "%s creation failure: %s", "video surface", vdp_get_error_string(sys->vdp, err)); return NULL; } vlc_vdp_video_field_t *field = vlc_vdp_video_create(sys->vdp, surface); if (unlikely(field == NULL)) vdp_video_surface_destroy(sys->vdp, surface); return field; }
static void vdpau_draw_horiz( AVCodecContext *codec_context, const AVFrame *frame, int offset[4], int y, int type, int height ) { producer_avformat self = codec_context->opaque; if ( self->vdpau ) { struct vdpau_render_state *render = (struct vdpau_render_state*) frame->data[0]; VdpVideoSurface surface = render->surface; VdpStatus status = vdp_decoder_render( self->vdpau->decoder, surface, (void*) &render->info, render->bitstream_buffers_used, render->bitstream_buffers ); if ( status != VDP_STATUS_OK ) { self->vdpau->is_decoded = 0; mlt_log_warning( MLT_PRODUCER_SERVICE(self->parent), "VDPAU failed to decode (%s)\n", vdp_get_error_string( status ) ); } else { self->vdpau->is_decoded = 1; } } }
static int Lock(vlc_va_t *va, void **opaque, uint8_t **data) { vlc_va_sys_t *sys = va->sys; VdpVideoSurface surface; VdpStatus err; err = vdp_video_surface_create(sys->vdp, sys->device, VDP_CHROMA_TYPE_420, sys->width, sys->height, &surface); if (err != VDP_STATUS_OK) { msg_Err(va, "%s creation failure: %s", "video surface", vdp_get_error_string(sys->vdp, err)); return VLC_EGENERIC; } vlc_vdp_video_field_t *field = vlc_vdp_video_create(sys->vdp, surface); if (unlikely(field == NULL)) return VLC_ENOMEM; *data = (void *)(uintptr_t)surface; *opaque = field; return VLC_SUCCESS; }
static int Init(vlc_va_t *va, void **ctxp, vlc_fourcc_t *chromap, int width, int height) { vlc_va_sys_t *sys = va->sys; VdpStatus err; width = (width + 1) & ~1; height = (height + 3) & ~3; sys->width = width; sys->height = height; unsigned surfaces = 2; switch (sys->profile) { case VDP_DECODER_PROFILE_H264_BASELINE: case VDP_DECODER_PROFILE_H264_MAIN: case VDP_DECODER_PROFILE_H264_HIGH: surfaces = 16; break; } err = vdp_decoder_create(sys->vdp, sys->device, sys->profile, width, height, surfaces, &sys->context->decoder); if (err != VDP_STATUS_OK) { msg_Err(va, "%s creation failure: %s", "decoder", vdp_get_error_string(sys->vdp, err)); sys->context->decoder = VDP_INVALID_HANDLE; return VLC_EGENERIC; } *ctxp = sys->context; /* TODO: select better chromas when appropriate */ *chromap = VLC_CODEC_VDPAU_VIDEO_420; return VLC_SUCCESS; }
bool CVDPAU::Open(AVCodecContext* avctx, const enum PixelFormat, unsigned int surfaces) { if(avctx->width == 0 || avctx->height == 0) { CLog::Log(LOGWARNING,"(VDPAU) no width/height available, can't init"); return false; } if (!dl_handle) { dl_handle = dlopen("libvdpau.so.1", RTLD_LAZY); if (!dl_handle) { const char* error = dlerror(); if (!error) error = "dlerror() returned NULL"; CLog::Log(LOGNOTICE,"(VDPAU) Unable to get handle to libvdpau: %s", error); //g_application.m_guiDialogKaiToast.QueueNotification(CGUIDialogKaiToast::Error, "VDPAU", error, 10000); return false; } } InitVDPAUProcs(); if (vdp_device != VDP_INVALID_HANDLE) { SpewHardwareAvailable(); VdpDecoderProfile profile = 0; if(avctx->codec_id == CODEC_ID_H264) profile = VDP_DECODER_PROFILE_H264_HIGH; #ifdef VDP_DECODER_PROFILE_MPEG4_PART2_ASP else if(avctx->codec_id == CODEC_ID_MPEG4) profile = VDP_DECODER_PROFILE_MPEG4_PART2_ASP; #endif if(profile) { if (!CDVDCodecUtils::IsVP3CompatibleWidth(avctx->width)) CLog::Log(LOGWARNING,"(VDPAU) width %i might not be supported because of hardware bug", avctx->width); /* attempt to create a decoder with this width/height, some sizes are not supported by hw */ VdpStatus vdp_st; vdp_st = vdp_decoder_create(vdp_device, profile, avctx->width, avctx->height, 5, &decoder); if(vdp_st != VDP_STATUS_OK) { CLog::Log(LOGERROR, " (VDPAU) Error: %s(%d) checking for decoder support\n", vdp_get_error_string(vdp_st), vdp_st); FiniVDPAUProcs(); return false; } vdp_decoder_destroy(decoder); CheckStatus(vdp_st, __LINE__); } InitCSCMatrix(avctx->height); MakePixmap(avctx->width,avctx->height); /* finally setup ffmpeg */ avctx->get_buffer = CVDPAU::FFGetBuffer; avctx->release_buffer = CVDPAU::FFReleaseBuffer; avctx->draw_horiz_band = CVDPAU::FFDrawSlice; avctx->slice_flags=SLICE_FLAG_CODED_ORDER|SLICE_FLAG_ALLOW_FIELD; return true; } return false; }
static int vdpau_decoder_init( producer_avformat self ) { mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "vdpau_decoder_init\n" ); int success = 1; self->video_codec->opaque = self; self->video_codec->get_format = vdpau_get_format; self->video_codec->get_buffer = vdpau_get_buffer; self->video_codec->release_buffer = vdpau_release_buffer; self->video_codec->draw_horiz_band = vdpau_draw_horiz; self->video_codec->slice_flags = SLICE_FLAG_CODED_ORDER | SLICE_FLAG_ALLOW_FIELD; self->video_codec->pix_fmt = PIX_FMT_VDPAU_H264; VdpDecoderProfile profile = VDP_DECODER_PROFILE_H264_HIGH; uint32_t max_references = self->video_codec->refs; pthread_mutex_lock( &mlt_sdl_mutex ); VdpStatus status = vdp_decoder_create( self->vdpau->device, profile, self->video_codec->width, self->video_codec->height, max_references, &self->vdpau->decoder ); pthread_mutex_unlock( &mlt_sdl_mutex ); if ( status == VDP_STATUS_OK ) { int i, n = FFMIN( self->video_codec->refs + 2, MAX_VDPAU_SURFACES ); self->vdpau->deque = mlt_deque_init(); for ( i = 0; i < n; i++ ) { if ( VDP_STATUS_OK == vdp_surface_create( self->vdpau->device, VDP_CHROMA_TYPE_420, self->video_codec->width, self->video_codec->height, &self->vdpau->render_states[i].surface ) ) { mlt_log_debug( MLT_PRODUCER_SERVICE(self->parent), "successfully created VDPAU surface %x\n", self->vdpau->render_states[i].surface ); mlt_deque_push_back( self->vdpau->deque, &self->vdpau->render_states[i] ); } else { mlt_log_info( MLT_PRODUCER_SERVICE(self->parent), "failed to create VDPAU surface %dx%d\n", self->video_codec->width, self->video_codec->height ); while ( mlt_deque_count( self->vdpau->deque ) ) { struct vdpau_render_state *render = mlt_deque_pop_front( self->vdpau->deque ); vdp_surface_destroy( render->surface ); } mlt_deque_close( self->vdpau->deque ); success = 0; break; } } if ( self->vdpau ) self->vdpau->b_age = self->vdpau->ip_age[0] = self->vdpau->ip_age[1] = 256*256*256*64; // magic from Avidemux } else { success = 0; self->vdpau->decoder = VDP_INVALID_HANDLE; mlt_log_error( MLT_PRODUCER_SERVICE(self->parent), "VDPAU failed to initialize decoder (%s)\n", vdp_get_error_string( status ) ); } return success; }