FFmpegPreset::Presets FFmpegPreset::getCodecListWithConfig( ) { Presets list; Presets::iterator config; for ( config = presets.begin() ; config != presets.end(); config++ ) { std::string codec = getCodecName( *config ); Presets::iterator fileIt; bool exist = false; for( fileIt = list.begin(); fileIt < list.end(); fileIt++ ) { if( std::strcmp( (*fileIt).c_str(), codec.c_str() ) == 0 ) { exist = true; break; } } if( !exist ) { list.push_back( codec ); } } return list; }
const char_t* TautoPresetProps::getDecoder(void) { if (!decoder) { decoder=getCodecName((CodecID)deci->getCurrentCodecId2()); } return decoder; }
FFmpegPreset::Presets FFmpegPreset::getConfigList( const std::string& codec ) { Presets list; Presets::iterator config; for ( config = presets.begin() ; config != presets.end(); config++ ) { std::string c = getCodecName( *config ); if( std::strcmp( c.c_str(), codec.c_str() ) == 0 ) { list.push_back( getConfigName( *config ) ); } } return list; }
std::string FFmpegPreset::getFilename( const std::string& codec, const std::string& preset ) { std::string filename; Presets::iterator config; for ( config = presets.begin() ; config != presets.end(); config++ ) { std::string c = getCodecName( *config ); std::string p = getConfigName( *config ); if( std::strcmp( c.c_str(), codec.c_str() ) == 0 && std::strcmp( p.c_str(), preset.c_str() ) == 0 ) { filename = *config; } } return filename; }
const char* captureGetAudioFormatName() { return getCodecName(&g_AudioFormat, g_Capture.AudioFormat); }
const char* captureGetIRFormatName() { return getCodecName(&g_IRFormat, g_Capture.IRFormat); }
const char* captureGetDepthFormatName() { return getCodecName(&g_DepthFormat, g_Capture.DepthFormat); }
STDMETHODIMP TffdshowDecAudioInputPin::Receive(IMediaSample* pIn) { if (this != filter->inpin) { //DPRINTF(_l("TffdshowDecAudioInputPin::Receive Not right pin : this = %u, filter inpin = %u"), this, filter->inpin); if (m_useBlock) { m_evBlock.Wait(); } else { return S_FALSE; } } if (!isActive()) { //DPRINTF(_l("TffdshowDecAudioInputPin::Receive Pin unlocked : this = %u, filter inpin = %u"), this, filter->inpin); if (this != filter->inpin) { return S_FALSE; } return E_FAIL; } //CAutoLock cAutoLock(&m_csReceive); if (filter->IsStopped()) { return S_FALSE; } HRESULT hr = TinputPin::Receive(pIn); if (hr != S_OK) { return hr; } AM_SAMPLE2_PROPERTIES* const pProps = SampleProps(); if (pProps->dwStreamId != AM_STREAM_MEDIA) { return filter->m_pOutput->Deliver(pIn); } AM_MEDIA_TYPE *pmt = NULL; if (SUCCEEDED(pIn->GetMediaType(&pmt)) && pmt) { CMediaType mt(*pmt); SetMediaType(&mt); DeleteMediaType(pmt); pmt = NULL; } BYTE *src = NULL; if (FAILED(hr = pIn->GetPointer(&src))) { return hr; } long srclen = pIn->GetActualDataLength(); if (strippacket) { StripPacket(src, srclen); } REFERENCE_TIME rtStart = _I64_MIN, rtStop = _I64_MIN; hr = pIn->GetTime(&rtStart, &rtStop); if (hr == S_OK) { insample_rtStart = rtStart; insample_rtStop = rtStop; //DPRINTF(_l("TffdshowDecAudioInputPin::Receive audio sample start duration %I64i %I64i"),rtStart,rtStop-rtStart); } if (pIn->IsDiscontinuity() == S_OK) { filter->discontinuity = true; buf.clear(); if (FAILED(hr)) { return S_OK; } filter->m_rtStartDec = filter->m_rtStartProc = rtStart; } if (SUCCEEDED(hr)) { REFERENCE_TIME j = filter->m_rtStartDec - rtStart; jitter = int(j); if ((uint64_t)ff_abs(j) > 100 * (REF_SECOND_MULT / 1000) // +-100ms jitter is allowed for now && codecId != AV_CODEC_ID_FLAC && codecId != AV_CODEC_ID_TTA && codecId != AV_CODEC_ID_WAVPACK && codecId != AV_CODEC_ID_TRUEHD && codecId != AV_CODEC_ID_MLP && codecId != AV_CODEC_ID_COOK && !bitstream_codec(codecId) && filter->getParam2(IDFF_audio_decoder_JitterCorrection)) { DPRINTF(_l("jitter correction")); buf.clear(); newSrcBuffer.clear(); filter->m_rtStartDec = filter->m_rtStartProc = rtStart; if (audioParser) { audioParser->NewSegment(); } } } buf.append(src, srclen); buf.reserve(buf.size() + 32); AVCodecID newCodecId = codecId; TaudioParserData audioParserData; // Before sending data to the decoder, we parse it switch (codecId) { case AV_CODEC_ID_DTS: case CODEC_ID_LIBDTS: case CODEC_ID_SPDIF_DTS: case AV_CODEC_ID_AC3: case AV_CODEC_ID_EAC3: case AV_CODEC_ID_MLP: case AV_CODEC_ID_TRUEHD: case CODEC_ID_LIBA52: case CODEC_ID_SPDIF_AC3: case CODEC_ID_PCM: case CODEC_ID_BITSTREAM_TRUEHD: case CODEC_ID_BITSTREAM_DTSHD: // Search for DTS in Wav only if option is checked if (codecId == CODEC_ID_PCM && !searchdts) { break; } // Do not search for DTS in PCM in next frames (otherwise DTS syncword maybe wrongly detected) searchdts = false; newCodecId = audioParser->parseStream(buf.size() ? &buf[0] : NULL, (int)buf.size(), &newSrcBuffer); if (newCodecId == AV_CODEC_ID_NONE) { newSrcBuffer.clear(); break; } // Get updated data from the parser audioParserData = audioParser->getParserData(); // Clear input buffer (if 2 source buffers are coexisting, sound will be garbled) buf.clear(); if (codecId != newCodecId) { DPRINTF(_l("TffdshowDecAudioInputPin : switching codec from %s to %s"), getCodecName(codecId), getCodecName(newCodecId)); codecId = newCodecId; // Update input sample format from (corrected or updated) parser data if (audioParserData.channels != 0) { filter->insf.setChannels(audioParserData.channels); } if (audioParserData.sample_rate != 0) { filter->insf.freq = audioParserData.sample_rate; } if (audioParserData.sample_format != 0) { filter->insf.sf = audioParserData.sample_format; } filter->insf.alternateSF = audioParserData.alternateSampleFormat; // Sample format from audio parser data TsampleFormat fmt = TsampleFormat( (audioParserData.sample_format != 0) ? audioParserData.sample_format : TsampleFormat::SF_PCM16, audioParserData.sample_rate, audioParserData.channels); // Reinitialize the audio codec according to the new codecId DPRINTF(_l("TffdshowDecAudioInputPin::Receive : Initialize audio codec %s"), getCodecName(codecId)); if (audio) { delete audio; codec = audio = NULL; } codec = audio = TaudioCodec::initSource(filter, this, codecId, filter->insf, filter->insf.toCMediaType()); if (!audio) { return false; } jitter = 0; } // Update libavcodec context with correct channels and bitrate read from parser if (lavc_codec(codecId)) { TaudioCodecLibavcodec *audioCodecLibavcodec = (TaudioCodecLibavcodec*)audio; if (audioCodecLibavcodec) { if (audioParserData.channels != 0) { audioCodecLibavcodec->avctx->channels = audioParserData.channels; } if (audioParserData.bit_rate != 0) { audioCodecLibavcodec->avctx->bit_rate = audioParserData.bit_rate; } if (audioParserData.sample_rate != 0) { audioCodecLibavcodec->avctx->sample_rate = audioParserData.sample_rate; } } } if (audioParserData.channels != 0) { filter->insf.setChannels(audioParserData.channels); } if (audioParserData.sample_rate != 0) { filter->insf.freq = audioParserData.sample_rate; } if (audioParserData.sample_format != 0) { filter->insf.sf = audioParserData.sample_format; } newSrcBuffer.reserve(newSrcBuffer.size() + 32); hr = audio->decode(newSrcBuffer); if (hr == S_FALSE) { return S_OK; } else if (hr != S_OK) { DPRINTF(_l("TffdshowDecAudioInputPin::Receive decode failed pin %u (%lx)"), this, hr); } return hr; break; default: // Decode data hr = audio->decode(buf); if (hr == S_FALSE) { return S_OK; } else if (hr != S_OK) { DPRINTF(_l("TffdshowDecAudioInputPin::Receive decode failed pin %u (%lx)"), this, hr); } return hr; break; } hr = audio->decode(buf); if (hr == S_FALSE) { return S_OK; } else if (hr != S_OK) { DPRINTF(_l("TffdshowDecAudioInputPin::Receive decode failed pin %u (%lx)"), this, hr); } return hr; }
bool TffdshowVideoInputPin::init(const CMediaType &mt) { DPRINTF(_l("TffdshowVideoInputPin::init")); bool dont_use_rtStop_from_upper_stream = false; isInterlacedRawVideo = false; if (mt.formattype == FORMAT_VideoInfo) { VIDEOINFOHEADER *vih = (VIDEOINFOHEADER*)mt.pbFormat; init_VIH_and_VIH2_common_part(vih->rcSource, vih->rcTarget, vih->dwBitRate, vih->dwBitErrorRate, vih->AvgTimePerFrame, vih->bmiHeader); } else if (mt.formattype == FORMAT_VideoInfo2) { VIDEOINFOHEADER2 *vih2 = (VIDEOINFOHEADER2*)mt.pbFormat; init_VIH_and_VIH2_common_part(vih2->rcSource, vih2->rcTarget, vih2->dwBitRate, vih2->dwBitErrorRate, vih2->AvgTimePerFrame, vih2->bmiHeader); isInterlacedRawVideo = vih2->dwInterlaceFlags & AMINTERLACE_IsInterlaced; pictIn.setDar(Rational(vih2->dwPictAspectRatioX, vih2->dwPictAspectRatioY)); DPRINTF(_l("TffdshowVideoInputPin::initVideo: darX:%i, darY:%i"), vih2->dwPictAspectRatioX, vih2->dwPictAspectRatioY); } else if (mt.formattype == FORMAT_MPEGVideo) { MPEG1VIDEOINFO *mpeg1info = (MPEG1VIDEOINFO*)mt.pbFormat; biIn.bmiHeader = mpeg1info->hdr.bmiHeader; biIn.bmiHeader.biCompression = FOURCC_MPG1; pictIn.setSize(std::max(mpeg1info->hdr.rcSource.right, mpeg1info->hdr.bmiHeader.biWidth), std::max(mpeg1info->hdr.rcSource.bottom, mpeg1info->hdr.bmiHeader.biHeight)); } else if (mt.formattype == FORMAT_MPEG2Video) { MPEG2VIDEOINFO *mpeg2info = (MPEG2VIDEOINFO*)mt.pbFormat; biIn.bmiHeader = mpeg2info->hdr.bmiHeader; pictIn.setSize(std::max(mpeg2info->hdr.rcSource.right, mpeg2info->hdr.bmiHeader.biWidth), std::max(mpeg2info->hdr.rcSource.bottom, mpeg2info->hdr.bmiHeader.biHeight)); pictIn.setDar(Rational(mpeg2info->hdr.dwPictAspectRatioX, mpeg2info->hdr.dwPictAspectRatioY)); if (biIn.bmiHeader.biCompression == 0 || biIn.bmiHeader.biCompression == 0x0038002d) { if (mt.subtype == MEDIASUBTYPE_H264_TRANSPORT) { biIn.bmiHeader.biCompression = FOURCC_H264; } else if (mt.subtype == MEDIASUBTYPE_AVC1 || mt.subtype == MEDIASUBTYPE_avc1 || mt.subtype == MEDIASUBTYPE_H264 || mt.subtype == MEDIASUBTYPE_h264 || mt.subtype == MEDIASUBTYPE_CCV1) { biIn.bmiHeader.biCompression = FOURCC_H264; } else { biIn.bmiHeader.biCompression = FOURCC_MPG2; } } else { biIn.bmiHeader.biCompression = FCCupper(biIn.bmiHeader.biCompression); dont_use_rtStop_from_upper_stream = true; } } else if (mt.formattype == FORMAT_TheoraIll) { memset(&biIn, 0, sizeof(biIn)); sTheoraFormatBlock *oggFormat = (sTheoraFormatBlock*)mt.pbFormat; biIn.bmiHeader.biCompression = FOURCC_THEO; pictIn.setSize(biIn.bmiHeader.biWidth = oggFormat->width, biIn.bmiHeader.biHeight = oggFormat->height); pictIn.setDar(Rational(oggFormat->aspectNumerator, oggFormat->aspectDenominator)); biIn.bmiHeader.biBitCount = 12; } else if (mt.formattype == FORMAT_RLTheora) { struct RLTheora { VIDEOINFOHEADER hdr; DWORD headerSize[3]; // 0: Header, 1: Comment, 2: Codebook }; const RLTheora *rl = (const RLTheora*)mt.pbFormat; GetBitContext gb; init_get_bits(&gb, (const uint8_t*)(rl + 1), rl->headerSize[0]); int ptype = get_bits(&gb, 8); if (!(ptype & 0x80)) { return false; } biIn.bmiHeader.biCompression = FOURCC_THEO; skip_bits(&gb, 6 * 8); /* "theora" */ int major = get_bits(&gb, 8); /* version major */ int minor = get_bits(&gb, 8); /* version minor */ int micro = get_bits(&gb, 8); /* version micro */ int theora = (major << 16) | (minor << 8) | micro; if (theora < 0x030200) { ;//flipped_image = 1; } biIn.bmiHeader.biWidth = get_bits(&gb, 16) << 4; biIn.bmiHeader.biHeight = get_bits(&gb, 16) << 4; pictIn.setSize(biIn.bmiHeader.biWidth, biIn.bmiHeader.biHeight); skip_bits(&gb, 24); /* frame width */ skip_bits(&gb, 24); /* frame height */ skip_bits(&gb, 8); /* offset x */ skip_bits(&gb, 8); /* offset y */ skip_bits(&gb, 32); /* fps numerator */ skip_bits(&gb, 32); /* fps denumerator */ Rational sample_aspect_ratio; sample_aspect_ratio.num = get_bits(&gb, 24); /* aspect numerator */ sample_aspect_ratio.den = get_bits(&gb, 24); /* aspect denumerator */ pictIn.setSar(sample_aspect_ratio); } else { return false; } REFERENCE_TIME avgTimePerFrame0 = getAvgTimePerFrame(mt); avgTimePerFrame = avgTimePerFrame0 ? avgTimePerFrame0 : 400000; char_t pomS[60]; DPRINTF(_l("TffdshowVideoInputPin::initVideo: %s, width:%i, height:%i, aspectX:%i, aspectY:%i"), fourcc2str(hdr2fourcc(&biIn.bmiHeader, &mt.subtype), pomS, 60) , pictIn.rectFull.dx, pictIn.rectFull.dy, pictIn.rectFull.dar().num, pictIn.rectFull.dar().den); again: codecId = (AVCodecID)getVideoCodecId(&biIn.bmiHeader, &mt.subtype, &biIn.bmiHeader.biCompression); // FIXME Experimental // // VC1 (in EVO) stream may have attached media type during playback (say, once per 5 second). // When I try to use its codec private data, the video heavily stutters. // pContext.pDMO->SetInputType (Currently ff_wmv.cpp line 769) takes too long. // I gave up using it and decided to ignore it during playback of VC1 stream. // It works fine for my sample. if (video) { if (/*video->codecId == CODEC_ID_WMV9_LIB && */wasVC1 && biIn.bmiHeader.biCompression == 0x31435657 /* "WVC1" */) { return true; } else if (is_quicksync_codec(video->codecId)) { // check if output pin is connected to a supported filter IPin *pConnectedPin = NULL; if (fv && fv->output) { pConnectedPin = fv->output->GetConnected(); const CLSID &out = GetCLSID(pConnectedPin); if (out == CLSID_SampleGrabber || out == CLSID_MediaDetFilter) { delete video; codec = video = NULL; switch (codecId) { case CODEC_ID_H264_QUICK_SYNC: codecId = AV_CODEC_ID_H264; break; case CODEC_ID_MPEG2_QUICK_SYNC: codecId = AV_CODEC_ID_MPEG2VIDEO; break; case CODEC_ID_VC1_QUICK_SYNC: codecId = CODEC_ID_WMV9_LIB; break; default: ASSERT(FALSE); // this shouldn't happen! } } } // no need to reset anything if (video) { return true; } } else { delete video; codec = video = NULL; } } DPRINTF(_l("TffdshowVideoInputPin::initVideo Codec detected : %s"), getCodecName(codecId)); if (codecId == AV_CODEC_ID_NONE) { if (pCompatibleFilter != NULL) { rawDecode = true; if (video) { delete video; codec = video = NULL; } return true; } return false; } if (h264_codec(codecId) || codecId == CODEC_ID_H264_DXVA) { Textradata extradata(mt, 16); if (extradata.size) { H264_SPS sps; decodeH264SPS(extradata.data, extradata.size, pictIn, &sps); // Set frame rate information from SPS::VUI. if (!avgTimePerFrame0 // Use information from the upper stream filter if available. && sps.timing_info_present_flag && sps.time_scale && sps.num_units_in_tick) { avgTimePerFrame = 2 * REF_SECOND_MULT * sps.num_units_in_tick / sps.time_scale; } } } else if (mpeg4_codec(codecId)) { Textradata extradata(mt, 16); if (extradata.size) { decodeMPEG4pictureHeader(extradata.data, extradata.size, pictIn); } } else if (mpeg12_codec(codecId)) { Textradata extradata(mt, 16); if (extradata.size) { bool isH264; if (decodeMPEGsequenceHeader(biIn.bmiHeader.biCompression == FOURCC_MPG2, extradata.data, extradata.size, pictIn, &isH264) && isH264) { biIn.bmiHeader.biCompression = FOURCC_H264; goto again; } } } if (!fv->sink) { rawDecode = true; if (video) { delete video; codec = video = NULL; } } else { fv->initCodecSettings(); codec = video = TvideoCodecDec::initDec(fv->deci, fv->sink, codecId, biIn.bmiHeader.biCompression, mt); if (!video) { return false; } else { static const GUID CLSID_NeroDigitalParser = {0xE206E4DE, 0xA7EE, 0x4A62, 0xB3, 0xE9, 0x4F, 0xBC, 0x8F, 0xE8, 0x4C, 0x73}; static const GUID CLSID_HaaliMatroskaFile = {0x55DA30FC, 0xF16B, 0x49FC, 0xBA, 0xA5, 0xAE, 0x59, 0xFC, 0x65, 0xF8, 0x2D}; codecId = video->codecId; //dont_use_rtStop_from_upper_stream=biIn.bmiHeader.biCompression==FOURCC_AVC1 && (searchPreviousFilter(this,CLSID_NeroDigitalParser) || searchPreviousFilter(this,CLSID_HaaliMatroskaFile)); video->connectedSplitter = connectedSplitter; video->isInterlacedRawVideo = isInterlacedRawVideo; video->containerSar = pictIn.rectFull.sar; if (!video->beginDecompress(pictIn, biIn.bmiHeader.biCompression, mt, (dont_use_rtStop_from_upper_stream ? TvideoCodecDec::SOURCE_REORDER : 0))) { delete video; codec = video = NULL; return false; } } rawDecode = raw_codec(codecId); } allocator.NotifyMediaType(mt); strippacket = !!(mt.majortype == MEDIATYPE_DVD_ENCRYPTED_PACK); wasVC1 = biIn.bmiHeader.biCompression == 0x31435657 /* "WVC1" */; return true; }