1. 程式人生 > >ffmpeg 接收h264+aac並解碼

ffmpeg 接收h264+aac並解碼

ffmpeg一直更新所以執行時有些方法和庫對應不上,我用的是http://ffmpeg.zeranoe.com/builds/中:ffmpeg-20140305-git-d08bb06-win32-shared和ffmpeg-20140305-git-d08bb06-win32-dev;直接上程式碼了
#include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
 
#ifdef __cplusplus
extern "C"{
#include "libavformat\avformat.h"
#include "libavcodec\avcodec.h"
#include "libavutil\avutil.h"
}
 
#endif //__cplusplus
 
#define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
 
 
int _tmain(int argc, _TCHAR* argv[])
{
 
    const char* input = "";
 
    AVInputFormat* pInForCtx = NULL;
    AVFormatContext* pFormatCtx = NULL;
    AVCodecContext *vpCodecCtx= NULL; 
    AVCodecContext *apCodecCtx= NULL; 
    AVCodec* video_codec = NULL;
    AVCodec* audio_codec = NULL;
    AVDictionary* pAVDictionary = NULL;
    AVFrame *pFrame = NULL;  
    AVFrame *pFrameRGB = NULL;
 
    struct SwsContext *img_convert_ctx;
 
    int numBytes = 0;
    //uint8_t *buffer; 
    int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE*100; 
    uint8_t * inbuf = (uint8_t *)malloc(out_size);
    unsigned vframecount = 0;
 
    av_register_all();
    avformat_network_init();
 
    char szError[256] = {0};
    CVCamSDKImpl* pVCam = NULL;
    pVCam = new CVCamSDKImpl();
 
    //input可以是url
    int nRet = avformat_open_input(&pFormatCtx, input, pInForCtx, &pAVDictionary);
 
    if (nRet != 0)
    {
        av_strerror(nRet, szError, 256);
        printf(szError);
        printf("\n");
        printf("Call avformat_open_input function failed!\n");
 
        return 0;
    }
     
    if (av_find_stream_info(pFormatCtx) < 0)
    {
        printf("Call av_find_stream_info function failed!\n");
        return 0;
    }
 
    int video_index = -1, audio_index = -1;
 
    for (unsigned int i = 0; i < pFormatCtx->nb_streams && (video_index < 0 || audio_index < 0); i++)
    {
        switch (pFormatCtx->streams[i]->codec->codec_type)
        {
        case AVMEDIA_TYPE_VIDEO:
            video_index = i;
            pFormatCtx->streams[i]->discard = AVDISCARD_NONE;
            break;
 
        case AVMEDIA_TYPE_AUDIO:
            audio_index = i;
            pFormatCtx->streams[i]->discard = AVDISCARD_NONE;
            break;
 
        default:
            pFormatCtx->streams[i]->discard = AVDISCARD_ALL;
            break;
 
        }
    }
 
    //視訊解碼準備部分
    if(video_index != -1){
        vpCodecCtx = pFormatCtx->streams[video_index]->codec;
        video_codec = avcodec_find_decoder(vpCodecCtx->codec_id);
        if (video_codec == NULL)
        {
            printf("Call avcodec_find_decoder function failed!\n");
            return 0;
        }
 
        if (avcodec_open2(vpCodecCtx, video_codec, &pAVDictionary) < 0)
        {
            printf("Call avcodec_open function failed !\n");
            return 0;
        }
 
        pFrame= avcodec_alloc_frame(); 
        pFrameRGB = avcodec_alloc_frame(); 
    }
    if(audio_index != -1){
        apCodecCtx = pFormatCtx->streams[audio_index]->codec;
        audio_codec = avcodec_find_decoder(apCodecCtx->codec_id);
        if (audio_codec == NULL)
        {
            printf("Call avcodec_find_decoder function failed!\n");
            return 0;
        }
 
        if (avcodec_open2(apCodecCtx, audio_codec, &pAVDictionary) < 0)
        {
            printf("Call avcodec_open function failed !\n");
            return 0;
        }
    }
 
    AVBitStreamFilterContext* bsfc =  av_bitstream_filter_init("h264_mp4toannexb"); 
 
    if(bsfc == NULL) 
    { 
        return -1; 
    }  
    int decode_done = 0;
    int len = 0;
    uint8_t *buffer = NULL;
    do
    {
        double segment_time = 0;
        AVPacket packet;
        decode_done = av_read_frame(pFormatCtx, &packet);//Returns the next frame of a stream.
        if (decode_done < 0)
            break;
 
        if (av_dup_packet(&packet) < 0)
        {
            printf("Call av_dup_packet function failed\n");
            av_free_packet(&packet);
            break;
        }
 
        if (packet.stream_index == video_index)
        {
            len = avcodec_decode_video2(vpCodecCtx, pFrame, &numBytes, &packet);
            if (numBytes != 0 )
            {
                if(vframecount == 0)
                {
                     numBytes=avpicture_get_size(PIX_FMT_RGB24, vpCodecCtx->width, vpCodecCtx->height);
                     buffer=(uint8_t *)av_malloc(numBytes*sizeof(uint8_t));  // buffer = new uint8_t[numBytes]; 
 
                     avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_BGR24,  vpCodecCtx->width, vpCodecCtx->height);
                    img_convert_ctx = sws_getContext(vpCodecCtx->width, vpCodecCtx->height, vpCodecCtx->pix_fmt,  
                             vpCodecCtx->width, vpCodecCtx->height, PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL); 
                    if(img_convert_ctx == NULL) 
                    { 
 
                    }
                    ++vframecount;
                }
                 sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, vpCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); 
 
                 /*交換上下記憶體*/
                for(;;){
                    int bytes_line = vpCodecCtx->width * 3;
                    int rows = vpCodecCtx->height/2;
                    int it=0;
                    unsigned char* tmp = (unsigned char*)malloc(bytes_line);
                    while(it<rows){
                        memcpy(tmp, pFrameRGB->data[0] + bytes_line*it, bytes_line);
                        memcpy(pFrameRGB->data[0] + bytes_line*it, pFrameRGB->data[0] + (vpCodecCtx->height-1-it)*bytes_line, bytes_line);
                        memcpy(pFrameRGB->data[0] + (vpCodecCtx->height-1-it)*bytes_line, tmp, bytes_line);
                        it++;
                    }
                    free(tmp);
                    break;
                }
 
                //然後就可以寫檔案或者用作其他
            }
        }else
        if (packet.stream_index == audio_index)//音訊這塊我沒有測試,不知道有沒有問題,等測試了在更新
            len = avcodec_decode_audio3(apCodecCtx, (short*)inbuf, &out_size, &packet);
 
        av_free_packet(&packet);
    }while(!decode_done);
 
    avcodec_free_frame(&pFrame);
    avcodec_free_frame(&pFrameRGB);
    av_bitstream_filter_close(bsfc); 
    sws_freeContext(img_convert_ctx);
 
    if (pVCam != NULL)
        delete pVCam;
 
    free(inbuf);
    getchar();
 
    return 0;
 
}