mirror of https://github.com/odrling/Aegisub
The Great Colorspace Reworking of '09, part 2 of ???: change all video providers to always output RGB32, and remove the formatMask parameter of GetFrame(). This may break the dshow video provider but I have no way of testing it and AFAIK nobody else does either. If someone actually uses it, they can fix it themselves. Updates #926.
Originally committed to SVN as r3185.
This commit is contained in:
parent
e7f2dc00f7
commit
d1762c5270
|
@ -52,7 +52,7 @@ public:
|
||||||
virtual ~VideoProvider() {}
|
virtual ~VideoProvider() {}
|
||||||
|
|
||||||
// Override this method to actually get frames
|
// Override this method to actually get frames
|
||||||
virtual const AegiVideoFrame GetFrame(int n, int formatMask)=0;
|
virtual const AegiVideoFrame GetFrame(int n)=0;
|
||||||
|
|
||||||
// Override the following methods to get video information:
|
// Override the following methods to get video information:
|
||||||
virtual int GetPosition()=0; // Get the number of the last frame loaded
|
virtual int GetPosition()=0; // Get the number of the last frame loaded
|
||||||
|
|
|
@ -140,7 +140,7 @@ void SubtitlesPreview::UpdateBitmap(int w,int h) {
|
||||||
// Get AegiVideoFrame
|
// Get AegiVideoFrame
|
||||||
if (!vid) vid = new DummyVideoProvider(0.0,10,w,h,backColour,true);
|
if (!vid) vid = new DummyVideoProvider(0.0,10,w,h,backColour,true);
|
||||||
AegiVideoFrame frame;
|
AegiVideoFrame frame;
|
||||||
frame.CopyFrom(vid->GetFrame(0,FORMAT_RGB32));
|
frame.CopyFrom(vid->GetFrame(0));
|
||||||
|
|
||||||
// Try to get subtitles provider
|
// Try to get subtitles provider
|
||||||
SubtitlesProvider *provider = NULL;
|
SubtitlesProvider *provider = NULL;
|
||||||
|
|
|
@ -85,7 +85,7 @@ void DVDSubtitleFormat::GetSubPictureList(std::vector<SubPicture> &pics) {
|
||||||
int w = 720;
|
int w = 720;
|
||||||
int h = 480;
|
int h = 480;
|
||||||
VideoProvider *video = new DummyVideoProvider(10,1,w,h,wxColour(255,0,0),false);
|
VideoProvider *video = new DummyVideoProvider(10,1,w,h,wxColour(255,0,0),false);
|
||||||
AegiVideoFrame srcFrame = video->GetFrame(0,FORMAT_RGB32);
|
AegiVideoFrame srcFrame = video->GetFrame(0);
|
||||||
delete video;
|
delete video;
|
||||||
|
|
||||||
// Count and index lines
|
// Count and index lines
|
||||||
|
|
|
@ -492,11 +492,8 @@ AegiVideoFrame VideoContext::GetFrame(int n,bool raw) {
|
||||||
// Current frame if -1
|
// Current frame if -1
|
||||||
if (n == -1) n = frame_n;
|
if (n == -1) n = frame_n;
|
||||||
|
|
||||||
// Get available formats
|
|
||||||
int formats = FORMAT_RGB32;
|
|
||||||
|
|
||||||
// Get frame
|
// Get frame
|
||||||
AegiVideoFrame frame = provider->GetFrame(n,formats);
|
AegiVideoFrame frame = provider->GetFrame(n);
|
||||||
|
|
||||||
// Raster subtitles if available/necessary
|
// Raster subtitles if available/necessary
|
||||||
if (!raw && subsProvider) {
|
if (!raw && subsProvider) {
|
||||||
|
@ -532,18 +529,9 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
|
||||||
if (glGetError() != 0) throw _T("Error enabling texture.");
|
if (glGetError() != 0) throw _T("Error enabling texture.");
|
||||||
|
|
||||||
// Image type
|
// Image type
|
||||||
GLenum format = GL_LUMINANCE;
|
GLenum format;
|
||||||
if (frame.format == FORMAT_RGB32) {
|
|
||||||
if (frame.invertChannels) format = GL_BGRA_EXT;
|
if (frame.invertChannels) format = GL_BGRA_EXT;
|
||||||
else format = GL_RGBA;
|
else format = GL_RGBA;
|
||||||
}
|
|
||||||
else if (frame.format == FORMAT_RGB24) {
|
|
||||||
if (frame.invertChannels) format = GL_BGR_EXT;
|
|
||||||
else format = GL_RGB;
|
|
||||||
}
|
|
||||||
else if (frame.format == FORMAT_YV12) {
|
|
||||||
format = GL_LUMINANCE;
|
|
||||||
}
|
|
||||||
isInverted = frame.flipped;
|
isInverted = frame.flipped;
|
||||||
|
|
||||||
if (lastTex == 0) {
|
if (lastTex == 0) {
|
||||||
|
@ -569,7 +557,6 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
|
||||||
|
|
||||||
// Allocate texture
|
// Allocate texture
|
||||||
int height = frame.h;
|
int height = frame.h;
|
||||||
if (frame.format == FORMAT_YV12) height = height * 3 / 2;
|
|
||||||
int tw = SmallestPowerOf2(MAX(frame.pitch[0]/frame.GetBpp(0),frame.pitch[1]+frame.pitch[2]));
|
int tw = SmallestPowerOf2(MAX(frame.pitch[0]/frame.GetBpp(0),frame.pitch[1]+frame.pitch[2]));
|
||||||
int th = SmallestPowerOf2(height);
|
int th = SmallestPowerOf2(height);
|
||||||
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,tw,th,0,format,GL_UNSIGNED_BYTE,NULL);
|
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,tw,th,0,format,GL_UNSIGNED_BYTE,NULL);
|
||||||
|
@ -599,20 +586,6 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
|
||||||
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,frame.pitch[0]/frame.GetBpp(0),frame.h,format,GL_UNSIGNED_BYTE,frame.data[0]);
|
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,frame.pitch[0]/frame.GetBpp(0),frame.h,format,GL_UNSIGNED_BYTE,frame.data[0]);
|
||||||
if (glGetError() != 0) throw _T("Error uploading primary plane");
|
if (glGetError() != 0) throw _T("Error uploading primary plane");
|
||||||
|
|
||||||
// UV planes for YV12
|
|
||||||
if (frame.format == FORMAT_YV12) {
|
|
||||||
int u = 1;
|
|
||||||
int v = 2;
|
|
||||||
if (frame.invertChannels) {
|
|
||||||
u = 2;
|
|
||||||
v = 1;
|
|
||||||
}
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D,0,0,frame.h,frame.pitch[1],frame.h/2,format,GL_UNSIGNED_BYTE,frame.data[u]);
|
|
||||||
if (glGetError() != 0) throw _T("Error uploading U plane.");
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D,0,frame.pitch[1],frame.h,frame.pitch[2],frame.h/2,format,GL_UNSIGNED_BYTE,frame.data[v]);
|
|
||||||
if (glGetError() != 0) throw _T("Error uploadinv V plane.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return texture number
|
// Return texture number
|
||||||
return lastTex;
|
return lastTex;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,12 +40,16 @@
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
// Video Frame format
|
// Video Frame format
|
||||||
|
// All formats use 8 bits per sample.
|
||||||
enum VideoFrameFormat {
|
enum VideoFrameFormat {
|
||||||
FORMAT_NONE = 0,
|
FORMAT_NONE = 0x0000,
|
||||||
FORMAT_RGB24 = 1,
|
FORMAT_RGB24 = 0x0001, // RGB, interleaved
|
||||||
FORMAT_RGB32 = 2,
|
FORMAT_RGB32 = 0x0002, // RGBA, interleaved
|
||||||
FORMAT_YUY2 = 4,
|
FORMAT_YUY2 = 0x0004, // YCbCr 4:2:2, planar
|
||||||
FORMAT_YV12 = 8
|
FORMAT_YV12 = 0x0008, // YCbCr 4:2:0, planar
|
||||||
|
FORMAT_YUV444 = 0x0010, // YCbCr 4:4:4, planar
|
||||||
|
FORMAT_YUV444A = 0x0020, // YCbCr 4:4:4 plus alpha, planar
|
||||||
|
FORMAT_YUVMONO = 0x0040, // Y only (greyscale)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,13 +62,13 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
unsigned char *data[4]; // Pointers to the data planes. Interleaved formats only use data[0]
|
unsigned char *data[4]; // Pointers to the data planes. Interleaved formats only use data[0]
|
||||||
VideoFrameFormat format; // Data format, one of FORMAT_RGB24, FORMAT_RGB32, FORMAT_YUY2 and FORMAT_YV12
|
VideoFrameFormat format; // Data format
|
||||||
unsigned int w; // Width in pixels
|
unsigned int w; // Width in pixels
|
||||||
unsigned int h; // Height in pixels
|
unsigned int h; // Height in pixels
|
||||||
unsigned int pitch[4]; // Pitch, that is, the number of bytes used by each row.
|
unsigned int pitch[4]; // Pitch, that is, the number of bytes used by each row.
|
||||||
|
|
||||||
bool flipped; // First row is actually the bottom one
|
bool flipped; // First row is actually the bottom one
|
||||||
bool invertChannels; // Invert Red and Blue channels or U and V planes
|
bool invertChannels; // Swap Red and Blue channels or U and V planes (controls RGB versus BGR ordering etc)
|
||||||
bool cppAlloc; // Allocated with C++'s "new" operator, instead of "malloc"
|
bool cppAlloc; // Allocated with C++'s "new" operator, instead of "malloc"
|
||||||
|
|
||||||
AegiVideoFrame();
|
AegiVideoFrame();
|
||||||
|
|
|
@ -341,7 +341,7 @@ PClip AvisynthVideoProvider::OpenVideo(Aegisub::String _filename, bool mpeg2dec3
|
||||||
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// Actually get a frame
|
// Actually get a frame
|
||||||
const AegiVideoFrame AvisynthVideoProvider::GetFrame(int _n,int formatMask) {
|
const AegiVideoFrame AvisynthVideoProvider::GetFrame(int _n) {
|
||||||
// Transform n if overriden
|
// Transform n if overriden
|
||||||
int n = _n;
|
int n = _n;
|
||||||
if (frameTime.Count()) {
|
if (frameTime.Count()) {
|
||||||
|
@ -365,25 +365,12 @@ const AegiVideoFrame AvisynthVideoProvider::GetFrame(int _n,int formatMask) {
|
||||||
final.invertChannels = false;
|
final.invertChannels = false;
|
||||||
|
|
||||||
// Format
|
// Format
|
||||||
if (vi.IsRGB32()) {
|
|
||||||
final.format = FORMAT_RGB32;
|
final.format = FORMAT_RGB32;
|
||||||
final.flipped = true;
|
final.flipped = true;
|
||||||
final.invertChannels = true;
|
final.invertChannels = true;
|
||||||
}
|
|
||||||
else if (vi.IsRGB24()) {
|
|
||||||
final.format = FORMAT_RGB24;
|
|
||||||
final.flipped = true;
|
|
||||||
final.invertChannels = true;
|
|
||||||
}
|
|
||||||
else if (vi.IsYV12()) final.format = FORMAT_YV12;
|
|
||||||
else if (vi.IsYUY2()) final.format = FORMAT_YUY2;
|
|
||||||
|
|
||||||
// Set size properties
|
// Set size properties
|
||||||
int uvpitch = 0;
|
|
||||||
if (final.format == FORMAT_YV12) uvpitch = frame->GetPitch(PLANAR_U);
|
|
||||||
final.pitch[0] = frame->GetPitch();
|
final.pitch[0] = frame->GetPitch();
|
||||||
final.pitch[1] = uvpitch;
|
|
||||||
final.pitch[2] = uvpitch;
|
|
||||||
final.w = frame->GetRowSize() / Bpp;
|
final.w = frame->GetRowSize() / Bpp;
|
||||||
final.h = frame->GetHeight();
|
final.h = frame->GetHeight();
|
||||||
|
|
||||||
|
@ -393,13 +380,6 @@ const AegiVideoFrame AvisynthVideoProvider::GetFrame(int _n,int formatMask) {
|
||||||
// Copy
|
// Copy
|
||||||
memcpy(final.data[0],frame->GetReadPtr(),final.pitch[0] * final.h);
|
memcpy(final.data[0],frame->GetReadPtr(),final.pitch[0] * final.h);
|
||||||
|
|
||||||
// Copy second and third planes for YV12
|
|
||||||
if (final.format == FORMAT_YV12) {
|
|
||||||
int uvh = frame->GetHeight(PLANAR_U);
|
|
||||||
memcpy(final.data[1],frame->GetReadPtr(PLANAR_U),uvpitch * uvh);
|
|
||||||
memcpy(final.data[2],frame->GetReadPtr(PLANAR_V),uvpitch * uvh);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set last number
|
// Set last number
|
||||||
last_fnum = n;
|
last_fnum = n;
|
||||||
return final;
|
return final;
|
||||||
|
|
|
@ -73,7 +73,7 @@ public:
|
||||||
AvisynthVideoProvider(Aegisub::String _filename);
|
AvisynthVideoProvider(Aegisub::String _filename);
|
||||||
~AvisynthVideoProvider();
|
~AvisynthVideoProvider();
|
||||||
|
|
||||||
const AegiVideoFrame GetFrame(int n,int formatMask);
|
const AegiVideoFrame GetFrame(int n);
|
||||||
void GetFloatFrame(float* Buffer, int n);
|
void GetFloatFrame(float* Buffer, int n);
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
|
|
|
@ -55,13 +55,12 @@ VideoProviderCache::VideoProviderCache(VideoProvider *parent) {
|
||||||
VideoProviderCache::~VideoProviderCache() {
|
VideoProviderCache::~VideoProviderCache() {
|
||||||
delete master;
|
delete master;
|
||||||
ClearCache();
|
ClearCache();
|
||||||
tempRGBFrame.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
// Get frame
|
// Get frame
|
||||||
const AegiVideoFrame VideoProviderCache::GetFrame(int n,int format) {
|
const AegiVideoFrame VideoProviderCache::GetFrame(int n) {
|
||||||
// See if frame is cached
|
// See if frame is cached
|
||||||
CachedFrame cached;
|
CachedFrame cached;
|
||||||
for (std::list<CachedFrame>::iterator cur=cache.begin();cur!=cache.end();cur++) {
|
for (std::list<CachedFrame>::iterator cur=cache.begin();cur!=cache.end();cur++) {
|
||||||
|
@ -74,20 +73,9 @@ const AegiVideoFrame VideoProviderCache::GetFrame(int n,int format) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not cached, retrieve it
|
// Not cached, retrieve it
|
||||||
const AegiVideoFrame frame = master->GetFrame(n, format);
|
const AegiVideoFrame frame = master->GetFrame(n);
|
||||||
const AegiVideoFrame *srcFrame = &frame;
|
const AegiVideoFrame *srcFrame = &frame;
|
||||||
|
|
||||||
// Convert to compatible format
|
|
||||||
if (!(frame.format & format)) {
|
|
||||||
if (format & FORMAT_RGB32) tempRGBFrame.format = FORMAT_RGB32;
|
|
||||||
else throw _T("Unable to negotiate video frame format.");
|
|
||||||
tempRGBFrame.w = frame.w;
|
|
||||||
tempRGBFrame.h = frame.h;
|
|
||||||
tempRGBFrame.pitch[0] = frame.w * 4;
|
|
||||||
tempRGBFrame.ConvertFrom(frame);
|
|
||||||
srcFrame = &tempRGBFrame;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache frame
|
// Cache frame
|
||||||
pos = n;
|
pos = n;
|
||||||
Cache(n,*srcFrame);
|
Cache(n,*srcFrame);
|
||||||
|
@ -98,7 +86,7 @@ const AegiVideoFrame VideoProviderCache::GetFrame(int n,int format) {
|
||||||
////////////////
|
////////////////
|
||||||
// Get as float
|
// Get as float
|
||||||
void VideoProviderCache::GetFloatFrame(float* buffer, int n) {
|
void VideoProviderCache::GetFloatFrame(float* buffer, int n) {
|
||||||
const AegiVideoFrame frame = GetFrame(n,FORMAT_RGB32);
|
const AegiVideoFrame frame = GetFrame(n);
|
||||||
frame.GetFloat(buffer);
|
frame.GetFloat(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,6 @@ private:
|
||||||
VideoProvider *master;
|
VideoProvider *master;
|
||||||
unsigned int cacheMax;
|
unsigned int cacheMax;
|
||||||
std::list<CachedFrame> cache;
|
std::list<CachedFrame> cache;
|
||||||
AegiVideoFrame tempRGBFrame;
|
|
||||||
int pos;
|
int pos;
|
||||||
|
|
||||||
void Cache(int n,const AegiVideoFrame frame);
|
void Cache(int n,const AegiVideoFrame frame);
|
||||||
|
@ -74,7 +73,7 @@ protected:
|
||||||
public:
|
public:
|
||||||
// Base methods
|
// Base methods
|
||||||
void GetFloatFrame(float* Buffer, int n); // Get frame as float
|
void GetFloatFrame(float* Buffer, int n); // Get frame as float
|
||||||
const AegiVideoFrame GetFrame(int n, int formatMask);
|
const AegiVideoFrame GetFrame(int n);
|
||||||
VideoProviderCache(VideoProvider *master);
|
VideoProviderCache(VideoProvider *master);
|
||||||
virtual ~VideoProviderCache();
|
virtual ~VideoProviderCache();
|
||||||
|
|
||||||
|
|
|
@ -271,14 +271,6 @@ HRESULT DirectShowVideoProvider::OpenVideo(wxString _filename) {
|
||||||
// Get video duration
|
// Get video duration
|
||||||
if (FAILED(hr = ms->GetDuration(&duration))) return hr;
|
if (FAILED(hr = ms->GetDuration(&duration))) return hr;
|
||||||
|
|
||||||
// Set pixel type
|
|
||||||
//switch (type) {
|
|
||||||
// case IVS_RGB32: m_vi.pixel_type = VideoInfo::CS_BGR32; break;
|
|
||||||
// case IVS_YUY2: m_vi.pixel_type = VideoInfo::CS_YUY2; break;
|
|
||||||
// case IVS_YV12: m_vi.pixel_type = VideoInfo::CS_YV12; break;
|
|
||||||
// default: return E_FAIL;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Set FPS and frame duration
|
// Set FPS and frame duration
|
||||||
if (defd == 0) defd = 417083;
|
if (defd == 0) defd = 417083;
|
||||||
if (fps != 0.0) defd = int64_t (10000000.0 / fps) + 1;
|
if (fps != 0.0) defd = int64_t (10000000.0 / fps) + 1;
|
||||||
|
@ -398,21 +390,11 @@ void DirectShowVideoProvider::ReadFrame(int64_t timestamp, unsigned format, unsi
|
||||||
df->frame.w = width;
|
df->frame.w = width;
|
||||||
df->frame.h = height;
|
df->frame.h = height;
|
||||||
df->frame.pitch[0] = stride;
|
df->frame.pitch[0] = stride;
|
||||||
if (format == IVS_YV12) {
|
|
||||||
df->frame.pitch[1] = stride/2;
|
|
||||||
df->frame.pitch[2] = stride/2;
|
|
||||||
}
|
|
||||||
df->frame.cppAlloc = false;
|
df->frame.cppAlloc = false;
|
||||||
df->frame.invertChannels = true;
|
df->frame.invertChannels = true;
|
||||||
|
|
||||||
// Set format
|
// Set format
|
||||||
if (format == IVS_RGB24) df->frame.format = FORMAT_RGB24;
|
df->frame.format = FORMAT_RGB32;
|
||||||
else if (format == IVS_RGB32) df->frame.format = FORMAT_RGB32;
|
|
||||||
else if (format == IVS_YV12) {
|
|
||||||
df->frame.format = FORMAT_YV12;
|
|
||||||
df->frame.invertChannels = true;
|
|
||||||
}
|
|
||||||
else if (format == IVS_YUY2) df->frame.format = FORMAT_YUY2;
|
|
||||||
|
|
||||||
// Allocate and copy data
|
// Allocate and copy data
|
||||||
df->frame.Allocate();
|
df->frame.Allocate();
|
||||||
|
@ -473,7 +455,7 @@ int DirectShowVideoProvider::NextFrame(DF &df,int &_fn) {
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
// Get frame
|
// Get frame
|
||||||
const AegiVideoFrame DirectShowVideoProvider::GetFrame(int n,int formatMask) {
|
const AegiVideoFrame DirectShowVideoProvider::GetFrame(int n) {
|
||||||
// Normalize frame number
|
// Normalize frame number
|
||||||
if (n >= (signed) num_frames) n = num_frames-1;
|
if (n >= (signed) num_frames) n = num_frames-1;
|
||||||
if (n < 0) n = 0;
|
if (n < 0) n = 0;
|
||||||
|
|
|
@ -110,7 +110,7 @@ public:
|
||||||
|
|
||||||
void RefreshSubtitles();
|
void RefreshSubtitles();
|
||||||
|
|
||||||
const AegiVideoFrame GetFrame(int n, int formatMask);
|
const AegiVideoFrame GetFrame(int n);
|
||||||
void GetFloatFrame(float* Buffer, int n);
|
void GetFloatFrame(float* Buffer, int n);
|
||||||
|
|
||||||
int GetPosition() { return last_fnum; };
|
int GetPosition() { return last_fnum; };
|
||||||
|
|
|
@ -206,7 +206,7 @@ wxString DummyVideoProvider::MakeFilename(double fps, int frames, int _width, in
|
||||||
|
|
||||||
/////////////
|
/////////////
|
||||||
// Get frame
|
// Get frame
|
||||||
const AegiVideoFrame DummyVideoProvider::GetFrame(int n,int formatMask) {
|
const AegiVideoFrame DummyVideoProvider::GetFrame(int n) {
|
||||||
lastFrame = n;
|
lastFrame = n;
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
DummyVideoProvider(double fps, int frames, int _width, int _height, const wxColour &colour, bool pattern);
|
DummyVideoProvider(double fps, int frames, int _width, int _height, const wxColour &colour, bool pattern);
|
||||||
~DummyVideoProvider();
|
~DummyVideoProvider();
|
||||||
|
|
||||||
const AegiVideoFrame GetFrame(int n, int formatMask);
|
const AegiVideoFrame GetFrame(int n);
|
||||||
static wxString MakeFilename(double fps, int frames, int _width, int _height, const wxColour &colour, bool pattern);
|
static wxString MakeFilename(double fps, int frames, int _width, int _height, const wxColour &colour, bool pattern);
|
||||||
|
|
||||||
int GetPosition();
|
int GetPosition();
|
||||||
|
|
|
@ -70,8 +70,6 @@ FFmpegSourceVideoProvider::FFmpegSourceVideoProvider(Aegisub::String filename) {
|
||||||
|
|
||||||
// clean up variables
|
// clean up variables
|
||||||
VideoSource = NULL;
|
VideoSource = NULL;
|
||||||
DstFormat = FFMS_GetPixFmt("none");
|
|
||||||
LastDstFormat = FFMS_GetPixFmt("none");
|
|
||||||
KeyFramesLoaded = false;
|
KeyFramesLoaded = false;
|
||||||
FrameNumber = -1;
|
FrameNumber = -1;
|
||||||
MsgSize = sizeof(FFMSErrMsg);
|
MsgSize = sizeof(FFMSErrMsg);
|
||||||
|
@ -217,6 +215,11 @@ void FFmpegSourceVideoProvider::LoadVideo(Aegisub::String filename) {
|
||||||
// load video properties
|
// load video properties
|
||||||
VideoInfo = FFMS_GetVideoProperties(VideoSource);
|
VideoInfo = FFMS_GetVideoProperties(VideoSource);
|
||||||
|
|
||||||
|
if (FFMS_SetOutputFormatV(VideoSource, 1 << FFMS_GetPixFmt("bgra"), VideoInfo->Width, VideoInfo->Height, FFMS_RESIZER_BICUBIC, FFMSErrMsg, MsgSize)) {
|
||||||
|
ErrorMsg.Append(wxString::Format(_T("Failed to set output format: %s"), FFMSErrMsg));
|
||||||
|
throw ErrorMsg;
|
||||||
|
}
|
||||||
|
|
||||||
// get frame info data
|
// get frame info data
|
||||||
FFTrack *FrameData = FFMS_GetTrackFromVideo(VideoSource);
|
FFTrack *FrameData = FFMS_GetTrackFromVideo(VideoSource);
|
||||||
if (FrameData == NULL)
|
if (FrameData == NULL)
|
||||||
|
@ -268,8 +271,6 @@ void FFmpegSourceVideoProvider::Close() {
|
||||||
FFMS_DestroyVideoSource(VideoSource);
|
FFMS_DestroyVideoSource(VideoSource);
|
||||||
VideoSource = NULL;
|
VideoSource = NULL;
|
||||||
|
|
||||||
DstFormat = FFMS_GetPixFmt("none");
|
|
||||||
LastDstFormat = FFMS_GetPixFmt("none");
|
|
||||||
KeyFramesLoaded = false;
|
KeyFramesLoaded = false;
|
||||||
KeyFramesList.clear();
|
KeyFramesList.clear();
|
||||||
TimecodesVector.clear();
|
TimecodesVector.clear();
|
||||||
|
@ -280,7 +281,7 @@ void FFmpegSourceVideoProvider::Close() {
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
// Get frame
|
// Get frame
|
||||||
const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n, int FormatType) {
|
const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n) {
|
||||||
// don't try to seek to insane places
|
// don't try to seek to insane places
|
||||||
int n = _n;
|
int n = _n;
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
|
@ -297,31 +298,6 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n, int FormatType)
|
||||||
// this is what we'll return eventually
|
// this is what we'll return eventually
|
||||||
AegiVideoFrame &DstFrame = CurFrame;
|
AegiVideoFrame &DstFrame = CurFrame;
|
||||||
|
|
||||||
// choose output format
|
|
||||||
if (FormatType & FORMAT_RGB32) {
|
|
||||||
DstFormat = FFMS_GetPixFmt("bgra");
|
|
||||||
DstFrame.format = FORMAT_RGB32;
|
|
||||||
} else if (FormatType & FORMAT_RGB24) {
|
|
||||||
DstFormat = FFMS_GetPixFmt("bgr24");
|
|
||||||
DstFrame.format = FORMAT_RGB24;
|
|
||||||
} else if (FormatType & FORMAT_YV12) {
|
|
||||||
DstFormat = FFMS_GetPixFmt("yuv420p");
|
|
||||||
DstFrame.format = FORMAT_YV12;
|
|
||||||
} else if (FormatType & FORMAT_YUY2) {
|
|
||||||
DstFormat = FFMS_GetPixFmt("yuyv422"); // may or may not work
|
|
||||||
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_SetOutputFormatV(VideoSource, 1 << DstFormat, w, h, FFMS_RESIZER_BICUBIC, FFMSErrMsg, MsgSize)) {
|
|
||||||
ErrorMsg.Append(wxString::Format(_T("Failed to set output format: %s"), FFMSErrMsg));
|
|
||||||
throw ErrorMsg;
|
|
||||||
}
|
|
||||||
LastDstFormat = DstFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// decode frame
|
// decode frame
|
||||||
const FFAVFrame *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrMsg, MsgSize);
|
const FFAVFrame *SrcFrame = FFMS_GetFrame(VideoSource, n, FFMSErrMsg, MsgSize);
|
||||||
if (SrcFrame == NULL) {
|
if (SrcFrame == NULL) {
|
||||||
|
@ -330,13 +306,11 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n, int FormatType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// set some properties
|
// set some properties
|
||||||
DstFrame.w = w;
|
DstFrame.format = FORMAT_RGB32;
|
||||||
DstFrame.h = h;
|
DstFrame.w = VideoInfo->Width;
|
||||||
|
DstFrame.h = VideoInfo->Height;
|
||||||
DstFrame.flipped = false;
|
DstFrame.flipped = false;
|
||||||
if (DstFrame.format == FORMAT_RGB32 || DstFrame.format == FORMAT_RGB24)
|
|
||||||
DstFrame.invertChannels = true;
|
DstFrame.invertChannels = true;
|
||||||
else
|
|
||||||
DstFrame.invertChannels = false;
|
|
||||||
|
|
||||||
// allocate destination
|
// allocate destination
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
|
@ -345,13 +319,6 @@ const AegiVideoFrame FFmpegSourceVideoProvider::GetFrame(int _n, int FormatType)
|
||||||
|
|
||||||
// copy data to destination
|
// copy data to destination
|
||||||
memcpy(DstFrame.data[0], SrcFrame->Data[0], DstFrame.pitch[0] * DstFrame.h);
|
memcpy(DstFrame.data[0], SrcFrame->Data[0], DstFrame.pitch[0] * DstFrame.h);
|
||||||
// if we're dealing with YUV formats we need to copy the U and V planes as well
|
|
||||||
if (DstFrame.format == FORMAT_YUY2 || DstFrame.format == FORMAT_YV12) {
|
|
||||||
// YV12 has half the vertical U/V resolution too because of the subsampling
|
|
||||||
int UVHeight = DstFrame.format == FORMAT_YUY2 ? DstFrame.h : DstFrame.h / 2;
|
|
||||||
memcpy(DstFrame.data[1], SrcFrame->Data[1], DstFrame.pitch[1] * UVHeight);
|
|
||||||
memcpy(DstFrame.data[2], SrcFrame->Data[2], DstFrame.pitch[2] * UVHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
return DstFrame;
|
return DstFrame;
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,8 +56,6 @@ private:
|
||||||
std::vector<int> TimecodesVector;
|
std::vector<int> TimecodesVector;
|
||||||
FrameRate Timecodes;
|
FrameRate Timecodes;
|
||||||
|
|
||||||
int DstFormat;
|
|
||||||
int LastDstFormat;
|
|
||||||
AegiVideoFrame CurFrame;
|
AegiVideoFrame CurFrame;
|
||||||
|
|
||||||
char FFMSErrMsg[1024];
|
char FFMSErrMsg[1024];
|
||||||
|
@ -75,7 +73,7 @@ public:
|
||||||
FFmpegSourceVideoProvider(Aegisub::String filename);
|
FFmpegSourceVideoProvider(Aegisub::String filename);
|
||||||
~FFmpegSourceVideoProvider();
|
~FFmpegSourceVideoProvider();
|
||||||
|
|
||||||
const AegiVideoFrame GetFrame(int n, int formatType);
|
const AegiVideoFrame GetFrame(int n);
|
||||||
int GetPosition();
|
int GetPosition();
|
||||||
int GetFrameCount();
|
int GetFrameCount();
|
||||||
|
|
||||||
|
|
|
@ -346,7 +346,7 @@ int YUV4MPEGVideoProvider::IndexFile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n, int desired_fmts) {
|
const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n) {
|
||||||
// don't try to seek to insane places
|
// don't try to seek to insane places
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
n = 0;
|
n = 0;
|
||||||
|
@ -356,40 +356,20 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n, int desired_fmts) {
|
||||||
cur_fn = n;
|
cur_fn = n;
|
||||||
|
|
||||||
VideoFrameFormat src_fmt, dst_fmt;
|
VideoFrameFormat src_fmt, dst_fmt;
|
||||||
|
dst_fmt = FORMAT_RGB32;
|
||||||
|
int uv_width, uv_height;
|
||||||
switch (pixfmt) {
|
switch (pixfmt) {
|
||||||
case Y4M_PIXFMT_420JPEG:
|
case Y4M_PIXFMT_420JPEG:
|
||||||
case Y4M_PIXFMT_420MPEG2:
|
case Y4M_PIXFMT_420MPEG2:
|
||||||
case Y4M_PIXFMT_420PALDV:
|
case Y4M_PIXFMT_420PALDV:
|
||||||
src_fmt = FORMAT_YV12; break;
|
src_fmt = FORMAT_YV12; uv_width = w / 2; uv_height = h / 2; break;
|
||||||
case Y4M_PIXFMT_422:
|
case Y4M_PIXFMT_422:
|
||||||
src_fmt = FORMAT_YUY2; break;
|
src_fmt = FORMAT_YUY2; uv_width = w / 2; uv_height = h; break;
|
||||||
// TODO: add support for more pixel formats
|
// TODO: add support for more pixel formats
|
||||||
default:
|
default:
|
||||||
throw wxString(_T("YUV4MPEG video provider: GetFrame: Unsupported source colorspace"));
|
throw wxString(_T("YUV4MPEG video provider: GetFrame: Unsupported source colorspace"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: fix this terrible piece of crap and implement colorspace conversions
|
|
||||||
// (write a function to select best output format)
|
|
||||||
if ((desired_fmts & FORMAT_YV12) && src_fmt == FORMAT_YV12)
|
|
||||||
dst_fmt = FORMAT_YV12;
|
|
||||||
else if ((desired_fmts & FORMAT_YUY2) && src_fmt == FORMAT_YUY2)
|
|
||||||
dst_fmt = FORMAT_YUY2;
|
|
||||||
else if ((desired_fmts & FORMAT_RGB32) && src_fmt == FORMAT_YV12)
|
|
||||||
dst_fmt = FORMAT_RGB32;
|
|
||||||
else
|
|
||||||
throw wxString(_T("YUV4MPEG video provider: GetFrame: Upstream video provider requested unknown or unsupported color format"));
|
|
||||||
|
|
||||||
int uv_width, uv_height;
|
|
||||||
// TODO: ugh, fix this
|
|
||||||
switch (src_fmt) {
|
|
||||||
case FORMAT_YV12:
|
|
||||||
uv_width = w / 2; uv_height = h / 2; break;
|
|
||||||
case FORMAT_YUY2:
|
|
||||||
uv_width = w / 2; uv_height = h; break;
|
|
||||||
default:
|
|
||||||
throw wxString(_T("YUV4MPEG video provider: GetFrame: sanity check failed"));
|
|
||||||
}
|
|
||||||
|
|
||||||
AegiVideoFrame tmp_frame;
|
AegiVideoFrame tmp_frame;
|
||||||
|
|
||||||
tmp_frame.format = src_fmt;
|
tmp_frame.format = src_fmt;
|
||||||
|
@ -415,13 +395,9 @@ const AegiVideoFrame YUV4MPEGVideoProvider::GetFrame(int n, int desired_fmts) {
|
||||||
dst_frame.format = dst_fmt;
|
dst_frame.format = dst_fmt;
|
||||||
dst_frame.w = w;
|
dst_frame.w = w;
|
||||||
dst_frame.h = h;
|
dst_frame.h = h;
|
||||||
if (dst_fmt == FORMAT_RGB32) {
|
|
||||||
dst_frame.invertChannels = true;
|
dst_frame.invertChannels = true;
|
||||||
dst_frame.pitch[0] = w * 4;
|
dst_frame.pitch[0] = w * 4;
|
||||||
dst_frame.ConvertFrom(tmp_frame);
|
dst_frame.ConvertFrom(tmp_frame);
|
||||||
}
|
|
||||||
else
|
|
||||||
dst_frame.CopyFrom(tmp_frame);
|
|
||||||
|
|
||||||
tmp_frame.Clear();
|
tmp_frame.Clear();
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ public:
|
||||||
YUV4MPEGVideoProvider(Aegisub::String filename);
|
YUV4MPEGVideoProvider(Aegisub::String filename);
|
||||||
~YUV4MPEGVideoProvider();
|
~YUV4MPEGVideoProvider();
|
||||||
|
|
||||||
const AegiVideoFrame GetFrame(int n, int formatType);
|
const AegiVideoFrame GetFrame(int n);
|
||||||
int GetPosition();
|
int GetPosition();
|
||||||
int GetFrameCount();
|
int GetFrameCount();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue