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
%d %d
255
", 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 }
原文地址:https://www.cnblogs.com/1024Planet/p/5803382.html