TaudioCodec* TaudioCodec::getDecLib(CodecID codecId,IffdshowBase *deci,IdecAudioSink *sink) { TaudioCodec *movie; if (lavc_codec (codecId)) { movie=new TaudioCodecLibavcodec(deci,sink); } else if (raw_codec (codecId)) { movie=new TaudioCodecUncompressed(deci,sink); } else if (codecId==CODEC_ID_LIBMAD) { movie=new TaudioCodecLibMAD(deci,sink); } else if (codecId==CODEC_ID_LIBFAAD) { movie=new TaudioCodecLibFAAD(deci,sink); } else if (codecId==CODEC_ID_AVISYNTH) { movie=new TaudioCodecAvisynth(deci,sink); } else if (codecId==CODEC_ID_LIBA52) { movie=new TaudioCodecLiba52(deci,sink); } else if (codecId==CODEC_ID_LIBDTS) { movie=new TaudioCodecLibDTS(deci,sink); } else if (spdif_codec(codecId) || bitstream_codec(codecId)) { movie=new TaudioCodecBitstream(deci,sink); } else { return NULL; } movie->codecId=codecId; return movie; }
STDMETHODIMP TffdshowVideoInputPin::GetAllocator(IMemAllocator** ppAllocator) { if (!raw_codec(codecId)) { return TinputPin::GetAllocator(ppAllocator); } else { CheckPointer(ppAllocator, E_POINTER); if (m_pAllocator == NULL) { m_pAllocator = &allocator; m_pAllocator->AddRef(); } m_pAllocator->AddRef(); *ppAllocator = m_pAllocator; return NOERROR; } }
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; }