Applied p-static's patch to use swscale with ffmpeg video provider for major speed improvement.

Originally committed to SVN as r1796.
This commit is contained in:
Rodrigo Braz Monteiro 2008-01-20 21:15:22 +00:00
parent 8ce9d53757
commit da09a52b59
2 changed files with 53 additions and 53 deletions

View file

@ -45,6 +45,7 @@
extern "C" { extern "C" {
#include <ffmpeg/avcodec.h> #include <ffmpeg/avcodec.h>
#include <ffmpeg/avformat.h> #include <ffmpeg/avformat.h>
#include <ffmpeg/swscale.h>
} }
#include <wx/wxprec.h> #include <wx/wxprec.h>
#include <wx/image.h> #include <wx/image.h>
@ -70,7 +71,11 @@ private:
AVCodec *codec; AVCodec *codec;
AVFrame *frame; AVFrame *frame;
int vidStream; int vidStream;
AVFrame *frameRGB;
uint8_t *bufferRGB;
SwsContext *sws_context;
int display_w; int display_w;
int display_h; int display_h;
@ -130,6 +135,9 @@ LAVCVideoProvider::LAVCVideoProvider(wxString filename,double fps) {
codec = NULL; codec = NULL;
stream = NULL; stream = NULL;
frame = NULL; frame = NULL;
frameRGB = NULL;
bufferRGB = NULL;
sws_context = NULL;
buffer1 = NULL; buffer1 = NULL;
buffer2 = NULL; buffer2 = NULL;
buffer1Size = 0; buffer1Size = 0;
@ -237,6 +245,17 @@ void LAVCVideoProvider::Close() {
if (frame) av_free((void*)frame); if (frame) av_free((void*)frame);
frame = NULL; 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 // Close codec context
if (codec && codecContext) avcodec_close(codecContext); if (codec && codecContext) avcodec_close(codecContext);
codecContext = NULL; codecContext = NULL;
@ -429,75 +448,54 @@ const AegiVideoFrame LAVCVideoProvider::DoGetFrame(int n) {
} }
#endif #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 // Get aegisub frame
AegiVideoFrame &final = curFrame; AegiVideoFrame &final = curFrame;
if (frame) { 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 // Set AegiVideoFrame
PixelFormat format = codecContext->pix_fmt;
unsigned int size = avpicture_get_size(format,codecContext->width,codecContext->height);
final.w = codecContext->width; final.w = codecContext->width;
final.h = codecContext->height; final.h = codecContext->height;
final.flipped = false; final.flipped = false;
final.invertChannels = false; final.invertChannels = true;
final.format = FORMAT_RGB32;
// 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.");
}
// Allocate // 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(); final.Allocate();
// Copy data // Convert to RGB32, and write directly to the output frame
if (final.format == FORMAT_YV12) { sws_scale(sws_context, frame->data, frame->linesize, 0, h, final.data, frameRGB->linesize);
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 // No frame available
} {
else memcpy(final.data[0],useFrame->data[0],size); final = AegiVideoFrame(GetWidth(),GetHeight());
} }
// No frame available
else final = AegiVideoFrame(GetWidth(),GetHeight());
// Set current frame // Set current frame
validFrame = true; validFrame = true;
//curFrame = final;
frameNumber = n; frameNumber = n;
if (frameRGB) av_free(frameRGB);
// Return // Return
return curFrame; return final;
} }

View file

@ -66,6 +66,7 @@ AC_CHECK_FUNCS([Pa_GetStreamTime])
PKG_CHECK_MODULES([LIBPULSE], libpulse >= 0.5, [found_audio=yes], [with_pulseaudio=no]) 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([avcodec], [avcodec_init],, [with_ffmpeg=no])
AC_CHECK_LIB([avformat], [av_read_frame],, [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 if test "$with_ffmpeg" != "no"; then
found_video_provider=yes found_video_provider=yes
fi fi
@ -257,3 +258,4 @@ fi