代码学习,将视频文件处理为ppm文件

学习了FFmpeg的一些转码流程和API后,参考示例代码,实现下面一段代码,主要实现了从一个视频文件抓取若干帧并保存成本地文件,以ppm格式
主要处理的流程:
这里写图片描述


#include <stdio.h>
#include "libavformat/avformat.h"   
#include "libswscale/swscale.h" 


void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame) 
{
    printf("SaveFrame... %d \n",iFrame);
    FILE *file;
    char outFilename[20];
    sprintf(outFilename,"frame%d.ppm",iFrame);
    file=fopen(outFilename,"wb");
    if(file == NULL)
        printf("open frame%d.ppm faild!\n",iFrame);
    // Write header 
    fprintf(file, "P6\n%d %d\n255\n", width, height);   

    int y;
    for(y=0; y<height; y++)  // Write pixel data 
        fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, file);  

   fclose(file);  

}

int img_convert2(AVPicture *dst, enum AVPixelFormat dst_pix_fmt,                 
                AVPicture *src,enum AVPixelFormat src_pix_fmt,                  
                int src_width, int src_height) 
{
    printf("img_convert2...\n");

    int w,h;
    w=src_width;
    h=src_height;
    struct SwsContext *sws_ctx;
    sws_ctx = sws_getContext(w,h,src_pix_fmt,w,h,dst_pix_fmt,SWS_BICUBIC,NULL,NULL,NULL);
    sws_scale(sws_ctx,src->data,src->linesize,0 ,h,dst->data,dst->linesize);
    //free SwsContext mem
    sws_freeContext(sws_ctx);
    return 0;

}




int main(int argc,char **argv)
{
    int ret;
    int i;
    int videostream = -1;
    AVFormatContext *fmt_ctx=NULL;
    AVStream *Stream=NULL;
    AVCodec *decode=NULL;
    AVCodecContext *code_ctx=NULL;


    av_register_all();
    // Open video file 
    ret = avformat_open_input(&fmt_ctx,argv[1],NULL,NULL);
    if(ret< 0)// Couldn't open file 
        printf("avformat_open_input failed!\n");
    ret = avformat_find_stream_info(fmt_ctx,NULL);  
    if(ret< 0)// Couldn't find stream information 
        printf("avformat_find_stream_info failed!\n");
    /*
    for (i = 0;i < fmt_ctx->nb_streams;i ++)
        {
            if(fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
            videostream = i;

        }
        */
    videostream =av_find_best_stream(fmt_ctx,AVMEDIA_TYPE_VIDEO,-1,-1,&decode,0);
    if(videostream == -1)
        printf("NO video stream\n");// Didn't find a video stream 
    Stream = fmt_ctx->streams[videostream];
    // Find the decoder for the video stream  
    decode = avcodec_find_decoder(Stream->codecpar->codec_id);
    if(decode == NULL)
        printf("decode is NULL!\n");// Codec not found  

    code_ctx = avcodec_alloc_context3(decode);

    ret = avcodec_parameters_to_context(code_ctx, Stream->codecpar);
    if (ret < 0) {
        av_log(NULL, AV_LOG_ERROR, "Failed to copy decoder parameters to input decoder context "
               "for stream #%u\n", i);
        }
    // Open codec
    ret = avcodec_open2(code_ctx, decode, NULL);
    if(ret < 0)
        printf("avcodec_find_decoder failed!\n");

    //check the parameter
    av_dump_format(fmt_ctx, 0, argv[1], 0);

    AVFrame *picture,*pictureRGB;
     // Allocate video frame 
    picture = av_frame_alloc();
    pictureRGB = av_frame_alloc();
    if(picture == NULL || pictureRGB == NULL)
        printf("av_frame_alloc failed!\n");

    int numByte;
    uint8_t *buf;
    // Determine required buffer size and allocate buffer
    numByte = avpicture_get_size(AV_PIX_FMT_RGB24,code_ctx->width,code_ctx->height);
    buf = (uint8_t *)av_malloc(numByte*sizeof(uint8_t));
    avpicture_fill((AVPicture *) pictureRGB,buf,AV_PIX_FMT_RGB24,code_ctx->width,code_ctx->height);


    AVPacket packet;
    av_init_packet(&packet);
    int frameFinished;
    while((ret = av_read_frame(fmt_ctx, &packet)) >= 0)
        {
            if(packet.stream_index == videostream){
                // Decode video frame  
                avcodec_decode_video2(code_ctx,picture,&frameFinished,&packet);
                if(frameFinished)//get a complete frame
                {
                    // Convert the image from its native format to RGB
                    img_convert2((AVPicture *)pictureRGB,AV_PIX_FMT_RGB24,(AVPicture *)picture,code_ctx->pix_fmt,code_ctx->width,code_ctx->height);
                    for(i = 0;i < 10;i ++)
                    {
                       // Save the frame to disk  
                       SaveFrame(pictureRGB,code_ctx->width,code_ctx->height,i);
                    }
                     break;
                 }
                 av_free_packet(&packet);

            }

    }
    // Free the RGB image 
    av_free(buf);
    av_free(pictureRGB);
    // Free the YUV frame 
    av_free(picture);
    // Close the codec 
    avcodec_close(code_ctx);
    avformat_free_context(fmt_ctx);
    return 0;
}


运行结果:
运行结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值