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

来源:互联网 发布:mysql远程客户端中文版 编辑:程序博客网 时间:2024/05/21 06:57

 

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 __cplusplusextern "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测试工程。

 

原创粉丝点击