Ejemplo n.º 1
0
static void read_subtitles(agi::ProgressSink *ps, MatroskaFile *file, MkvStdIO *input, bool srt, double totalTime, AssParser *parser) {
	std::vector<std::pair<int, std::string>> subList;

	// Load blocks
	uint64_t startTime, endTime, filePos;
	unsigned int rt, frameSize, frameFlags;

	while (mkv_ReadFrame(file, 0, &rt, &startTime, &endTime, &filePos, &frameSize, &frameFlags) == 0) {
		if (ps->IsCancelled()) return;
		if (frameSize == 0) continue;

		const auto readBuf = input->file.read(filePos, frameSize);
		const auto readBufEnd = readBuf + frameSize;

		// Get start and end times
		int64_t timecodeScaleLow = 1000000;
		agi::Time subStart = startTime / timecodeScaleLow;
		agi::Time subEnd = endTime / timecodeScaleLow;

		using str_range = boost::iterator_range<const char *>;

		// Process SSA/ASS
		if (!srt) {
			auto first = std::find(readBuf, readBufEnd, ',');
			if (first == readBufEnd) continue;
			auto second = std::find(first + 1, readBufEnd, ',');
			if (second == readBufEnd) continue;

			subList.emplace_back(
				boost::lexical_cast<int>(str_range(readBuf, first)),
				agi::format("Dialogue: %d,%s,%s,%s"
					, boost::lexical_cast<int>(str_range(first + 1, second))
					, subStart.GetAssFormatted()
					, subEnd.GetAssFormatted()
					, str_range(second + 1, readBufEnd)));
		}
		// Process SRT
		else {
			auto line = agi::format("Dialogue: 0,%s,%s,Default,,0,0,0,,%s"
				, subStart.GetAssFormatted()
				, subEnd.GetAssFormatted()
				, str_range(readBuf, readBufEnd));
			boost::replace_all(line, "\r\n", "\\N");
			boost::replace_all(line, "\r", "\\N");
			boost::replace_all(line, "\n", "\\N");

			subList.emplace_back(subList.size(), std::move(line));
		}

		ps->SetProgress(startTime / timecodeScaleLow, totalTime);
	}

	// Insert into file
	sort(begin(subList), end(subList));
	for (auto order_value_pair : subList)
		parser->AddLine(order_value_pair.second);
}
Ejemplo n.º 2
0
//////////////////
// Actually parse
void MatroskaWrapper::Parse() {
    // Clear keyframes and timecodes
    keyFrames.Clear();
    bytePos.Clear();
    timecodes.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
            __int64 timecodeScale = mkv_TruncFloat(trackInfo->TimecodeScale) * segInfo->TimecodeScale;

            // Mask other tracks away
            mkv_SetTrackMask(file, ~(1 << track));

            // Progress bar
            int totalTime = 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
            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 _T("Canceled");
                }

                // Update progress
                progress->SetProgress(curTime,totalTime);
            }

            // Clean up progress
            if (!canceled) progress->Destroy();

            break;
        }
    }

    // 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);
    int i = 0;
    for (std::list<MkvFrame>::iterator cur=frames.begin(); cur!=frames.end(); cur++) {
        curFrame = *cur;
        if (curFrame.isKey) keyFrames.Add(i);
        bytePos.Add(curFrame.filePos);
        timecodes.push_back(curFrame.time);
        i++;
    }
}
/////////////
// Get frame
wxBitmap LAVCVideoProvider::GetFrame(int n) {
	// Return stored frame
	n = MID(0,n,GetFrameCount()-1);
	if (n == frameNumber) {
		if (!validFrame) {
			curFrame = AVFrameToWX(frame, n);
			validFrame = true;
		}
		return curFrame;
	}

	// Following frame, just get it
	if (n == frameNumber+1) {
		GetNextFrame();
		//wxLogMessage(wxString::Format(_T("%i"),lastDecodeTime));
	}

	// Needs to seek
	else {
		// Prepare seek
		__int64 seekTo;
		int result = 0;

#if 0
		// Get time to seek to
		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];

			//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 (unsigned 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 {
#endif
			seekTo = n;
			result = av_seek_frame(lavcfile->fctx,vidStream,seekTo,AVSEEK_FLAG_BACKWARD);

			// Seek to keyframe
			if (result == 0) {
				avcodec_flush_buffers(codecContext);

				// Seek until final frame
				bool ok = true;
				do {
					ok = GetNextFrame();
				} while (lastDecodeTime <= n && ok);
			}

			// Failed seeking
			else {
				GetNextFrame();
			}
#if 0
		}
#endif
	}

	// Bitmap
	wxBitmap bmp;
	if (frame) bmp = AVFrameToWX(frame, n);
	else bmp = wxBitmap(GetWidth(),GetHeight());

	// Set current frame
	validFrame = true;
	curFrame = bmp;
	frameNumber = n;

	// Return
	return curFrame;
}