【求助】关于FFMPEG解码H264保存成BMP问题!!!

菜鸟一只_热爱ASM 2013-04-24 04:29:03
大侠们,谁帮我解决一下我的程序问题,qq292060282。
如果加好友帮助我的都会有分,如果帮我解决了,我可以另外给分!!!谢谢了。
...全文
291 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
老衲爱上树 2013-05-23
  • 打赏
  • 举报
回复
关于FFMPEG解码H264保存成BMP问题,很简单 LPBITMAPINFO lpbmih = new BITMAPINFO; lpbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); lpbmih->bmiHeader.biWidth = n_width; lpbmih->bmiHeader.biHeight = n_height; lpbmih->bmiHeader.biPlanes = 1; lpbmih->bmiHeader.biBitCount = iPixel; lpbmih->bmiHeader.biCompression = BI_RGB; lpbmih->bmiHeader.biSizeImage = (n_width*n_height*iPixel)/8; lpbmih->bmiHeader.biXPelsPerMeter = 0; lpbmih->bmiHeader.biYPelsPerMeter = 0; lpbmih->bmiHeader.biClrUsed = 0; lpbmih->bmiHeader.biClrImportant = 0; av_register_all(); avcodec_register_all(); AVCodec *codec = avcodec_find_decoder(CODEC_ID_H264); AVCodecContext *dec = avcodec_alloc_context(); if (avcodec_open(dec, codec) < 0) { fprintf(stderr, "ERR: open H264 decoder err\n"); exit(-1); } AVFrame *pFrameYUV = new AVFrame[1];; //YUV帧数据avcodec_alloc_frame(); AVFrame *pFrameRGB = new AVFrame[1]; //RGB帧数据 avcodec_alloc_frame(); // h264解压 int got; AVPacket pkt; av_init_packet(&pkt); pkt.data = buffer; pkt.size = rsize; int ret = avcodec_decode_video2(dec, pFrameYUV, &got, &pkt); if (ret > 0 && got) { // 解码成功 int numBytes=avpicture_get_size(PIX_FMT_BGR24, dec->width,dec->height); img_width = dec->width; img_height = dec->height; img_size = (img_width*img_height*iPixel)/8; uint8_t *bmp_buffer = (uint8_t *)malloc(img_size*sizeof(uint8_t)); uint8_t *yuv_buffer = (uint8_t *)malloc(img_size*sizeof(uint8_t)/2); // Assign appropriate parts of buffer to image planes in pFrameRGB avpicture_fill((AVPicture *)pFrameRGB, bmp_buffer, PIX_FMT_BGR24,img_width, img_height); // 翻转YUV图像 pFrameYUV->data[0] += pFrameYUV->linesize[0] * (img_height - 1); pFrameYUV->linesize[0] *= -1; pFrameYUV->data[1] += pFrameYUV->linesize[1] * (img_height / 2 - 1); pFrameYUV->linesize[1] *= -1; pFrameYUV->data[2] += pFrameYUV->linesize[2] * (img_height / 2 - 1); pFrameYUV->linesize[2] *= -1; //初始化SwsContext SwsContext * scxt = sws_getContext(img_width,img_height,dec->pix_fmt,img_width,img_height,PIX_FMT_BGR24,SWS_BICUBIC,NULL,NULL,NULL); //将YUV转化为RGB sws_scale(scxt,pFrameYUV->data,pFrameYUV->linesize,0,img_height,pFrameRGB->data,pFrameRGB->linesize); lpbmih->bmiHeader.biWidth = img_width; lpbmih->bmiHeader.biHeight = img_height; lpbmih->bmiHeader.biSizeImage = (img_width*img_height*iPixel)/8; pDC->SetStretchBltMode(HALFTONE); ::StretchDIBits(pDC->GetSafeHdc(), 0, 0,screensize.cx,screensize.cy, 0, 0, lpbmih->bmiHeader.biWidth,lpbmih->bmiHeader.biHeight,pFrameRGB->data[0], (BITMAPINFO*)lpbmih, DIB_RGB_COLORS,SRCCOPY);
smilestone322 2013-05-04
  • 打赏
  • 举报
回复
这个我会做,你看下我的博客
  • 打赏
  • 举报
回复
引用 1 楼 dream238 的回复:
H264解码后一般就是YV12数据,转成RGB24或RGB32就行了...
谢谢大侠~~ 能帮我看看我的代码有什么问题吗?avcodec_decode_video2一直返回1找了半天找不到问题

#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)




void H264_Init()
{
        av_register_all();
}



