forked from mia/Aegisub
Fix ffmpegsource video provider to no longer depend on ffmpeg directly, everything is now done by API calls to the ffmpegsource DLL.
Originally committed to SVN as r2340.
This commit is contained in:
parent
d92efd1f54
commit
0026ba38ec
2 changed files with 47 additions and 64 deletions
|
@ -51,10 +51,9 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(Aegisub::String filename, d
|
|||
|
||||
// clean up variables
|
||||
VideoSource = NULL;
|
||||
SWSContext = NULL;
|
||||
BufferRGB = NULL;
|
||||
DstFormat = FFMS_PIX_FMT_NONE;
|
||||
LastDstFormat = FFMS_PIX_FMT_NONE;
|
||||
KeyFramesLoaded = false;
|
||||
FrameAllocated = false;
|
||||
FrameNumber = -1;
|
||||
MessageSize = sizeof(FFMSErrorMessage);
|
||||
|
||||
|
@ -184,19 +183,12 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
|
|||
///////////////
|
||||
// Close video
|
||||
void FFmpegSourceVideoProvider::Close() {
|
||||
if (SWSContext)
|
||||
sws_freeContext(SWSContext);
|
||||
SWSContext = NULL;
|
||||
if (VideoSource)
|
||||
FFMS_DestroyVideoSource(VideoSource);
|
||||
VideoSource = NULL;
|
||||
// this seems to cause a heap corruption in debug mode
|
||||
/* if (FrameAllocated)
|
||||
avpicture_free(&FrameRGB); */
|
||||
FrameAllocated = false;
|
||||
if (BufferRGB)
|
||||
delete BufferRGB;
|
||||
|
||||
DstFormat = FFMS_PIX_FMT_NONE;
|
||||
LastDstFormat = FFMS_PIX_FMT_NONE;
|
||||
KeyFramesLoaded = false;
|
||||
KeyFramesList.clear();
|
||||
TimecodesVector.clear();
|
||||
|
@ -228,62 +220,63 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n, int FormatType)
|
|||
n = GetFrameCount()-1;
|
||||
// set position
|
||||
FrameNumber = n;
|
||||
|
||||
// these are for convenience
|
||||
int w = VideoInfo->Width;
|
||||
int h = VideoInfo->Height;
|
||||
|
||||
// this is what we'll return eventually
|
||||
AegiVideoFrame &DstFrame = CurFrame;
|
||||
|
||||
// choose output format
|
||||
if (FormatType & FORMAT_RGB32) {
|
||||
DstFormat = FFMS_PIX_FMT_RGB32; // FIXME: should be RGB32
|
||||
DstFrame.format = FORMAT_RGB32;
|
||||
} else if (FormatType & FORMAT_RGB24) {
|
||||
DstFormat = FFMS_PIX_FMT_RGB24;
|
||||
DstFrame.format = FORMAT_RGB24;
|
||||
} else if (FormatType & FORMAT_YV12) {
|
||||
DstFormat = FFMS_PIX_FMT_YUV420P; // may or may not work
|
||||
DstFrame.format = FORMAT_YV12;
|
||||
} else if (FormatType & FORMAT_YUY2) {
|
||||
DstFormat = FFMS_PIX_FMT_YUYV422;
|
||||
DstFrame.format = FORMAT_YUY2;
|
||||
} else
|
||||
throw _T("FFmpegSource video provider: upstream provider requested unknown or unsupported pixel format");
|
||||
|
||||
// requested format was changed since last time we were called, (re)set output format
|
||||
if (LastDstFormat != DstFormat) {
|
||||
if (FFMS_SetOutputFormat(VideoSource, DstFormat, w, h))
|
||||
throw _T("FFmpegSource video provider: failed to set desired output format");
|
||||
LastDstFormat = DstFormat;
|
||||
}
|
||||
|
||||
// decode frame
|
||||
const AVFrameLite *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrorMessage, MessageSize);
|
||||
if (SrcFrame == NULL) {
|
||||
ErrorMsg.Printf(_T("FFmpegSource video provider: %s"), FFMSErrorMessage);
|
||||
throw ErrorMsg;
|
||||
}
|
||||
|
||||
AVPicture *SrcPicture = reinterpret_cast<AVPicture *>(const_cast<AVFrameLite *>(SrcFrame));
|
||||
|
||||
// prepare stuff for conversion to RGB32
|
||||
int w = VideoInfo->Width;
|
||||
int h = VideoInfo->Height;
|
||||
PixelFormat DstFormat;
|
||||
|
||||
switch (FormatType) {
|
||||
case FORMAT_RGB32: DstFormat = PIX_FMT_RGB32; break;
|
||||
case FORMAT_RGB24: DstFormat = PIX_FMT_RGB24; break;
|
||||
case FORMAT_YV12: DstFormat = PIX_FMT_YUV420P; break; // may or may not work
|
||||
case FORMAT_YUY2: DstFormat = PIX_FMT_YUYV422; break;
|
||||
default: throw _T("FFmpegSource video provider: upstream provider requested unknown or unsupported pixel format");
|
||||
}
|
||||
|
||||
if (!SWSContext) {
|
||||
if (avpicture_alloc(&FrameRGB, DstFormat, w, h) != 0)
|
||||
throw _T("FFmpegSource video provider: could not allocate output picture buffer");
|
||||
FrameAllocated = true;
|
||||
unsigned int DstSize = avpicture_get_size(DstFormat,w,h);
|
||||
BufferRGB = new uint8_t[DstSize];
|
||||
|
||||
// initialize swscaler context
|
||||
SWSContext = sws_getContext(w, h, VideoInfo->PixelFormat, w, h, DstFormat, SWS_BICUBIC, NULL, NULL, NULL);
|
||||
if (SWSContext == NULL)
|
||||
throw _T("FFmpegSource video provider: failed to initialize SWScale colorspace conversion");
|
||||
}
|
||||
avpicture_fill(&FrameRGB, BufferRGB, DstFormat, w, h);
|
||||
|
||||
// this is what we'll return eventually
|
||||
AegiVideoFrame &DstFrame = CurFrame;
|
||||
|
||||
// set some properties
|
||||
DstFrame.w = w;
|
||||
DstFrame.h = h;
|
||||
DstFrame.flipped = false;
|
||||
if (FormatType == FORMAT_RGB32 || FormatType == FORMAT_RGB24) {
|
||||
if (DstFrame.format == FORMAT_RGB32 || DstFrame.format == FORMAT_RGB24)
|
||||
DstFrame.invertChannels = true;
|
||||
} else {
|
||||
else
|
||||
DstFrame.invertChannels = false;
|
||||
}
|
||||
DstFrame.format = (VideoFrameFormat)FormatType;
|
||||
|
||||
// allocate destination frame
|
||||
for (int i=0;i<4;i++) DstFrame.pitch[i] = FrameRGB.linesize[i];
|
||||
// allocate destination
|
||||
for (int i = 0; i < 4; i++)
|
||||
DstFrame.pitch[i] = SrcFrame->Linesize[i];
|
||||
DstFrame.Allocate();
|
||||
|
||||
// let swscale do the conversion to RGB and write directly to the output frame
|
||||
sws_scale(SWSContext, SrcPicture->data, SrcPicture->linesize, 0, h, DstFrame.data, FrameRGB.linesize);
|
||||
// copy data to destination, skipping planes with no data in them
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if (SrcFrame->Linesize[j] > 0)
|
||||
memcpy(DstFrame.data[j], SrcFrame->Data[j], DstFrame.pitch[j] * DstFrame.h);
|
||||
}
|
||||
|
||||
return DstFrame;
|
||||
}
|
||||
|
|
|
@ -37,18 +37,10 @@
|
|||
// Headers
|
||||
#include <wx/wxprec.h>
|
||||
#ifdef WITH_FFMPEGSOURCE
|
||||
#ifdef WIN32
|
||||
#define EMULATE_INTTYPES
|
||||
#endif /* WIN32 */
|
||||
#include "include/aegisub/video_provider.h"
|
||||
#include "include/aegisub/aegisub.h"
|
||||
#include "dialog_progress.h"
|
||||
#include "vfr.h"
|
||||
extern "C" {
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libswscale/swscale.h>
|
||||
}
|
||||
#include <vector>
|
||||
#include <ffms.h>
|
||||
|
||||
|
@ -60,7 +52,6 @@ class FFmpegSourceVideoProvider : public VideoProvider {
|
|||
private:
|
||||
VideoBase *VideoSource;
|
||||
const VideoProperties *VideoInfo;
|
||||
SwsContext *SWSContext;
|
||||
|
||||
int FrameNumber;
|
||||
wxArrayInt KeyFramesList;
|
||||
|
@ -68,9 +59,8 @@ private:
|
|||
std::vector<int> TimecodesVector;
|
||||
FrameRate Timecodes;
|
||||
|
||||
AVPicture FrameRGB;
|
||||
bool FrameAllocated;
|
||||
uint8_t *BufferRGB;
|
||||
FFMS_PixelFormat DstFormat;
|
||||
FFMS_PixelFormat LastDstFormat;
|
||||
AegiVideoFrame CurFrame;
|
||||
|
||||
char FFMSErrorMessage[1024];
|
||||
|
|
Loading…
Reference in a new issue