新版本ffmpeg在Visual Studio中的使用。

 

FFMpeg是跨平台的开源软件,但是由于采用C99语法,在Visual Studio中无法编译,对于想要使用ffmpeg而不想去配置MinGw和其他依赖库的同学,提供以下方案。

首先去:http://ffmpeg.zeranoe.com/builds/此网站有ffmpeg 编译好的相关文件。此处下载ffmpeg动态链接库,32-bit build(shard),其中包括了所有的动态库,同时也包括了ffmpeg.exe(可以直接做视频转化,参数很强大),ffplay.exe(直接播放音视频)。此处需要用到其中的动态库用于在应用程序中使用,同时DLL需要lib导出,也需要相应的头文件,这个需要下载32 bit build(dev),其中包含了lib,和相应的头文件,但是却没有dll文件,所以需要用到前面的shared库。

好了,准备工作都做好了,就是编码测试了,我写了个简单的测试工程。ffmpeg.c太过复杂了,4000多行代码,而且在visual studio中根本编译不过。

代码如下:

 

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#ifdef __cplusplus
extern "C" 
{
#include "libavutil/avutil.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libswscale/swscale.h"
}
#endif

#pragma comment(lib,"avutil.lib")
#pragma comment(lib,"avcodec.lib")
#pragma comment(lib,"avformat.lib")
#pragma comment(lib,"swscale.lib")

#include <windows.h>

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame);
int img_convert2(AVPicture *dst, int dst_pix_fmt,AVPicture *src, int src_pix_fmt,int src_width, int src_height);

int main(int argc, char* argv[])
{
    av_register_all();
    AVFormatContext *pFormatCtx = NULL;
    // Open video file
    AVInputFormat *pInputFormat = NULL;
    if (avformat_open_input(&pFormatCtx, argv[1], NULL, NULL)!=0) {
        return -1; // Couldn't open file
    }
    if(av_find_stream_info(pFormatCtx)<0) {
        return -1; // Couldn't find stream information
    }

    int i = 0;
    int videoStream=-1;
    AVCodecContext *pCodecCtx = NULL;
    for(i=0; i < pFormatCtx->nb_streams; i++)
    {
        if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
        {
            videoStream = i;
            break;
        }
    }

    if(videoStream==-1) {
        return -1; // Didn't find a video stream
    }
    // Get a pointer to the codec context for the video stream
    pCodecCtx=pFormatCtx->streams[videoStream]->codec;

    AVCodec *pCodec = NULL;
    // Find the decoder for the video stream
    pCodec=avcodec_find_decoder(pCodecCtx->codec_id);

    if(pCodec==NULL)
    {
        fprintf(stderr, "Unsupported codec!\n");
        return -1; // Codec not found
    }

    // Open codec	
    if(avcodec_open(pCodecCtx, pCodec)<0) {
        return -1; // Could not open codec
    }
    AVFrame *pFrame,*pFrameRGB;
    // Allocate video frame
    pFrame=avcodec_alloc_frame();
    pFrameRGB=avcodec_alloc_frame();
    if(pFrameRGB==NULL) {
        return -1;
    }
    uint8_t *buffer;
    int numBytes;
    // Determine required buffer size and allocate buffer
    numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);
    buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));
    avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,pCodecCtx->width, pCodecCtx->height);

    int frameFinished;
    AVPacket packet;
    i=0;
    while(av_read_frame(pFormatCtx, &packet) >= 0)
    {
        // Is this a packet from the video stream?		
        if(packet.stream_index==videoStream)
        {
            // Decode video frame	
            avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished,&packet);
            // Did we get a video frame?	
            if(frameFinished)
            {
                // Convert the image from its native format to RGB	
                img_convert2((AVPicture *)pFrameRGB,PIX_FMT_RGB24,(AVPicture*)pFrame, pCodecCtx->pix_fmt,	
                    pCodecCtx->width, pCodecCtx->height);
                // Save the frame to disk
                if(++i<=100)	
                    SaveFrame(pFrameRGB, pCodecCtx->width,pCodecCtx->height, i);
            }
        }
        // Free the packet that was allocated by av_read_frame
        av_free_packet(&packet);	
    }


    // Free the RGB image
    av_free(buffer);
    av_free(pFrameRGB);
    // Free the YUV frame	
    av_free(pFrame);
    // Close the codec	
    avcodec_close(pCodecCtx);
    av_close_input_file(pFormatCtx);
    return 0;
}

int img_convert2(AVPicture *dst, int dst_pix_fmt,
                 AVPicture *src, int src_pix_fmt,
                 int src_width, int src_height)
{

    int w;	
    int h;
    SwsContext *pSwsCtx;
    w = src_width;	
    h = src_height;	
    pSwsCtx = sws_getContext(w, h, PIX_FMT_YUV420P, w, h, PIX_FMT_RGB24,SWS_BICUBIC, NULL, NULL, NULL);

    sws_scale(pSwsCtx,src->data, src->linesize,0, h, dst->data, dst->linesize);

    SaveFrame((AVFrame *)dst, src_width, src_height, 0);

    sws_freeContext(pSwsCtx);

    return 0;	
}

void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
{

    FILE *pFile;
    char szFilename[32];
    int y;
    // Open file
    sprintf(szFilename, "frame%d.ppm", iFrame);
    pFile=fopen(szFilename, "wb");

    //构造文件头
    BITMAPFILEHEADER bmpFileHeader;
    memset(&bmpFileHeader, 0, sizeof(BITMAPFILEHEADER));
    bmpFileHeader.bfType	= 0x4D42;
    bmpFileHeader.bfOffBits	= 54;
    bmpFileHeader.bfSize	= 54 + width * height * 24/8;

    BITMAPINFOHEADER bmpInfoHeader;
    memset(&bmpInfoHeader, 0, sizeof(BITMAPINFOHEADER));
    bmpInfoHeader.biCompression	= BI_RGB;
    bmpInfoHeader.biSize		= sizeof(BITMAPINFOHEADER);
    bmpInfoHeader.biPlanes		= 1;
    bmpInfoHeader.biBitCount	= 24;	//定死为24位图
    bmpInfoHeader.biWidth		= width;
    bmpInfoHeader.biHeight		= height;

    fwrite(&bmpFileHeader, sizeof(bmpFileHeader), 1, pFile);
    fwrite(&bmpInfoHeader, sizeof(bmpInfoHeader), 1, pFile);
    // Write pixel data
    for(y=0; y<height; y++) {
        fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
    }
    fclose(pFile);

}


此代码完成了视频的解码并将原始YUV数据转化为RGB存储到bmp文件中,但此处没做处理,bmp文件图像是反的。

注意一点:ffmpeg头文件需要依赖一些visual studio的头文件,我将自己的测试工程上传到资源中了。

此为完整可编译的ffmpeg vs测试工程。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值