关闭

ffmpeg播放视频音频

标签: codecaudioinputvideostream
2423人阅读 评论(0) 收藏 举报
分类:
void CProgram::Test()
{
    avcodec_init();
    av_register_all();

    AVFormatContext *pFormatCtx; 
    int i, videoStream; 
    int audioStream; 

    const char *input_file_name = "F:\\fashion_100M.ts"; 

    // Open video file 
    if(av_open_input_file(&pFormatCtx, input_file_name, NULL, 0, NULL)!=0) 
        return ; 

    // Retrieve stream information 
    if(av_find_stream_info(pFormatCtx) < 0) 
        return ; 

    // Find the first video stream 
    videoStream = -1; 
    audioStream = -1; 
    for(i = 0; i < pFormatCtx->nb_streams; i++) 
    { 
        if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) 
        { 
            videoStream = i; 
        } 
        else if(pFormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO) 
        { 
            audioStream = i; 
        } 
    } 
    if(videoStream == -1) 
    { 
        return ; 
    } 

    AVCodecContext  *pVideoCodecCtx=pFormatCtx->streams[videoStream]->codec;
    AVCodec         *pVideoCodec=avcodec_find_decoder(pVideoCodecCtx->codec_id);

    AVCodecContext  *pAudioCodecCtx=pFormatCtx->streams[audioStream]->codec;
    AVCodec         *pAudioCodec=avcodec_find_decoder(pAudioCodecCtx->codec_id);


    //打开视频解码器
    if(avcodec_open(pVideoCodecCtx,pVideoCodec) < 0)
    {
        return ; 
    }

    //通知解码器,我们能处理截断的bit流
    if (pAudioCodec->capabilities&CODEC_CAP_TRUNCATED)
    {
        pAudioCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
    }

    //打开音频解码器
    if(avcodec_open(pAudioCodecCtx,pAudioCodec) < 0)
    {
        return ; 
    }

    uint8_t *pktdata;
    int pktsize;
    int out_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
    uint8_t * inbuf = (uint8_t *)malloc(out_size);


    int nRet=0;
    int nGopPicture=1;
    int nFrameCount=0;
    int nLostFrame=0;

    AVPacket pktData;
    av_init_packet(&pktData);

    while(av_read_frame(pFormatCtx, &pktData) >= 0) 
    { 
        if(pktData.stream_index == videoStream) 
        { 
            AVFrame *pFrame1=avcodec_alloc_frame();

                //解码视频
                nRet=avcodec_decode_video(pVideoCodecCtx,pFrame1,&nGopPicture,pktData.data,pktData.size);

                if ( nGopPicture > 0 )
                {
                                           //将解码出的YUV数据拷贝到自己分配的节点中
                    PYUV_FRAME pYUVFrame=new YUV_FRAME;

                    pYUVFrame->pYFrame=new unsigned char[m_stFileEncodeInfo.pVideoCodecCtx->width*m_stFileEncodeInfo.pVideoCodecCtx->height];
                    pYUVFrame->pUFrame=new unsigned char[m_stFileEncodeInfo.pVideoCodecCtx->width*m_stFileEncodeInfo.pVideoCodecCtx->height/4];
                    pYUVFrame->pVFrame=new unsigned char[m_stFileEncodeInfo.pVideoCodecCtx->width*m_stFileEncodeInfo.pVideoCodecCtx->height/4];

                    unsigned char *pY=pYUVFrame->pYFrame;
                    unsigned char *pU=pYUVFrame->pUFrame;
                    unsigned char *pV=pYUVFrame->pVFrame;

                    //拷贝Y数据
                    for (int i=0;i<m_stFileEncodeInfo.pVideoCodecCtx->height;i++)
                    {
                        memcpy(pY,pFrame1->data[0], m_stFileEncodeInfo.pVideoCodecCtx->width);
                        pFrame1->data[0]+=pFrame1->linesize[0];
                        pY+=m_stFileEncodeInfo.pVideoCodecCtx->width;
                    }

                    //拷贝U数据
                    for (int i=0;i<m_stFileEncodeInfo.pVideoCodecCtx->height/2;i++)
                    {
                        memcpy(pU,pFrame1->data[1], m_stFileEncodeInfo.pVideoCodecCtx->width/2);
                        pFrame1->data[1]+=pFrame1->linesize[1];
                        pU+=m_stFileEncodeInfo.pVideoCodecCtx->width/2;
                    }

                    //拷贝V数据
                    for (int i=0;i<m_stFileEncodeInfo.pVideoCodecCtx->height/2;i++)
                    {
                        memcpy(pV,pFrame1->data[2], m_stFileEncodeInfo.pVideoCodecCtx->width/2);
                        pFrame1->data[2]+=pFrame1->linesize[2];
                        pV+=m_stFileEncodeInfo.pVideoCodecCtx->width/2;
                    }
               
                                           //将节点保存到链表中供DirectDraw显示
                    m_videoPlay.m_csVideoQueueSection.Lock();
                    m_videoPlay.m_listVideoFrame.AddTail(pYUVFrame);
                    m_videoPlay.m_csVideoQueueSection.Unlock();

                    nFrameCount++;
                    TRACE("nGopPicture > 0  成功解码!  %d 帧,nGopPicture值为 %d ,nRet值为 %d ,输入包长为 %d \n",nFrameCount,nGopPicture,nRet,pktData.size);

                }
                else 
                {
                    nLostFrame++;
                    TRACE("-----丢失帧的总数为 %d ,nGopPicture值为 %d ,nRet值为 %d,输入包长为 %d----\n",nLostFrame,nGopPicture,nRet,pktData.size);

                }

            av_free(pFrame1);
        } 
        else if(pktData.stream_index == audioStream) 
        { 
            //解码音频
            int nInSize=pktData.size;
            unsigned char *pInBuff=pktData.data;

            int outSize=AVCODEC_MAX_AUDIO_FRAME_SIZE;
            unsigned char *pOutBuff=new unsigned char[outSize];
            memset(pOutBuff,0,AVCODEC_MAX_AUDIO_FRAME_SIZE);

            nRet=avcodec_decode_audio2(m_stFileEncodeInfo.pAudioCodecCtx,(short*)pOutBuff,&outSize,pInBuff,nInSize);

            if (nRet >= 0)
            {
                                    //将解码得到的PCM数据保存到缓冲区中中供DirectSound播放
                m_audioPlay.m_audioRingBuff.InputData(pOutBuff,outSize);
            }

            delete[] pOutBuff;
            pOutBuff=NULL;

        } 
        // Free the packet that was allocated by av_read_frame 
        av_free_packet(&pktData); 
    } 

    av_close_input_file(pFormatCtx); 

};
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:436417次
    • 积分:5319
    • 等级:
    • 排名:第5392名
    • 原创:98篇
    • 转载:102篇
    • 译文:0篇
    • 评论:55条
    最新评论