diff --git a/core/mkv_wrap.cpp b/core/mkv_wrap.cpp index 50b138248..8a0265f81 100644 --- a/core/mkv_wrap.cpp +++ b/core/mkv_wrap.cpp @@ -128,7 +128,6 @@ void MatroskaWrapper::Parse() { keyFrames.Clear(); bytePos.Clear(); timecodes.clear(); - std::list frames; // Get info int tracks = mkv_GetNumTracks(file); @@ -184,6 +183,11 @@ void MatroskaWrapper::Parse() { } } + // Copy raw + for (std::list::iterator cur=frames.begin();cur!=frames.end();cur++) { + rawFrames.push_back(*cur); + } + // Process timecodes and keyframes frames.sort(); MkvFrame curFrame(false,0,0); diff --git a/core/mkv_wrap.h b/core/mkv_wrap.h index f2350058a..686145336 100644 --- a/core/mkv_wrap.h +++ b/core/mkv_wrap.h @@ -42,6 +42,7 @@ #include #include #include +#include #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 timecodes; wxArrayInt bytePos; @@ -87,6 +86,11 @@ private: void Parse(); public: + MkvStdIO *input; + MatroskaFile *file; + std::list frames; + std::vector rawFrames; + MatroskaWrapper(); ~MatroskaWrapper(); diff --git a/core/subs_grid.cpp b/core/subs_grid.cpp index c41998287..e86ad9de3 100644 --- a/core/subs_grid.cpp +++ b/core/subs_grid.cpp @@ -36,6 +36,10 @@ //////////// // Includes +#include +#include +#include +#include #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 -#include -#include -#include +#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)); } diff --git a/core/subtitle_format_srt.cpp b/core/subtitle_format_srt.cpp index 04aa5a26b..75a6c2bc2 100644 --- a/core/subtitle_format_srt.cpp +++ b/core/subtitle_format_srt.cpp @@ -162,6 +162,7 @@ void SRTSubtitleFormat::WriteFile(wxString _filename,wxString encoding) { } else throw _T("Unexpected line type"); } + ClearCopy(); } diff --git a/core/video_provider.h b/core/video_provider.h index c4cb0a488..3e72637fb 100644 --- a/core/video_provider.h +++ b/core/video_provider.h @@ -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); }; diff --git a/core/video_provider_lavc.cpp b/core/video_provider_lavc.cpp index 2bf374675..b5c38f771 100644 --- a/core/video_provider_lavc.cpp +++ b/core/video_provider_lavc.cpp @@ -38,6 +38,7 @@ // Headers #ifdef USE_LAVC #include +#include #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 #include #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; diff --git a/docs/help.hm3 b/docs/help.hm3 index f8d17b359..53e025237 100644 Binary files a/docs/help.hm3 and b/docs/help.hm3 differ