video_stream.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #include "video_stream.h"
  2. #include <c10/util/Logging.h>
  3. #include "util.h"
  4. namespace ffmpeg {
  5. namespace {
  6. bool operator==(const VideoFormat& x, const AVFrame& y) {
  7. return x.width == static_cast<size_t>(y.width) &&
  8. x.height == static_cast<size_t>(y.height) && x.format == y.format;
  9. }
  10. bool operator==(const VideoFormat& x, const AVCodecContext& y) {
  11. return x.width == static_cast<size_t>(y.width) &&
  12. x.height == static_cast<size_t>(y.height) && x.format == y.pix_fmt;
  13. }
  14. VideoFormat& toVideoFormat(VideoFormat& x, const AVFrame& y) {
  15. x.width = y.width;
  16. x.height = y.height;
  17. x.format = y.format;
  18. return x;
  19. }
  20. VideoFormat& toVideoFormat(VideoFormat& x, const AVCodecContext& y) {
  21. x.width = y.width;
  22. x.height = y.height;
  23. x.format = y.pix_fmt;
  24. return x;
  25. }
  26. } // namespace
  27. VideoStream::VideoStream(
  28. AVFormatContext* inputCtx,
  29. int index,
  30. bool convertPtsToWallTime,
  31. const VideoFormat& format,
  32. int64_t loggingUuid)
  33. : Stream(
  34. inputCtx,
  35. MediaFormat::makeMediaFormat(format, index),
  36. convertPtsToWallTime,
  37. loggingUuid) {}
  38. VideoStream::~VideoStream() {
  39. if (sampler_) {
  40. sampler_->shutdown();
  41. sampler_.reset();
  42. }
  43. }
  44. int VideoStream::initFormat() {
  45. // set output format
  46. if (!Util::validateVideoFormat(format_.format.video)) {
  47. LOG(ERROR) << "Invalid video format"
  48. << ", width: " << format_.format.video.width
  49. << ", height: " << format_.format.video.height
  50. << ", format: " << format_.format.video.format
  51. << ", minDimension: " << format_.format.video.minDimension
  52. << ", crop: " << format_.format.video.cropImage;
  53. return -1;
  54. }
  55. // keep aspect ratio
  56. Util::setFormatDimensions(
  57. format_.format.video.width,
  58. format_.format.video.height,
  59. format_.format.video.width,
  60. format_.format.video.height,
  61. codecCtx_->width,
  62. codecCtx_->height,
  63. format_.format.video.minDimension,
  64. format_.format.video.maxDimension,
  65. 0);
  66. if (format_.format.video.format == AV_PIX_FMT_NONE) {
  67. format_.format.video.format = codecCtx_->pix_fmt;
  68. }
  69. return format_.format.video.width != 0 && format_.format.video.height != 0 &&
  70. format_.format.video.format != AV_PIX_FMT_NONE
  71. ? 0
  72. : -1;
  73. }
  74. // copies frame bytes via sws_scale call in video_sampler.cpp
  75. int VideoStream::copyFrameBytes(ByteStorage* out, bool flush) {
  76. if (!sampler_) {
  77. sampler_ = std::make_unique<VideoSampler>(SWS_AREA, loggingUuid_);
  78. }
  79. // check if input format gets changed
  80. if (flush ? !(sampler_->getInputFormat().video == *codecCtx_)
  81. : !(sampler_->getInputFormat().video == *frame_)) {
  82. // - reinit sampler
  83. SamplerParameters params;
  84. params.type = format_.type;
  85. params.out = format_.format;
  86. params.in = FormatUnion(0);
  87. flush ? toVideoFormat(params.in.video, *codecCtx_)
  88. : toVideoFormat(params.in.video, *frame_);
  89. if (!sampler_->init(params)) {
  90. return -1;
  91. }
  92. VLOG(1) << "Set input video sampler format"
  93. << ", width: " << params.in.video.width
  94. << ", height: " << params.in.video.height
  95. << ", format: " << params.in.video.format
  96. << " : output video sampler format"
  97. << ", width: " << format_.format.video.width
  98. << ", height: " << format_.format.video.height
  99. << ", format: " << format_.format.video.format
  100. << ", minDimension: " << format_.format.video.minDimension
  101. << ", crop: " << format_.format.video.cropImage;
  102. }
  103. // calls to a sampler that converts the frame from YUV422 to RGB24, and
  104. // optionally crops and resizes the frame. Frame bytes are copied from
  105. // frame_->data to out buffer
  106. return sampler_->sample(flush ? nullptr : frame_, out);
  107. }
  108. void VideoStream::setHeader(DecoderHeader* header, bool flush) {
  109. Stream::setHeader(header, flush);
  110. if (!flush) { // no frames for video flush
  111. header->keyFrame = frame_->key_frame;
  112. header->fps = av_q2d(av_guess_frame_rate(
  113. inputCtx_, inputCtx_->streams[format_.stream], nullptr));
  114. }
  115. }
  116. } // namespace ffmpeg