C++调用ffmpeg sdk开发

刚入职编解码开发岗,之前做的都是算法设计,没有接触过sdk开发。

开始用博客来记录自己的学习过程吧,希望有一天自己也可以成为大佬。

调用ffmpeg sdk来实现mp4格式到avi格式的转换

...本来想通过实现各个格式的相互转换来熟悉ffmpeg的,但是发现内容有点多,就只实现了mp4转成avi格式。

1.ffmpeg库编译

①直接从官网下载已经编译好的ffmpeg,这个网上很多介绍的文章

大佬的博客:【精选】Windows编译和使用ffmpeg_windows ffmpeg_心愿许得无限大的博客-CSDN博客

②自己动手,编译源码得到自己想要的库。在linux下比较简单,编译三步曲就OK了。

./configure 

make

make install

windows下面得下载MINGW来编译,听说是专门用来编译ffmpeg的,确实不错。

编译完以后就可以得到这样一个文件夹了,想要的东西里面都有

2.c++调用ffmpeg的库

用我们宇宙最强IDE VS来创建C++项目,整个空项目就行

配置一下项目链接器里的常规和输入两个地方把咱们的ffmpeg库给它配进去

常规->附加库目录:把lib库的路径加进去

输入->附加依赖项:把需要用到的dll.a库全部写进去

3.编写格式转换代码

环境没问题了就开始写我们的格式转换吧。首先整体的流程,在网上看到有大佬给出了基于ffmpeg格式转换的流程,如下图,是FLV转到AVI的,我只有几个MP4文件,所以就参考大佬的流程做一个MP4转AVI吧。

总体来说流程还不是太难

①解封装,包括了视频和音频,两个咱们分开处理

②解码,用输入文件对应的解码器将音视频码流解码成普通数据(YUV、PCM等等)

③编码,我们想要输出的格式对应的编码器将数据再编码成码流

④再封装,装好就可以输出了,得到我们想要的格式了。

在网上也看到有大佬总结了各种音视频封装格式可以使用的编解码器,如下图

下面直接给上代码,每一步都有相应的注释

