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();
|
||||
bytePos.Clear();
|
||||
timecodes.clear();
|
||||
std::list<MkvFrame> frames;
|
||||
|
||||
// Get info
|
||||
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
|
||||
frames.sort();
|
||||
MkvFrame curFrame(false,0,0);
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <wx/wxprec.h>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include "MatroskaParser.h"
|
||||
#include "vfr.h"
|
||||
|
||||
|
@ -78,8 +79,6 @@ bool operator < (MkvFrame &t1, MkvFrame &t2);
|
|||
// Matroska wrapper class
|
||||
class MatroskaWrapper {
|
||||
private:
|
||||
MatroskaFile *file;
|
||||
MkvStdIO *input;
|
||||
wxArrayInt keyFrames;
|
||||
std::vector<double> timecodes;
|
||||
wxArrayInt bytePos;
|
||||
|
@ -87,6 +86,11 @@ private:
|
|||
void Parse();
|
||||
|
||||
public:
|
||||
MkvStdIO *input;
|
||||
MatroskaFile *file;
|
||||
std::list<MkvFrame> frames;
|
||||
std::vector<MkvFrame> rawFrames;
|
||||
|
||||
MatroskaWrapper();
|
||||
~MatroskaWrapper();
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@
|
|||
|
||||
////////////
|
||||
// Includes
|
||||
#include <algorithm>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/filename.h>
|
||||
#include "subs_grid.h"
|
||||
#include "ass_file.h"
|
||||
#include "ass_dialogue.h"
|
||||
|
@ -46,10 +50,7 @@
|
|||
#include "options.h"
|
||||
#include "frame_main.h"
|
||||
#include "hotkeys.h"
|
||||
#include <algorithm>
|
||||
#include <wx/clipbrd.h>
|
||||
#include <wx/tokenzr.h>
|
||||
#include <wx/filename.h>
|
||||
#include "utils.h"
|
||||
|
||||
|
||||
///////////////
|
||||
|
@ -812,6 +813,9 @@ void SubtitlesGrid::DeleteLines(wxArrayInt target) {
|
|||
AdjustScrollbar();
|
||||
ass->FlagAsModified();
|
||||
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");
|
||||
}
|
||||
ClearCopy();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -37,6 +37,11 @@
|
|||
#pragma once
|
||||
|
||||
|
||||
//////////////
|
||||
// Prototypes
|
||||
class SubtitleRasterizer;
|
||||
|
||||
|
||||
////////////////////////////
|
||||
// Video Provider interface
|
||||
class VideoProvider {
|
||||
|
@ -61,5 +66,7 @@ public:
|
|||
virtual int GetSourceWidth()=0; // Returns the original source width in pixels
|
||||
virtual int GetSourceHeight()=0; // Returns the original source height in pixels
|
||||
|
||||
SubtitleRasterizer *subsRaster;
|
||||
|
||||
static VideoProvider *GetProvider(wxString video,wxString subtitles);
|
||||
};
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
// Headers
|
||||
#ifdef USE_LAVC
|
||||
#include <wx/wxprec.h>
|
||||
#include <algorithm>
|
||||
#include "video_provider_lavc.h"
|
||||
#include "utils.h"
|
||||
#include "vfr.h"
|
||||
|
@ -125,15 +126,15 @@ void LAVCVideoProvider::LoadVideo(wxString filename) {
|
|||
if (result < 0) throw _T("Failed to open video decoder");
|
||||
|
||||
// Check length
|
||||
isVFR = false;
|
||||
isMkv = false;
|
||||
length = stream->duration;
|
||||
if (length <= 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.");
|
||||
MatroskaWrapper::wrapper.Open(filename);
|
||||
length = MatroskaWrapper::wrapper.GetFrameCount();
|
||||
bytePos = MatroskaWrapper::wrapper.GetBytePositions();
|
||||
isVFR = true;
|
||||
//throw _T("FFmpeg fails at seeking Matroska. If you have any idea on how to fix it, Aegisub is open source.");
|
||||
mkv.Open(filename);
|
||||
length = mkv.GetFrameCount();
|
||||
bytePos = mkv.GetBytePositions();
|
||||
isMkv = true;
|
||||
}
|
||||
if (length <= 0) throw _T("Returned invalid stream length");
|
||||
}
|
||||
|
@ -160,6 +161,9 @@ void LAVCVideoProvider::LoadVideo(wxString filename) {
|
|||
///////////////
|
||||
// Close video
|
||||
void LAVCVideoProvider::Close() {
|
||||
// Close mkv
|
||||
if (isMkv) mkv.Close();
|
||||
|
||||
// Clean buffers
|
||||
if (buffer1) delete buffer1;
|
||||
if (buffer2) delete buffer2;
|
||||
|
@ -305,39 +309,60 @@ wxBitmap LAVCVideoProvider::GetFrame(int n) {
|
|||
else {
|
||||
// Prepare seek
|
||||
__int64 seekTo;
|
||||
int result;
|
||||
int result = 0;
|
||||
|
||||
// Get time to seek to
|
||||
if (isVFR) {
|
||||
if (isMkv) {
|
||||
//__int64 base = AV_TIME_BASE;
|
||||
//__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 = __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
|
||||
else {
|
||||
seekTo = n;
|
||||
result = av_seek_frame(formatContext,vidStream,seekTo,AVSEEK_FLAG_BACKWARD);
|
||||
}
|
||||
|
||||
// Seek to keyframe
|
||||
if (result == 0) {
|
||||
avcodec_flush_buffers(codecContext);
|
||||
// Seek to keyframe
|
||||
if (result == 0) {
|
||||
avcodec_flush_buffers(codecContext);
|
||||
|
||||
// Seek until final frame
|
||||
bool ok = true;
|
||||
do {
|
||||
ok = GetNextFrame();
|
||||
} while (lastDecodeTime <= n && ok);
|
||||
}
|
||||
// Seek until final frame
|
||||
bool ok = true;
|
||||
do {
|
||||
ok = GetNextFrame();
|
||||
} while (lastDecodeTime <= n && ok);
|
||||
}
|
||||
|
||||
// Failed seeking
|
||||
else {
|
||||
GetNextFrame();
|
||||
// Failed seeking
|
||||
else {
|
||||
GetNextFrame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,12 +52,15 @@
|
|||
#include <ffmpeg/avcodec.h>
|
||||
#include <ffmpeg/avformat.h>
|
||||
#include "video_provider.h"
|
||||
#include "mkv_wrap.h"
|
||||
|
||||
|
||||
///////////////////////
|
||||
// LibAVCodec provider
|
||||
class LAVCVideoProvider : public VideoProvider {
|
||||
private:
|
||||
MatroskaWrapper mkv;
|
||||
|
||||
AVFormatContext *formatContext;
|
||||
AVCodecContext *codecContext;
|
||||
AVStream *stream;
|
||||
|
@ -72,7 +75,7 @@ private:
|
|||
|
||||
wxArrayInt bytePos;
|
||||
|
||||
bool isVFR;
|
||||
bool isMkv;
|
||||
__int64 lastDecodeTime;
|
||||
int frameNumber;
|
||||
int length;
|
||||
|
|
BIN
docs/help.hm3
BIN
docs/help.hm3
Binary file not shown.
Loading…
Reference in a new issue