zoukankan      html  css  js  c++  java
  • ffmpeg结合SDL编写播放器(三)

    接下来是解析影片的帧

    /***
    project.c
    ***/
    #include<stdio.h>
    #include<libavcodec/avcodec.h>
    #include<libavformat/avformat.h>
    #include<libswscale/swscale.h>
    
    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");
        if (NULL == pFile)
            return;
        
        //write header
        fprintf(pFile, "P6
    %d %d
    255
    ",width,height);
    
        //write pixel data
        for (y = 0; y < height; y++)
        {
            fwrite(pFrame->data[0] + y * pFrame->linesize[0],
                    1, width * 3, pFile);
        }
        
        //close file
        fclose(pFile);
    }
    int main(int argc, char *argv[])
    {
        AVFormatContext *pFormatCtx = NULL;
        AVCodecContext     *pCodecCtx = NULL;
        AVCodec            *pCodec = NULL;
        AVFrame            *pFrame = NULL;
        AVFrame            *pFrameRGB = NULL;
        AVPacket         packet;
        int                i,videoStream;
        int             frameFinished;
        int             numBytes;
        uint8_t            *buffer = NULL;
        
        AVDictionary    *optionsDict = NULL;
        struct SwsContext    *sws_ctx = NULL;
    
        if (argc < 2)
        {
            printf("Please provide a movie file
    ");
            return -1;
        }
        
        //register all formats and codecs
        av_register_all();
        
        //open video file
        if (avformat_open_input(&pFormatCtx,argv[1], NULL, NULL) != 0)
        {
            return -1;        //couldn't open file
        }
        
        //retrive stream information
        if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
        {
            return -1;        //couldn't find stream information
        }
        
        //dump information about file onto standard error
        av_dump_format(pFormatCtx, 0, argv[1], 0);
        
        //find the first video stream
        videoStream = -1;
        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;        //Don't find a video stream
        }
        
        //Get a pointer to the codec context for the video stream
        pCodecCtx = pFormatCtx->streams[videoStream]->codec;
        
        //Find the decoder for the video stream
        pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
        if (pCodec == NULL)
        {
            fprintf(stderr,"Unsupported codec!
    ");
            return -1;    //Codec not found
        }
    
        //open codec
        if (avcodec_open2(pCodecCtx, pCodec, &optionsDict) < 0)
        {
            return -1;    //Could not open codec
        }
        
        //Allcocate an AVFrame structure
        pFrame = av_frame_alloc();
        pFrameRGB = av_frame_alloc();
        if (pFrameRGB == NULL)
        {
            return -1;
        }
        
        //Determine required buffer size and allocate buffer
        numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx->width,
                pCodecCtx->height);
        buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
    
        sws_ctx = sws_getContext
            (
             pCodecCtx->width,
             pCodecCtx->height,
             pCodecCtx->pix_fmt,
             pCodecCtx->width,
             pCodecCtx->height,
             AV_PIX_FMT_RGB24,
             SWS_BILINEAR,
             NULL, NULL, NULL
            );
        
        //Assign appropriate parts of buffer to image planes in pFrameRGB
        //Note that pFrameRGB is an AVFrame, but AVFrame is a superset
        // of AVFPicture
        avpicture_fill((AVPicture *)pFrameRGB, buffer,
                AV_PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
    
        //Read frames and save first five frames to disk
        i = 0;
        while (av_read_frame(pFormatCtx, &packet) >= 0)
        {
            //Is this a packet from video stream
            if (packet.stream_index == videoStream)
            {
                //decode video frame
                avcodec_decode_video2(pCodecCtx, pFrame,
                        &frameFinished, &packet);
                
                //Did wo get a video frame
                if (frameFinished)
                {
                    //Convert the image from its native format to RGB
                    sws_scale(sws_ctx,
                            (uint8_t const * const *)pFrame->data,
                            pFrame->linesize,
                            0,
                            pCodecCtx->height,
                            pFrameRGB->data,
                            pFrameRGB->linesize
                            );
                    
                    //Save the frame to disk
                    SaveFrame(pFrameRGB,pCodecCtx->width, 
                            pCodecCtx->height,i);
                    printf("decde %d frame
    ",i);
                    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);
        
        //Close the video file
        avformat_close_input(&pFormatCtx);
        return 0;
    }

    makefile如下:

    //makefile
    
    DIR_INC = -I/usr/local/include
    DIR_LIB = -L/usr/local/lib
    
    LIBS = -lavformat
            -lavcodec
            -lva-x11 
            -lva 
            -lxcb-shm 
            -lxcb-xfixes 
            -lxcb-render 
            -lxcb-shape 
            -lxcb -lX11 
            -lasound 
            -lz 
            -lswresample 
            -lswscale 
            -lavutil 
            -lm 
            -pthread
    
    FLAGS = -Wall -ggdb
    
    project : project.c
        gcc project.c ${FLAGS} ${DIR_INC} ${DIR_LIB} ${LIBS} -o project
        
    .PHONY:clean
    clean:
        rm project

    运行结果:

    完成后有很多ppm文件,可以将ppm转为jpg:

    编写一个脚本转化,内容如下:

    /***
    1.sh
    ***/
    #!/bin/bash
    
    ff=`ls *.ppm`
    
    for f in $ff
    do
        file=`echo ${f%.*}`
        ffmpeg -i "$file".ppm "$file".jpg
    done
    
    mkdir -p jpgs
    mv *.jpg jpgs
    rm *.ppm

    运行脚本:

    sh 1.sh

    可以在当前文件夹下找到jpgs文件夹下找到所有转化的jpg图片。

  • 相关阅读:
    JavaScript
    94.Binary Tree Inorder Traversal
    144.Binary Tree Preorder Traversal
    106.Construct Binary Tree from Inorder and Postorder Traversal
    105.Construct Binary Tree from Preorder and Inorder Traversal
    90.Subsets II
    78.Subsets
    83.Merge Sorted Array
    80.Remove Duplicates from Sorted Array II
    79.Word Search
  • 原文地址:https://www.cnblogs.com/wanghao-boke/p/11731072.html
Copyright © 2011-2022 走看看