美文网首页
实现最小YUV视频解码器

实现最小YUV视频解码器

作者: 北极星的笔记 | 来源:发表于2021-05-29 23:25 被阅读0次

本文记录了使用ffmpeg进行视频解码的最小解码器代码,通过这个小程序可以理解ffmpeg的解码过程及用到的api。这里将解码码后得到的YUV格式的视频保存到文件中,可以使用YUV Playe播放。代码已上传git,
https://github.com/beijixing/ffmpegStudy

流程图.jpg

extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
}

void devoder()
{
    //注册编解码器
    av_register_all();

    AVFormatContext *pAVFormatCtx = NULL;
    int ret = avformat_open_input(&pAVFormatCtx,"Titanic.mkv",NULL, NULL);
    if(ret != 0)
    {
        printf("avformat_open_input failed!");
        return;
    }

    //查找流信息
    ret = avformat_find_stream_info(pAVFormatCtx, NULL);
    if(ret != 0)
    {
        printf("avformat_find_stream_info failed!");
        return;
    }

    //查找视频流索引
   int videoIndex = -1;
   videoIndex = av_find_best_stream(pAVFormatCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, NULL);
   if(videoIndex < 0)
   {
       printf("av_find_best_stream failed!");
       return;
   }

   //查找解码器上下文
   AVCodecContext *pAVCodecCtx = pAVFormatCtx->streams[videoIndex]->codec;
   //查找解码器
   AVCodec *pAVCodec = avcodec_find_decoder(pAVCodecCtx->codec_id);

   if(pAVCodec == NULL)
   {
       printf("Codec not found.\n");
       return;
   }
    //打开解码器
   ret = avcodec_open2(pAVCodecCtx, pAVCodec, NULL);
   if(ret < 0)
   {
       printf("avcodec_open2 failed !\n");
       return;
   }

   //解码视频
   AVFrame *pAVFrame = av_frame_alloc();
   AVFrame *pAVFrameYUV = av_frame_alloc();

   //创建缓存
   int nBuffSize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pAVCodecCtx->width, pAVCodecCtx->height, 1);
   unsigned char* buffer = (unsigned char *)av_malloc(nBuffSize);
   //设置缓存
   av_image_fill_arrays(pAVFrameYUV->data, pAVFrameYUV->linesize, buffer,
                        AV_PIX_FMT_YUV420P, pAVCodecCtx->width,
                        pAVCodecCtx->height, 1);
   //创建AVPacket
   AVPacket *pAVPacket = (AVPacket *)av_malloc(sizeof (AVPacket));
   //创建图像转换上下文
   SwsContext *pSwsCtx = sws_getContext(pAVCodecCtx->width, pAVCodecCtx->height,
                                       pAVCodecCtx->pix_fmt, pAVCodecCtx->width, pAVCodecCtx->height,
                                        AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);


   int gotPicture = 0;
   FILE* pYuvFile = fopen("test.yuv", "wb");
   if(!pYuvFile)
   {
       printf("fopen test.yuv failed !\n");
       return;
   }

   int frameCnt = 0;
   while (av_read_frame(pAVFormatCtx, pAVPacket) >= 0)
   {
       //只解码视频
       if(pAVPacket->stream_index == videoIndex)
       {
            ret = avcodec_decode_video2(pAVCodecCtx, pAVFrame, &gotPicture, pAVPacket);
            if(ret < 0)
            {
                printf("avcodec_decode_video2 failed !\n");
                break;
            }
            if(gotPicture)
            {
                //格式转换
                sws_scale(pSwsCtx, pAVFrame->data,
                          pAVFrame->linesize,
                          0,
                          pAVCodecCtx->height,
                          pAVFrameYUV->data,
                          pAVFrameYUV->linesize);
                fwrite(pAVFrameYUV->data[0],1,pAVCodecCtx->width*pAVCodecCtx->height, pYuvFile);
                fwrite(pAVFrameYUV->data[1],1,pAVCodecCtx->width*pAVCodecCtx->height/4, pYuvFile);
                fwrite(pAVFrameYUV->data[2],1,pAVCodecCtx->width*pAVCodecCtx->height/4, pYuvFile);
                frameCnt++;
                printf("frameCnt = %d !\n", frameCnt);
            }

       }
   }

   //释放指针
   fclose(pYuvFile);
   sws_freeContext(pSwsCtx);
   av_frame_free(&pAVFrame);
   av_frame_free(&pAVFrameYUV);
   av_packet_free(&pAVPacket);
   avformat_close_input(&pAVFormatCtx);
}


int main(int argc, char *argv[])
{
    devoder();
    return 0;
}

相关文章

  • 实现最小YUV视频解码器

    本文记录了使用ffmpeg进行视频解码的最小解码器代码,通过这个小程序可以理解ffmpeg的解码过程及用到的api...

  • FFmpeg4-视频编码

    一、视频编码?->YUV编码为H.264 分析视频编码原理->流程 第一步:注册组件->编码器、解码器等等…av_...

  • 音视频解码器

    解码器分为音频与视频。视频又分为硬解与软解。 以下是初始化视频解码器: //视频解码器 软解码器AVCodec *...

  • 23_FFmpeg像素格式转换

    简介 前面使用 SDL 显示了一张YUV图片以及YUV视频。接下来使用Qt中的QImage来实现一个简单的 YUV...

  • NDK--利用FFmpeg进行安卓原生绘制播放

    上次说到视频编码和转码,得到了yuv格式的文件,我们平常看到的视频画面实际都是yuv格式,今天来实现在APP中播放...

  • YUV 颜色编码格式

    背景 音视频、直播、短视频等图像处理过程中涉及到 YUV 信息,在维基百科阅读 YUV 协议、编写代码实现、输出可...

  • 《Android FFmpeg 播放器开发梳理》第二章 音视解码

    前面一章我们讲解了解复用的实现流程,但并没有详细讲解解码器部分的处理,这一章我们将会介绍音频解码器以及视频解码器的...

  • 音视频相关问题

    视频相关的问与答: 一、YUV的内存存储格式YUV格式有很多种,比如YUV420,YUV422,YUV444等。比...

  • 转码的四个案例

    一,swcale实现rgb24转yuv420p 二,swcale实现YUV转RGB

  • CPU与OpenGL ES实现YUV数据左右留白边

    以YUV420p为例实现视频左右留白边功能。因YUV颜色空间的UV通道在转换成RGB时需进行偏置,偏置前范围为[-...

网友评论

      本文标题:实现最小YUV视频解码器

      本文链接:https://www.haomeiwen.com/subject/hvmusltx.html