当前位置:   article > 正文

ffmpeg视频解码原理和实战-(2)对avpacket中的数据进行解码并防止丢帧

ffmpeg视频解码原理和实战-(2)对avpacket中的数据进行解码并防止丢帧

源文件:

  1. #include <iostream>
  2. #include <fstream>
  3. using namespace std;
  4. extern "C" { //指定函数是c语言函数,函数名不包含重载标注
  5. //引用ffmpeg头文件
  6. #include <libavcodec/avcodec.h>
  7. }
  8. //预处理指令导入库
  9. #pragma comment(lib,"avcodec.lib")
  10. #pragma comment(lib,"avutil.lib")
  11. int main(int argc, char* argv[])
  12. {
  13. //1 分割h264 存入AVPacket
  14. // ffmpeg -i v1080.mp4 -s 400x300 test.h264
  15. string filename = "test.h264";
  16. ifstream ifs(filename, ios::binary);
  17. if (!ifs)return -1;
  18. unsigned char inbuf[4096] = { 0 };//用于存储h264编码流
  19. AVCodecID codec_id = AV_CODEC_ID_H264;
  20. //1 找解码器
  21. auto codec = avcodec_find_decoder(codec_id);
  22. //2 创建解码器上下文
  23. auto c = avcodec_alloc_context3(codec);
  24. //3 打开上下文
  25. avcodec_open2(c, NULL, NULL);
  26. //分割上下文
  27. auto parser = av_parser_init(codec_id);
  28. auto pkt = av_packet_alloc();
  29. auto frame = av_frame_alloc();
  30. while (!ifs.eof())
  31. {
  32. ifs.read((char*)inbuf, sizeof(inbuf));//将h264编码的流读入inbuf中,一次读4096
  33. int data_size = ifs.gcount();// 读取的字节数,inbuf中的字节数
  34. if (data_size <= 0)break;
  35. auto data = inbuf;
  36. while (data_size > 0) //一次有多帧数据
  37. {
  38. //通过0001 截断输出到AVPacket 返回帧大小
  39. int ret = av_parser_parse2(parser, c,
  40. &pkt->data, &pkt->size, //截断后输出到AVpacket的data中
  41. data, data_size, //h264编码流,待处理数据
  42. AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0
  43. );//返回消耗的输入数据字节数ret。如果所有输入数据都被消耗,则返回值等于 buf_size。如果解析过程中出现错误,则返回负数。
  44. data += ret;//data指针向前移动 ret个字节,继续处理inbuf未处理的数据
  45. data_size -= ret; //待处理的数据大小
  46. if (pkt->size)
  47. {
  48. //cout << pkt->size << " "<<flush;
  49. //发送packet到解码线程
  50. ret = avcodec_send_packet(c, pkt);//把avpacket给解码器进行解码
  51. if (ret < 0)
  52. break;
  53. //获取多帧解码数据
  54. while (ret >= 0)
  55. {
  56. //每次回调用av_frame_unref
  57. ret = avcodec_receive_frame(c, frame);//拿到解码后的数据
  58. if (ret < 0)
  59. break;
  60. cout << frame->format << " " << flush;
  61. }
  62. }
  63. }
  64. }
  65. ///取出缓存数据,防止丢帧
  66. int ret = avcodec_send_packet(c, NULL);
  67. while (ret >= 0)
  68. {
  69. ret = avcodec_receive_frame(c, frame);
  70. if (ret < 0)
  71. break;
  72. cout << frame->format << "-" << flush;
  73. }
  74. av_parser_close(parser);
  75. avcodec_free_context(&c);
  76. av_frame_free(&frame);
  77. av_packet_free(&pkt);
  78. getchar();
  79. return 0;
  80. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/689175
推荐阅读
  

闽ICP备14008679号