BOOL YUVtoRGB(AVFrame * pAVFrame, int width, int height, char *filename)
{
        struct SwsContext *img_convert_ctx;
        strcat(filename, ".bmp");
        AVFrame *pAVFrameRGB;
        pAVFrameRGB = avcodec_alloc_frame();
        if (pAVFrameRGB == NULL)
        {
                return FALSE;
        }
        int numBytes = avpicture_get_size(PIX_FMT_RGB24, width, height);
        uint8_t  *buffer = (UINT8 *)av_malloc(numBytes*sizeof(uint8_t));

        avpicture_fill((AVPicture*)pAVFrameRGB, buffer, PIX_FMT_RGB24, width, height);

        img_convert_ctx = sws_getContext(
                width, height, PIX_FMT_YUVJ420P, width, height, PIX_FMT_RGB24,
                SWS_BICUBIC, NULL, NULL, NULL);
        sws_scale(img_convert_ctx, pAVFrame->data, pAVFrame->linesize,
                0, height, pAVFrameRGB->data, pAVFrameRGB->linesize);
        sws_freeContext(img_convert_ctx);
        av_free(buffer);

        DWORD w = width;
        DWORD h = height;
        DWORD BufferLen = WIDTHBYTES(w*24)*h;
        BYTE *pBuffer = new BYTE[BufferLen];
        memset(pBuffer, 0 , BufferLen);

        for (int i=0; i<height; i++)
        {
                //将图像转为bmp存到内存中,这里的图像是倒立的
                memcpy(pBuffer +(WIDTHBYTES(w*24)*i),pAVFrameRGB->data[0]+i*pAVFrameRGB->linesize[0],width*3);
        }

        LPBYTE pbmp = new BYTE[sizeof(BITMAPFILEHEADER) + sizeof(BITMAPFILEHEADER)+BufferLen];

        BITMAPFILEHEADER bitmapfileheader; memset( &bitmapfileheader, 0, sizeof( BITMAPFILEHEADER ) );     
        bitmapfileheader.bfType = 'MB';    
        bitmapfileheader.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+BufferLen ;   
        bitmapfileheader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);    
        memcpy(pbmp,&bitmapfileheader,sizeof(BITMAPFILEHEADER));    

        BITMAPINFOHEADER fmtFrame; memset(&fmtFrame, 0, sizeof(fmtFrame));     
        fmtFrame.biSize = sizeof(fmtFrame);  
        fmtFrame.biPlanes  = 1;  
        fmtFrame.biBitCount = 24;  
        fmtFrame.biWidth =   w;   
        fmtFrame.biHeight =  -h;//注意,这里的bmpinfo.bmiHeader.biHeight变量的正负决定bmp文件的存储方式,如果为负值,表示像素是倒过来的*/
        fmtFrame.biSizeImage = BufferLen;  
        memcpy(pbmp+sizeof(BITMAPFILEHEADER),&fmtFrame,sizeof(BITMAPINFOHEADER));   
        memcpy(pbmp+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER),pBuffer, BufferLen);

        FILE * f = fopen(filename,"w+b");
        fwrite(pbmp,1,sizeof(BITMAPFILEHEADER)+sizeof(fmtFrame)+BufferLen, f );  
        fclose(f) ; 

        delete [] pbmp; pbmp = NULL;
        delete [] pBuffer; pBuffer = NULL; 
        return TRUE;
}
//void log_picture(AVPicture *pic, int width, int height, char *filename,int pixel_format);

BOOL H264_Decode(const PBYTE pSrcData, const DWORD dwDataSize, char *pFileName, int height, int width)
{
        AVFormatContext *pFormatCtx = NULL;
        AVCodecContext        *pCodecCtx = NULL;
        AVCodec                        *pCodec = NULL;
        //AVOutputFormat        fmt;
        AVFrame                        *pFrame = NULL;
        AVPicture                *pPic = NULL;
        AVFrame                        *pFrameRGB = NULL;
        AVPacket                pkt;
        int                                numBytes;
        BOOL                        nGot;
        int                                deCodePicSize;

        //初始化
        pCodec = avcodec_find_decoder(CODEC_ID_H264);
        if (!pCodec)
        {
                fprintf(stderr, "Codec not found\n");
                return FALSE;
        }
        pCodecCtx = avcodec_alloc_context();
        if (!pCodecCtx)
        {
                return FALSE;
        }
        pCodecCtx->time_base.num = 1;
        pCodecCtx->time_base.den = 25;
        pCodecCtx->bit_rate = 0;
        pCodecCtx->frame_number = 1;
        pCodecCtx->width = width;
        pCodecCtx->height = height;
        pCodecCtx->pix_fmt = PIX_FMT_YUVJ420P;
        //打开解码器
        if (avcodec_open(pCodecCtx, pCodec) < 0)
        {
                return FALSE;
        }
        pFrame = avcodec_alloc_frame();
        //初始化packet
        av_init_packet(&pkt);
        pkt.data = (unsigned char *)pSrcData;
        pkt.size = dwDataSize;

        //开始解码
        if(avcodec_decode_video2(pCodecCtx, pFrame, &deCodePicSize, &pkt) > 0)
        {
                //转换为RGB24
                if(FALSE == YUVtoRGB(pFrame, width, height, pFileName))
ArcRain 2013-04-24
  • 打赏
  • 举报
回复
H264解码后一般就是YV12数据,转成RGB24或RGB32就行了...

2,542

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