Skip to content

Commit

Permalink
fixed: probing of some mpeg formats (#8500, #10213, #11121)
Browse files Browse the repository at this point in the history
Use the newly public higher-level libavformat probing function
av_probe_input_buffer() for probing when available.

This fixes several cases where files could not be played back due to too
small a probe buffer. Also, lavf can automatically re-use data read by
av_probe_input_buffer() for subsequent buffer reads, allowing us to drop
the extra seek to the beginning after the probe when that function is
used.

Keep the old lower-level method for use when built against old external
FFmpeg or when we want to probe for IEC 61937 or DTS specifically
(dts-in-wav, ac3-in-wav, AC3/DTS audio discs).
  • Loading branch information
anssih committed Feb 11, 2011
1 parent cedaab7 commit dc4f7ab
Showing 1 changed file with 63 additions and 59 deletions.
122 changes: 63 additions & 59 deletions xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,64 +312,84 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)

if( iformat == NULL )
{
#if defined(USE_EXTERNAL_FFMPEG) && LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(52,98,0)
// API added on: 2011-02-09
// Old versions of ffmpeg do not have av_probe_input_format, so we need
// to always probe using the lower-level functions as well.
const bool legacyProbing = true;
#else
const bool legacyProbing = false;
#endif
// let ffmpeg decide which demuxer we have to open
AVProbeData pd;
BYTE probe_buffer[FFMPEG_FILE_BUFFER_SIZE + AVPROBE_PADDING_SIZE];

// init probe data
pd.buf = probe_buffer;
pd.filename = strFile.c_str();

// read data using avformat's buffers
pd.buf_size = m_dllAvFormat.get_buffer(m_ioContext, pd.buf, m_ioContext->max_packet_size ? m_ioContext->max_packet_size : m_ioContext->buffer_size);
if (pd.buf_size <= 0)
{
CLog::Log(LOGERROR, "%s - error reading from input stream, %s", __FUNCTION__, strFile.c_str());
return false;
}
memset(pd.buf+pd.buf_size, 0, AVPROBE_PADDING_SIZE);

// restore position again
m_dllAvFormat.url_fseek(m_ioContext , 0, SEEK_SET);

bool trySPDIFonly = (m_pInput->GetContent() == "audio/x-spdif-compressed");

if (!trySPDIFonly)
iformat = m_dllAvFormat.av_probe_input_format(&pd, 1);

// the advancedsetting is for allowing the user to force outputting the
// 44.1 kHz DTS wav file as PCM, so that an A/V receiver can decode
// it (this is temporary until we handle 44.1 kHz passthrough properly)
if (trySPDIFonly || (iformat && strcmp(iformat->name, "wav") == 0 && !g_advancedSettings.m_dvdplayerIgnoreDTSinWAV))
m_dllAvFormat.av_probe_input_buffer(m_ioContext, &iformat, strFile.c_str(), NULL, 0, 0);

// Use the more low-level code in case we have been built against an old
// FFmpeg without the above av_probe_input_buffer(), or in case we only
// want to probe for spdif (DTS or IEC 61937) compressed audio
// specifically, or in case the file is a wav which may contain DTS or
// IEC 61937 (e.g. ac3-in-wav) and we want to check for those formats.
if (legacyProbing || trySPDIFonly || (iformat && strcmp(iformat->name, "wav") == 0))
{
// check for spdif and dts
// This is used with wav files and audio CDs that may contain
// a DTS or AC3 track padded for S/PDIF playback. If neither of those
// is present, we assume it is PCM audio.
// AC3 is always wrapped in iec61937 (ffmpeg "spdif"), while DTS
// may be just padded.
AVInputFormat *iformat2;
iformat2 = m_dllAvFormat.av_find_input_format("spdif");

if (iformat2 && iformat2->read_probe(&pd) > AVPROBE_SCORE_MAX / 4)
AVProbeData pd;
BYTE probe_buffer[FFMPEG_FILE_BUFFER_SIZE + AVPROBE_PADDING_SIZE];

// init probe data
pd.buf = probe_buffer;
pd.filename = strFile.c_str();

// read data using avformat's buffers
pd.buf_size = m_dllAvFormat.get_buffer(m_ioContext, pd.buf, m_ioContext->max_packet_size ? m_ioContext->max_packet_size : m_ioContext->buffer_size);
if (pd.buf_size <= 0)
{
iformat = iformat2;
CLog::Log(LOGERROR, "%s - error reading from input stream, %s", __FUNCTION__, strFile.c_str());
return false;
}
else
memset(pd.buf+pd.buf_size, 0, AVPROBE_PADDING_SIZE);

// restore position again
m_dllAvFormat.url_fseek(m_ioContext , 0, SEEK_SET);

if (legacyProbing && !trySPDIFonly)
iformat = m_dllAvFormat.av_probe_input_format(&pd, 1);

// the advancedsetting is for allowing the user to force outputting the
// 44.1 kHz DTS wav file as PCM, so that an A/V receiver can decode
// it (this is temporary until we handle 44.1 kHz passthrough properly)
if (trySPDIFonly || (iformat && strcmp(iformat->name, "wav") == 0 && !g_advancedSettings.m_dvdplayerIgnoreDTSinWAV))
{
// not spdif or no spdif demuxer, try dts
iformat2 = m_dllAvFormat.av_find_input_format("dts");
// check for spdif and dts
// This is used with wav files and audio CDs that may contain
// a DTS or AC3 track padded for S/PDIF playback. If neither of those
// is present, we assume it is PCM audio.
// AC3 is always wrapped in iec61937 (ffmpeg "spdif"), while DTS
// may be just padded.
AVInputFormat *iformat2;
iformat2 = m_dllAvFormat.av_find_input_format("spdif");

if (iformat2 && iformat2->read_probe(&pd) > AVPROBE_SCORE_MAX / 4)
{
iformat = iformat2;
}
else if (trySPDIFonly)
else
{
// not dts either, return false in case we were explicitely
// requested to only check for S/PDIF padded compressed audio
CLog::Log(LOGDEBUG, "%s - not spdif or dts file, fallbacking", __FUNCTION__);
return false;
// not spdif or no spdif demuxer, try dts
iformat2 = m_dllAvFormat.av_find_input_format("dts");

if (iformat2 && iformat2->read_probe(&pd) > AVPROBE_SCORE_MAX / 4)
{
iformat = iformat2;
}
else if (trySPDIFonly)
{
// not dts either, return false in case we were explicitely
// requested to only check for S/PDIF padded compressed audio
CLog::Log(LOGDEBUG, "%s - not spdif or dts file, fallbacking", __FUNCTION__);
return false;
}
}
}
}
Expand All @@ -389,22 +409,6 @@ bool CDVDDemuxFFmpeg::Open(CDVDInputStream* pInput)
iformat = m_dllAvFormat.av_find_input_format("flv");
}

if (!iformat)
{
// av_probe_input_format failed, re-probe the ffmpeg/ffplay method.
// av_open_input_file uses av_probe_input_format2 for probing format,
// starting at 2048, up to max buffer size of 1048576. We just probe to
// the buffer size allocated above so as to avoid seeks on content that
// might not be seekable.
int max_buf_size = pd.buf_size;
for (int probe_size=std::min(2048, pd.buf_size); probe_size <= max_buf_size && !iformat; probe_size<<=1)
{
CLog::Log(LOGDEBUG, "%s - probing failed, re-probing with probe size [%d]", __FUNCTION__, probe_size);
int score= probe_size < max_buf_size ? AVPROBE_SCORE_MAX/4 : 0;
pd.buf_size = probe_size;
iformat = m_dllAvFormat.av_probe_input_format2(&pd, 1, &score);
}
}
if (!iformat)
{
CLog::Log(LOGERROR, "%s - error probing input format, %s", __FUNCTION__, strFile.c_str());
Expand Down

0 comments on commit dc4f7ab

Please sign in to comment.