Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/LAVFilters.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHendrik Leppkes <h.leppkes@gmail.com>2012-11-05 14:27:27 +0400
committerHendrik Leppkes <h.leppkes@gmail.com>2012-11-05 14:27:27 +0400
commit2840ba3d532e9ebcfd03b3a0297f191330112bbf (patch)
tree7e24a22b22f30b9a3165c4e15f347f9754fef749
parent511e2341bf61e8d1241227e193398e65c3c6f064 (diff)
Move EndOfSequence detection into the main processing code.
Avoid duplicating the detection in every decoder, and avoid any threading issues by calling the EndOfStream from the main processing thread, instead of trying to flush from the decode thread.
-rw-r--r--decoder/LAVVideo/DecodeThread.cpp39
-rw-r--r--decoder/LAVVideo/DecodeThread.h4
-rw-r--r--decoder/LAVVideo/decoders/avcodec.cpp30
-rw-r--r--decoder/LAVVideo/decoders/avcodec.h1
-rw-r--r--decoder/LAVVideo/decoders/cuvid.cpp25
-rw-r--r--decoder/LAVVideo/decoders/cuvid.h1
6 files changed, 43 insertions, 57 deletions
diff --git a/decoder/LAVVideo/DecodeThread.cpp b/decoder/LAVVideo/DecodeThread.cpp
index 560e4ea1..f2c6f52b 100644
--- a/decoder/LAVVideo/DecodeThread.cpp
+++ b/decoder/LAVVideo/DecodeThread.cpp
@@ -37,6 +37,7 @@ CDecodeThread::CDecodeThread(CLAVVideo *pLAVVideo)
, m_evEOSDone(TRUE)
, m_evInput(TRUE)
, m_NextSample(NULL)
+ , m_bEndOfSequence(FALSE)
{
WCHAR fileName[1024];
GetModuleFileName(NULL, fileName, 1024);
@@ -195,6 +196,18 @@ STDMETHODIMP CDecodeThread::Decode(IMediaSample *pSample)
ProcessOutput();
+ // Check for MPEG2 End-Of-Sequence code, and immediately flush all frames out of the decoder
+ // This is mostly required to get still-frames in DVDs (and possibly Blu-rays) to output as soon as they are ready,
+ // otherwise they might be delayed until the next track switch, and all you see is black (or the previous image)
+ if (m_Codec == AV_CODEC_ID_MPEG2VIDEO) {
+ if (CheckForEndOfSequence(pSample)) {
+ m_bEndOfSequence = TRUE;
+ EndOfStream();
+ m_bEndOfSequence = FALSE;
+ m_pLAVVideo->Deliver(GetFlushFrame());
+ }
+ }
+
return S_OK;
}
@@ -237,6 +250,8 @@ STDMETHODIMP CDecodeThread::ProcessOutput()
HRESULT hr = S_FALSE;
while (LAVFrame *pFrame = m_Output.Pop()) {
hr = S_OK;
+ if (m_bEndOfSequence)
+ pFrame->flags |= LAV_FRAME_FLAG_END_OF_SEQUENCE;
m_pLAVVideo->Deliver(pFrame);
}
return hr;
@@ -258,6 +273,30 @@ STDMETHODIMP CDecodeThread::ClearQueues()
return S_OK;
}
+extern "C" const uint8_t *avpriv_mpv_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state);
+
+bool CDecodeThread::CheckForEndOfSequence(IMediaSample *pSample)
+{
+ HRESULT hr = S_OK;
+ BYTE *buf = NULL;
+ long len = 0;
+ hr = pSample->GetPointer(&buf);
+ if (SUCCEEDED(hr) && buf && (len = pSample->GetActualDataLength()) > 0) {
+ if (m_Codec == AV_CODEC_ID_MPEG2VIDEO) {
+ uint32_t state = (uint32_t)-1;
+ const uint8_t *p = buf, *end = buf + len;
+ while (p < end) {
+ p = avpriv_mpv_find_start_code(p, end, &state);
+ if (state == 0x000001b7) {
+ DbgLog((LOG_TRACE, 50, L"Found SEQ_END_CODE at %p (end: %p)", p, end));
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
DWORD CDecodeThread::ThreadProc()
{
HRESULT hr;
diff --git a/decoder/LAVVideo/DecodeThread.h b/decoder/LAVVideo/DecodeThread.h
index b7071752..3fc6136d 100644
--- a/decoder/LAVVideo/DecodeThread.h
+++ b/decoder/LAVVideo/DecodeThread.h
@@ -82,6 +82,8 @@ private:
IMediaSample* GetSample();
void ReleaseSample();
+ bool CheckForEndOfSequence(IMediaSample *pSample);
+
private:
enum {CMD_CREATE_DECODER, CMD_CLOSE_DECODER, CMD_FLUSH, CMD_EOS, CMD_EXIT, CMD_INIT_ALLOCATOR, CMD_POST_CONNECT};
@@ -100,6 +102,8 @@ private:
CAMEvent m_evDecodeDone;
CAMEvent m_evEOSDone;
+ BOOL m_bEndOfSequence;
+
CCritSec m_ThreadCritSec;
struct {
const CMediaType *pmt;
diff --git a/decoder/LAVVideo/decoders/avcodec.cpp b/decoder/LAVVideo/decoders/avcodec.cpp
index ec6bd2d2..fbb67e88 100644
--- a/decoder/LAVVideo/decoders/avcodec.cpp
+++ b/decoder/LAVVideo/decoders/avcodec.cpp
@@ -293,7 +293,6 @@ CDecAvcodec::CDecAvcodec(void)
, m_bDXVA(FALSE)
, m_bInputPadded(FALSE)
, m_bDR1(FALSE)
- , m_bEndOfSequence(FALSE)
{
}
@@ -781,15 +780,12 @@ void CDecAvcodec::lav_frame_destruct(struct LAVFrame *f)
#endif
-extern "C" const uint8_t *avpriv_mpv_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state);
-
STDMETHODIMP CDecAvcodec::Decode(const BYTE *buffer, int buflen, REFERENCE_TIME rtStartIn, REFERENCE_TIME rtStopIn, BOOL bSyncPoint, BOOL bDiscontinuity)
{
int got_picture = 0;
int used_bytes = 0;
BOOL bParserFrame = FALSE;
BOOL bFlush = (buffer == NULL);
- BOOL bEndOfSequenceFlush = FALSE;
AVPacket avpkt;
av_init_packet(&avpkt);
@@ -927,22 +923,6 @@ STDMETHODIMP CDecAvcodec::Decode(const BYTE *buffer, int buflen, REFERENCE_TIME
avpkt.size = 0;
}
- // Check for MPEG2 End-Of-Sequence code, and immediately flush all frames out of the decoder
- // This is mostly required to get still-frames in DVDs (and possibly Blu-rays) to output as soon as they are ready,
- // otherwise they might be delayed until the next track switch, and all you see is black (or the previous image)
- if (m_nCodecId == AV_CODEC_ID_MPEG2VIDEO && avpkt.data && avpkt.size >= 4) {
- uint32_t state = (uint32_t)-1;
- const uint8_t *p = avpkt.data, *end = avpkt.data + avpkt.size;
- while (p < end) {
- p = avpriv_mpv_find_start_code(p, end, &state);
- if (state == 0x000001b7) {
- DbgLog((LOG_TRACE, 50, L"Found SEQ_END_CODE at %p (end: %p)", p, end));
- bEndOfSequenceFlush = TRUE;
- break;
- }
- }
- }
-
int ret2 = avcodec_decode_video2 (m_pAVCtx, m_pFrame, &got_picture, &avpkt);
if (ret2 < 0) {
DbgLog((LOG_TRACE, 50, L"::Decode() - decoding failed despite successfull parsing"));
@@ -1065,9 +1045,6 @@ STDMETHODIMP CDecAvcodec::Decode(const BYTE *buffer, int buflen, REFERENCE_TIME
if (m_nCodecId == AV_CODEC_ID_MPEG2VIDEO)
pOutFrame->avgFrameDuration = GetFrameDuration();
- if (m_bEndOfSequence)
- pOutFrame->flags |= LAV_FRAME_FLAG_END_OF_SEQUENCE;
-
if (map.conversion) {
ConvertPixFmt(m_pFrame, pOutFrame);
} else {
@@ -1098,13 +1075,6 @@ STDMETHODIMP CDecAvcodec::Decode(const BYTE *buffer, int buflen, REFERENCE_TIME
}
}
- if (bEndOfSequenceFlush) {
- m_bEndOfSequence = TRUE;
- EndOfStream();
- m_bEndOfSequence = FALSE;
- Deliver(m_pCallback->GetFlushFrame());
- }
-
return S_OK;
}
diff --git a/decoder/LAVVideo/decoders/avcodec.h b/decoder/LAVVideo/decoders/avcodec.h
index 5e916c13..bbaa2d04 100644
--- a/decoder/LAVVideo/decoders/avcodec.h
+++ b/decoder/LAVVideo/decoders/avcodec.h
@@ -110,7 +110,6 @@ private:
int m_iInterlaced;
BOOL m_bDR1;
- BOOL m_bEndOfSequence;
#if AVCODEC_USE_DR1
CCritSec m_BufferCritSec;
diff --git a/decoder/LAVVideo/decoders/cuvid.cpp b/decoder/LAVVideo/decoders/cuvid.cpp
index 5aaae189..2d21c1e4 100644
--- a/decoder/LAVVideo/decoders/cuvid.cpp
+++ b/decoder/LAVVideo/decoders/cuvid.cpp
@@ -127,7 +127,6 @@ CDecCuvid::CDecCuvid(void)
, m_bVDPAULevelC(FALSE)
, m_rtPrevDiff(AV_NOPTS_VALUE)
, m_bARPresent(TRUE)
- , m_bEndOfSequence(FALSE)
{
ZeroMemory(&cuda, sizeof(cuda));
ZeroMemory(&m_VideoFormat, sizeof(m_VideoFormat));
@@ -1061,9 +1060,6 @@ STDMETHODIMP CDecCuvid::Deliver(CUVIDPARSERDISPINFO *cuviddisp, int field)
pFrame->stride[0] = pFrame->stride[1] = pitch;
pFrame->flags |= LAV_FRAME_FLAG_BUFFER_MODIFY;
- if (m_bEndOfSequence)
- pFrame->flags |= LAV_FRAME_FLAG_END_OF_SEQUENCE;
-
m_pCallback->Deliver(pFrame);
return S_OK;
@@ -1094,8 +1090,6 @@ STDMETHODIMP CDecCuvid::CheckH264Sequence(const BYTE *buffer, int buflen)
return S_FALSE;
}
-extern "C" const uint8_t *avpriv_mpv_find_start_code(const uint8_t *p, const uint8_t *end, uint32_t *state);
-
STDMETHODIMP CDecCuvid::Decode(const BYTE *buffer, int buflen, REFERENCE_TIME rtStart, REFERENCE_TIME rtStop, BOOL bSyncPoint, BOOL bDiscontinuity)
{
CUresult result;
@@ -1152,25 +1146,6 @@ STDMETHODIMP CDecCuvid::Decode(const BYTE *buffer, int buflen, REFERENCE_TIME rt
return E_FAIL;
}
- // Check for MPEG2 End-Of-Sequence code, and immediately flush all frames out of the decoder
- // This is mostly required to get still-frames in DVDs (and possibly Blu-rays) to output as soon as they are ready,
- // otherwise they might be delayed until the next track switch, and all you see is black (or the previous image)
- if (m_VideoDecoderInfo.CodecType == cudaVideoCodec_MPEG2 && pCuvidPacket.payload && pCuvidPacket.payload_size >= 4) {
- uint32_t state = (uint32_t)-1;
- const uint8_t *p = pCuvidPacket.payload, *end = pCuvidPacket.payload + pCuvidPacket.payload_size;
- while (p < end) {
- p = avpriv_mpv_find_start_code(p, end, &state);
- if (state == 0x000001b7) {
- DbgLog((LOG_TRACE, 50, L"Found SEQ_END_CODE at %p (end: %p)", p, end));
- m_bEndOfSequence = TRUE;
- EndOfStream();
- m_bEndOfSequence = FALSE;
- m_pCallback->Deliver(m_pCallback->GetFlushFrame());
- break;
- }
- }
- }
-
return S_OK;
}
diff --git a/decoder/LAVVideo/decoders/cuvid.h b/decoder/LAVVideo/decoders/cuvid.h
index 595629be..84b3945f 100644
--- a/decoder/LAVVideo/decoders/cuvid.h
+++ b/decoder/LAVVideo/decoders/cuvid.h
@@ -165,7 +165,6 @@ private:
int m_nSoftTelecine;
BOOL m_bTFF;
BOOL m_bARPresent;
- BOOL m_bEndOfSequence;
HWND m_hwnd;
};