forked from mia/Aegisub
add vfr handling (broken) and keyframe reading (works) to the ffmpegsource video provider
Originally committed to SVN as r2312.
This commit is contained in:
parent
1ffa0a95a1
commit
98341f62be
2 changed files with 41 additions and 20 deletions
|
@ -35,13 +35,8 @@
|
||||||
|
|
||||||
#ifdef WITH_FFMPEGSOURCE
|
#ifdef WITH_FFMPEGSOURCE
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#define EMULATE_INTTYPES
|
|
||||||
#endif /* WIN32 */
|
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
// Headers
|
// Headers
|
||||||
#include <wx/wxprec.h>
|
|
||||||
#include "video_provider_ffmpegsource.h"
|
#include "video_provider_ffmpegsource.h"
|
||||||
#include <ffms.h>
|
#include <ffms.h>
|
||||||
#include "vfr.h"
|
#include "vfr.h"
|
||||||
|
@ -121,29 +116,48 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename, double fps)
|
||||||
VideoInfo = FFMS_GetVideoProperties(VideoSource);
|
VideoInfo = FFMS_GetVideoProperties(VideoSource);
|
||||||
|
|
||||||
// get frame info data
|
// get frame info data
|
||||||
// disabled until Myrsloik answers some questions
|
FrameInfoVector *FrameData = FFMS_GetVSTrackIndex(VideoSource, FFMSErrorMessage, MessageSize);
|
||||||
#if 0
|
|
||||||
FrameInfoVector FrameData = FFMS_GetTITrackIndex(Index, -1, FFMSErrorMessage, MessageSize);
|
|
||||||
if (FrameData == NULL) {
|
if (FrameData == NULL) {
|
||||||
ErrorMsg.Printf(_T("FFmpegSource video provider: %s"), FFMSErrorMessage);
|
ErrorMsg.Printf(_T("FFmpegSource video provider: %s"), FFMSErrorMessage);
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
FrameInfo CurFrameData;
|
const TrackTimeBase *TimeBase = FFMS_GetTimeBase(FrameData, FFMSErrorMessage, MessageSize);
|
||||||
|
if (TimeBase == NULL) {
|
||||||
|
ErrorMsg.Printf(_T("FFmpegSource video provider: %s"), FFMSErrorMessage);
|
||||||
|
throw ErrorMsg;
|
||||||
|
}
|
||||||
|
|
||||||
// build list of keyframes
|
const FrameInfo *CurFrameData;
|
||||||
|
|
||||||
|
// build list of keyframes and timecodes
|
||||||
for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
|
for (int CurFrameNum = 0; CurFrameNum < VideoInfo->NumFrames; CurFrameNum++) {
|
||||||
CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum, FFMSErrorMessage, MessageSize);
|
CurFrameData = FFMS_GetFrameInfo(FrameData, CurFrameNum, FFMSErrorMessage, MessageSize);
|
||||||
if (CurFrameData == NULL) {
|
if (CurFrameData == NULL) {
|
||||||
ErrorMsg.Printf(_T("FFmpegSource video provider: %s"), FFMSErrorMessage);
|
ErrorMsg.Printf(_T("FFmpegSource video provider: %s"), FFMSErrorMessage);
|
||||||
throw ErrorMsg;
|
throw ErrorMsg;
|
||||||
}
|
}
|
||||||
if (CurFrameData.KeyFrame)
|
|
||||||
|
// keyframe?
|
||||||
|
if (CurFrameData->KeyFrame)
|
||||||
KeyFramesList.Add(CurFrameNum);
|
KeyFramesList.Add(CurFrameNum);
|
||||||
|
|
||||||
|
// calculate timestamp and add to timecodes vector
|
||||||
|
int64_t Timestamp = (int64_t)((CurFrameData->DTS * TimeBase->Num) / (double)TimeBase->Den);
|
||||||
|
// dumb to cast this to an int but the vfr functions all want it as that
|
||||||
|
TimecodesVector.push_back(int(Timestamp));
|
||||||
}
|
}
|
||||||
KeyFramesLoaded = true;
|
KeyFramesLoaded = true;
|
||||||
#endif
|
|
||||||
|
|
||||||
// TODO: VFR handling
|
// override already loaded timecodes?
|
||||||
|
Timecodes.SetVFR(TimecodesVector);
|
||||||
|
int OverrideTC = wxYES;
|
||||||
|
if (VFR_Output.IsLoaded()) {
|
||||||
|
OverrideTC = wxMessageBox(_("You already have timecodes loaded. Would you like to replace them with timecodes from the video file?"), _("Replace timecodes?"), wxYES_NO | wxICON_QUESTION);
|
||||||
|
if (OverrideTC == wxYES) {
|
||||||
|
VFR_Input.SetVFR(TimecodesVector);
|
||||||
|
VFR_Output.SetVFR(TimecodesVector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// we don't need this anymore
|
// we don't need this anymore
|
||||||
FFMS_DestroyFrameIndex(Index);
|
FFMS_DestroyFrameIndex(Index);
|
||||||
|
@ -168,6 +182,7 @@ void FFmpegSourceVideoProvider::Close() {
|
||||||
|
|
||||||
KeyFramesLoaded = false;
|
KeyFramesLoaded = false;
|
||||||
KeyFramesList.clear();
|
KeyFramesList.clear();
|
||||||
|
TimecodesVector.clear();
|
||||||
FrameNumber = -1;
|
FrameNumber = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,9 +206,10 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int n, int FormatType)
|
||||||
PixelFormat DstFormat;
|
PixelFormat DstFormat;
|
||||||
|
|
||||||
switch (FormatType) {
|
switch (FormatType) {
|
||||||
case FORMAT_RGB32: DstFormat = PIX_FMT_RGB32; break;
|
case FORMAT_RGB32: DstFormat = PIX_FMT_RGB32; break;
|
||||||
case FORMAT_RGB24: DstFormat = PIX_FMT_RGB24; break;
|
case FORMAT_RGB24: DstFormat = PIX_FMT_RGB24; break;
|
||||||
// TODO: add YV12?
|
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");
|
default: throw _T("FFmpegSource video provider: upstream provider requested unknown or unsupported pixel format");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,9 +233,12 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int n, int FormatType)
|
||||||
// set some properties
|
// set some properties
|
||||||
DstFrame.w = w;
|
DstFrame.w = w;
|
||||||
DstFrame.h = h;
|
DstFrame.h = h;
|
||||||
// only rgb supported for now
|
|
||||||
DstFrame.flipped = false;
|
DstFrame.flipped = false;
|
||||||
DstFrame.invertChannels = true;
|
if (FormatType == FORMAT_RGB32 || FormatType == FORMAT_RGB24) {
|
||||||
|
DstFrame.invertChannels = true;
|
||||||
|
} else {
|
||||||
|
DstFrame.invertChannels = false;
|
||||||
|
}
|
||||||
DstFrame.format = (VideoFrameFormat)FormatType;
|
DstFrame.format = (VideoFrameFormat)FormatType;
|
||||||
|
|
||||||
// allocate destination frame
|
// allocate destination frame
|
||||||
|
|
|
@ -63,6 +63,8 @@ private:
|
||||||
int FrameNumber;
|
int FrameNumber;
|
||||||
wxArrayInt KeyFramesList;
|
wxArrayInt KeyFramesList;
|
||||||
bool KeyFramesLoaded;
|
bool KeyFramesLoaded;
|
||||||
|
std::vector<int> TimecodesVector;
|
||||||
|
FrameRate Timecodes;
|
||||||
|
|
||||||
AVPicture FrameRGB;
|
AVPicture FrameRGB;
|
||||||
bool FrameAllocated;
|
bool FrameAllocated;
|
||||||
|
@ -91,8 +93,8 @@ public:
|
||||||
double GetFPS();
|
double GetFPS();
|
||||||
bool AreKeyFramesLoaded() { return KeyFramesLoaded; };
|
bool AreKeyFramesLoaded() { return KeyFramesLoaded; };
|
||||||
wxArrayInt GetKeyFrames() { return KeyFramesList; };
|
wxArrayInt GetKeyFrames() { return KeyFramesList; };
|
||||||
bool IsVFR() { return false; }; // FIXME: might want to talk to Myrsloik about this
|
bool IsVFR() { return true; };
|
||||||
FrameRate GetTrueFrameRate() { return FrameRate(); }; // FIXME: try to remember what this actually means
|
FrameRate GetTrueFrameRate() { return FrameRate(); };
|
||||||
Aegisub::String GetDecoderName() { return L"FFmpegSource"; }
|
Aegisub::String GetDecoderName() { return L"FFmpegSource"; }
|
||||||
bool IsNativelyByFrames() { return true; }
|
bool IsNativelyByFrames() { return true; }
|
||||||
int GetDesiredCacheSize() { return 8; }
|
int GetDesiredCacheSize() { return 8; }
|
||||||
|
|
Loading…
Reference in a new issue