Delete all the unused things in MatroskaWrapper (i.e. most of it), fix some derpy things, and make it throw typed exceptions.

Originally committed to SVN as r5632.
This commit is contained in:
Thomas Goyne 2011-09-28 19:47:21 +00:00
parent 2ca9392942
commit f341a63f14
3 changed files with 137 additions and 501 deletions

View file

@ -38,6 +38,8 @@
#ifndef AGI_PRE #ifndef AGI_PRE
#include <errno.h> #include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <algorithm> #include <algorithm>
#include <iterator> #include <iterator>
@ -47,249 +49,79 @@
#include <wx/choicdlg.h> // Keep this last so wxUSE_CHOICEDLG is set. #include <wx/choicdlg.h> // Keep this last so wxUSE_CHOICEDLG is set.
#endif #endif
#include "ass_file.h"
#include "ass_time.h"
#include "dialog_progress.h"
#include <libaegisub/vfr.h>
#include "mkv_wrap.h" #include "mkv_wrap.h"
/// DOCME #include "ass_file.h"
MatroskaWrapper MatroskaWrapper::wrapper; #include "ass_time.h"
#include "compat.h"
#include "dialog_progress.h"
#include "MatroskaParser.h"
/// DOCME class MkvStdIO : public InputStream {
#define CACHESIZE 65536 public:
MkvStdIO(wxString filename);
~MkvStdIO() { if (fp) fclose(fp); }
/// @brief Constructor FILE *fp;
/// int error;
MatroskaWrapper::MatroskaWrapper() { };
file = NULL;
}
/// @brief Destructor #define CACHESIZE 65536
///
MatroskaWrapper::~MatroskaWrapper() {
Close();
}
/// @brief Open file void MatroskaWrapper::GetSubtitles(wxString const& filename, AssFile *target) {
/// @param filename MkvStdIO input(filename);
/// @param parse
///
void MatroskaWrapper::Open(wxString filename,bool parse) {
// Make sure it's closed first
Close();
// Open
char err[2048]; char err[2048];
input = new MkvStdIO(filename); MatroskaFile *file = mkv_Open(&input, err, sizeof(err));
if (input->fp) { if (!file) throw MatroskaException(err);
file = mkv_Open(input,err,sizeof(err));
// Failed parsing try {
if (!file) { // Get info
delete input; unsigned tracks = mkv_GetNumTracks(file);
throw wxString("MatroskaParser error: " + wxString(err,wxConvUTF8)); TrackInfo *trackInfo;
} std::vector<unsigned> tracksFound;
wxArrayString tracksNames;
unsigned trackToRead;
// Parse // Haali's library variables
if (parse) Parse(); ulonglong startTime, endTime, filePos;
} unsigned int rt, frameSize, frameFlags;
// Failed opening // Find tracks
else { for (unsigned track = 0; track < tracks; track++) {
delete input; trackInfo = mkv_GetTrackInfo(file,track);
throw "Unable to open Matroska file for parsing.";
}
}
/// @brief Close file // Subtitle track
/// @return if (trackInfo->Type == 0x11) {
/// wxString CodecID = wxString(trackInfo->CodecID,*wxConvCurrent);
void MatroskaWrapper::Close() { wxString TrackName = wxString(trackInfo->Name,*wxConvCurrent);
if (file) { wxString TrackLanguage = wxString(trackInfo->Language,*wxConvCurrent);
mkv_Close(file);
file = NULL; // Known subtitle format
delete input; if (CodecID == "S_TEXT/SSA" || CodecID == "S_TEXT/ASS" || CodecID == "S_TEXT/UTF8") {
} tracksFound.push_back(track);
keyFrames.clear(); tracksNames.Add(wxString::Format("%d (%s %s): %s", track, CodecID, TrackLanguage, TrackName));
timecodes.clear();
}
/// @brief Return keyframes
/// @return
///
std::vector<int> MatroskaWrapper::GetKeyFrames() {
return keyFrames;
}
/// @brief Comparison operator
/// @param t1
/// @param t2
/// @return
///
bool operator < (MkvFrame &t1, MkvFrame &t2) {
return t1.time < t2.time;
}
/// @brief Actually parse
///
void MatroskaWrapper::Parse() {
// Clear keyframes and timecodes
keyFrames.clear();
bytePos.Clear();
timecodes.clear();
frames.clear();
rawFrames.clear();
bytePos.Clear();
// Get info
int tracks = mkv_GetNumTracks(file);
TrackInfo *trackInfo;
SegmentInfo *segInfo = mkv_GetFileInfo(file);
// Parse tracks
for (int track=0;track<tracks;track++) {
trackInfo = mkv_GetTrackInfo(file,track);
// Video track
if (trackInfo->Type == 1) {
// Variables
ulonglong startTime, endTime, filePos;
unsigned int rt, frameSize, frameFlags;
//CompressedStream *cs = NULL;
// Timecode scale
longlong timecodeScale = mkv_TruncFloat(trackInfo->TimecodeScale) * segInfo->TimecodeScale;
// Mask other tracks away
mkv_SetTrackMask(file, ~(1 << track));
// Progress bar
int totalTime = int(double(segInfo->Duration) / timecodeScale);
volatile bool canceled = false;
DialogProgress *progress = new DialogProgress(NULL,_("Parsing Matroska"),&canceled,_("Reading keyframe and timecode data from Matroska file."),0,totalTime);
progress->Show();
progress->SetProgress(0,1);
// Read frames
register int frameN = 0;
while (mkv_ReadFrame(file,0,&rt,&startTime,&endTime,&filePos,&frameSize,&frameFlags) == 0) {
// Read value
double curTime = double(startTime) / 1000000.0;
frames.push_back(MkvFrame((frameFlags & FRAME_KF) != 0,curTime,filePos));
frameN++;
// Cancelled?
if (canceled) {
Close();
throw agi::UserCancelException("Canceled");
} }
// Identical to (frameN % 2048) == 0,
// but much faster.
if ((frameN & (2048 - 1)) == 0)
// Update progress
progress->SetProgress(int(curTime),totalTime);
}
// Clean up progress
if (!canceled) progress->Destroy();
break;
}
}
rawFrames.reserve(frames.size());
std::copy(frames.begin(), frames.end(), std::back_inserter(rawFrames));
// Process timecodes and keyframes
frames.sort();
int i = 0;
for (std::list<MkvFrame>::iterator cur=frames.begin();cur!=frames.end();cur++) {
if (cur->isKey) keyFrames.push_back(i);
bytePos.Add(cur->filePos);
timecodes.push_back(cur->time);
i++;
}
}
static int mkv_round(double num) {
return (int)(num + .5);
}
/// @brief Set target to timecodes
/// @param target
/// @return
///
void MatroskaWrapper::SetToTimecodes(agi::vfr::Framerate &target) {
if (timecodes.size() <= 1) return;
std::vector<int> times;
times.reserve(timecodes.size());
std::transform(timecodes.begin(), timecodes.end(), std::back_inserter(times), &mkv_round);
target = agi::vfr::Framerate(times);
}
/// @brief Get subtitles
/// @param target
///
void MatroskaWrapper::GetSubtitles(AssFile *target) {
// Get info
int tracks = mkv_GetNumTracks(file);
TrackInfo *trackInfo;
//SegmentInfo *segInfo = mkv_GetFileInfo(file);
wxArrayInt tracksFound;
wxArrayString tracksNames;
int trackToRead = -1;
// Haali's library variables
ulonglong startTime, endTime, filePos;
unsigned int rt, frameSize, frameFlags;
//CompressedStream *cs = NULL;
// Find tracks
for (int track=0;track<tracks;track++) {
trackInfo = mkv_GetTrackInfo(file,track);
// Subtitle track
if (trackInfo->Type == 0x11) {
wxString CodecID = wxString(trackInfo->CodecID,*wxConvCurrent);
wxString TrackName = wxString(trackInfo->Name,*wxConvCurrent);
wxString TrackLanguage = wxString(trackInfo->Language,*wxConvCurrent);
// Known subtitle format
if (CodecID == "S_TEXT/SSA" || CodecID == "S_TEXT/ASS" || CodecID == "S_TEXT/UTF8") {
tracksFound.Add(track);
tracksNames.Add(wxString::Format("%i (",track) + CodecID + " " + TrackLanguage + "): " + TrackName);
} }
} }
}
// No tracks found // No tracks found
if (tracksFound.Count() == 0) { if (tracksFound.empty())
target->LoadDefault(true); throw MatroskaException("File has no recognised subtitle tracks.");
Close();
throw "File has no recognised subtitle tracks.";
}
// Only one track found // Only one track found
else if (tracksFound.Count() == 1) { if (tracksFound.size() == 1) {
trackToRead = tracksFound[0]; trackToRead = tracksFound[0];
}
// Pick a track
else {
int choice = wxGetSingleChoiceIndex("Choose which track to read:","Multiple subtitle tracks found",tracksNames);
if (choice == -1) {
target->LoadDefault(true);
Close();
throw agi::UserCancelException("cancelled");
} }
trackToRead = tracksFound[choice]; // Pick a track
} else {
int choice = wxGetSingleChoiceIndex(_("Choose which track to read:"), _("Multiple subtitle tracks found"), tracksNames);
if (choice == -1)
throw agi::UserCancelException("cancelled");
// Picked track trackToRead = tracksFound[choice];
if (trackToRead != -1) { }
// Picked track
// Get codec type (0 = ASS/SSA, 1 = SRT) // Get codec type (0 = ASS/SSA, 1 = SRT)
trackInfo = mkv_GetTrackInfo(file,trackToRead); trackInfo = mkv_GetTrackInfo(file,trackToRead);
wxString CodecID = wxString(trackInfo->CodecID,*wxConvCurrent); wxString CodecID = wxString(trackInfo->CodecID,*wxConvCurrent);
@ -300,12 +132,7 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) {
if (codecType == 0) { if (codecType == 0) {
// Read raw data // Read raw data
trackInfo = mkv_GetTrackInfo(file,trackToRead); trackInfo = mkv_GetTrackInfo(file,trackToRead);
unsigned int privSize = trackInfo->CodecPrivateSize; wxString privString((const char *)trackInfo->CodecPrivate, wxConvUTF8, trackInfo->CodecPrivateSize);
char *privData = new char[privSize+1];
memcpy(privData,trackInfo->CodecPrivate,privSize);
privData[privSize] = 0;
wxString privString(privData,wxConvUTF8);
delete[] privData;
// Load into file // Load into file
wxString group = "[Script Info]"; wxString group = "[Script Info]";
@ -317,13 +144,7 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) {
if (next[0] == '[') group = next; if (next[0] == '[') group = next;
target->AddLine(next,group,version,&group); target->AddLine(next,group,version,&group);
} }
// Insert "[Events]"
//target->AddLine("",group,lasttime,version,&group);
//target->AddLine("[Events]",group,lasttime,version,&group);
//target->AddLine("Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text",group,lasttime,version,&group);
} }
// Load default if it's SRT // Load default if it's SRT
else { else {
target->LoadDefault(false); target->LoadDefault(false);
@ -333,10 +154,6 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) {
SegmentInfo *segInfo = mkv_GetFileInfo(file); SegmentInfo *segInfo = mkv_GetFileInfo(file);
longlong timecodeScale = mkv_TruncFloat(trackInfo->TimecodeScale) * segInfo->TimecodeScale; longlong timecodeScale = mkv_TruncFloat(trackInfo->TimecodeScale) * segInfo->TimecodeScale;
// Prepare STD vector to get lines inserted
std::vector<wxString> subList;
long int order = -1;
// Progress bar // Progress bar
int totalTime = int(double(segInfo->Duration) / timecodeScale); int totalTime = int(double(segInfo->Duration) / timecodeScale);
volatile bool canceled = false; volatile bool canceled = false;
@ -344,155 +161,120 @@ void MatroskaWrapper::GetSubtitles(AssFile *target) {
progress->Show(); progress->Show();
progress->SetProgress(0,1); progress->SetProgress(0,1);
std::map<int, wxString> subList;
char *readBuf = 0;
size_t readBufSize = 0;
// Load blocks // Load blocks
mkv_SetTrackMask(file, ~(1 << trackToRead)); mkv_SetTrackMask(file, ~(1 << trackToRead));
while (mkv_ReadFrame(file,0,&rt,&startTime,&endTime,&filePos,&frameSize,&frameFlags) == 0) { while (mkv_ReadFrame(file,0,&rt,&startTime,&endTime,&filePos,&frameSize,&frameFlags) == 0) {
// Canceled
if (canceled) { if (canceled) {
target->LoadDefault(true); delete readBuf;
Close();
throw agi::UserCancelException("cancelled"); throw agi::UserCancelException("cancelled");
} }
// Read to temp // Read to temp
char *tmp = new char[frameSize+1]; if (frameSize > readBufSize) {
fseek(input->fp, filePos, SEEK_SET); delete readBuf;
fread(tmp,1,frameSize,input->fp); readBufSize = frameSize * 2;
tmp[frameSize] = 0; readBuf = new char[readBufSize];
wxString blockString(tmp,wxConvUTF8); }
delete[] tmp;
fseek(input.fp, filePos, SEEK_SET);
fread(readBuf, 1, frameSize, input.fp);
wxString blockString(readBuf, wxConvUTF8, frameSize);
// Get start and end times // Get start and end times
//longlong timecodeScaleLow = timecodeScale / 100;
longlong timecodeScaleLow = 1000000; longlong timecodeScaleLow = 1000000;
AssTime subStart,subEnd; AssTime subStart,subEnd;
subStart.SetMS(startTime / timecodeScaleLow); subStart.SetMS(startTime / timecodeScaleLow);
subEnd.SetMS(endTime / timecodeScaleLow); subEnd.SetMS(endTime / timecodeScaleLow);
//wxLogMessage(subStart.GetASSFormated() + "-" + subEnd.GetASSFormated() + ": " + blockString);
// Process SSA/ASS // Process SSA/ASS
if (codecType == 0) { if (codecType == 0) {
// Get order number long order = 0, layer = 0;
int pos = blockString.Find(","); blockString.BeforeFirst(',', &blockString).ToLong(&order);
wxString orderString = blockString.Left(pos); blockString.BeforeFirst(',', &blockString).ToLong(&layer);
orderString.ToLong(&order);
blockString = blockString.Mid(pos+1);
// Get layer number subList[order] = wxString::Format("Dialogue: %d,%s,%s,%s", layer, subStart.GetASSFormated(), subEnd.GetASSFormated(), blockString);
pos = blockString.Find(",");
long int layer = 0;
if (pos) {
wxString layerString = blockString.Left(pos);
layerString.ToLong(&layer);
blockString = blockString.Mid(pos+1);
}
// Assemble final
blockString = wxString::Format("Dialogue: %i,",layer) + subStart.GetASSFormated() + "," + subEnd.GetASSFormated() + "," + blockString;
} }
// Process SRT // Process SRT
else { else {
blockString = wxString("Dialogue: 0,") + subStart.GetASSFormated() + "," + subEnd.GetASSFormated() + ",Default,,0000,0000,0000,," + blockString; blockString = wxString::Format("Dialogue: 0,%s,%s,%s", subStart.GetASSFormated(), subEnd.GetASSFormated(), blockString);
blockString.Replace("\r\n","\\N"); blockString.Replace("\r\n","\\N");
blockString.Replace("\r","\\N"); blockString.Replace("\r","\\N");
blockString.Replace("\n","\\N"); blockString.Replace("\n","\\N");
order++;
subList[subList.size()] = blockString;
} }
// Insert into vector
if (subList.size() == (unsigned int)order) subList.push_back(blockString);
else {
if ((signed)(subList.size()) < order+1) subList.resize(order+1);
subList[order] = blockString;
}
// Update progress bar
progress->SetProgress(int(double(startTime) / 1000000.0),totalTime); progress->SetProgress(int(double(startTime) / 1000000.0),totalTime);
} }
delete readBuf;
// Insert into file // Insert into file
wxString group = "[Events]"; wxString group = "[Events]";
int version = (CodecID == "S_TEXT/SSA"); int version = (CodecID == "S_TEXT/SSA");
for (unsigned int i=0;i<subList.size();i++) { for (std::map<int, wxString>::iterator it = subList.begin(); it != subList.end(); ++it) {
target->AddLine(subList[i],group,version,&group); target->AddLine(it->second,group,version,&group);
} }
// Close progress bar // Close progress bar
if (!canceled) progress->Destroy(); if (!canceled) progress->Destroy();
} }
catch (...) {
// No track to load mkv_Close(file);
else { throw;
target->LoadDefault(true);
} }
} }
bool MatroskaWrapper::HasSubtitles(wxString const& filename) { bool MatroskaWrapper::HasSubtitles(wxString const& filename) {
char err[2048]; char err[2048];
MkvStdIO input(filename); try {
if (!input.fp) return false; MkvStdIO input(filename);
MatroskaFile* file = mkv_Open(&input, err, sizeof(err));
if (!file) return false;
MatroskaFile* file = mkv_Open(&input, err, sizeof(err)); // Find tracks
if (!file) return false; int tracks = mkv_GetNumTracks(file);
for (int track = 0; track < tracks; track++) {
TrackInfo *trackInfo = mkv_GetTrackInfo(file, track);
// Find tracks if (trackInfo->Type == 0x11) {
int tracks = mkv_GetNumTracks(file); wxString CodecID = wxString(trackInfo->CodecID, *wxConvCurrent);
for (int track = 0; track < tracks; track++) { if (CodecID == "S_TEXT/SSA" || CodecID == "S_TEXT/ASS" || CodecID == "S_TEXT/UTF8") {
TrackInfo *trackInfo = mkv_GetTrackInfo(file, track); mkv_Close(file);
return true;
if (trackInfo->Type == 0x11) { }
wxString CodecID = wxString(trackInfo->CodecID, *wxConvCurrent);
if (CodecID == "S_TEXT/SSA" || CodecID == "S_TEXT/ASS" || CodecID == "S_TEXT/UTF8") {
mkv_Close(file);
return true;
} }
} }
}
mkv_Close(file); mkv_Close(file);
return false; return false;
}
catch (...) {
// We don't care about why we couldn't read subtitles here
return false;
}
} }
////////////////////////////// LOTS OF HAALI C CODE DOWN HERE ///////////////////////////////////////
#ifdef __VISUALC__ #ifdef __VISUALC__
/// DOCME
#define std_fread fread
/// DOCME
#define std_fseek _fseeki64 #define std_fseek _fseeki64
/// DOCME
#define std_ftell _ftelli64 #define std_ftell _ftelli64
#else #else
/// DOCME
#define std_fread fread
/// DOCME
#define std_fseek fseeko #define std_fseek fseeko
/// DOCME
#define std_ftell ftello #define std_ftell ftello
#endif #endif
/// @brief STDIO class
/// @param _st
/// @param pos
/// @param buffer
/// @param count
/// @return
///
int StdIoRead(InputStream *_st, ulonglong pos, void *buffer, int count) { int StdIoRead(InputStream *_st, ulonglong pos, void *buffer, int count) {
MkvStdIO *st = (MkvStdIO *) _st; MkvStdIO *st = (MkvStdIO *) _st;
size_t rd; size_t rd;
if (std_fseek(st->fp, pos, SEEK_SET)) { if (fseek(st->fp, pos, SEEK_SET)) {
st->error = errno; st->error = errno;
return -1; return -1;
} }
rd = std_fread(buffer, 1, count, st->fp); rd = fread(buffer, 1, count, st->fp);
if (rd == 0) { if (rd == 0) {
if (feof(st->fp)) if (feof(st->fp))
return 0; return 0;
@ -502,15 +284,8 @@ int StdIoRead(InputStream *_st, ulonglong pos, void *buffer, int count) {
return rd; return rd;
} }
/* scan for a signature sig(big-endian) starting at file position pos /// @brief scan for a signature sig(big-endian) starting at file position pos
* return position of the first byte of signature or -1 if error/not found /// @return position of the first byte of signature or -1 if error/not found
/// @brief */
/// @param _st
/// @param start
/// @param signature
/// @return
///
longlong StdIoScan(InputStream *_st, ulonglong start, unsigned signature) { longlong StdIoScan(InputStream *_st, ulonglong start, unsigned signature) {
MkvStdIO *st = (MkvStdIO *) _st; MkvStdIO *st = (MkvStdIO *) _st;
int c; int c;
@ -530,63 +305,32 @@ longlong StdIoScan(InputStream *_st, ulonglong start, unsigned signature) {
} }
/// @brief This is used to limit readahead. /// @brief This is used to limit readahead.
/// @param _st unsigned StdIoGetCacheSize(InputStream *st) {
/// @return Cache size
///
unsigned StdIoGetCacheSize(InputStream *_st) {
return CACHESIZE; return CACHESIZE;
} }
/// @brief Get last error message /// @brief Get last error message
/// @param _st const char *StdIoGetLastError(InputStream *st) {
/// @return Last error message return strerror(((MkvStdIO *)st)->error);
///
const char *StdIoGetLastError(InputStream *_st) {
MkvStdIO *st = (MkvStdIO *) _st;
return strerror(st->error);
} }
/// @brief Memory allocation, this is done via stdlib /// @brief Memory allocation, this is done via stdlib
/// @param _st void *StdIoMalloc(InputStream *, size_t size) {
/// @param size
/// @return
///
void *StdIoMalloc(InputStream *_st, size_t size) {
return malloc(size); return malloc(size);
} }
/// @brief DOCME void *StdIoRealloc(InputStream *, void *mem, size_t size) {
/// @param _st return realloc(mem, size);
/// @param mem
/// @param size
/// @return
///
void *StdIoRealloc(InputStream *_st, void *mem, size_t size) {
return realloc(mem,size);
} }
/// @brief DOCME void StdIoFree(InputStream *, void *mem) {
/// @param _st
/// @param mem
///
void StdIoFree(InputStream *_st, void *mem) {
free(mem); free(mem);
} }
/// @brief DOCME int StdIoProgress(InputStream *, ulonglong cur, ulonglong max) {
/// @param _st
/// @param cur
/// @param max
/// @return
///
int StdIoProgress(InputStream *_st, ulonglong cur, ulonglong max) {
return 1; return 1;
} }
/// @brief DOCME
/// @param _st
/// @return
///
longlong StdIoGetFileSize(InputStream *_st) { longlong StdIoGetFileSize(InputStream *_st) {
MkvStdIO *st = (MkvStdIO *) _st; MkvStdIO *st = (MkvStdIO *) _st;
longlong epos = 0; longlong epos = 0;
@ -597,9 +341,6 @@ longlong StdIoGetFileSize(InputStream *_st) {
return epos; return epos;
} }
/// @brief DOCME
/// @param filename
///
MkvStdIO::MkvStdIO(wxString filename) { MkvStdIO::MkvStdIO(wxString filename) {
read = StdIoRead; read = StdIoRead;
scan = StdIoScan; scan = StdIoScan;
@ -610,10 +351,17 @@ MkvStdIO::MkvStdIO(wxString filename) {
memfree = StdIoFree; memfree = StdIoFree;
progress = StdIoProgress; progress = StdIoProgress;
getfilesize = StdIoGetFileSize; getfilesize = StdIoGetFileSize;
wxFileName fname(filename); wxFileName fname(filename);
fp = fopen(fname.GetShortPath().mb_str(wxConvUTF8),"rb"); #ifdef __VISUALC__
fp = _wfopen(fname.GetFullPath().wc_str(), L"rb");
#else
fp = fopen(fname.GetFullPath().utf8_str(), "rb");
#endif
if (fp) { if (fp) {
setvbuf(fp, NULL, _IOFBF, CACHESIZE); setvbuf(fp, NULL, _IOFBF, CACHESIZE);
} }
else {
throw agi::FileNotFoundError(STD_STR(filename));
}
} }

View file

@ -35,76 +35,14 @@
/// ///
#ifndef AGI_PRE #ifndef AGI_PRE
#include <stdint.h> #include <wx/string.h>
#include <stdio.h>
#include <list>
#include <vector>
#include <wx/dynarray.h>
#endif #endif
#include "MatroskaParser.h" #include <libaegisub/exception.h>
DEFINE_SIMPLE_EXCEPTION_NOINNER(MatroskaException, agi::Exception, "matroksa_wrapper/generic")
class AssFile; class AssFile;
namespace agi { namespace vfr { class Framerate; } }
/// DOCME
/// @class MkvStdIO
/// @brief DOCME
///
/// DOCME
class MkvStdIO : public InputStream {
public:
MkvStdIO(wxString filename);
~MkvStdIO() { if (fp) fclose(fp); }
/// DOCME
FILE *fp;
/// DOCME
int error;
};
/// DOCME
/// @class MkvFrame
/// @brief DOCME
///
/// DOCME
class MkvFrame {
public:
/// DOCME
double time;
/// DOCME
bool isKey;
/// DOCME
int64_t filePos;
/// @brief DOCME
///
MkvFrame() {
time = 0;
isKey = false;
filePos = -1;
}
/// @brief DOCME
/// @param keyframe
/// @param timecode
/// @param _filePos
///
MkvFrame(bool keyframe,double timecode,int64_t _filePos) {
isKey = keyframe;
time = timecode;
filePos = _filePos;
}
};
bool operator < (MkvFrame &t1, MkvFrame &t2);
/// DOCME /// DOCME
/// @class MatroskaWrapper /// @class MatroskaWrapper
@ -112,57 +50,9 @@ bool operator < (MkvFrame &t1, MkvFrame &t2);
/// ///
/// DOCME /// DOCME
class MatroskaWrapper { class MatroskaWrapper {
private:
/// DOCME
std::vector<int> keyFrames;
/// DOCME
std::vector<double> timecodes;
/// DOCME
wxArrayInt bytePos;
public: public:
/// Check if the file is a matroska file with at least one subtitle track
/// DOCME
MkvStdIO *input;
/// DOCME
MatroskaFile *file;
/// DOCME
std::list<MkvFrame> frames;
/// DOCME
std::vector<MkvFrame> rawFrames;
MatroskaWrapper();
~MatroskaWrapper();
/// @brief DOCME
/// @return
///
bool IsOpen() { return file != NULL; }
void Open(wxString filename,bool parse=true);
void Close();
void Parse();
void SetToTimecodes(agi::vfr::Framerate &target);
/// @brief DOCME
/// @return
///
wxArrayInt GetBytePositions() { return bytePos; }
/// @brief DOCME
/// @return
///
unsigned int GetFrameCount() { return timecodes.size(); }
std::vector<int> GetKeyFrames();
void GetSubtitles(AssFile *target);
static bool HasSubtitles(wxString const& filename); static bool HasSubtitles(wxString const& filename);
/// Load subtitles from a matroska file
/// DOCME static void GetSubtitles(wxString const& filename, AssFile *target);
static MatroskaWrapper wrapper;
}; };

View file

@ -53,8 +53,6 @@ wxArrayString MKVSubtitleFormat::GetReadWildcards() const {
return formats; return formats;
} }
void MKVSubtitleFormat::ReadFile(wxString const& filename, wxString const& encoding) { void MKVSubtitleFormat::ReadFile(wxString const& filename, wxString const&) {
MatroskaWrapper wrap; MatroskaWrapper::GetSubtitles(filename, GetAssFile());
wrap.Open(filename, false);
wrap.GetSubtitles(GetAssFile());
} }