解碼問題

我有一個TS格式的文件,裏面有一個視頻和一個音頻,視頻是mpeg2編碼,音頻是mp3編碼。我使用ffmpeg庫對文件進行解碼,然後使用DirectDraw播放視頻,使用DirectSound播放聲音。現在音視頻的顯示和播放都沒有問題了。可測試時發現,視頻圖像上面有很多的馬賽克。我懷疑是我視頻解碼的操作有問題導致解碼時丟數據了。自己弄了一天還是沒找到原因,請大家幫忙看看,看看視頻處理上是否有問題。代碼如下:
C/C++ code
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);

    //通知解碼器,我們能處理截斷的bit流
    if (pVideoCodec->capabilities&CODEC_CAP_TRUNCATED)
    {
        pVideoCodecCtx->flags|=CODEC_FLAG_TRUNCATED;
    }

    //打開視頻解碼器
    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); 

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