/*
* @Time: 2023.10.24
* @Author: Wu Liu
* @File: T_format6.cpp
* @Function: format conversion
*/
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>

}
#include <iostream>
/* @T_format6.cpp
* 基本流程:
* 1.解析输入文件,获得流信息,确定音视频解码器参数、上下文。
* 2.根据输出要求配置音视频编码器参数
* 3.循环每一帧解码、再编码输出
* 4.内存清理
*/
bool Format_conver(const std::string& inputFile, const std::string& outputFileName, const std::string& Format) {
    avformat_network_init(); // 初始化网络库
    AVFormatContext* inputFormatContext = nullptr;
    AVCodecContext* videoCodecContext = nullptr;
    AVCodecContext* audioCodecContext = nullptr;
    AVFormatContext* outputFormatContext = nullptr;
    AVStream* videoStream = nullptr;
    AVStream* audioStream = nullptr;
    SwsContext* swsContext = nullptr;
    AVCodecID videoCodecId ;
    AVCodecID audioCodecId ;

    if (Format == "avi") 
    {
       videoCodecId = AV_CODEC_ID_MPEG2VIDEO;
       audioCodecId = AV_CODEC_ID_PCM_S16LE;
    }
    else if (Format == "mp4")
    {
        videoCodecId = AV_CODEC_ID_H264;
        audioCodecId = AV_CODEC_ID_AAC;
    }
    else if (Format == "wmv")
    {
       videoCodecId = AV_CODEC_ID_MSMPEG4V3;
       audioCodecId = AV_CODEC_ID_WMAV2;
    }
    else if (Format == "mkv")
    {
        videoCodecId = AV_CODEC_ID_H264;
        audioCodecId = AV_CODEC_ID_MP3;
    }
    else if (Format == "flv")
    {
        videoCodecId = AV_CODEC_ID_MPEG4;
        audioCodecId = AV_CODEC_ID_AAC;
    }
    else {
        std::cout << "不支持转换为这种格式" << std::endl;
        return false;
    }
    

    // 打开输入文件
    if (avformat_open_input(&inputFormatContext, inputFile.c_str(), nullptr, nullptr) != 0) {
        std::cout << "无法打开输入文件" << std::endl;
        return false;
    }

    // 获取流信息
    if (avformat_find_stream_info(inputFormatContext, nullptr) < 0) {
        std::cout << "无法获取输入文件流信息" << std::endl;
        avformat_close_input(&inputFormatContext);
        return false;
    }

    // 查找视频流和音频流索引
    int videoStreamIndex = -1;
    int audioStreamIndex = -1;
    for (int i = 0; i < inputFormatContext->nb_streams; i++) {
        if (inputFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            videoStreamIndex = i;
        }
        else if (inputFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) {
            audioStreamIndex = i;
        }
    }

    if (videoStreamIndex == -1 || audioStreamIndex == -1) {
        std::cout << "没有找到视频流" << std::endl;
        avformat_close_input(&inputFormatContext);
        return false;
    }

    // 获取视频和音频流
    videoStream = inputFormatContext->streams[videoStreamIndex];
    audioStream = inputFormatContext->streams[audioStreamIndex];

    // 获取视频解码器
    const AVCodec* videoCodec = avcodec_find_decoder(videoStream->codecpar->codec_id);
    if (!videoCodec) {
        std::cout << "没有找到视频解码器" << std::endl;
        avformat_close_input(&inputFormatContext);
        return false;
    }

    // 创建并打开视频解码器上下文
    videoCodecContext = avcodec_alloc_context3(videoCodec);
    if (!videoCodecContext) {
        std::cout << "创建视频解码器上下文失败"<< std::endl;
        avformat_close_input(&inputFormatContext);
        return false;
    }
    //视频流参数去填充上下文context
    avcodec_parameters_to_context(videoCodecContext, videoStream->codecpar);
    if (avcodec_open2(videoCodecContext, videoCodec, nullptr) < 0) {
        std::cout << "打开视频解码器失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        return false;
    }

    // 获取音频编码器
    const AVCodec* audioCodec = avcodec_find_decoder(audioStream->codecpar->codec_id);
    if (!audioCodec) {
        std::cout << "获取音频编码器失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        return false;
    }

    // 创建并打开音频解码器上下文
    audioCodecContext = avcodec_alloc_context3(audioCodec);
    if (!audioCodecContext) {
        std::cout << "创建音频编码器上下文失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        return false;
    }
    //音频流参数填充上下文
    avcodec_parameters_to_context(audioCodecContext, audioStream->codecpar);
    if (avcodec_open2(audioCodecContext, audioCodec, nullptr) < 0) {
        std::cout << "打开音频编码器失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        return false;
    }

    // 创建输出文件的上下文
    avformat_alloc_output_context2(&outputFormatContext, nullptr, nullptr, outputFileName.c_str());
    if (!outputFormatContext) {
        std::cout << "创建输出文件的上下文失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        return false;
    }

    // 添加视频流到输出上下文
    AVStream* outVideoStream = avformat_new_stream(outputFormatContext, nullptr);
    if (!outVideoStream) {
        std::cout << "添加视频流到输出文件失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext); 
        avformat_free_context(outputFormatContext);
        return false;
    }
    outVideoStream->id = outputFormatContext->nb_streams - 1;
 //   avcodec_parameters_copy(outVideoStream->codecpar, videoStream->codecpar);
    outVideoStream->codecpar->codec_tag = 0;

    // 设置视频编码器
    const AVCodec* outVideoCodec = avcodec_find_encoder(videoCodecId);
    if (!outVideoCodec) {
        std::cout << "设置视频编码器失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        return false;
    }
    AVCodecContext* outVideoCodecContext = avcodec_alloc_context3(outVideoCodec);
    if (!outVideoCodecContext) {
        std::cout << "设置视频编码器上下文失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        return false;
    }
    //视频编码器参数设置
    //avcodec_parameters_to_context(outVideoCodecContext, outVideoStream->codecpar);
    outVideoCodecContext->codec_id = videoCodecId;
    //outVideoCodecContext->time_base = videoStream->time_base;
    outVideoCodecContext->time_base.den = 25;
    outVideoCodecContext->time_base.num = 1;
    outVideoCodecContext->gop_size = 13;
    outVideoCodecContext->bit_rate = 8000000;
    outVideoCodecContext->refs = 0;
    outVideoCodecContext->max_b_frames = 4;
    outVideoCodecContext->width = 1920;
    outVideoCodecContext->height = 1080;
    outVideoCodecContext->pix_fmt = AV_PIX_FMT_YUV420P;
    
    //从输出上下文中复制参数到输出流
    avcodec_parameters_from_context(outVideoStream->codecpar, outVideoCodecContext);    
    // 打开视频编码器
    if (avcodec_open2(outVideoCodecContext, outVideoCodec, nullptr) < 0) {
        std::cout << "无法打开视频编码器" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        avcodec_free_context(&outVideoCodecContext);
        return false;
    }

    // 添加音频流到输出文件
    AVStream* outAudioStream = avformat_new_stream(outputFormatContext, nullptr);
    if (!outAudioStream) {
        std::cout << "添加音频流到输出文件失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        avcodec_free_context(&outVideoCodecContext);
        return false;
    }
    outAudioStream->id = outputFormatContext->nb_streams - 1;
    //输出音频流参数复制
    avcodec_parameters_copy(outAudioStream->codecpar, audioStream->codecpar);
    outAudioStream->codecpar->codec_tag = 0;

    // 设置音频编码器
    const AVCodec* outAudioCodec = avcodec_find_encoder(audioCodecId);
    if (!outAudioCodec) {
        std::cout << "设置音频编码器失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        avcodec_free_context(&outVideoCodecContext);
        return false;
    }
    AVCodecContext* outAudioCodecContext = avcodec_alloc_context3(outAudioCodec);
    if (!outAudioCodecContext) {
        std::cout << "设置音频编码器上下文失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        avcodec_free_context(&outVideoCodecContext);
        return false;
    }
    //音频编码器参数
    avcodec_parameters_to_context(outAudioCodecContext, outAudioStream->codecpar);
    outAudioCodecContext->codec_id = audioCodecId;
    outAudioCodecContext->time_base = audioStream->time_base;
    outAudioCodecContext->sample_fmt = AV_SAMPLE_FMT_S16;
    avcodec_parameters_from_context(outAudioStream->codecpar, outAudioCodecContext);

    // 打开音频编码器
    if (avcodec_open2(outAudioCodecContext, outAudioCodec, nullptr) < 0) {
        std::cout << "无法打开音频编码器" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        avcodec_free_context(&outVideoCodecContext);
        avcodec_free_context(&outAudioCodecContext);
        return false;
    }

    // 打开输出文件
    if (!(outputFormatContext->oformat->flags & AVFMT_NOFILE)) {
        if (avio_open(&outputFormatContext->pb, outputFileName.c_str(), AVIO_FLAG_WRITE) < 0) {
            std::cout << "无法打开输出文件" << std::endl;
            avformat_close_input(&inputFormatContext);
            avcodec_free_context(&videoCodecContext);
            avcodec_free_context(&audioCodecContext);
            avformat_free_context(outputFormatContext);
            avcodec_free_context(&outVideoCodecContext);
            avcodec_free_context(&outAudioCodecContext);
            return false;
        }
    }

    // 写入输出文件头
    if (avformat_write_header(outputFormatContext, nullptr) < 0) {
        std::cout << "无法写入输出文件头" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        avcodec_free_context(&outVideoCodecContext);
        avcodec_free_context(&outAudioCodecContext);
        return false;
    }
    //打印输出相关信息
    av_dump_format(outputFormatContext, 0, outputFileName.c_str(), 1);
    // 分配帧对象
    AVFrame* videoFrame = av_frame_alloc();
    AVFrame* audioFrame = av_frame_alloc();
    AVPacket* inputPacket = av_packet_alloc();
    AVPacket* videoOutputPacket = av_packet_alloc();
    AVPacket* audioOutputPacket = av_packet_alloc();
    if (!videoFrame || !audioFrame || !inputPacket || !videoOutputPacket || !audioOutputPacket) {
        std::cout << "分配帧对象失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        avcodec_free_context(&outVideoCodecContext);
        avcodec_free_context(&outAudioCodecContext);
        return false;
    }

    // 初始化像素格式转换器
    swsContext = sws_getContext(videoCodecContext->width, videoCodecContext->height, videoCodecContext->pix_fmt,
        outVideoCodecContext->width, outVideoCodecContext->height, outVideoCodecContext->pix_fmt,
        SWS_BILINEAR, nullptr, nullptr, nullptr);
    if (!swsContext) {
        std::cout << "初始化像素格式转换器失败" << std::endl;
        avformat_close_input(&inputFormatContext);
        avcodec_free_context(&videoCodecContext);
        avcodec_free_context(&audioCodecContext);
        avformat_free_context(outputFormatContext);
        avcodec_free_context(&outVideoCodecContext);
        avcodec_free_context(&outAudioCodecContext);
        av_frame_free(&videoFrame);
        av_frame_free(&audioFrame);
        av_packet_free(&inputPacket);
        av_packet_free(&videoOutputPacket);
        av_packet_free(&audioOutputPacket);
        return false;
    }

    // 解码并编码每一帧
    int ret = 0;
    int nVideoCount = 0;
    while (av_read_frame(inputFormatContext, inputPacket) >= 0) {
        if (inputPacket->stream_index == videoStreamIndex) {
            // 视频流处理
            ret = avcodec_send_packet(videoCodecContext, inputPacket);
            if (ret < 0) {
                break;
            }
            while (ret >= 0) {
                ret = avcodec_receive_frame(videoCodecContext, videoFrame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    break;
                }
                else if (ret < 0) {
                    std::cout << "视频解码 ret 异常" << std::endl;
                    avformat_close_input(&inputFormatContext);
                    avcodec_free_context(&videoCodecContext);
                    avcodec_free_context(&audioCodecContext);
                    avformat_free_context(outputFormatContext);
                    avcodec_free_context(&outVideoCodecContext);
                    avcodec_free_context(&outAudioCodecContext);
                    av_frame_free(&videoFrame);
                    av_frame_free(&audioFrame);
                    av_packet_free(&inputPacket);
                    av_packet_free(&videoOutputPacket);
                    av_packet_free(&audioOutputPacket);
                    return false;
                }

                // 转换像素格式
                sws_scale(swsContext, videoFrame->data, videoFrame->linesize, 0, videoCodecContext->height,
                    videoFrame->data, videoFrame->linesize);
      
                // 编码视频帧
                videoFrame->pts = (int64_t)(40 * (nVideoCount) / av_q2d(outVideoCodecContext->time_base) / 1000.0);//时间
                nVideoCount++;
                ret = avcodec_send_frame(outVideoCodecContext, videoFrame);
                if (ret < 0) {
                    break;
                }

                while (ret >= 0) {
                    ret = avcodec_receive_packet(outVideoCodecContext, videoOutputPacket);
                    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                        break;
                    }
                    else if (ret < 0) {
                        std::cout << "视频编码 ret 异常" << std::endl;
                        avformat_close_input(&inputFormatContext);
                        avcodec_free_context(&videoCodecContext);
                        avcodec_free_context(&audioCodecContext);
                        avformat_free_context(outputFormatContext);
                        avcodec_free_context(&outVideoCodecContext);
                        avcodec_free_context(&outAudioCodecContext);
                        av_frame_free(&videoFrame);
                        av_frame_free(&audioFrame);
                        av_packet_free(&inputPacket);
                        av_packet_free(&videoOutputPacket);
                        av_packet_free(&audioOutputPacket);
                        return false;
                    }

                    av_packet_rescale_ts(videoOutputPacket, outVideoCodecContext->time_base, outVideoStream->time_base);
                    videoOutputPacket->stream_index = outVideoStream->index;

                    // 写入视频帧到输出文件
                    ret = av_interleaved_write_frame(outputFormatContext, videoOutputPacket);
                    if (ret < 0) {
                        break;
                    }
                }
            }
        }
        else if (inputPacket->stream_index == audioStreamIndex) {
            // 音频流处理
            ret = avcodec_send_packet(audioCodecContext, inputPacket);
            if (ret < 0) {
                break;
            }

            while (ret >= 0) {
                ret = avcodec_receive_frame(audioCodecContext, audioFrame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    break;
                }
                else if (ret < 0) {
                    std::cout << "音频解码 ret 异常" << std::endl;
                    avformat_close_input(&inputFormatContext);
                    avcodec_free_context(&videoCodecContext);
                    avcodec_free_context(&audioCodecContext);
                    avformat_free_context(outputFormatContext);
                    avcodec_free_context(&outVideoCodecContext);
                    avcodec_free_context(&outAudioCodecContext);
                    av_frame_free(&videoFrame);
                    av_frame_free(&audioFrame);
                    av_packet_free(&inputPacket);
                    av_packet_free(&videoOutputPacket);
                    av_packet_free(&audioOutputPacket);
                    return false;
                }

                // 编码音频帧
                ret = avcodec_send_frame(outAudioCodecContext, audioFrame);
                if (ret < 0) {
                    break;
                }

                while (ret >= 0) {
                    ret = avcodec_receive_packet(outAudioCodecContext, audioOutputPacket);
                    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                        break;
                    }
                    else if (ret < 0) {
                        std::cout << "音频编码 ret 异常" << std::endl;
                        avformat_close_input(&inputFormatContext);
                        avcodec_free_context(&videoCodecContext);
                        avcodec_free_context(&audioCodecContext);
                        avformat_free_context(outputFormatContext);
                        avcodec_free_context(&outVideoCodecContext);
                        avcodec_free_context(&outAudioCodecContext);
                        av_frame_free(&videoFrame);
                        av_frame_free(&audioFrame);
                        av_packet_free(&inputPacket);
                        av_packet_free(&videoOutputPacket);
                        av_packet_free(&audioOutputPacket);
                        return false;
                    }

                    av_packet_rescale_ts(audioOutputPacket, outAudioCodecContext->time_base, outAudioStream->time_base);
                    audioOutputPacket->stream_index = outAudioStream->index;

                    // 写入音频帧到输出文件
                    ret = av_interleaved_write_frame(outputFormatContext, audioOutputPacket);
                    if (ret < 0) {
                        break;
                    }
                }
            }
        }

        av_packet_unref(inputPacket);
    }

    // 写入输出文件尾部
    av_write_trailer(outputFormatContext);

    // 释放资源
    av_frame_free(&videoFrame);
    av_frame_free(&audioFrame);
    av_packet_free(&inputPacket);
    av_packet_free(&videoOutputPacket);
    av_packet_free(&audioOutputPacket);

    avcodec_free_context(&videoCodecContext);
    avcodec_free_context(&audioCodecContext);
    avcodec_free_context(&outVideoCodecContext);
    avcodec_free_context(&outAudioCodecContext);

    avformat_close_input(&inputFormatContext);
    avformat_free_context(outputFormatContext);

    sws_freeContext(swsContext);

    return true;
}
int main() {
    // 输入文件名和输出文件名
    std::string inputFilename, outputFilename, Format;
    std::cout << "请输入输入文件名(带后缀):";
    std::cin >> inputFilename;
    std::cout << "请输入输出格式(avi,mp4,wmv,mkv,flv...):";
    std::cin >> Format;
    std::cout << "请输入输出文件名(带后缀):";
    std::cin >> outputFilename;
    if (!Format_conver(inputFilename, outputFilename, Format)) {
        std::cout << "Failed to convert!" << std::endl;
        return -1;
    }
    std::cout << "Conversion complete!" << std::endl;
    return 0;

}

这里我也想多转换点格式的,但是发现好像有点麻烦,就算了吧。里面主要是关于参数和时间戳的设计,我处理了很久是比较复杂的一点。一开始我想直接就用输入源的参数,参数太多了懒得一个一个报错了再去改,谁知道错的离谱,代码里面我自己设定了几个参数,可能不太全,但是代码可以运行了,结果也是准确的,还是不错的,毕竟自己也是刚开始学习。以后慢慢的接触的多了,再回来好好改现在存在的问题吧。

  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本书共16章,分为4篇,详细讲解了使用各种软件和平台进行音、视频多媒体编程的技术,以案例为对象展示实现过程、分析技术难点。主要内容包括软件Visual C++2005的开发技术、DirectSound开发音频、DirectShow/VFW开发视频、MMX/SSE进行多媒体汇编编程、DM642 DSP进行音视频算法优化和主流视频算法MPEG-4/H.264的编码原理及工程实践。本书系统地介绍Visual C++ 2005进行流媒体编程的基本思路和方法,采用案例为主的叙述方式,将大量的技术理论融入具体的案例剖析中。采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2 各种数字音频文件格式基础 4 1.1.3 视频的相关基础概念 8 1.1.4 常见的视频文件格式 8 1.2 数字音视频数据的编解码技术 10 1.2.1 音频数据的编解码 11 1.2.2 视频数据的编解码 13 1.2.3 音视频编码的相关标准 13 1.3 音视频处理平台的选择 15 1.3.1 个人多媒体计算机 15 1.3.2 嵌入式处理器ARM 16 1.3.3 数字媒体处理器DSP 16 1.4 音视频开发的典型应用 16 1.4.1 个人消费类电子产品 16 1.4.2 公共领域的音视频应用 18 1.5 常用音视频开发工具 21 1.5.1 DirectSound音频开发 21 1.5.2 DirectShow视频开发 21 1.5.3 DSP CCS算法开发 22 1.6 本章小结 23 第2章 Visual C++ 2005开发基础 25 2.1 Visual C++ 2005新增特性 26 2.1.1 句柄(Handles) 26 2.1.2 类型的声明 26 2.1.3 对代码编辑的改进 27 2.2 VC能做的事情 27 2.2.1 生成传统的控制台应用程序 27 2.2.2 生成基于MFC的应用程序 32 2.2.3 生成静态链接库 40 2.2.4 生成动态链接库 41 2.3 利用向导完成基本开发 46 2.3.1 生成应用程序 46 2.3.2 生成应用库LIB/DLL 53 2.4 MFC编程基础 56 2.4.1 Windows消息与事件 56 2.4.2 消息与事件的响应 63 2.4.3 常用消息 66 2.5 基于对话框的编程 68 2.5.1 创建和编辑对话框 68 2.5.2 对话框种类 75 2.6 常用控件使用技巧 79 2.6.1 按钮类控件的使用 80 2.6.2 文本可编辑类控件的使用 81 2.6.3 静态类控件的使用 82 2.6.4 其他控件 83 2.7 Visual 2005开发技术资源 84 2.7.1 MSDN在线帮助 84 2.7.2 丰富的网络资源 86 2.8 Visual 2005开发的常见问题 86 2.8.1 如何使用volatile和const_cast 86 2.8.2 如何构造unicode版本的程序 87 2.8.3 如何使用.def文件 87 2.8.4 如何正确编写Win32 DLL 87 2.8.5 如何编写和使用资源DLL 88 2.8.6 如何实现对话框的数据交换 88 2.9 本章小结 89 第2篇 音频开发 91 第3章 DirectSound开发基础 93 3.1 Microsoft DirectSound SDK 94 3.1.1 比较DirectSound与DirectMusic 94 3.1.2 DirectSound SDK能做什么 95 3.1.3 如何获取DirectSound SDK 96 3.1.4 DirectSound SDK的基本结构 98 3.1.5 Directsound SDK安装 100 3.1.6 选择最适合用户的DirectSound SDK 100 3.1.7 用DirectSound进行编程的必要步骤 102 3.2 DirectSound的详细使用方法 103 3.2.1 DirectSound设备对象 104 3.2.2 DirectSound缓冲区对象 107 3.2.3 使用WAV数据 114 3.2.4 使用音效 116 3.3 开发环境配置 118 3.3.1 Visual C++基本开发环境配置 119 3.3.2 DirectSound应用程序的开发环境配置 119 3.3.3 DirectSound Filter开发环境配置 121 3.4 调试音频处理程序 125 3.4.1 Visual C++调试器 125 3.4.2 DirectSound中常用的调试技术 128 3.5 DirectSound开发的常见问题 130 3.6 本章小结 131 第4章 打造自己的音频播放器 133 4.1 系统设计和分析 134 4.2 缓冲区和通知基础 135 4.2.1 缓冲区的概念 135 4.2.2 缓冲区的通知 136 4.3 播放文件 137 4.3.1 创建DirectSound对象 137 4.3.2 创建播放缓冲区 138 4.3.3 调用方法播放声音 145 4.3.4 结束播放 146 4.4 系统效果演示 146 4.4.1 新建基于对话框的程序框架 147 4.4.2 添加控件及变量 147 4.4.3 封装CDirectSound类实现DirectSound声音播放 148 4.4.4 与对话框界面相关操作实现 156 4.4.5 程序运行结果 159 4.5 DirectSound开发常见问题 160 4.6 本章小结 161 第5章 语音3D特效器制作 163 5.1 系统设计和分析 164 5.2 DirectSound 3D缓冲区 164 5.2.1 获取3D缓冲区对象 165 5.2.2 最大距离和最小距离 166 5.2.3 处理模式 167 5.2.4 声音圆锥 167 5.3 DirectSound 3D虚拟听众 168 5.3.1 获得3D听众 168 5.3.2 听众的空间参数 169 5.3.3 距离因子与Doppler效应 171 5.3.4 滚降因子与延迟设置 173 5.4 系统效果演示 174 5.4.1 具体的实现步骤 174 5.4.2 程序的实现代码 176 5.4.3 程序运行结果 186 5.5 DirectSound 3D开发常见问题 187 5.6 本章小结 188 第6章 对拾音设备录制自己的语音文件 189 6.1 系统分析和设计 190 6.2 管理捕获缓冲区 191 6.2.1 创建捕获缓冲区 191 6.2.2 启动缓冲区 197 6.2.3 封锁缓冲区 197 6.2.4 解锁缓冲区 198 6.2.5 中止捕获 199 6.3 系统效果演示 199 6.3.1 声音类的封装 199 6.3.2 声音管理函数的实现 202 6.3.3 程序运行结果 214 6.4 DirectSound录制语音文件开发常见问题 215 6.5 本章小结 216 第3篇 视频开发 217 第7章 DirectShow开发基础 219 7.1 Microsoft DirectShow SDK 220 7.1.1 DirectX及成员组成 220 7.1.2 DirectShow SDK能做什么 221 7.1.3 如何获取DirectShow SDK 221 7.1.4 安装Direshow SDK 222 7.2 开发环境配置 224 7.2.1 生成DirectShow SDK开发库 224 7.2.2 Visual C++开发环境配置 229 7.2.3 常见问题解析集锦 232 7.3 DirectShow SDK基本架构 234 7.3.1 DirectShow SDK总体架构 234 7.3.2 DirectShow SDK简单应用程序案例 236 7.3.3 滤波器链表Filer Graph及各种组件 244 7.3.4 构建滤波器链表(Building Filer Graph) 252 7.3.5 滤波器链表中的数据流动Data Flow 257 7.3.6 DirectShow中的事件通知机制 261 7.3.7 常用DirectShow SDK接口 267 7.4 DirectShow SDK常用开发案例 267 7.4.1 通用开发流程 268 7.4.2 系统初始化 268 7.4.3 媒体播放方法 268 7.4.4 消息处理方法 270 7.4.5 视频采集技术 271 7.4.6 音频采集案例 282 7.5 本章小结 293 第8章 打造自己的媒体播放器 295 8.1 系统分析与设计 296 8.1.1 FilterGraph结构设计 297 8.1.2 GraphEdit模拟实现 297 8.1.3 界面设计 299 8.2 实现媒体控制类 307 8.2.1 CDXGraph类初始化 308 8.2.2 创建Graph滤波器链表 309 8.2.3 图像窗口设计 311 8.2.4 媒体播放控制 312 8.2.5 全屏显示及抓图存盘实现 315 8.3 实现一个简单的媒体播放器 317 8.4 升级你的播放器 321 8.4.1 添加控制功能 321 8.4.2 添加拖放功能 325 8.4.3 添加音量调节功能 326 8.4.4 添加欢迎背景图片 328 8.5 系统效果展示 328 8.6 如何播放更多的文件格式 329 8.7 本章小结 330 第9章 自制DV实现视频采集 331 9.1 系统分析与设计 332 9.1.1 采集设备的枚举 332 9.1.2 使用Capture Graph Builder 335 9.1.3 采集参数的设置 336 9.2 使用经典采集技术实现视频捕获 338 9.2.1 GraphEdit模拟实现 338 9.2.2 视频捕获类CCaptureClass的实现 340 9.2.3 界面设计 345 9.3 使用VMR技术实现视频图像捕获 350 9.3.1 VMR技术基础 350 9.3.2 GraphEdit模拟实现视频捕获预览 350 9.3.3 视频图像捕获类CVMR_Capture的实现 353 9.3.4 界面设计 361 9.4 系统效果演示 366 9.4.1 实例一 系统效果演示 367 9.4.2 实例二 系统效果演示 368 9.5 本章小结 369 第10章 VFW技术实现视频处理通用平台 371 10.1 VFW开发技术流程分析 372 10.1.1 技术概述 372 10.1.2 VFW采集开发流程图 373 10.2 使用VFW实现视频捕获和预览 373 10.2.1 建立单文档应用程序 373 10.2.2 创建视频窗口 375 10.2.3 设计回调函数 376 10.2.4 视频图像显示设置 378 10.2.5 捕获预览视频 379 10.2.6 配置视频格式及图像参数 381 10.3 使用系统插件实现视频编解码 382 10.3.1 使用系统视频编解码插件 383 10.3.2 视频编码码流写AVI文件 385 10.3.3 关闭平台 387 10.4 使用XviD CODEC算法实现视频编解码 388 10.4.1 生成XviD算法静态库(编译过程) 388 10.4.2 实现XviD CODEC视频编码算法函数 389 10.4.3 实现XviD CODEC视频解码算法函数 393 10.4.4 使用XviD CODEC编解码算法 395 10.5 平台应用效果展示 398 10.6 本章小结 399 第4篇 编解码技术 401 第11章 纵览音视频编解码技术 403 11.1 数字音视频基础 404 11.2 音视频编解码及方法 406 11.2.1 音频编码方法 406 11.2.2 视频编码方法 410 11.3 编解码技术标准 417 11.3.1 静态图像编码标准 418 11.3.2 MPEG-4/H.264视频算法 424 11.3.3 AVS国产视频编码标准 430 11.4 编解码产业及发展 431 11.4.1 编解码资源一览 431 11.4.2 编解码发展前景 432 11.5 本章小结 433 第12章 使用MMX/SSE 2进行多媒体编程 435 12.1 MMX/SSE 2技术基础 436 12.2 MMX/SSE 2指令剖析 439 12.2.1 MMX媒体扩展指令 439 12.2.2 MMX程序设计 444 12.2.3 SSE/SSE 2媒体扩展指令 455 12.2.4 SSE程序设计详细解析 457 12.3 使用MMX/SSE 2进行音视频开发 463 12.3.1 开发前技术准备 464 12.3.2 MMX/SSE 2视频编解码编程 465 12.3.3 使用VC调试MMX/SSE 2程序 470 12.4 MMX/SSE 2开发常见问题 472 12.4.1 制订计划 472 12.4.2 哪部分代码可使用MMX技术改进 473 12.4.3 代码是浮点型还是整型 473 12.4.4 EMMS准则 474 12.4.5 CPUID的检测MMX技术的用法 474 12.4.6 数据对齐 474 12.4.7 数据安排 475 12.4.8 应用程序最后的调整 476 12.5 本章小结 476 第13章 用DM642实现视频编解码技术 477 13.1 数字媒体处理器TMS320DM642DSP概述 478 13.2 DSP软件开发环境CCS 481 13.2.1 安装CCS 481 13.2.2 CCS主要部件 482 13.2.3 使用CCS优化工具实现算法优化 488 13.3 用C语言进行视频算法框架编程 492 13.3.1 C编程规则和参考 492 13.3.2 DSP关键字与CMD文件使用 493 13.3.3 算法系统资源剖析 495 13.4 DM642实现视频算法优化 497 13.4.1 并行算法指令和建立软件流水 497 13.4.2 使用intrinsic指令完成核心模块的优化 499 13.4.3 使用DSP线性汇编优化核心模块 500 13.4.4 使用Cache技术实现算法优化 507 13.4.5 使用乒乓式EDMA实现算法优化 508 13.5 DM642优化视频算法常见问题 513 13.6 本章小结 518 第14章 XviD CODEC实现MPEG-4编解码 519 14.1 MPEG-4编解码概述 520 14.1.1 基于对象的MPEG-4视频编码 520 14.1.2 XviD格式文件播放 520 14.2 XviD CODEC编解码分析 521 14.2.1 MPEG-4编解码设计与剖析 521 14.2.2 MMX/SSE 2实现XviD CODEC 549 14.2.3 DM642下XviD CODEC优化 553 14.3 运行XviD CODEC系统 559 14.3.1 YUV原始视频数据及其显示 559 14.3.2 VC平台下编译和运行XviD CODEC 559 14.3.3 CODEC在DSP下软仿真和硬仿真 562 14.4 系统效果展示 562 14.5 本章小结 563 第15章 X264实现H.264/AVC视频编码 565 15.1 H.264/AVC编码概要 566 15.1.1 开源代码工程管理软件 566 15.1.2 获取开源算法工程 566 15.1.3 H.264/AVC新特性 567 15.2 X264视频编码分析 568 15.2.1 H.264/AVC关键技术要点 569 15.2.2 X264视频编码设计与剖析 577 15.2.3 X264核心模块MMX/DSP汇编优化 599 15.3 运行X264编码系统 606 15.3.1 VC平台下编译和运行X264 606 15.3.2 JM验证X264码流 610 15.3.3 ffmpeg中的H.264视频解码 611 15.4 系统效果展示 611 15.4.1 X264实现H.264/AVC视频编码 611 15.4.2 ffmpeg-h264-vc工程实现H.264视频解码 612 15.5 本章小结 613 第16章 打造自己的DVR监控系统 615 16.1 DVR监控系统分析与设计 616 16.1.1 监控系统分类 616 16.1.2 监控系统组成 617 16.1.3 基于压缩板卡的SDK软件开发包 619 16.2 DVR监控系统主界面软件设计 621 16.2.1 对话框应用程序开发 621 16.2.2 位图按钮设计 622 16.3 模拟DVR视频采集 636 16.3.1 基于DirectShow的视频采集回放 636 16.3.2 基于DirectShow的影音文件回放 638 16.4 系统效果展示 643 16.5 本章小结 644 附录A 旧版VC升级到VC 2005程序安全的10点注意事项 645 附录B 开发常见问题 (附源码) 由于文件过大所以本文件采用分卷压缩的,需要安装好压,并下载完全部压缩分卷。共12个分卷
