mirror of https://github.com/odrling/Aegisub
LAVC video provider can now somewhat decode frames
Originally committed to SVN as r143.
This commit is contained in:
parent
00e7b923ea
commit
40341df934
|
@ -49,6 +49,9 @@ LAVCVideoProvider::LAVCVideoProvider(wxString filename, wxString subfilename, do
|
||||||
formatContext = NULL;
|
formatContext = NULL;
|
||||||
codec = NULL;
|
codec = NULL;
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
|
frame = NULL;
|
||||||
|
buffer = NULL;
|
||||||
|
bufferSize = 0;
|
||||||
vidStream = -1;
|
vidStream = -1;
|
||||||
|
|
||||||
// Register types
|
// Register types
|
||||||
|
@ -113,6 +116,9 @@ void LAVCVideoProvider::LoadVideo(wxString filename) {
|
||||||
// Open codec
|
// Open codec
|
||||||
result = avcodec_open(codecContext,codec);
|
result = avcodec_open(codecContext,codec);
|
||||||
if (result < 0) throw _T("Failed to open video decoder");
|
if (result < 0) throw _T("Failed to open video decoder");
|
||||||
|
|
||||||
|
// Allocate frame
|
||||||
|
frame = avcodec_alloc_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catch errors
|
// Catch errors
|
||||||
|
@ -126,8 +132,17 @@ void LAVCVideoProvider::LoadVideo(wxString filename) {
|
||||||
///////////////
|
///////////////
|
||||||
// Close video
|
// Close video
|
||||||
void LAVCVideoProvider::Close() {
|
void LAVCVideoProvider::Close() {
|
||||||
|
// Clean buffer
|
||||||
|
if (buffer) delete buffer;
|
||||||
|
buffer = NULL;
|
||||||
|
bufferSize = 0;
|
||||||
|
|
||||||
|
// Clean frame
|
||||||
|
if (frame) av_free(frame);
|
||||||
|
frame = NULL;
|
||||||
|
|
||||||
// Close codec context
|
// Close codec context
|
||||||
if (codec) avcodec_close(codecContext);
|
if (codec && codecContext) avcodec_close(codecContext);
|
||||||
codecContext = NULL;
|
codecContext = NULL;
|
||||||
codec = NULL;
|
codec = NULL;
|
||||||
|
|
||||||
|
@ -137,6 +152,99 @@ void LAVCVideoProvider::Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////
|
||||||
|
// Get next frame
|
||||||
|
void LAVCVideoProvider::GetNextFrame() {
|
||||||
|
static AVPacket packet;
|
||||||
|
static bool firstTime = true;
|
||||||
|
static int bytesRemaining = 0;
|
||||||
|
static uint8_t *rawdata;
|
||||||
|
int decoded;
|
||||||
|
int frameFinished;
|
||||||
|
|
||||||
|
// First call
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = false;
|
||||||
|
packet.data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start processing packets
|
||||||
|
bool run = true;
|
||||||
|
while (run) {
|
||||||
|
// Current packet has more bytes
|
||||||
|
while (bytesRemaining > 0) {
|
||||||
|
// Decode
|
||||||
|
decoded = avcodec_decode_video(codecContext,frame,&frameFinished,rawdata,bytesRemaining);
|
||||||
|
|
||||||
|
// Error?
|
||||||
|
if (decoded < 0) throw _T("Error reading frame");
|
||||||
|
|
||||||
|
// Update counts
|
||||||
|
bytesRemaining -= decoded;
|
||||||
|
rawdata += decoded;
|
||||||
|
|
||||||
|
// Finished?
|
||||||
|
if (frameFinished) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a packet
|
||||||
|
do {
|
||||||
|
// Free packet
|
||||||
|
if (packet.data != NULL) av_free_packet(&packet);
|
||||||
|
|
||||||
|
// Get new
|
||||||
|
int result = av_read_packet(formatContext,&packet);
|
||||||
|
if (result < 0) {
|
||||||
|
run = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (packet.stream_index != vidStream);
|
||||||
|
|
||||||
|
// Get packet data
|
||||||
|
if (run) {
|
||||||
|
bytesRemaining = packet.size;
|
||||||
|
rawdata = packet.data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of last pack
|
||||||
|
decoded = avcodec_decode_video(codecContext,frame,&frameFinished,rawdata,bytesRemaining);
|
||||||
|
if (packet.data != NULL) av_free_packet(&packet);
|
||||||
|
|
||||||
|
// Frame finished?
|
||||||
|
if (!frameFinished) throw _T("Unable to finish decoding frame");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////
|
||||||
|
// Convert AVFrame to wxBitmap
|
||||||
|
wxBitmap LAVCVideoProvider::AVFrameToWX(AVFrame *source) {
|
||||||
|
// Get sizes
|
||||||
|
int w = codecContext->width;
|
||||||
|
int h = codecContext->height;
|
||||||
|
PixelFormat format = PIX_FMT_RGBA32;
|
||||||
|
unsigned int size = avpicture_get_size(format,w,h);
|
||||||
|
|
||||||
|
// Prepare buffer
|
||||||
|
if (!buffer || bufferSize != size) {
|
||||||
|
if (buffer) delete buffer;
|
||||||
|
buffer = new uint8_t[size];
|
||||||
|
bufferSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate RGB32 buffer
|
||||||
|
AVFrame *frameRGB = avcodec_alloc_frame();
|
||||||
|
avpicture_fill((AVPicture*) frameRGB, buffer, format, w, h);
|
||||||
|
|
||||||
|
// Convert to RGB32
|
||||||
|
img_convert((AVPicture*) frameRGB, format, (AVPicture*) source, codecContext->pix_fmt, w, h);
|
||||||
|
|
||||||
|
// Convert to wxBitmap
|
||||||
|
wxBitmap bmp((const char*) frameRGB->data[0],w,h,32);
|
||||||
|
return bmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// Refresh subs
|
// Refresh subs
|
||||||
void LAVCVideoProvider::RefreshSubtitles() {
|
void LAVCVideoProvider::RefreshSubtitles() {
|
||||||
|
@ -146,8 +254,14 @@ void LAVCVideoProvider::RefreshSubtitles() {
|
||||||
/////////////
|
/////////////
|
||||||
// Get frame
|
// Get frame
|
||||||
wxBitmap LAVCVideoProvider::GetFrame(int n) {
|
wxBitmap LAVCVideoProvider::GetFrame(int n) {
|
||||||
wxBitmap frame(GetWidth(),GetHeight());
|
// Get frame
|
||||||
return frame;
|
GetNextFrame();
|
||||||
|
|
||||||
|
// Bitmap
|
||||||
|
wxBitmap bmp = AVFrameToWX(frame);
|
||||||
|
|
||||||
|
// Return
|
||||||
|
return bmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -53,10 +53,16 @@ private:
|
||||||
AVCodecContext *codecContext;
|
AVCodecContext *codecContext;
|
||||||
AVStream *stream;
|
AVStream *stream;
|
||||||
AVCodec *codec;
|
AVCodec *codec;
|
||||||
|
AVFrame *frame;
|
||||||
int vidStream;
|
int vidStream;
|
||||||
|
|
||||||
|
uint8_t *buffer;
|
||||||
|
int bufferSize;
|
||||||
|
|
||||||
|
void GetNextFrame();
|
||||||
void LoadVideo(wxString filename);
|
void LoadVideo(wxString filename);
|
||||||
void Close();
|
void Close();
|
||||||
|
wxBitmap AVFrameToWX(AVFrame *frame);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
LAVCVideoProvider(wxString filename, wxString subfilename, double zoom);
|
LAVCVideoProvider(wxString filename, wxString subfilename, double zoom);
|
||||||
|
|
Loading…
Reference in New Issue