player.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include "player.h"
  2. #include <algorithm>
  3. #include <chrono>
  4. #include <iostream>
  5. extern "C" {
  6. #include <libavutil/time.h>
  7. #include <libavutil/imgutils.h>
  8. }
  9. const size_t Player::queue_size_{5};
  10. Player::Player(const std::string &file_name) :
  11. demuxer_{std::make_unique<Demuxer>(file_name)},
  12. video_decoder_{std::make_unique<VideoDecoder>(
  13. demuxer_->video_codec_parameters())},
  14. format_converter_{std::make_unique<FormatConverter>(
  15. video_decoder_->width(), video_decoder_->height(),
  16. video_decoder_->pixel_format(), AV_PIX_FMT_YUV420P)},
  17. display_{std::make_unique<Display>(
  18. video_decoder_->width(), video_decoder_->height())},
  19. timer_{std::make_unique<Timer>()},
  20. packet_queue_{std::make_unique<PacketQueue>(queue_size_)},
  21. frame_queue_{std::make_unique<FrameQueue>(queue_size_)} {
  22. printf("Comp: %d vs %d\n", video_decoder_->pixel_format(), AV_PIX_FMT_YUV420P);
  23. }
  24. void Player::operator()() {
  25. stages_.emplace_back(&Player::demultiplex, this);
  26. stages_.emplace_back(&Player::decode_video, this);
  27. video();
  28. for (auto &stage : stages_) {
  29. stage.join();
  30. }
  31. if (exception_) {
  32. std::rethrow_exception(exception_);
  33. }
  34. }
  35. void Player::demultiplex() {
  36. try {
  37. for (;;) {
  38. // Create AVPacket
  39. std::unique_ptr<AVPacket, std::function<void(AVPacket*)>> packet{
  40. new AVPacket,
  41. [](AVPacket* p){ av_packet_unref(p); delete p; }};
  42. av_init_packet(packet.get());
  43. packet->data = nullptr;
  44. // Read frame into AVPacket
  45. if (!(*demuxer_)(*packet)) {
  46. packet_queue_->finished();
  47. break;
  48. }
  49. // Move into queue if first video stream
  50. if (packet->stream_index == demuxer_->video_stream_index()) {
  51. if (!packet_queue_->push(move(packet))) {
  52. break;
  53. }
  54. }
  55. }
  56. } catch (...) {
  57. exception_ = std::current_exception();
  58. frame_queue_->quit();
  59. packet_queue_->quit();
  60. }
  61. }
  62. void Player::decode_video() {
  63. try {
  64. const AVRational microseconds = {1, 1000000};
  65. for (;;) {
  66. // Create AVFrame and AVQueue
  67. std::unique_ptr<AVFrame, std::function<void(AVFrame*)>>
  68. frame_decoded{
  69. av_frame_alloc(), [](AVFrame* f){ av_frame_free(&f); }};
  70. std::unique_ptr<AVPacket, std::function<void(AVPacket*)>> packet{
  71. nullptr, [](AVPacket* p){ av_packet_unref(p); delete p; }};
  72. // Read packet from queue
  73. if (!packet_queue_->pop(packet)) {
  74. frame_queue_->finished();
  75. break;
  76. }
  77. // If the packet didn't send, receive more frames and try again
  78. bool sent = false;
  79. while (!sent) {
  80. sent = video_decoder_->send(packet.get());
  81. // If a whole frame has been decoded,
  82. // adjust time stamps and add to queue
  83. while (video_decoder_->receive(frame_decoded.get())) {
  84. frame_decoded->pts = av_rescale_q(
  85. frame_decoded->pkt_dts,
  86. demuxer_->time_base(),
  87. microseconds);
  88. std::unique_ptr<AVFrame, std::function<void(AVFrame*)>>
  89. frame_converted{
  90. av_frame_alloc(),
  91. [](AVFrame* f){ av_free(f->data[0]); }};
  92. if (av_frame_copy_props(frame_converted.get(),
  93. frame_decoded.get()) < 0) {
  94. throw std::runtime_error("Copying frame properties");
  95. }
  96. if (av_image_alloc(
  97. frame_converted->data, frame_converted->linesize,
  98. video_decoder_->width(), video_decoder_->height(),
  99. video_decoder_->pixel_format(), 1) < 0) {
  100. throw std::runtime_error("Allocating picture");
  101. }
  102. (*format_converter_)(
  103. frame_decoded.get(), frame_converted.get());
  104. if (!frame_queue_->push(move(frame_converted))) {
  105. break;
  106. }
  107. }
  108. }
  109. }
  110. } catch (...) {
  111. exception_ = std::current_exception();
  112. frame_queue_->quit();
  113. packet_queue_->quit();
  114. }
  115. }
  116. void Player::video() {
  117. try {
  118. int64_t last_pts = 0;
  119. for (uint64_t frame_number = 0;; ++frame_number) {
  120. display_->input();
  121. if (display_->get_quit()) {
  122. break;
  123. } else if (display_->get_play()) {
  124. std::unique_ptr<AVFrame, std::function<void(AVFrame*)>> frame{
  125. nullptr, [](AVFrame* f){ av_frame_free(&f); }};
  126. if (!frame_queue_->pop(frame)) {
  127. break;
  128. }
  129. if (frame_number) {
  130. const int64_t frame_delay = frame->pts - last_pts;
  131. last_pts = frame->pts;
  132. timer_->wait(frame_delay);
  133. } else {
  134. last_pts = frame->pts;
  135. timer_->update();
  136. }
  137. display_->refresh(
  138. {frame->data[0], frame->data[1], frame->data[2]},
  139. {static_cast<size_t>(frame->linesize[0]),
  140. static_cast<size_t>(frame->linesize[1]),
  141. static_cast<size_t>(frame->linesize[2])});
  142. } else {
  143. std::chrono::milliseconds sleep(10);
  144. std::this_thread::sleep_for(sleep);
  145. timer_->update();
  146. }
  147. }
  148. } catch (...) {
  149. exception_ = std::current_exception();
  150. }
  151. frame_queue_->quit();
  152. packet_queue_->quit();
  153. }