Advertisement
Guest User

Untitled

a guest
Feb 14th, 2016
55
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.70 KB | None | 0 0
  1. /*
  2. * Read video frame with FFmpeg and convert to OpenCV image
  3. *
  4. * Copyright (c) 2016 yohhoy
  5. */
  6. #include <iostream>
  7. #include <vector>
  8. // FFmpeg
  9. extern "C" {
  10. #include <libavformat/avformat.h>
  11. #include <libavcodec/avcodec.h>
  12. #include <libavutil/avutil.h>
  13. #include <libavutil/pixdesc.h>
  14. #include <libswscale/swscale.h>
  15. }
  16. // OpenCV
  17. #include <opencv2/core.hpp>
  18. #include <opencv2/highgui.hpp>
  19.  
  20.  
  21. int main(int argc, char* argv[])
  22. {
  23. if (argc < 2) {
  24. std::cout << "Usage: ff2cv <infile>" << std::endl;
  25. return 1;
  26. }
  27. const char* infile = argv[1];
  28.  
  29. // initialize FFmpeg library
  30. av_register_all();
  31. int ret;
  32.  
  33. // open input file context
  34. AVFormatContext* inctx = nullptr;
  35. ret = avformat_open_input(&inctx, infile, nullptr, nullptr);
  36. if (ret < 0) {
  37. std::cerr << "fail to avforamt_open_input(\"" << infile << "\"): ret=" << ret;
  38. return 2;
  39. }
  40. // retrive input stream information
  41. ret = avformat_find_stream_info(inctx, nullptr);
  42. if (ret < 0) {
  43. std::cerr << "fail to avformat_find_stream_info: ret=" << ret;
  44. return 2;
  45. }
  46.  
  47. // find primary video stream
  48. AVCodec* vcodec = nullptr;
  49. ret = av_find_best_stream(inctx, AVMEDIA_TYPE_VIDEO, -1, -1, &vcodec, 0);
  50. if (ret < 0) {
  51. std::cerr << "fail to av_find_best_stream: ret=" << ret;
  52. return 2;
  53. }
  54. const int vstrm_idx = ret;
  55. AVStream* vstrm = inctx->streams[vstrm_idx];
  56.  
  57. // open video decoder context
  58. ret = avcodec_open2(vstrm->codec, vcodec, nullptr);
  59. if (ret < 0) {
  60. std::cerr << "fail to avcodec_open2: ret=" << ret;
  61. return 2;
  62. }
  63.  
  64. // print input video stream informataion
  65. std::cout
  66. << "infile: " << infile << "\n"
  67. << "format: " << inctx->iformat->name << "\n"
  68. << "vcodec: " << vcodec->name << "\n"
  69. << "size: " << vstrm->codec->width << 'x' << vstrm->codec->height << "\n"
  70. << "fps: " << av_q2d(vstrm->codec->framerate) << " [fps]\n"
  71. << "length: " << av_rescale_q(vstrm->duration, vstrm->time_base, {1,1000}) / 1000. << " [sec]\n"
  72. << "pixfmt: " << av_get_pix_fmt_name(vstrm->codec->pix_fmt) << "\n"
  73. << "frame: " << vstrm->nb_frames << "\n"
  74. << std::flush;
  75.  
  76. // initialize sample scaler
  77. const int dst_width = vstrm->codec->width;
  78. const int dst_height = vstrm->codec->height;
  79. const AVPixelFormat dst_pix_fmt = AV_PIX_FMT_BGR24;
  80. SwsContext* swsctx = sws_getCachedContext(
  81. nullptr, vstrm->codec->width, vstrm->codec->height, vstrm->codec->pix_fmt,
  82. dst_width, dst_height, dst_pix_fmt, SWS_BICUBIC, nullptr, nullptr, nullptr);
  83. if (!swsctx) {
  84. std::cerr << "fail to sws_getCachedContext";
  85. return 2;
  86. }
  87. std::cout << "output: " << dst_width << 'x' << dst_height << ',' << av_get_pix_fmt_name(dst_pix_fmt) << std::endl;
  88.  
  89. // allocate frame buffer for output
  90. AVFrame* frame = av_frame_alloc();
  91. std::vector<uint8_t> framebuf(avpicture_get_size(dst_pix_fmt, dst_width, dst_height));
  92. avpicture_fill(reinterpret_cast<AVPicture*>(frame), framebuf.data(), dst_pix_fmt, dst_width, dst_height);
  93.  
  94. // decoding loop
  95. AVFrame* decframe = av_frame_alloc();
  96. unsigned nb_frames = 0;
  97. bool end_of_stream = false;
  98. int got_pic = 0;
  99. AVPacket pkt;
  100. do {
  101. if (!end_of_stream) {
  102. // read packet from input file
  103. ret = av_read_frame(inctx, &pkt);
  104. if (ret < 0 && ret != AVERROR_EOF) {
  105. std::cerr << "fail to av_read_frame: ret=" << ret;
  106. return 2;
  107. }
  108. if (ret == 0 && pkt.stream_index != vstrm_idx)
  109. goto next_packet;
  110. end_of_stream = (ret == AVERROR_EOF);
  111. }
  112. if (end_of_stream) {
  113. // null packet for bumping process
  114. av_init_packet(&pkt);
  115. pkt.data = nullptr;
  116. pkt.size = 0;
  117. }
  118. // decode video frame
  119. avcodec_decode_video2(vstrm->codec, decframe, &got_pic, &pkt);
  120. if (!got_pic)
  121. goto next_packet;
  122. // convert frame to OpenCV matrix
  123. sws_scale(swsctx, decframe->data, decframe->linesize, 0, decframe->height, frame->data, frame->linesize);
  124. {
  125. cv::Mat image(dst_height, dst_width, CV_8UC3, framebuf.data(), frame->linesize[0]);
  126. cv::imshow("press ESC to exit", image);
  127. if (cv::waitKey(1) == 0x1b)
  128. break;
  129. }
  130. std::cout << nb_frames << '\r' << std::flush; // dump progress
  131. ++nb_frames;
  132. next_packet:
  133. av_free_packet(&pkt);
  134. } while (!end_of_stream || got_pic);
  135. std::cout << nb_frames << " frames decoded" << std::endl;
  136.  
  137. av_frame_free(&decframe);
  138. av_frame_free(&frame);
  139. avcodec_close(vstrm->codec);
  140. avformat_close_input(&inctx);
  141. return 0;
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement