ffmpeg入門(四) 解碼部分代碼整理

通過調試,最終下面的代碼,在VS2013版本上已經調試通過,並且也能從mp4或者其他文件格式轉成yuv的格式。所以備忘錄收藏下:

#include <iostream>
using namespace std;

#ifdef __cplusplus
extern "C"{
#endif
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/pixfmt.h"
#include "libavutil/imgutils.h"

int main(int argc, char** argv)
{
    av_register_all();

    avformat_network_init();

    AVFormatContext *pFormatCtx;
    int ret = 0;

    char filepath[] = "D:\\G\\project\\01_31_1\\Debug\\1.mp4";

    pFormatCtx = avformat_alloc_context();
    if (avformat_open_input(&pFormatCtx, filepath, NULL, NULL) != 0)
    {
        cout << "Couldn't not open input stream." << endl;
        return -1;
    }

    av_dump_format(pFormatCtx, 0, filepath, 0);

    do 
    {
        if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
        {
            cout << "Couldn't not find stream info." << endl;
            break;
        }

        int videoIndex = -1;
        unsigned int i = 0;
        for (; i < pFormatCtx->nb_streams; i++)
        {
            if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)
            {
                videoIndex = i;
                break;
            }
        }

        if (videoIndex == -1)
        {
            cout << "can't find a video stream." << endl;
            break;
        }

        AVCodecContext  *pCodecCtx;
        pCodecCtx = pFormatCtx->streams[videoIndex]->codec;
        AVCodec *pCodec = NULL;
        pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
        cout << "codec_id:" << pCodecCtx->codec_id << endl;
        if (NULL == pCodec)
        {
            cout << "Fail to find decoder" << endl;
            break;
        }

        if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
        {
            cout << "Fail to avcodec_open2 " << endl;
            break;
        }

        do 
        {
            AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));
            AVFrame *pFrame = av_frame_alloc();
            AVFrame *pFrameYUV = av_frame_alloc();
            int got_picture = 0;
            struct SwsContext *img_convert_ctx;
            av_dump_format(pFormatCtx, 0, filepath, 0);
            uint8_t *out_buffer;
            out_buffer = (uint8_t *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1));
            av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 1);
            img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
            if (NULL == img_convert_ctx)
            {
                cout << "img_convert_ctx is wrong!" << endl;
                break;
            }
            cout << pCodecCtx->width << "-----" << pCodecCtx->height << endl;
            FILE *fp_yuv = NULL;
            fopen_s(&fp_yuv, "output.yuv", "wb+");
            while (av_read_frame(pFormatCtx, packet) >= 0)
            {
                if (packet->stream_index == videoIndex)
                {
                    ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, packet);
                    if (ret < 0)
                    {
                        cout << "decode error.\n";
                        break;
                    }
                    if (got_picture)
                    {
                        sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0,
                            pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);

                        //  420
                        //cout << "123" << endl;
#if 1
                        int y_size = pCodecCtx->width*pCodecCtx->height;
                        fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv);    //Y   
                        fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv);  //U  
                        fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv);  //V  
#endif
                    }
                }
                av_packet_unref(packet);
            }
            av_frame_unref(pFrameYUV);
            av_frame_unref(pFrame);

            cout << "=====>" << endl;
        } while (0);

        avcodec_close(pCodecCtx);
    } while (0);

    avformat_close_input(&pFormatCtx);

    getchar();

    return 0;
}

#ifdef __cplusplus
}
#endif


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章