`

ffdshow 源代码分析 7: libavcodec视频解码器类(TvideoCodecLibavcodec)

 
阅读更多

 

注:写了一系列的有关ffdshow对解码器的封装的代码,列表如下:
ffdshow 源代码分析 6: 对解码器的dll的封装(libavcodec)
ffdshow 源代码分析 7: libavcodec视频解码器类(TvideoCodecLibavcodec)
ffdshow 源代码分析 8: 视频解码器类(TvideoCodecDec)
ffdshow 源代码分析 9: 编解码器有关类的总结

==========

 

前文已经介绍了ffdshow中对libavcodec封装的类Tlibavcodec:

ffdshow 源代码分析 6: 对解码器的dll的封装(libavcodec)

在这里我们进一步介绍一下其libavcodec解码器类。注意前一篇文章介绍的类Tlibavcodec仅仅是对libavcodec所在的“ffmpeg.dll”的函数进行封装的类。但Tlibavcodec并不是一个解码器类,其没有继承任何类,还不能为ffdshow所用。本文介绍的TvideoCodecLibavcodec才是libavcodec解码器类,其继承了TvideoCodecDec。

 

先来看一看TvideoCodecLibavcodec的定义吧,位于codecs-> TvideoCodecLibavcodec.h中。

 

/* 
 *雷霄骅 
 *leixiaohua1020@126.com 
 *中国传媒大学/数字电视技术 
 */ 
#ifndef _TVIDEOCODECLIBAVCODEC_H_
#define _TVIDEOCODECLIBAVCODEC_H_

#include "TvideoCodec.h"
#include "ffmpeg/Tlibavcodec.h"
#include "ffmpeg/libavcodec/avcodec.h"

#define MAX_THREADS 8 // FIXME: This is defined in mpegvideo.h.

struct Textradata;
class TccDecoder;
//libavcodec解码器(视频)
struct TlibavcodecExt {
private:
    static int get_buffer(AVCodecContext *s, AVFrame *pic);
    int (*default_get_buffer)(AVCodecContext *s, AVFrame *pic);
    static void release_buffer(AVCodecContext *s, AVFrame *pic);
    void (*default_release_buffer)(AVCodecContext *s, AVFrame *pic);
    static int reget_buffer(AVCodecContext *s, AVFrame *pic);
    int (*default_reget_buffer)(AVCodecContext *s, AVFrame *pic);
    static void handle_user_data0(AVCodecContext *c, const uint8_t *buf, int buf_len);
public:
    virtual ~TlibavcodecExt() {}
    void connectTo(AVCodecContext *ctx, Tlibavcodec *libavcodec);
    virtual void onGetBuffer(AVFrame *pic) {}
    virtual void onRegetBuffer(AVFrame *pic) {}
    virtual void onReleaseBuffer(AVFrame *pic) {}
    virtual void handle_user_data(const uint8_t *buf, int buf_len) {}
};
//libavcodec解码,不算是Filter?
class TvideoCodecLibavcodec : public TvideoCodecDec, public TvideoCodecEnc, public TlibavcodecExt
{
    friend class TDXVADecoderVC1;
    friend class TDXVADecoderH264;
protected:
	//各种信息(源自AVCodecContext中)
    Tlibavcodec *libavcodec;
    void create(void);
    AVCodec *avcodec;
    mutable char_t codecName[100];
    AVCodecContext *avctx;
    uint32_t palette[AVPALETTE_COUNT];
    int palette_size;
    AVFrame *frame;
    FOURCC fcc;
    FILE *statsfile;
    int cfgcomode;
    int psnr;
    bool isAdaptive;
    int threadcount;
    bool dont_use_rtStop_from_upper_stream; // and reordering of timpestams is justified.
    bool theorart;
    bool codecinited, ownmatrices;
    REFERENCE_TIME rtStart, rtStop, avgTimePerFrame, segmentTimeStart;
    REFERENCE_TIME prior_in_rtStart, prior_in_rtStop;
    REFERENCE_TIME prior_out_rtStart, prior_out_rtStop;

    struct {
        REFERENCE_TIME rtStart, rtStop;
        unsigned int srcSize;
    } b[MAX_THREADS + 1];
    int inPosB;

    Textradata *extradata;
    bool sendextradata;
    unsigned int mb_width, mb_height, mb_count;
    static void line(unsigned char *dst, unsigned int _x0, unsigned int _y0, unsigned int _x1, unsigned int _y1, stride_t strideY);
    static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, stride_t stride, int mulx, int muly, int dstdx, int dstdy);
    unsigned char *ffbuf;
    unsigned int ffbuflen;
    bool wasKey;
    virtual void handle_user_data(const uint8_t *buf, int buf_len);
    TccDecoder *ccDecoder;
    bool autoSkipingLoopFilter;
    enum AVDiscard initialSkipLoopFilter;
    int got_picture;
    bool firstSeek; // firstSeek means start of palyback.
    bool mpeg2_in_doubt;
    bool mpeg2_new_sequence;
    bool bReorderBFrame;
	//时长(AVCodecContext中)
    REFERENCE_TIME getDuration();
    int isReallyMPEG2(const unsigned char *src, size_t srcLen);
protected:
    virtual LRESULT beginCompress(int cfgcomode, uint64_t csp, const Trect &r);
    virtual bool beginDecompress(TffPictBase &pict, FOURCC infcc, const CMediaType &mt, int sourceFlags);
    virtual HRESULT flushDec(void);
    AVCodecParserContext *parser;
public:
    TvideoCodecLibavcodec(IffdshowBase *Ideci, IdecVideoSink *IsinkD);
    TvideoCodecLibavcodec(IffdshowBase *Ideci, IencVideoSink *IsinkE);
    virtual ~TvideoCodecLibavcodec();
    virtual int getType(void) const {
        return IDFF_MOVIE_LAVC;
    }
    virtual const char_t* getName(void) const;
    virtual int caps(void) const {
        return CAPS::VIS_MV | CAPS::VIS_QUANTS;
    }

    virtual void end(void);

    virtual void getCompressColorspaces(Tcsps &csps, unsigned int outDx, unsigned int outDy);
    virtual bool supExtradata(void);
    //获得ExtraData(AVCodecContext中)
	virtual bool getExtradata(const void* *ptr, size_t *len);
    virtual HRESULT compress(const TffPict &pict, TencFrameParams ¶ms);
    virtual HRESULT flushEnc(const TffPict &pict, TencFrameParams ¶ms) {
        return compress(pict, params);
    }

    virtual HRESULT decompress(const unsigned char *src, size_t srcLen, IMediaSample *pIn);
    virtual void onGetBuffer(AVFrame *pic);
    virtual bool onSeek(REFERENCE_TIME segmentStart);
    virtual bool onDiscontinuity(void);
	//画出运动矢量(AVCodecContext中)
    virtual bool drawMV(unsigned char *dst, unsigned int dx, stride_t stride, unsigned int dy) const;
    //编码器信息(AVCodecContext中)
	virtual void getEncoderInfo(char_t *buf, size_t buflen) const;
    virtual const char* get_current_idct(void);
    virtual HRESULT BeginFlush();
    bool isReorderBFrame() {
        return bReorderBFrame;
    };
    virtual void reorderBFrames(REFERENCE_TIME& rtStart, REFERENCE_TIME& rtStop);

    class Th264RandomAccess
    {
        friend class TvideoCodecLibavcodec;
    private:
        TvideoCodecLibavcodec* parent;
        int recovery_mode;  // 0:OK, 1:searching 2: found, 3:waiting for frame_num decoded, 4:waiting for POC outputed
        int recovery_frame_cnt;
        int recovery_poc;
        int thread_delay;

    public:
        Th264RandomAccess(TvideoCodecLibavcodec* Iparent);
        int search(uint8_t* buf, int buf_size);
        void onSeek(void);
        void judgeUsability(int *got_picture_ptr);
    } h264RandomAccess;
};

#endif

 

 

这里有一个类TlibavcodecExt,我觉得应该是扩展了Tlibavcodec的一些功能,在这里我们先不管它,直接看看TvideoCodecLibavcodec都包含了什么变量:

 

Tlibavcodec *libavcodec:该类封装了libavcodec的各种函数,在前一篇文章中已经做过介绍,在此不再重复叙述了。可以认为该变量是TvideoCodecLibavcodec类的灵魂,所有libavcodec中的函数都是通过该类调用的。

AVCodec *avcodec:FFMPEG中的结构体,解码器
AVCodecContext *avctx:FFMPEG中的结构体,解码器上下文
AVFrame *frame FFMPEG中的结构体,视频帧
mutable char_t codecName[100]:解码器名称
FOURCC fcc:FourCC
Textradata *extradata:附加数据

 

 

再来看一下TvideoCodecLibavcodec都包含什么方法:

create():创建解码器的时候调用
getDuration():获得时长
getExtradata():获得附加数据
drawMV():画运动矢量
getEncoderInfo():获得编码器信息
此外还包括一些有关解码的方法【这个是最关键的】:

beginDecompress():解码初始化

decompress():解码

 

下面我们来详细看看这些函数的实现吧:

先来看一下TvideoCodecLibavcodec的构造函数:

//libavcodec解码器(视频)
//内容大部分都很熟悉,因为是FFmpeg的API
TvideoCodecLibavcodec::TvideoCodecLibavcodec(IffdshowBase *Ideci, IdecVideoSink *IsinkD):
    Tcodec(Ideci), TcodecDec(Ideci, IsinkD),
    TvideoCodec(Ideci),
    TvideoCodecDec(Ideci, IsinkD),
    TvideoCodecEnc(Ideci, NULL),
    h264RandomAccess(this),
    bReorderBFrame(true)
{
    create();
}


可见构造函数调用了Create(),我们再来看看Create():

 

void TvideoCodecLibavcodec::create(void)
{
    ownmatrices = false;
    deci->getLibavcodec(&libavcodec);
    ok = libavcodec ? libavcodec->ok : false;
    avctx = NULL;
    avcodec = NULL;
    frame = NULL;
    quantBytes = 1;
    statsfile = NULL;
    threadcount = 0;
    codecinited = false;
    extradata = NULL;
    theorart = false;
    ffbuf = NULL;
    ffbuflen = 0;
    codecName[0] = '\0';
    ccDecoder = NULL;
    autoSkipingLoopFilter = false;
    inPosB = 1;
    firstSeek = true;
    mpeg2_new_sequence = true;
    parser = NULL;
}

 

 

从Create()函数我们可以看出,其完成了各种变量的初始化工作。其中有一行代码:

deci->getLibavcodec(&libavcodec);

 

完成了Tlibavcodec*libavcodec的初始化工作。

再来看几个函数。

getDuration(),用于从AVCodecContext中获取时长:

REFERENCE_TIME TvideoCodecLibavcodec::getDuration()
{
    REFERENCE_TIME duration = REF_SECOND_MULT / 100;
    if (avctx && avctx->time_base.num && avctx->time_base.den) {
        duration = REF_SECOND_MULT * avctx->time_base.num / avctx->time_base.den;
        if (codecId == AV_CODEC_ID_H264) {
            duration *= 2;
        }
    }
    if (duration == 0) {
        return REF_SECOND_MULT / 100;
    }
    return duration;
}

 

getExtradata()用于从AVCodecContext中获取附加信息:

bool TvideoCodecLibavcodec::getExtradata(const void* *ptr, size_t *len)
{
    if (!avctx || !len) {
        return false;
    }
    *len = avctx->extradata_size;
    if (ptr) {
        *ptr = avctx->extradata;
    }
    return true;
}


drawMV()用于从AVFrame中获取运动矢量信息,并画出来(这个函数用于一个名为“可视化”的滤镜里面,用于显示视频的运动矢量信息)。

 

//画出运动矢量
bool TvideoCodecLibavcodec::drawMV(unsigned char *dst, unsigned int dstdx, stride_t stride, unsigned int dstdy) const
{
    if (!frame->motion_val || !frame->mb_type || !frame->motion_val[0]) {
        return false;
    }

#define IS_8X8(a)  ((a)&MB_TYPE_8x8)
#define IS_16X8(a) ((a)&MB_TYPE_16x8)
#define IS_8X16(a) ((a)&MB_TYPE_8x16)
#define IS_INTERLACED(a) ((a)&MB_TYPE_INTERLACED)
#define USES_LIST(a, list) ((a) & ((MB_TYPE_P0L0|MB_TYPE_P1L0)<<(2*(list))))

    const int shift = 1 + ((frame->play_flags & CODEC_FLAG_QPEL) ? 1 : 0);
    const int mv_sample_log2 = 4 - frame->motion_subsample_log2;
    const int mv_stride = (frame->mb_width << mv_sample_log2) + (avctx->codec_id == AV_CODEC_ID_H264 ? 0 : 1);
    int direction = 0;

    int mulx = (dstdx << 12) / avctx->width;
    int muly = (dstdy << 12) / avctx->height;
	//提取两个方向上的运动矢量信息(根据不同的宏块划分,可以分成几种情况)
	//在AVCodecContext的motion_val中
    for (int mb_y = 0; mb_y < frame->mb_height; mb_y++)
        for (int mb_x = 0; mb_x < frame->mb_width; mb_x++) {
            const int mb_index = mb_x + mb_y * frame->mb_stride;
            if (!USES_LIST(frame->mb_type[mb_index], direction)) {
                continue;
            }
            …此处代码太长,略
        }
#undef IS_8X8
#undef IS_16X8
#undef IS_8X16
#undef IS_INTERLACED
#undef USES_LIST
    return true;
}

 

 

下面来看几个很重要的函数,这几个函数继承自TvideoCodecDec类。

beginDecompress()用于解码器的初始化。注:这个函数的代码太长了,因此只选择一点关键的代码。

//----------------------------- decompression -----------------------------
bool TvideoCodecLibavcodec::beginDecompress(TffPictBase &pict, FOURCC fcc, const CMediaType &mt, int sourceFlags)
{
    palette_size = 0;
    prior_out_rtStart = REFTIME_INVALID;
    prior_out_rtStop = 0;
    rtStart = rtStop = REFTIME_INVALID;
    prior_in_rtStart = prior_in_rtStop = REFTIME_INVALID;
    mpeg2_in_doubt = codecId == AV_CODEC_ID_MPEG2VIDEO;

    int using_dxva = 0;

    int numthreads = deci->getParam2(IDFF_numLAVCdecThreads);
    int thread_type = 0;
    if (numthreads > 1 && sup_threads_dec_frame(codecId)) {
        thread_type = FF_THREAD_FRAME;
    } else if (numthreads > 1 && sup_threads_dec_slice(codecId)) {
        thread_type = FF_THREAD_SLICE;
    }

    if (numthreads > 1 && thread_type != 0) {
        threadcount = numthreads;
    } else {
        threadcount = 1;
    }

    if (codecId == CODEC_ID_H264_DXVA) {
        codecId = AV_CODEC_ID_H264;
        using_dxva = 1;
    } else if (codecId == CODEC_ID_VC1_DXVA) {
        codecId = AV_CODEC_ID_VC1;
        using_dxva = 1;
    }

    avcodec = libavcodec->avcodec_find_decoder(codecId);
    if (!avcodec) {
        return false;
    }
    avctx = libavcodec->avcodec_alloc_context(avcodec, this);
    avctx->thread_type = thread_type;
    avctx->thread_count = threadcount;
    avctx->h264_using_dxva = using_dxva;
    if (codecId == AV_CODEC_ID_H264) {
        // If we do not set this, first B-frames before the IDR pictures are dropped.
        avctx->has_b_frames = 1;
    }

    frame = libavcodec->avcodec_alloc_frame();
    avctx->width = pict.rectFull.dx;
    avctx->height = pict.rectFull.dy;
    intra_matrix = avctx->intra_matrix = (uint16_t*)calloc(sizeof(uint16_t), 64);
    inter_matrix = avctx->inter_matrix = (uint16_t*)calloc(sizeof(uint16_t), 64);
    ownmatrices = true;


    // Fix for new Haali custom media type and fourcc. ffmpeg does not understand it, we have to change it to FOURCC_AVC1
    if (fcc == FOURCC_CCV1) {
        fcc = FOURCC_AVC1;
    }

    avctx->codec_tag = fcc;
    avctx->workaround_bugs = deci->getParam2(IDFF_workaroundBugs);
#if 0
    avctx->error_concealment = FF_EC_GUESS_MVS | FF_EC_DEBLOCK;
    avctx->err_recognition   = AV_EF_CRCCHECK | AV_EF_BITSTREAM | AV_EF_BUFFER | AV_EF_COMPLIANT | AV_EF_AGGRESSIVE;
#endif
    if (codecId == AV_CODEC_ID_MJPEG) {
        avctx->flags |= CODEC_FLAG_TRUNCATED;
    }
    if (mpeg12_codec(codecId) && deci->getParam2(IDFF_fastMpeg2)) {
        avctx->flags2 = CODEC_FLAG2_FAST;
    }
    if (codecId == AV_CODEC_ID_H264)
        if (int skip = deci->getParam2(IDFF_fastH264)) {
            avctx->skip_loop_filter = skip & 2 ? AVDISCARD_ALL : AVDISCARD_NONREF;
        }
    initialSkipLoopFilter = avctx->skip_loop_filter;

    avctx->debug_mv = !using_dxva; //(deci->getParam2(IDFF_isVis) & deci->getParam2(IDFF_visMV));

    avctx->idct_algo = limit(deci->getParam2(IDFF_idct), 0, 6);
    if (extradata) {
        delete extradata;
    }
extradata = new Textradata(mt, FF_INPUT_BUFFER_PADDING_SIZE);
此处代码太长,略…
}

 

从代码中可以看出这个函数的流程是:

1.avcodec_find_decoder();
2.avcodec_alloc_context();
3.avcodec_alloc_frame();
4.avcodec_open();

 

主要做了libavcodec初始化工作。

 

begin decompress()用于解码器的初始化。 注:这个函数的代码太长了,因此只选择一点关键的代码。

HRESULT TvideoCodecLibavcodec::decompress(const unsigned char *src, size_t srcLen0, IMediaSample *pIn)
{
	代码太长,略…
    AVPacket avpkt;
    libavcodec->av_init_packet(&avpkt);
    if (palette_size) {
        uint32_t *pal = (uint32_t *)libavcodec->av_packet_new_side_data(&avpkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
        for (int i = 0; i < palette_size / 4; i++) {
            pal[i] = 0xFF << 24 | AV_RL32(palette + i);
        }
    }

    while (!src || size > 0) {
        int used_bytes;

        avctx->reordered_opaque = rtStart;
        avctx->reordered_opaque2 = rtStop;
        avctx->reordered_opaque3 = size;

        if (sendextradata && extradata->data && extradata->size > 0) {
            avpkt.data = (uint8_t *)extradata->data;
            avpkt.size = (int)extradata->size;
            used_bytes = libavcodec->avcodec_decode_video2(avctx, frame, &got_picture, &avpkt);
            sendextradata = false;
            if (used_bytes > 0) {
                used_bytes = 0;
            }
            if (mpeg12_codec(codecId)) {
                avctx->extradata = NULL;
                avctx->extradata_size = 0;
            }
        } else {
            unsigned int neededsize = size + FF_INPUT_BUFFER_PADDING_SIZE;

            if (ffbuflen < neededsize) {
                ffbuf = (unsigned char*)realloc(ffbuf, ffbuflen = neededsize);
            }

            if (src) {
                memcpy(ffbuf, src, size);
                memset(ffbuf + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
            }
            if (parser) {
                uint8_t *outBuf = NULL;
                int out_size = 0;
                used_bytes = libavcodec->av_parser_parse2(parser, avctx, &outBuf, &out_size, src ? ffbuf : NULL, size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
                if (prior_in_rtStart == REFTIME_INVALID) {
                    prior_in_rtStart = rtStart;
                    prior_in_rtStop = rtStop;
                }
                if (out_size > 0 || !src) {
                    mpeg2_in_doubt = false;
                    avpkt.data = out_size > 0 ? outBuf : NULL;
                    avpkt.size = out_size;
                    if (out_size > used_bytes) {
                        avctx->reordered_opaque = prior_in_rtStart;
                        avctx->reordered_opaque2 = prior_in_rtStop;
                    } else {
                        avctx->reordered_opaque = rtStart;
                        avctx->reordered_opaque2 = rtStop;
                    }
                    prior_in_rtStart = rtStart;
                    prior_in_rtStop = rtStop;
                    avctx->reordered_opaque3 = out_size;
                    if (h264RandomAccess.search(avpkt.data, avpkt.size)) {
                        libavcodec->avcodec_decode_video2(avctx, frame, &got_picture, &avpkt);
                        h264RandomAccess.judgeUsability(&got_picture);
                    } else {
                        got_picture = 0;
                    }
                } else {
                    got_picture = 0;
                }
            } else {
                avpkt.data = src ? ffbuf : NULL;
                avpkt.size = size;
                if (codecId == AV_CODEC_ID_H264) {
                    if (h264RandomAccess.search(avpkt.data, avpkt.size)) {
                        used_bytes = libavcodec->avcodec_decode_video2(avctx, frame, &got_picture, &avpkt);
                        if (used_bytes < 0) {
                            return S_OK;
                        }
                        h264RandomAccess.judgeUsability(&got_picture);
                    } else {
                        got_picture = 0;
                        return S_OK;
                    }
                } else {
                    used_bytes = libavcodec->avcodec_decode_video2(avctx, frame, &got_picture, &avpkt);
                }
            }
        }
	代码太长,略…
}

 

从代码中可以看出这个函数的流程是:

1.AVPacket avpkt;
2.av_init_packet();
3.avcodec_decode_video2();

 

和ffmpeg的解码流程相差不大。

分享到:
评论

相关推荐

    开源的ffdshow源代码

    ffdshow的源代码是学习视频解码和处理技术的宝贵资源,对于开发者来说,深入研究它的实现细节有助于提升在多媒体领域的专业技能。 首先,让我们来看看ffdshow的核心功能: 1. **视频解码**:ffdshow能够解码多种...

    FFmpeg基础库编程开发

    ffdshow 源代码分析 8: 视频解码器类(TvideoCodecDec) 344 ffdshow 源代码分析 9: 编解码器有关类的总结 352 9.2 LAV filters 357 LAV Filter 源代码分析 1: 总体结构 357 LAV Filter 源代码分析 2: LAV ...

    ffmpeg基础开发资料自总结

    ffdshow 源代码分析 8: 视频解码器类(TvideoCodecDec) 328 ffdshow 源代码分析 9: 编解码器有关类的总结 335 9.2 LAV filters 340 LAV Filter 源代码分析 1: 总体结构 340 LAV Filter 源代码分析 2: LAV ...

    ffdshow的源代码(2012)

    10. **持续学习与进阶**:通过对ffdshow源代码的学习,开发者可以进一步研究更复杂的多媒体处理技术,如硬件加速、3D视频解码、实时编码等。 总的来说,ffdshow的源代码是一个宝贵的教育资源,无论对于初学者还是...

    FFDSHOW 源代码

    FFDSHOW是一款著名的开源视频解码过滤器,广泛应用于多媒体播放软件中,如VLC、Media Player Classic等。它的源代码提供了对多种视频和音频格式的解码支持,包括但不限于MPEG-4 ASP(DivX,XviD)、H.264、VP9、AV1...

    ffdshow源代码

    ffdshow是一款著名的开源视频解码过滤器,广泛应用于Windows平台上的多媒体播放软件中。它能够解码多种视频编码格式,包括但不限于MPEG-4 ASP(如DivX和XviD)、H.264、MPEG-1、MPEG-2、VP8以及Theora等。ffdshow的...

    ffdshow的源代码

    FFDShow是一个开源的视频解码过滤器,主要用于在Windows平台上播放各种编码格式的视频文件。它是基于FFmpeg项目的一部分,而FFmpeg则是一个全面的多媒体处理框架,涵盖了音视频编码、解码、转码、流媒体等多个领域。...

    ffdshow音视频解码器

    ffdshow是一款著名的开源音视频解码器,广泛应用于多媒体播放领域。它支持众多音视频编码格式,使得用户能够在不安装多种解码器的情况下,顺利播放各种格式的媒体文件。ffdshow以其高效、灵活和可定制性著称,是许多...

    ffdshow-视频解码

    ffdshow是一款著名的开源视频解码过滤器,专为Windows操作系统设计。它被广泛应用于多媒体播放领域,因其强大的解码能力和广泛的格式支持而受到用户青睐。ffdshow能够在DirectShow框架下工作,与各种媒体播放器(如...

    Windows 7 音视频解码器 Windows 7 Codec Pack 4.2.7 免费版.zip

    Windows 7 音视频解码器 Windows 7 Codec Pack 下载Windows 7 音视频解码器 Windows 7 Codec Pack 中文版 封装编解码器组件: ●LAV视频解码器0.74.1 Build 60 x86。 ●LAV视频解码器0.74.1 Build 60 x64。 ●Cole的...

    ffdshow 解码器

    ffdshow 解码器 ffdshow 解码器 ffdshow 解码器

    ffdshow20130525x64解码器

    ffdshow20130525x64解码器是一款专为64位操作系统设计的视频解码工具,其主要功能是帮助用户解析和播放各种格式的视频文件。在数字媒体领域,解码器扮演着至关重要的角色,因为不同格式的视频文件需要对应的解码器...

    ffdshow解码器2012.3.22官方中文版.rar

    这是一个全能的音频视频解码器,支持N多的媒体格式,丰富的选项设置可以自由调节画面的音频参数,安装后能够让你的电脑播放最新的视频文件。可自定义选择安装以下组件:ffdshow DirectShow 滤镜DXVA video ...

    FFDShow全能解码器 2012.1213 官方版.rar

    最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远远超出了mepg4的范围,包括indeo video,WMV,mpeg2等等.同时,它也提供了丰富的加工处理选项,可以锐化画面,调节画面的亮度等等...

    ffdshow sdk

    - 学习FFDShow的源代码,了解如何高效地处理视频解码和编码。 - 创建自定义的解码器和编码器,以适应特定的需求或优化性能。 - 将FFDShow的功能集成到多媒体播放器、视频编辑软件或其他多媒体应用中。 - 开发新的...

    ffdshow(20070210)源码

    ffdshow是一款著名的开源视频解码过滤器,广泛应用于Windows平台上的多媒体播放软件中。它能够解码多种视频格式,如MPEG-4 ASP (DivX, XviD), H.264, VC-1, MJPEG, MPEG-1, MPEG-2等,并且支持硬件加速,提供高质量...

    ffdshow代码

    总的来说,ffdshow代码是一个涵盖视频解码、画质优化和用户自定义功能的综合性工具。通过学习它的源码,开发者可以提升在视频处理领域的专业技能,同时也可以为自己的项目引入类似的功能。无论是对个人学习还是商业...

    kLite解码器安装包

    【kLite解码器安装包】是一个专为Qt5版本设计的音视频解码工具,旨在帮助用户在使用Qt5开发音视频应用时能够顺利播放各种格式的媒体文件。这个安装包包含了完整的解码组件,使得Qt5应用程序无需依赖额外的第三方库就...

    视频全能解码(FFDShow MPEG-4 Video Decoder) 20131117.rar

    FFDSHOW MPEG - 4视频解码器的特点: - 各种压缩方法: MPEG - 4兼容(XVID,DIVX,DIVX 6的DivX 4,DivX的5 7 8,DIVX)使用libavcodec的或XviD DIVX 3兼容,MSMPEG4v2,MSMPEG4v1 WMV2 WMV1 / 7 / 8 H263...

    ffdshow解码器

    ffdshow解码器是一款在IT领域中广泛应用的视频解码工具,尤其对于处理各种编码格式的视频文件至关重要。它的核心功能在于能够解析和解码多种复杂的视频编码格式,使得原本因缺少相应解码器而无法播放的视频文件得以...

Global site tag (gtag.js) - Google Analytics