HRESULT FFmpegInterop::MediaSampleProvider::GetNextPacket()

in FFmpegInterop/Source/MediaSampleProvider.cpp [164:237]


HRESULT FFmpegInterop::MediaSampleProvider::GetNextPacket(DataWriter ^ writer, LONGLONG & pts, LONGLONG & dur, bool allowSkip)
{
	HRESULT hr = S_OK;

	AVPacket avPacket;
	av_init_packet(&avPacket);
	avPacket.data = NULL;
	avPacket.size = 0;

	bool frameComplete = false;
	bool decodeSuccess = true;
	int64_t framePts = 0, frameDuration = 0;
	int errorCount = 0;

	while (SUCCEEDED(hr) && !frameComplete)
	{
		// Continue reading until there is an appropriate packet in the stream
		while (m_packetQueue.empty())
		{
			if (m_pReader->ReadPacket() < 0)
			{
				DebugMessage(L"GetNextSample reaching EOF\n");
				hr = E_FAIL;
				break;
			}
		}

		if (!m_packetQueue.empty())
		{
			// Pick the packets from the queue one at a time
			avPacket = PopPacket();
			framePts = avPacket.pts;
			frameDuration = avPacket.duration;

			// Decode the packet if necessary, it will update the presentation time if necessary
			hr = DecodeAVPacket(writer, &avPacket, framePts, frameDuration);
			frameComplete = (hr == S_OK);

			if (!frameComplete)
			{
				m_isDiscontinuous = true;
				if (allowSkip && errorCount++ < 10)
				{
					// skip a few broken packets (maybe make this configurable later)
					DebugMessage(L"Skipping broken packet\n");
					hr = S_OK;
				}
			}
		}
	}

	if (SUCCEEDED(hr))
	{
		// Write the packet out
		hr = WriteAVPacketToStream(writer, &avPacket);

		if (m_startOffset == AV_NOPTS_VALUE)
		{
			//if we havent set m_startOffset already
			DebugMessage(L"Saving m_startOffset\n");

			//in some real-time streams framePts is less than 0 so we need to make sure m_startOffset is never negative
			m_startOffset = framePts < 0 ? 0 : framePts;
		}

		pts = LONGLONG(av_q2d(m_pAvFormatCtx->streams[m_streamIndex]->time_base) * 10000000 * (framePts - m_startOffset));

		dur = LONGLONG(av_q2d(m_pAvFormatCtx->streams[m_streamIndex]->time_base) * 10000000 * frameDuration);
	}

	av_packet_unref(&avPacket);

	return hr;
}