zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    线程共享全局变量和私有全局变量
    线程退出前操作
    Linux下线程pid和tid
    几种常见的光纤接头(ST,SC,LC,FC)以及PC、APC和UPC的区别
    Javascript对象及数组用法笔记
    Javascript对象及数组用法笔记
    程序员特有的9个坏习惯
    程序员特有的9个坏习惯
    程序人生:真正的效率源自专注
    程序人生:真正的效率源自专注
  • 原文地址:https://www.cnblogs.com/1024Planet/p/5803382.html
Copyright © 2011-2022 走看看