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>2016-02-16 15:09:16 +0300
committerHendrik Leppkes <h.leppkes@gmail.com>2016-02-16 15:09:16 +0300
commitc2793e03be34855fac4e9f24040ae06d66e4eacd (patch)
tree3268f8edfb022c2037724c95b347da90b94e4540 /demuxer/Demuxers/LAVFDemuxer.cpp
parent10acd07718a1390e6c0458e5c3b5c94b02c2c7d6 (diff)
Add support for combining H264 Base and MVC Extensions streams
This allows support for demuxing SSIF files from Blu-ray discs.
Diffstat (limited to 'demuxer/Demuxers/LAVFDemuxer.cpp')
-rw-r--r--demuxer/Demuxers/LAVFDemuxer.cpp86
1 files changed, 85 insertions, 1 deletions
diff --git a/demuxer/Demuxers/LAVFDemuxer.cpp b/demuxer/Demuxers/LAVFDemuxer.cpp
index b8b586a2..5106bb2e 100644
--- a/demuxer/Demuxers/LAVFDemuxer.cpp
+++ b/demuxer/Demuxers/LAVFDemuxer.cpp
@@ -703,6 +703,7 @@ done:
void CLAVFDemuxer::CleanupAVFormat()
{
+ FlushMVCExtensionQueue();
if (m_avFormat) {
avformat_close_input(&m_avFormat);
}
@@ -749,6 +750,10 @@ HRESULT CLAVFDemuxer::SetActiveStream(StreamType type, int pid)
AVStream *st = m_avFormat->streams[idx];
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
st->discard = (m_dActiveStreams[video] == idx) ? AVDISCARD_DEFAULT : AVDISCARD_ALL;
+
+ // don't discard h264 mvc streams
+ if (m_bH264MVCCombine && st->codec->codec_id == AV_CODEC_ID_H264_MVC)
+ st->discard = AVDISCARD_DEFAULT;
} else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
st->discard = (m_dActiveStreams[audio] == idx) ? AVDISCARD_DEFAULT : AVDISCARD_ALL;
// If the stream is a sub stream, make sure to activate the main stream as well
@@ -1119,6 +1124,7 @@ STDMETHODIMP CLAVFDemuxer::GetNextPacket(Packet **ppPacket)
av_packet_unref(&pkt);
} else {
// Check right here if the stream is active, we can drop the package otherwise.
+ AVStream *stream = m_avFormat->streams[pkt.stream_index];
BOOL streamActive = FALSE;
BOOL forcedSubStream = FALSE;
for(int i = 0; i < unknown; ++i) {
@@ -1133,12 +1139,15 @@ STDMETHODIMP CLAVFDemuxer::GetNextPacket(Packet **ppPacket)
forcedSubStream = streamActive = TRUE;
}
+ // Accept H264 MVC streams, as they get combined with the base stream later
+ if (m_bH264MVCCombine && stream->codec->codec_id == AV_CODEC_ID_H264_MVC)
+ streamActive = TRUE;
+
if(!streamActive) {
av_packet_unref(&pkt);
return S_FALSE;
}
- AVStream *stream = m_avFormat->streams[pkt.stream_index];
pPacket = new Packet();
if (!pPacket)
return E_OUTOFMEMORY;
@@ -1258,6 +1267,26 @@ STDMETHODIMP CLAVFDemuxer::GetNextPacket(Packet **ppPacket)
av_packet_unref(&pkt);
}
+ if (m_bH264MVCCombine && pPacket && pPacket->StreamId == m_nH264MVCExtensionStream) {
+ if (FAILED(QueueMVCExtension(pPacket))) {
+ SAFE_DELETE(pPacket);
+ return E_FAIL;
+ }
+
+ return S_FALSE;
+ }
+
+ if (m_bH264MVCCombine && pPacket && pPacket->StreamId == m_nH264MVCBaseStream) {
+ HRESULT hr = CombineMVCBaseExtension(pPacket);
+ if (hr != S_OK) {
+ SAFE_DELETE(pPacket);
+
+ // S_FALSE indicates a skipped packet, not a hard failure
+ if (hr == S_FALSE)
+ bReturnEmpty = true;
+ }
+ }
+
if (bReturnEmpty && !pPacket) {
return S_FALSE;
}
@@ -1271,6 +1300,50 @@ STDMETHODIMP CLAVFDemuxer::GetNextPacket(Packet **ppPacket)
return S_OK;
}
+STDMETHODIMP CLAVFDemuxer::QueueMVCExtension(Packet *pPacket)
+{
+ m_MVCExtensionQueue.push_back(pPacket);
+ return S_OK;
+}
+
+STDMETHODIMP CLAVFDemuxer::FlushMVCExtensionQueue()
+{
+ for (auto it = m_MVCExtensionQueue.begin(); it != m_MVCExtensionQueue.end(); it++) {
+ delete (*it);
+ }
+
+ m_MVCExtensionQueue.clear();
+ return S_OK;
+}
+
+STDMETHODIMP CLAVFDemuxer::CombineMVCBaseExtension(Packet *pBasePacket)
+{
+ while (!m_MVCExtensionQueue.empty()) {
+ Packet *pExtensionPacket = m_MVCExtensionQueue.front();
+ if (pExtensionPacket->rtDTS == pBasePacket->rtDTS) {
+ if (pBasePacket->Append(pExtensionPacket) < 0)
+ return E_FAIL;
+
+ m_MVCExtensionQueue.pop_front();
+ delete pExtensionPacket;
+ return S_OK;
+ }
+ else if (pExtensionPacket->rtDTS < pBasePacket->rtDTS)
+ {
+ DbgLog((LOG_TRACE, 10, L"CLAVFDemuxer::CombineMVCBaseExtension(): Dropping extension %I64d, base is %I64d", pExtensionPacket->rtDTS, pBasePacket->rtDTS));
+ m_MVCExtensionQueue.pop_front();
+ delete pExtensionPacket;
+ }
+ else if (pExtensionPacket->rtDTS > pBasePacket->rtDTS)
+ {
+ DbgLog((LOG_TRACE, 10, L"CLAVFDemuxer::CombineMVCBaseExtension(): Dropping base %I64d, next extension is %I64d", pBasePacket->rtDTS, pExtensionPacket->rtDTS));
+ return S_FALSE;
+ }
+ }
+ DbgLog((LOG_TRACE, 10, L"CLAVFDemuxer::CombineMVCBaseExtension(): Ran out of extension packets for base %I64d", pBasePacket->rtDTS));
+ return S_FALSE;
+}
+
STDMETHODIMP CLAVFDemuxer::Seek(REFERENCE_TIME rTime)
{
int seekStreamId = m_dActiveStreams[video];
@@ -1319,6 +1392,9 @@ retry:
m_bVC1SeenTimestamp = FALSE;
+ // Flush MVC extensions on seek (no-op if empty)
+ FlushMVCExtensionQueue();
+
return S_OK;
}
@@ -1336,6 +1412,9 @@ STDMETHODIMP CLAVFDemuxer::SeekByte(int64_t pos, int flags)
m_bVC1SeenTimestamp = FALSE;
+ // Flush MVC extensions on seek (no-op if empty)
+ FlushMVCExtensionQueue();
+
return S_OK;
}
@@ -1881,6 +1960,11 @@ STDMETHODIMP CLAVFDemuxer::CreateStreams()
if(!m_streams[subpic].empty()) {
CreateNoSubtitleStream();
}
+
+ if (m_bMPEGTS && !m_pBluRay) {
+ m_bH264MVCCombine = GetH264MVCStreamIndices(m_avFormat, &m_nH264MVCBaseStream, &m_nH264MVCExtensionStream);
+ }
+
return S_OK;
}