From da09a52b59b73eaf82b62a5ee1215c0bdfc56d59 Mon Sep 17 00:00:00 2001 From: Rodrigo Braz Monteiro Date: Sun, 20 Jan 2008 21:15:22 +0000 Subject: [PATCH] Applied p-static's patch to use swscale with ffmpeg video provider for major speed improvement. Originally committed to SVN as r1796. --- aegisub/video_provider_lavc.cpp | 104 ++++++++++++++++---------------- configure.ac | 2 + 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/aegisub/video_provider_lavc.cpp b/aegisub/video_provider_lavc.cpp index 83a013d64..2ea5c153b 100644 --- a/aegisub/video_provider_lavc.cpp +++ b/aegisub/video_provider_lavc.cpp @@ -45,6 +45,7 @@ extern "C" { #include #include +#include } #include #include @@ -70,7 +71,11 @@ private: AVCodec *codec; AVFrame *frame; int vidStream; - + + AVFrame *frameRGB; + uint8_t *bufferRGB; + SwsContext *sws_context; + int display_w; int display_h; @@ -130,6 +135,9 @@ LAVCVideoProvider::LAVCVideoProvider(wxString filename,double fps) { codec = NULL; stream = NULL; frame = NULL; + frameRGB = NULL; + bufferRGB = NULL; + sws_context = NULL; buffer1 = NULL; buffer2 = NULL; buffer1Size = 0; @@ -237,6 +245,17 @@ void LAVCVideoProvider::Close() { if (frame) av_free((void*)frame); frame = NULL; + // Free SWS context and other stuff from RGB conversion + if (sws_context) + sws_freeContext(sws_context); + sws_context = NULL; + if(frameRGB) + av_free(frameRGB); + frameRGB = NULL; + if(bufferRGB) + delete(bufferRGB); + bufferRGB = NULL; + // Close codec context if (codec && codecContext) avcodec_close(codecContext); codecContext = NULL; @@ -429,75 +448,54 @@ const AegiVideoFrame LAVCVideoProvider::DoGetFrame(int n) { } #endif } - - // Convert to RGB32 - AVFrame *useFrame = frame; - AVFrame *frameRGB = NULL; - //if (true) { - // // Set properties - // int w = codecContext->width; - // int h = codecContext->height; - // PixelFormat convFormat = PIX_FMT_RGB24; - // unsigned int dstSize = avpicture_get_size(convFormat,w,h); - - // // Allocate RGB32 buffer - // frameRGB = avcodec_alloc_frame(); - // uint8_t *buffer = new uint8_t[dstSize]; - // avpicture_fill((AVPicture*) frameRGB, buffer, convFormat, w, h); - - // // Convert to RGB32 - // img_convert((AVPicture*) frameRGB, convFormat, (AVPicture*) frame, codecContext->pix_fmt, w, h); - // useFrame = frameRGB; - //} - + + // Get aegisub frame AegiVideoFrame &final = curFrame; + if (frame) { + int w = codecContext->width; + int h = codecContext->height; + PixelFormat srcFormat = codecContext->pix_fmt; + PixelFormat dstFormat = PIX_FMT_RGB32; + + // Allocate RGB32 buffer + if(!sws_context) //first frame + { + frameRGB = avcodec_alloc_frame(); + unsigned int dstSize = avpicture_get_size(dstFormat,w,h); + bufferRGB = new uint8_t[dstSize]; + + sws_context = sws_getContext(w, h, srcFormat, w, h, dstFormat, SWS_PRINT_INFO, NULL, NULL, NULL); + } + avpicture_fill((AVPicture*) frameRGB, bufferRGB, dstFormat, w, h); + // Set AegiVideoFrame - PixelFormat format = codecContext->pix_fmt; - unsigned int size = avpicture_get_size(format,codecContext->width,codecContext->height); final.w = codecContext->width; final.h = codecContext->height; final.flipped = false; - final.invertChannels = false; - - // Set format - switch (format) { - case PIX_FMT_BGR24: final.invertChannels = true; - case PIX_FMT_RGB24: final.format = FORMAT_RGB24; break; - #ifdef __WINDOWS__ - case PIX_FMT_BGR32: final.invertChannels = true; - #endif - case PIX_FMT_RGB32: final.format = FORMAT_RGB32; break; - case PIX_FMT_YUYV422: final.format = FORMAT_YUY2; break; - case PIX_FMT_YUV420P: final.format = FORMAT_YV12; break; - default: throw _T("ffmpeg returned an unknown frame format."); - } + final.invertChannels = true; + final.format = FORMAT_RGB32; // Allocate - for (int i=0;i<4;i++) final.pitch[i] = useFrame->linesize[i]; + for (int i=0;i<4;i++) final.pitch[i] = frameRGB->linesize[i]; final.Allocate(); - - // Copy data - if (final.format == FORMAT_YV12) { - memcpy(final.data[0],useFrame->data[0],useFrame->linesize[0] * final.h); - memcpy(final.data[1],useFrame->data[1],useFrame->linesize[1] * final.h / 2); - memcpy(final.data[2],useFrame->data[2],useFrame->linesize[2] * final.h / 2); - } - else memcpy(final.data[0],useFrame->data[0],size); + + // Convert to RGB32, and write directly to the output frame + sws_scale(sws_context, frame->data, frame->linesize, 0, h, final.data, frameRGB->linesize); + + } + else // No frame available + { + final = AegiVideoFrame(GetWidth(),GetHeight()); } - - // No frame available - else final = AegiVideoFrame(GetWidth(),GetHeight()); // Set current frame validFrame = true; - //curFrame = final; frameNumber = n; - if (frameRGB) av_free(frameRGB); // Return - return curFrame; + return final; } diff --git a/configure.ac b/configure.ac index 424d72a8d..4339576a2 100644 --- a/configure.ac +++ b/configure.ac @@ -66,6 +66,7 @@ AC_CHECK_FUNCS([Pa_GetStreamTime]) PKG_CHECK_MODULES([LIBPULSE], libpulse >= 0.5, [found_audio=yes], [with_pulseaudio=no]) AC_CHECK_LIB([avcodec], [avcodec_init],, [with_ffmpeg=no]) AC_CHECK_LIB([avformat], [av_read_frame],, [with_ffmpeg=no]) +AC_CHECK_LIB([swscale], [sws_scale],, [with_ffmpeg=no]) if test "$with_ffmpeg" != "no"; then found_video_provider=yes fi @@ -257,3 +258,4 @@ fi +