ffmpeg從AVFrame取出yuv數據到保存到char*中


ffmpeg從AVFrame取出yuv數據到保存到char*中

 
很多人一直不知道怎么利用ffmpeg從AVFrame取出yuv數據到保存到char*中,下面代碼將yuv420p和yuv422p的數據取出並保存到char*buf中。
其他格式可以自己去擴展,前提先看戲yuv的各種格式,yuv的各種格式鏈接: 數據格式分析
 
先確保視頻格式 sws_getContext()轉換后是YUV格式:
1     out_buffer=(uint8_t *)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height));//分配AVFrame所需內存
2     avpicture_fill((AVPicture *)pFrameYUV, out_buffer, PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height);//填充AVFrame
3 
4     img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
5             pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

 

那么在后續的視頻數據處理時,可以把YUV視頻格式數據進行存儲:
 1 //如果是視頻
 2 else if (pstream_info[i].dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
 3 {
 4     int new_videosize = pkt.size;
 5     int video_decode_size = avpicture_get_size(pstream_info->dec_ctx->pix_fmt, Zoom_Width,Zoom_Height);
 6     uint8_t * video_decode_buf =( uint8_t *)calloc(1,video_decode_size * 3 * sizeof(char)); //最大分配的空間,能滿足yuv的各種格式
 7 
 8     // Decode video frame
 9     avcodec_decode_video2(pstream_info->dec_ctx, pDecodeFrame, &frameFinished,&pkt);
10     if(frameFinished)
11     {
12         if (pstream_info->dec_ctx->pix_fmt == AV_PIX_FMT_YUV420P) //如果是yuv420p的
13         {
14             for(i = 0; i < pstream_info->dec_ctx->height; i++)
15             {
16                 memcpy(video_decode_buf+pstream_info->dec_ctx->width*i,
17                         pDecodeFrame->data[0]+pDecodeFrame->linesize[0]*i,
18                         pstream_info->dec_ctx->width);
19             }
20             for(j = 0; j < pstream_info->dec_ctx->height/2; j++)
21             {
22                 memcpy(video_decode_buf+pstream_info->dec_ctx->width*i+pstream_info->dec_ctx->width/2*j,
23                         pDecodeFrame->data[1]+pDecodeFrame->linesize[1]*j,
24                         pstream_info->dec_ctx->width/2);
25             }
26             for(k =0; k < pstream_info->dec_ctx->height/2; k++)
27             {
28                 memcpy(video_decode_buf+pstream_info->dec_ctx->width*i+pstream_info->dec_ctx->width/2*j+pstream_info->dec_ctx->width/2*k,
29                         pDecodeFrame->data[2]+pDecodeFrame->linesize[2]*k,
30                         pstream_info->dec_ctx->width/2);
31             }
32         }
33         else if (pstream_info->dec_ctx->pix_fmt == AV_PIX_FMT_YUV422P)//如果是yuv422p的
34         {
35             for(i = 0; i < pstream_info->dec_ctx->height; i++)
36             {
37                 memcpy(video_decode_buf+pstream_info->dec_ctx->width*i,
38                     pDecodeFrame->data[0]+pDecodeFrame->linesize[0]*i,
39                     pstream_info->dec_ctx->width);
40             }
41             for(j = 0; j < pstream_info->dec_ctx->height; j++)
42             {
43                 memcpy(video_decode_buf+pstream_info->dec_ctx->width*i+pstream_info->dec_ctx->width/2*j,
44                     pDecodeFrame->data[1]+pDecodeFrame->linesize[1]*j,
45                     pstream_info->dec_ctx->width/2);
46             }
47             for(k =0; k < pstream_info->dec_ctx->height; k++)
48             {
49                 memcpy(video_decode_buf+pstream_info->dec_ctx->width*i+pstream_info->dec_ctx->width/2*j+pstream_info->dec_ctx->width/2*k,
50                     pDecodeFrame->data[2]+pDecodeFrame->linesize[2]*k,
51                     pstream_info->dec_ctx->width/2);
52             }
53         }
54         else
55         {
56             //可擴展
57         }
58         video_decode_size = avpicture_get_size(pstream_info->dec_ctx->pix_fmt, pstream_info->dec_ctx->width,pstream_info->dec_ctx->height);
59         new_videosize = video_decode_size;
60         
61         //縮放或格式轉換
62         if (pstream_info->dec_ctx->width != Zoom_Width ||
63             pstream_info->dec_ctx->height != Zoom_Height ||
64             pstream_info->dec_ctx->pix_fmt != Zoom_pix_fmt)
65         {
66             new_videosize = VideoScaleYuvZoom(Is_flip,pstream_info->dec_ctx->width ,pstream_info->dec_ctx->height,(int)pstream_info->dec_ctx->pix_fmt,
67             Zoom_Width,Zoom_Height,Zoom_pix_fmt,video_decode_buf);
68         }
69         //這里可以取出數據
70         frame_info->stream_idx = pstream_info->stream_idx;
71         //frame_info->pts = pDecodeFrame->pkt_pts * 1000 * av_q2d(pstream_info->stream->time_base); //轉化成毫秒
72         frame_info->pts = pDecodeFrame->pkt_pts;
73         frame_info->timebase_den = pstream_info->stream->time_base.den;
74         frame_info->timebase_num = pstream_info->stream->time_base.num;
75         frame_info->bufsize = new_videosize;
76         memcpy(frame_info->buf,video_decode_buf,new_videosize);
77     }
78     else
79     {
80         //緩存
81         frame_info->stream_idx = pstream_info->stream_idx;
82         frame_info->pts = 0;
83         frame_info->timebase_den = 0;
84         frame_info->timebase_num = 0;
85         frame_info->bufsize = 0;
86         memset(frame_info->buf,0,MAX_FRAME_SIZE);
87     }
88     if (video_decode_buf)
89     {
90         free(video_decode_buf);
91         video_decode_buf = NULL;
92     }
93     video_decode_size = 0;
94 }

 

也可以把YUV數據進行存儲為PPM格式(Linux系統下的圖片格式):

 1 //如果是視頻
 2 else if (pstream_info[i].dec_ctx->codec_type == AVMEDIA_TYPE_VIDEO)
 3 {
 4     // Decode video frame
 5     avcodec_decode_video2(pstream_info->dec_ctx, pDecodeFrame, &frameFinished,&pkt);
 6     if(frameFinished)
 7     {
 8         sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
 9         if((++k<=30) && (k%3==0)) {
10             SaveFrame(pFrameYUV, pCodecCtx->width, pCodecCtx->height, k);
11         }
12     }
13 }
14 
15 void SaveFrame(AVFrame *pFrame, int width, int height, int iFrame)
16 {
17     FILE *pFile;
18     char szFilename[32];
19     int  y;
20     
21     SDL_Log("%d * %d", width, height);
22     // Open file
23     sprintf(szFilename, "frame/frame%d.ppm", iFrame);
24     pFile=fopen(szFilename, "wb");
25     if(pFile==NULL)
26     return;
27     
28     // Write header
29     fprintf(pFile, "P6\n%d %d\n255\n", width, height);
30     
31     // Write pixel data
32     for(y=0; y<height; y++) {
33         fwrite(pFrame->data[0]+y*pFrame->linesize[0], 1, width*3, pFile);
34     }
35     
36     // Close file
37     fclose(pFile);
38 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM