ffmpeg 解码 并编码 保存文件 使用流程

一. 解码

1. 注册ffmpeg 所有编码/解码器

    av_register_all();

avdevice_register_all();

2.  打开一个输入格式上下文: AVFormatContext 

     avformat_open_input()

 

3. 从输入格式上下文读取流,并分析出流信息

   avformat_find_stream_info()

 

4. 从格式上下文信息中,通过流ID,获取到解码器上下文 :AVCodecContext 

  pCodecCtx_Video = pFormatCtx_Video->streams[x]->codec;

 

5. 从解码器上下文信息的解码ID查找解码器:AVCodec 

  avcodec_find_decoder ()

 

6. 通过解码器上下文AVCodecContext与解码器AVCodec打开解码器:

 avcodec_open2()

 

7.循环读出数据包:通过格式信息读出包

   av_read_frame(pFormatCtx_Video, packet)

8. 通过解码器上下文件AVCodecContext 解码包:

  if (avcodec_decode_video2(pCodecCtx_Video, pFrame, &got_picture, packet) < 0)

 

9. 数据写入队列: AVFifoBuffer 

 

二. 编码并保存文件:

  1.  通过文件名,打开一个输出格式上下文:AVFormatContext * pFormatCtx_Out 

         avformat_alloc_output_context2()

  2.  通过输出格式AVFormatContext,打开一个流: AVStream 

         avformat_new_stream()

  3.  通过一中的格式信息:格式上下文件AVFormatContext,初始化2中的流信息

       包括: 

        pVideoStream->codec->codec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);

pVideoStream->codec->height = pFormatCtx_Video->streams[0]->codec->height;

pVideoStream->codec->width = pFormatCtx_Video->streams[0]->codec->width;

pVideoStream->codec->time_base = pFormatCtx_Video->streams[0]->codec->time_base;

pVideoStream->codec->sample_aspect_ratio = pFormatCtx_Video->streams[0]->codec->sample_aspect_ratio;

// take first format from list of supported formats

pVideoStream->codec->pix_fmt = pFormatCtx_Out->streams[VideoIndex]->codec->codec->pix_fmts[0];

 

   4. 打开编码器:从流中的编码上下文件,下ID

       avcodec_open2()

   5. 打开IO,也即初始化,输出格式中的AVIOContext

      avio_open(&pFormatCtx_Out->pb, outFileName, AVIO_FLAG_WRITE)

 

   6. 写入文件格式头:

      avformat_write_header(pFormatCtx_Out, NULL)

 

   7. 循环从队列读出数据:

       av_fifo_generic_read(fifo_video, picture_buf, size, NULL);

 

   8. 初始化数据到 AVFrame:

      avpicture_fill((AVPicture *)picture, picture_buf, 

pFormatCtx_Out->streams[VideoIndex]->codec->pix_fmt, 

pFormatCtx_Out->streams[VideoIndex]->codec->width, 

pFormatCtx_Out->streams[VideoIndex]->codec->height);

  9. 计算avframe的PTS:

    picture->pts = VideoFrameIndex * ((pFormatCtx_Video->streams[0]->time_base.den / pFormatCtx_Video->streams[0]->time_base.num) / 15);

 

 10 编码成PACKET;

     int ret = avcodec_encode_video2(pFormatCtx_Out->streams[VideoIndex]->codec, &pkt, picture, &got_picture);

 

 11. 计算pakcet的pts pps,

 

       pkt.stream_index = VideoIndex;

pkt.pts = av_rescale_q_rnd(pkt.pts, pFormatCtx_Video->streams[0]->time_base, 

pFormatCtx_Out->streams[VideoIndex]->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  

pkt.dts = av_rescale_q_rnd(pkt.dts,  pFormatCtx_Video->streams[0]->time_base, 

pFormatCtx_Out->streams[VideoIndex]->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  

 

pkt.duration = ((pFormatCtx_Out->streams[0]->time_base.den / pFormatCtx_Out->streams[0]->time_base.num) / 15);

 

cur_pts_v = pkt.pts;

12. 写入文件 :

ret = av_interleaved_write_frame(pFormatCtx_Out, &pkt);

 

  13. 循环结束后写文件尾

    av_write_trailer(pFormatCtx_Out);

你可能感兴趣的:(ffmpeg 解码 并编码 保存文件 使用流程)