Example #1
0
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;
}