Some highly failed attempt to fix mkv support with lavc, and updated manual to include information on how to use FexTracker
Originally committed to SVN as r189.
This commit is contained in:
parent
9da55729c6
commit
e7ec7ec68a
8 changed files with 79 additions and 31 deletions
|
@ -128,7 +128,6 @@ void MatroskaWrapper::Parse() {
|
||||||
keyFrames.Clear();
|
keyFrames.Clear();
|
||||||
bytePos.Clear();
|
bytePos.Clear();
|
||||||
timecodes.clear();
|
timecodes.clear();
|
||||||
std::list<MkvFrame> frames;
|
|
||||||
|
|
||||||
// Get info
|
// Get info
|
||||||
int tracks = mkv_GetNumTracks(file);
|
int tracks = mkv_GetNumTracks(file);
|
||||||
|
@ -184,6 +183,11 @@ void MatroskaWrapper::Parse() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy raw
|
||||||
|
for (std::list<MkvFrame>::iterator cur=frames.begin();cur!=frames.end();cur++) {
|
||||||
|
rawFrames.push_back(*cur);
|
||||||
|
}
|
||||||
|
|
||||||
// Process timecodes and keyframes
|
// Process timecodes and keyframes
|
||||||
frames.sort();
|
frames.sort();
|
||||||
MkvFrame curFrame(false,0,0);
|
MkvFrame curFrame(false,0,0);
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include <wx/wxprec.h>
|
#include <wx/wxprec.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
#include "MatroskaParser.h"
|
#include "MatroskaParser.h"
|
||||||
#include "vfr.h"
|
#include "vfr.h"
|
||||||
|
|
||||||
|
@ -78,8 +79,6 @@ bool operator < (MkvFrame &t1, MkvFrame &t2);
|
||||||
// Matroska wrapper class
|
// Matroska wrapper class
|
||||||
class MatroskaWrapper {
|
class MatroskaWrapper {
|
||||||
private:
|
private:
|
||||||
MatroskaFile *file;
|
|
||||||
MkvStdIO *input;
|
|
||||||
wxArrayInt keyFrames;
|
wxArrayInt keyFrames;
|
||||||
std::vector<double> timecodes;
|
std::vector<double> timecodes;
|
||||||
wxArrayInt bytePos;
|
wxArrayInt bytePos;
|
||||||
|
@ -87,6 +86,11 @@ private:
|
||||||
void Parse();
|
void Parse();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
MkvStdIO *input;
|
||||||
|
MatroskaFile *file;
|
||||||
|
std::list<MkvFrame> frames;
|
||||||
|
std::vector<MkvFrame> rawFrames;
|
||||||
|
|
||||||
MatroskaWrapper();
|
MatroskaWrapper();
|
||||||
~MatroskaWrapper();
|
~MatroskaWrapper();
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
|
|
||||||
////////////
|
////////////
|
||||||
// Includes
|
// Includes
|
||||||
|
#include <algorithm>
|
||||||
|
#include <wx/clipbrd.h>
|
||||||
|
#include <wx/tokenzr.h>
|
||||||
|
#include <wx/filename.h>
|
||||||
#include "subs_grid.h"
|
#include "subs_grid.h"
|
||||||
#include "ass_file.h"
|
#include "ass_file.h"
|
||||||
#include "ass_dialogue.h"
|
#include "ass_dialogue.h"
|
||||||
|
@ -46,10 +50,7 @@
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "frame_main.h"
|
#include "frame_main.h"
|
||||||
#include "hotkeys.h"
|
#include "hotkeys.h"
|
||||||
#include <algorithm>
|
#include "utils.h"
|
||||||
#include <wx/clipbrd.h>
|
|
||||||
#include <wx/tokenzr.h>
|
|
||||||
#include <wx/filename.h>
|
|
||||||
|
|
||||||
|
|
||||||
///////////////
|
///////////////
|
||||||
|
@ -812,6 +813,9 @@ void SubtitlesGrid::DeleteLines(wxArrayInt target) {
|
||||||
AdjustScrollbar();
|
AdjustScrollbar();
|
||||||
ass->FlagAsModified();
|
ass->FlagAsModified();
|
||||||
CommitChanges();
|
CommitChanges();
|
||||||
|
|
||||||
|
// Update editbox
|
||||||
|
editBox->SetToLine(MID(0,editBox->linen,GetRows()-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,7 @@ void SRTSubtitleFormat::WriteFile(wxString _filename,wxString encoding) {
|
||||||
}
|
}
|
||||||
else throw _T("Unexpected line type");
|
else throw _T("Unexpected line type");
|
||||||
}
|
}
|
||||||
|
ClearCopy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
//////////////
|
||||||
|
// Prototypes
|
||||||
|
class SubtitleRasterizer;
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////
|
////////////////////////////
|
||||||
// Video Provider interface
|
// Video Provider interface
|
||||||
class VideoProvider {
|
class VideoProvider {
|
||||||
|
@ -61,5 +66,7 @@ public:
|
||||||
virtual int GetSourceWidth()=0; // Returns the original source width in pixels
|
virtual int GetSourceWidth()=0; // Returns the original source width in pixels
|
||||||
virtual int GetSourceHeight()=0; // Returns the original source height in pixels
|
virtual int GetSourceHeight()=0; // Returns the original source height in pixels
|
||||||
|
|
||||||
|
SubtitleRasterizer *subsRaster;
|
||||||
|
|
||||||
static VideoProvider *GetProvider(wxString video,wxString subtitles);
|
static VideoProvider *GetProvider(wxString video,wxString subtitles);
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
// Headers
|
// Headers
|
||||||
#ifdef USE_LAVC
|
#ifdef USE_LAVC
|
||||||
#include <wx/wxprec.h>
|
#include <wx/wxprec.h>
|
||||||
|
#include <algorithm>
|
||||||
#include "video_provider_lavc.h"
|
#include "video_provider_lavc.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "vfr.h"
|
#include "vfr.h"
|
||||||
|
@ -125,15 +126,15 @@ void LAVCVideoProvider::LoadVideo(wxString filename) {
|
||||||
if (result < 0) throw _T("Failed to open video decoder");
|
if (result < 0) throw _T("Failed to open video decoder");
|
||||||
|
|
||||||
// Check length
|
// Check length
|
||||||
isVFR = false;
|
isMkv = false;
|
||||||
length = stream->duration;
|
length = stream->duration;
|
||||||
if (length <= 0) {
|
if (length <= 0) {
|
||||||
if (strcmp(formatContext->iformat->name,"matroska") == 0) {
|
if (strcmp(formatContext->iformat->name,"matroska") == 0) {
|
||||||
throw _T("FFmpeg fails at seeking Matroska. If you have any idea on how to fix it, Aegisub is open source.");
|
//throw _T("FFmpeg fails at seeking Matroska. If you have any idea on how to fix it, Aegisub is open source.");
|
||||||
MatroskaWrapper::wrapper.Open(filename);
|
mkv.Open(filename);
|
||||||
length = MatroskaWrapper::wrapper.GetFrameCount();
|
length = mkv.GetFrameCount();
|
||||||
bytePos = MatroskaWrapper::wrapper.GetBytePositions();
|
bytePos = mkv.GetBytePositions();
|
||||||
isVFR = true;
|
isMkv = true;
|
||||||
}
|
}
|
||||||
if (length <= 0) throw _T("Returned invalid stream length");
|
if (length <= 0) throw _T("Returned invalid stream length");
|
||||||
}
|
}
|
||||||
|
@ -160,6 +161,9 @@ void LAVCVideoProvider::LoadVideo(wxString filename) {
|
||||||
///////////////
|
///////////////
|
||||||
// Close video
|
// Close video
|
||||||
void LAVCVideoProvider::Close() {
|
void LAVCVideoProvider::Close() {
|
||||||
|
// Close mkv
|
||||||
|
if (isMkv) mkv.Close();
|
||||||
|
|
||||||
// Clean buffers
|
// Clean buffers
|
||||||
if (buffer1) delete buffer1;
|
if (buffer1) delete buffer1;
|
||||||
if (buffer2) delete buffer2;
|
if (buffer2) delete buffer2;
|
||||||
|
@ -305,39 +309,60 @@ wxBitmap LAVCVideoProvider::GetFrame(int n) {
|
||||||
else {
|
else {
|
||||||
// Prepare seek
|
// Prepare seek
|
||||||
__int64 seekTo;
|
__int64 seekTo;
|
||||||
int result;
|
int result = 0;
|
||||||
|
|
||||||
// Get time to seek to
|
// Get time to seek to
|
||||||
if (isVFR) {
|
if (isMkv) {
|
||||||
//__int64 base = AV_TIME_BASE;
|
//__int64 base = AV_TIME_BASE;
|
||||||
//__int64 time = VFR_Output.GetTimeAtFrame(n,true) * base / 1000000;
|
//__int64 time = VFR_Output.GetTimeAtFrame(n,true) * base / 1000000;
|
||||||
//seekTo = av_rescale(time,stream->time_base.den,AV_TIME_BASE * __int64(stream->time_base.num));
|
//seekTo = av_rescale(time,stream->time_base.den,AV_TIME_BASE * __int64(stream->time_base.num));
|
||||||
//seekTo = __int64(n) * 1000 * stream->r_frame_rate.den / stream->r_frame_rate.num;
|
//seekTo = __int64(n) * 1000 * stream->r_frame_rate.den / stream->r_frame_rate.num;
|
||||||
seekTo = bytePos[n];
|
//seekTo = bytePos[n];
|
||||||
|
|
||||||
result = av_seek_frame(formatContext,vidStream,seekTo,AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_BYTE);
|
//result = av_seek_frame(formatContext,vidStream,seekTo,AVSEEK_FLAG_BACKWARD | AVSEEK_FLAG_BYTE);
|
||||||
|
|
||||||
|
// Prepare mkv seek
|
||||||
|
ulonglong startTime, endTime, filePos;
|
||||||
|
unsigned int rt, frameSize, frameFlags;
|
||||||
|
ulonglong targetTime = __int64(VFR_Output.GetTimeAtFrame(n,true,true))*1000000;
|
||||||
|
//ulonglong targetTime = __int64(n) * 1000 * stream->r_frame_rate.den / stream->r_frame_rate.num;
|
||||||
|
//ulonglong targetTime = mkv.rawFrames[n].time * 1000000;
|
||||||
|
mkv_Seek(mkv.file,targetTime,MKVF_SEEK_TO_PREV_KEYFRAME);
|
||||||
|
|
||||||
|
// Seek
|
||||||
|
if (mkv_ReadFrame(mkv.file,0,&rt,&startTime,&endTime,&filePos,&frameSize,&frameFlags) == 0) {
|
||||||
|
result = av_seek_frame(formatContext,vidStream,filePos,AVSEEK_FLAG_BYTE | AVSEEK_FLAG_BACKWARD);
|
||||||
|
int curpos = 0;
|
||||||
|
for (int i=0;i<mkv.rawFrames.size();i++) {
|
||||||
|
if (mkv.rawFrames[i].time == startTime / 1000000.0) curpos = i;
|
||||||
|
}
|
||||||
|
int seek = n - curpos;
|
||||||
|
for (int i=0;i<seek;i++) {
|
||||||
|
GetNextFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constant frame rate
|
// Constant frame rate
|
||||||
else {
|
else {
|
||||||
seekTo = n;
|
seekTo = n;
|
||||||
result = av_seek_frame(formatContext,vidStream,seekTo,AVSEEK_FLAG_BACKWARD);
|
result = av_seek_frame(formatContext,vidStream,seekTo,AVSEEK_FLAG_BACKWARD);
|
||||||
}
|
|
||||||
|
|
||||||
// Seek to keyframe
|
// Seek to keyframe
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
avcodec_flush_buffers(codecContext);
|
avcodec_flush_buffers(codecContext);
|
||||||
|
|
||||||
// Seek until final frame
|
// Seek until final frame
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
do {
|
do {
|
||||||
ok = GetNextFrame();
|
ok = GetNextFrame();
|
||||||
} while (lastDecodeTime <= n && ok);
|
} while (lastDecodeTime <= n && ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed seeking
|
// Failed seeking
|
||||||
else {
|
else {
|
||||||
GetNextFrame();
|
GetNextFrame();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,15 @@
|
||||||
#include <ffmpeg/avcodec.h>
|
#include <ffmpeg/avcodec.h>
|
||||||
#include <ffmpeg/avformat.h>
|
#include <ffmpeg/avformat.h>
|
||||||
#include "video_provider.h"
|
#include "video_provider.h"
|
||||||
|
#include "mkv_wrap.h"
|
||||||
|
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
// LibAVCodec provider
|
// LibAVCodec provider
|
||||||
class LAVCVideoProvider : public VideoProvider {
|
class LAVCVideoProvider : public VideoProvider {
|
||||||
private:
|
private:
|
||||||
|
MatroskaWrapper mkv;
|
||||||
|
|
||||||
AVFormatContext *formatContext;
|
AVFormatContext *formatContext;
|
||||||
AVCodecContext *codecContext;
|
AVCodecContext *codecContext;
|
||||||
AVStream *stream;
|
AVStream *stream;
|
||||||
|
@ -72,7 +75,7 @@ private:
|
||||||
|
|
||||||
wxArrayInt bytePos;
|
wxArrayInt bytePos;
|
||||||
|
|
||||||
bool isVFR;
|
bool isMkv;
|
||||||
__int64 lastDecodeTime;
|
__int64 lastDecodeTime;
|
||||||
int frameNumber;
|
int frameNumber;
|
||||||
int length;
|
int length;
|
||||||
|
|
BIN
docs/help.hm3
BIN
docs/help.hm3
Binary file not shown.
Loading…
Reference in a new issue