本书共16章,分为4篇,详细讲解了使用各种软件和平台进行音、视频多媒体编程的技术,以案例为对象展示实现过程、分析技术难点。主要内容包括软件Visual C++2005的开发技术、DirectSound开发音频、DirectShow/VFW开发视频、MMX/SSE进行多媒体汇编编程、DM642 DSP进行音视频算法优化和主流视频算法MPEG-4/H.264的编码原理及工程实践。本书系统地介绍Visual C++ 2005进行流媒体编程的基本思路和方法,采用案例为主的叙述方式,将大量的技术理论融入具体的案例剖析中。采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2 各种数字音频文件格式基础 4 1.1.3 视频的相关基础概念 8 1.1.4 常见的视频文件格式 8 1.2 数字音视频数据的编解码技术 10 1.2.1 音频数据的编解码 11 1.2.2 视频数据的编解码 13 1.2.3 音视频编码的相关标准 13 1.3 音视频处理平台的选择 15 1.3.1 个人多媒体计算机 15 1.3.2 嵌入式处理器ARM 16 1.3.3 数字媒体处理器DSP 16 1.4 音视频开发的典型应用 16 1.4.1 个人消费类电子产品 16 1.4.2 公共领域的音视频应用 18 1.5 常用音视频开发工具 21 1.5.1 DirectSound音频开发 21 1.5.2 DirectShow视频开发 21 1.5.3 DSP CCS算法开发 22 1.6 本章小结 23 第2章 Visual C++ 2005开发基础 25 2.1 Visual C++ 2005新增特性 26 2.1.1 句柄(Handles) 26 2.1.2 类型的声明 26 2.1.3 对代码编辑的改进 27 2.2 VC能做的事情 27 2.2.1 生成传统的控制台应用程序 27 2.2.2 生成基于MFC的应用程序 32 2.2.3 生成静态链接库 40 2.2.4 生成动态链接库 41 2.3 利用向导完成基本开发 46 2.3.1 生成应用程序 46 2.3.2 生成应用库LIB/DLL 53 2.4 MFC编程基础 56 2.4.1 Windows消息与事件 56 2.4.2 消息与事件的响应 63 2.4.3 常用消息 66 2.5 基于对话框的编程 68 2.5.1 创建和编辑对话框 68 2.5.2 对话框种类 75 2.6 常用控件使用技巧 79 2.6.1 按钮类控件的使用 80 2.6.2 文本可编辑类控件的使用 81 2.6.3 静态类控件的使用 82 2.6.4 其他控件 83 2.7 Visual 2005开发技术资源 84 2.7.1 MSDN在线帮助 84 2.7.2 丰富的网络资源 86 2.8 Visual 2005开发的常见问题 86 2.8.1 如何使用volatile和const_cast 86 2.8.2 如何构造unicode版本的程序 87 2.8.3 如何使用.def文件 87 2.8.4 如何正确编写Win32 DLL 87 2.8.5 如何编写和使用资源DLL 88 2.8.6 如何实现对话框的数据交换 88 2.9 本章小结 89 第2篇 音频开发 91 第3章 DirectSound开发基础 93 3.1 Microsoft DirectSound SDK 94 3.1.1 比较DirectSound与DirectMusic 94 3.1.2 DirectSound SDK能做什么 95 3.1.3 如何获取DirectSound SDK 96 3.1.4 DirectSound SDK的基本结构 98 3.1.5 Directsound SDK安装 100 3.1.6 选择最适合用户的DirectSound SDK 100 3.1.7 用DirectSound进行编程的必要步骤 102 3.2 DirectSound的详细使用方法 103 3.2.1 DirectSound设备对象 104 3.2.2 DirectSound缓冲区对象 107 3.2.3 使用WAV数据 114 3.2.4 使用音效 116 3.3 开发环境配置 118 3.3.1 Visual C++基本开发环境配置 119 3.3.2 DirectSound应用程序的开发环境配置 119 3.3.3
本书共16章,分为4篇,详细讲解了使用各种软件和平台进行音、视频多媒体编程的技术,以案例为对象展示实现过程、分析技术难点。主要内容包括软件Visual C++2005的开发技术、DirectSound开发音频、DirectShow/VFW开发视频、MMX/SSE进行多媒体汇编编程、DM642 DSP进行音视频算法优化和主流视频算法MPEG-4/H.264的编码原理及工程实践。本书系统地介绍Visual C++ 2005进行流媒体编程的基本思路和方法,采用案例为主的叙述方式,将大量的技术理论融入具体的案例剖析中。采用的案例均来源于作者实际开发工作,具有很好的实用价值,可以帮助读者在开发中进行参考或直接应用。 第1篇 开发基础 1 第1章 数字音视频开发技术基础 3 1.1 数字音视频基本概念 4 1.1.1 数字音频技术基础 4 1.1.2 各种数字音频文件格式基础 4 1.1.3 视频的相关基础概念 8 1.1.4 常见的视频文件格式 8 1.2 数字音视频数据的编解码技术 10 1.2.1 音频数据的编解码 11 1.2.2 视频数据的编解码 13 1.2.3 音视频编码的相关标准 13 1.3 音视频处理平台的选择 15 1.3.1 个人多媒体计算机 15 1.3.2 嵌入式处理器ARM 16 1.3.3 数字媒体处理器DSP 16 1.4 音视频开发的典型应用 16 1.4.1 个人消费类电子产品 16 1.4.2 公共领域的音视频应用 18 1.5 常用音视频开发工具 21 1.5.1 DirectSound音频开发 21 1.5.2 DirectShow视频开发 21 1.5.3 DSP CCS算法开发 22 1.6 本章小结 23 第2章 Visual C++ 2005开发基础 25 2.1 Visual C++ 2005新增特性 26 2.1.1 句柄(Handles) 26 2.1.2 类型的声明 26 2.1.3 对代码编辑的改进 27 2.2 VC能做的事情 27 2.2.1 生成传统的控制台应用程序 27 2.2.2 生成基于MFC的应用程序 32 2.2.3 生成静态链接库 40 2.2.4 生成动态链接库 41 2.3 利用向导完成基本开发 46 2.3.1 生成应用程序 46 2.3.2 生成应用库LIB/DLL 53 2.4 MFC编程基础 56 2.4.1 Windows消息与事件 56 2.4.2 消息与事件的响应 63 2.4.3 常用消息 66 2.5 基于对话框的编程 68 2.5.1 创建和编辑对话框 68 2.5.2 对话框种类 75 2.6 常用控件使用技巧 79 2.6.1 按钮类控件的使用 80 2.6.2 文本可编辑类控件的使用 81 2.6.3 静态类控件的使用 82 2.6.4 其他控件 83 2.7 Visual 2005开发技术资源 84 2.7.1 MSDN在线帮助 84 2.7.2 丰富的网络资源 86 2.8 Visual 2005开发的常见问题 86 2.8.1 如何使用volatile和const_cast 86 2.8.2 如何构造unicode版本的程序 87 2.8.3 如何使用.def文件 87 2.8.4 如何正确编写Win32 DLL 87 2.8.5 如何编写和使用资源DLL 88 2.8.6 如何实现对话框的数据交换 88 2.9 本章小结 89 第2篇 音频开发 91 第3章 DirectSound开发基础 93 3.1 Microsoft DirectSound SDK 94 3.1.1 比较DirectSound与DirectMusic 94 3.1.2 DirectSound SDK能做什么 95 3.1.3 如何获取DirectSound SDK 96 3.1.4 DirectSound SDK的基本结构 98 3.1.5 Directsound SDK安装 100 3.1.6 选择最适合用户的DirectSound SDK 100 3.1.7 用DirectSound进行编程的必要步骤 102 3.2 DirectSound的详细使用方法 103 3.2.1 DirectSound设备对象 104 3.2.2 DirectSound缓冲区对象 107 3.2.3 使用WAV数据 114 3.2.4 使用音效 116 3.3 开发环境配置 118 3.3.1 Visual C++基本开发环境配置 119 3.3.2 DirectSound应用程序的开发环境配置 119 3.3.3 DirectSound Filter开发环境配置 121 3.4 调试音频处理程序 125 3.4.1 Visual C++调试器 125 3.4.2 DirectSound中常用的调试技术 128 3.5 DirectSound开发的常见问题 130 3.6 本章小结 131 第4章 打造自己的音频播放器 133 4.1 系统设计和分析 134 4.2 缓冲区和通知基础 135 4.2.1 缓冲区的概念 135 4.2.2 缓冲区的通知 136 4.3 播放文件 137 4.3.1 创建DirectSound对象 137 4.3.2 创建播放缓冲区 138 4.3.3 调用方法播放声音 145 4.3.4 结束播放 146 4.4 系统效果演示 146 4.4.1 新建基于对话框的程序框架 147 4.4.2 添加控件及变量 147 4.4.3 封装CDirectSound类实现DirectSound声音播放 148 4.4.4 与对话框界面相关操作实现 156 4.4.5 程序运行结果 159 4.5 DirectSound开发常见问题 160 4.6 本章小结 161 第5章 语音3D特效器制作 163 5.1 系统设计和分析 164 5.2 DirectSound 3D缓冲区 164 5.2.1 获取3D缓冲区对象 165 5.2.2 最大距离和最小距离 166 5.2.3 处理模式 167 5.2.4 声音圆锥 167 5.3 DirectSound 3D虚拟听众 168 5.3.1 获得3D听众 168 5.3.2 听众的空间参数 169 5.3.3 距离因子与Doppler效应 171 5.3.4 滚降因子与延迟设置 173 5.4 系统效果演示 174 5.4.1 具体的实现步骤 174 5.4.2 程序的实现代码 176 5.4.3 程序运行结果 186 5.5 DirectSound 3D开发常见问题 187 5.6 本章小结 188 第6章 对拾音设备录制自己的语音文件 189 6.1 系统分析和设计 190 6.2 管理捕获缓冲区 191 6.2.1 创建捕获缓冲区 191 6.2.2 启动缓冲区 197 6.2.3 封锁缓冲区 197 6.2.4 解锁缓冲区 198 6.2.5 中止捕获 199 6.3 系统效果演示 199 6.3.1 声音类的封装 199 6.3.2 声音管理函数的实现 202 6.3.3 程序运行结果 214 6.4 DirectSound录制语音文件开发常见问题 215 6.5 本章小结 216 第3篇 视频开发 217 第7章 DirectShow开发基础 219 7.1 Microsoft DirectShow SDK 220 7.1.1 DirectX及成员组成 220 7.1.2 DirectShow SDK能做什么 221 7.1.3 如何获取DirectShow SDK 221 7.1.4 安装Direshow SDK 222 7.2 开发环境配置 224 7.2.1 生成DirectShow SDK开发库 224 7.2.2 Visual C++开发环境配置 229 7.2.3 常见问题解析集锦 232 7.3 DirectShow SDK基本架构 234 7.3.1 DirectShow SDK总体架构 234 7.3.2 DirectShow SDK简单应用程序案例 236 7.3.3 滤波器链表Filer Graph及各种组件 244 7.3.4 构建滤波器链表(Building Filer Graph) 252 7.3.5 滤波器链表中的数据流动Data Flow 257 7.3.6 DirectShow中的事件通知机制 261 7.3.7 常用DirectShow SDK接口 267 7.4 DirectShow SDK常用开发案例 267 7.4.1 通用开发流程 268 7.4.2 系统初始化 268 7.4.3 媒体播放方法 268 7.4.4 消息处理方法 270 7.4.5 视频采集技术 271 7.4.6 音频采集案例 282 7.5 本章小结 293 第8章 打造自己的媒体播放器 295 8.1 系统分析与设计 296 8.1.1 FilterGraph结构设计 297 8.1.2 GraphEdit模拟实现 297 8.1.3 界面设计 299 8.2 实现媒体控制类 307 8.2.1 CDXGraph类初始化 308 8.2.2 创建Graph滤波器链表 309 8.2.3 图像窗口设计 311 8.2.4 媒体播放控制 312 8.2.5 全屏显示及抓图存盘实现 315 8.3 实现一个简单的媒体播放器 317 8.4 升级你的播放器 321 8.4.1 添加控制功能 321 8.4.2 添加拖放功能 325 8.4.3 添加音量调节功能 326 8.4.4 添加欢迎背景图片 328 8.5 系统效果展示 328 8.6 如何播放更多的文件格式 329 8.7 本章小结 330 第9章 自制DV实现视频采集 331 9.1 系统分析与设计 332 9.1.1 采集设备的枚举 332 9.1.2 使用Capture Graph Builder 335 9.1.3 采集参数的设置 336 9.2 使用经典采集技术实现视频捕获 338 9.2.1 GraphEdit模拟实现 338 9.2.2 视频捕获类CCaptureClass的实现 340 9.2.3 界面设计 345 9.3 使用VMR技术实现视频图像捕获 350 9.3.1 VMR技术基础 350 9.3.2 GraphEdit模拟实现视频捕获预览 350 9.3.3 视频图像捕获类CVMR_Capture的实现 353 9.3.4 界面设计 361 9.4 系统效果演示 366 9.4.1 实例一 系统效果演示 367 9.4.2 实例二 系统效果演示 368 9.5 本章小结 369 第10章 VFW技术实现视频处理通用平台 371 10.1 VFW开发技术流程分析 372 10.1.1 技术概述 372 10.1.2 VFW采集开发流程图 373 10.2 使用VFW实现视频捕获和预览 373 10.2.1 建立单文档应用程序 373 10.2.2 创建视频窗口 375 10.2.3 设计回调函数 376 10.2.4 视频图像显示设置 378 10.2.5 捕获预览视频 379 10.2.6 配置视频格式及图像参数 381 10.3 使用系统插件实现视频编解码 382 10.3.1 使用系统视频编解码插件 383 10.3.2 视频编码码流写AVI文件 385 10.3.3 关闭平台 387 10.4 使用XviD CODEC算法实现视频编解码 388 10.4.1 生成XviD算法静态库(编译过程) 388 10.4.2 实现XviD CODEC视频编码算法函数 389 10.4.3 实现XviD CODEC视频解码算法函数 393 10.4.4 使用XviD CODEC编解码算法 395 10.5 平台应用效果展示 398 10.6 本章小结 399 第4篇 编解码技术 401 第11章 纵览音视频编解码技术 403 11.1 数字音视频基础 404 11.2 音视频编解码及方法 406 11.2.1 音频编码方法 406 11.2.2 视频编码方法 410 11.3 编解码技术标准 417 11.3.1 静态图像编码标准 418 11.3.2 MPEG-4/H.264视频算法 424 11.3.3 AVS国产视频编码标准 430 11.4 编解码产业及发展 431 11.4.1 编解码资源一览 431 11.4.2 编解码发展前景 432 11.5 本章小结 433 第12章 使用MMX/SSE 2进行多媒体编程 435 12.1 MMX/SSE 2技术基础 436 12.2 MMX/SSE 2指令剖析 439 12.2.1 MMX媒体扩展指令 439 12.2.2 MMX程序设计 444 12.2.3 SSE/SSE 2媒体扩展指令 455 12.2.4 SSE程序设计详细解析 457 12.3 使用MMX/SSE 2进行音视频开发 463 12.3.1 开发前技术准备 464 12.3.2 MMX/SSE 2视频编解码编程 465 12.3.3 使用VC调试MMX/SSE 2程序 470 12.4 MMX/SSE 2开发常见问题 472 12.4.1 制订计划 472 12.4.2 哪部分代码可使用MMX技术改进 473 12.4.3 代码是浮点型还是整型 473 12.4.4 EMMS准则 474 12.4.5 CPUID的检测MMX技术的用法 474 12.4.6 数据对齐 474 12.4.7 数据安排 475 12.4.8 应用程序最后的调整 476 12.5 本章小结 476 第13章 用DM642实现视频编解码技术 477 13.1 数字媒体处理器TMS320DM642DSP概述 478 13.2 DSP软件开发环境CCS 481 13.2.1 安装CCS 481 13.2.2 CCS主要部件 482 13.2.3 使用CCS优化工具实现算法优化 488 13.3 用C语言进行视频算法框架编程 492 13.3.1 C编程规则和参考 492 13.3.2 DSP关键字与CMD文件使用 493 13.3.3 算法系统资源剖析 495 13.4 DM642实现视频算法优化 497 13.4.1 并行算法指令和建立软件流水 497 13.4.2 使用intrinsic指令完成核心模块的优化 499 13.4.3 使用DSP线性汇编优化核心模块 500 13.4.4 使用Cache技术实现算法优化 507 13.4.5 使用乒乓式EDMA实现算法优化 508 13.5 DM642优化视频算法常见问题 513 13.6 本章小结 518 第14章 XviD CODEC实现MPEG-4编解码 519 14.1 MPEG-4编解码概述 520 14.1.1 基于对象的MPEG-4视频编码 520 14.1.2 XviD格式文件播放 520 14.2 XviD CODEC编解码分析 521 14.2.1 MPEG-4编解码设计与剖析 521 14.2.2 MMX/SSE 2实现XviD CODEC 549 14.2.3 DM642下XviD CODEC优化 553 14.3 运行XviD CODEC系统 559 14.3.1 YUV原始视频数据及其显示 559 14.3.2 VC平台下编译和运行XviD CODEC 559 14.3.3 CODEC在DSP下软仿真和硬仿真 562 14.4 系统效果展示 562 14.5 本章小结 563 第15章 X264实现H.264/AVC视频编码 565 15.1 H.264/AVC编码概要 566 15.1.1 开源代码工程管理软件 566 15.1.2 获取开源算法工程 566 15.1.3 H.264/AVC新特性 567 15.2 X264视频编码分析 568 15.2.1 H.264/AVC关键技术要点 569 15.2.2 X264视频编码设计与剖析 577 15.2.3 X264核心模块MMX/DSP汇编优化 599 15.3 运行X264编码系统 606 15.3.1 VC平台下编译和运行X264 606 15.3.2 JM验证X264码流 610 15.3.3 ffmpeg中的H.264视频解码 611 15.4 系统效果展示 611 15.4.1 X264实现H.264/AVC视频编码 611 15.4.2 ffmpeg-h264-vc工程实现H.264视频解码 612 15.5 本章小结 613 第16章 打造自己的DVR监控系统 615 16.1 DVR监控系统分析与设计 616 16.1.1 监控系统分类 616 16.1.2 监控系统组成 617 16.1.3 基于压缩板卡的SDK软件开发包 619 16.2 DVR监控系统主界面软件设计 621 16.2.1 对话框应用程序开发 621 16.2.2 位图按钮设计 622 16.3 模拟DVR视频采集 636 16.3.1 基于DirectShow的视频采集回放 636 16.3.2 基于DirectShow的影音文件回放 638 16.4 系统效果展示 643 16.5 本章小结 644 附录A 旧版VC升级到VC 2005程序安全的10点注意事项 645 附录B 开发常见问题 (附源码) 由于文件过大所以本文件采用分卷压缩的,需要安装好压,并下载完全部压缩分卷。共11个分卷。
C++可以通过调用FFmpeg库来实现音视频处理。下面是一个简单的示例代码,演示了如何使用FFmpegC++中进行音频解码和视频解码: ```cpp #include <iostream> #include <string> extern "C" { #include <libavformat/avformat.h> #include <libswscale/swscale.h> } int main() { // 注册所有的FFmpeg组件 av_register_all(); // 打开输入文件 AVFormatContext* formatContext = nullptr; if (avformat_open_input(&formatContext, "input.mp4", nullptr, nullptr) != 0) { std::cerr << "无法打开输入文件" << std::endl; return -1; } // 获取流信息 if (avformat_find_stream_info(formatContext, nullptr) < 0) { std::cerr << "无法获取流信息" << std::endl; return -1; } // 查找第一个视频流 int videoStreamIndex = -1; for (unsigned int i = 0; i < formatContext->nb_streams; ++i) { if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoStreamIndex = i; break; } } if (videoStreamIndex == -1) { std::cerr << "找不到视频流" << std::endl; return -1; } // 获取视频解码器 AVCodecParameters* codecParameters = formatContext->streams[videoStreamIndex]->codecpar; AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id); if (codec == nullptr) { std::cerr << "找不到解码器" << std::endl; return -1; } // 创建解码器上下文 AVCodecContext* codecContext = avcodec_alloc_context3(codec); if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) { std::cerr << "无法创建解码器上下文" << std::endl; return -1; } // 打开解码器 if (avcodec_open2(codecContext, codec, nullptr) < 0) { std::cerr << "无法打开解码器" << std::endl; return -1; } // 创建帧对象 AVFrame* frame = av_frame_alloc(); // 读取视频帧 AVPacket packet; while (av_read_frame(formatContext, &packet) >= 0) { if (packet.stream_index == videoStreamIndex) { // 解码视频帧 avcodec_send_packet(codecContext, &packet); while (avcodec_receive_frame(codecContext, frame) == 0) { // 在这里可以对视频帧进行处理 } } av_packet_unref(&packet); } // 清理资源 av_frame_free(&frame); avcodec_free_context(&codecContext); avformat_close_input(&formatContext); return 0; } ``` 这段代码使用了FFmpeg库来打开一个视频文件,查找视频流,获取解码器并解码视频帧。你可以根据需要在代码中添加额外的处理逻辑。请确保你已经正确地安装并链接了FFmpeg库,并将输入文件名更改为你实际的视频文件路径。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值