VideoDecoder.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /* ---------------------------------------------------------------------------
  2. ** This software is in the public domain, furnished "as is", without technical
  3. ** support, and with no warranty, express or implied, as to its usefulness for
  4. ** any purpose.
  5. **
  6. ** VideoDecoder.h
  7. **
  8. ** -------------------------------------------------------------------------*/
  9. #pragma once
  10. #include <string.h>
  11. #include <vector>
  12. #include "api/video/i420_buffer.h"
  13. #include "modules/video_coding/include/video_error_codes.h"
  14. #include "modules/video_coding/h264_sprop_parameter_sets.h"
  15. class VideoDecoder : public webrtc::DecodedImageCallback {
  16. private:
  17. class Frame
  18. {
  19. public:
  20. Frame(): m_timestamp_ms(0) {}
  21. Frame(const rtc::scoped_refptr<webrtc::EncodedImageBuffer> & content, uint64_t timestamp_ms, webrtc::VideoFrameType frameType) : m_content(content), m_timestamp_ms(timestamp_ms), m_frameType(frameType) {}
  22. rtc::scoped_refptr<webrtc::EncodedImageBuffer> m_content;
  23. uint64_t m_timestamp_ms;
  24. webrtc::VideoFrameType m_frameType;
  25. };
  26. public:
  27. VideoDecoder(rtc::VideoBroadcaster& broadcaster, std::unique_ptr<webrtc::VideoDecoderFactory>& videoDecoderFactory, bool wait) :
  28. m_broadcaster(broadcaster),
  29. m_factory(videoDecoderFactory),
  30. m_stop(false),
  31. m_wait(wait),
  32. m_previmagets(0),
  33. m_prevts(0) {
  34. }
  35. virtual ~VideoDecoder() {
  36. }
  37. void DecoderThread()
  38. {
  39. while (!m_stop) {
  40. std::unique_lock<std::mutex> mlock(m_queuemutex);
  41. while (m_queue.empty())
  42. {
  43. m_queuecond.wait(mlock);
  44. }
  45. Frame frame = m_queue.front();
  46. m_queue.pop();
  47. mlock.unlock();
  48. if (frame.m_content.get() != NULL) {
  49. RTC_LOG(LS_VERBOSE) << "VideoDecoder::DecoderThread size:" << frame.m_content->size() << " ts:" << frame.m_timestamp_ms;
  50. ssize_t size = frame.m_content->size();
  51. if (size) {
  52. webrtc::EncodedImage input_image;
  53. input_image.SetEncodedData(frame.m_content);
  54. input_image._frameType = frame.m_frameType;
  55. input_image.ntp_time_ms_ = frame.m_timestamp_ms;
  56. input_image.SetTimestamp(frame.m_timestamp_ms); // store time in ms that overflow the 32bits
  57. int res = m_decoder->Decode(input_image, false, frame.m_timestamp_ms);
  58. if (res != WEBRTC_VIDEO_CODEC_OK) {
  59. RTC_LOG(LS_ERROR) << "VideoDecoder::DecoderThread failure:" << res;
  60. }
  61. }
  62. }
  63. }
  64. }
  65. void Start()
  66. {
  67. RTC_LOG(LS_INFO) << "VideoDecoder::start";
  68. m_stop = false;
  69. m_decoderthread = std::thread(&VideoDecoder::DecoderThread, this);
  70. }
  71. void Stop()
  72. {
  73. RTC_LOG(LS_INFO) << "VideoDecoder::stop";
  74. m_stop = true;
  75. Frame frame;
  76. {
  77. std::unique_lock<std::mutex> lock(m_queuemutex);
  78. m_queue.push(frame);
  79. }
  80. m_queuecond.notify_all();
  81. m_decoderthread.join();
  82. }
  83. std::vector< std::vector<uint8_t> > getInitFrames(const std::string & codec, const char* sdp) {
  84. std::vector< std::vector<uint8_t> > frames;
  85. if (codec == "H264") {
  86. const char* pattern="sprop-parameter-sets=";
  87. const char* sprop=strstr(sdp, pattern);
  88. if (sprop)
  89. {
  90. std::string sdpstr(sprop+strlen(pattern));
  91. size_t pos = sdpstr.find_first_of(" ;\r\n");
  92. if (pos != std::string::npos)
  93. {
  94. sdpstr.erase(pos);
  95. }
  96. webrtc::H264SpropParameterSets sprops;
  97. if (sprops.DecodeSprop(sdpstr))
  98. {
  99. std::vector<uint8_t> sps;
  100. sps.insert(sps.end(), H26X_marker, H26X_marker+sizeof(H26X_marker));
  101. sps.insert(sps.end(), sprops.sps_nalu().begin(), sprops.sps_nalu().end());
  102. frames.push_back(sps);
  103. std::vector<uint8_t> pps;
  104. pps.insert(pps.end(), H26X_marker, H26X_marker+sizeof(H26X_marker));
  105. pps.insert(pps.end(), sprops.pps_nalu().begin(), sprops.pps_nalu().end());
  106. frames.push_back(pps);
  107. }
  108. else
  109. {
  110. RTC_LOG(WARNING) << "Cannot decode SPS:" << sprop;
  111. }
  112. }
  113. }
  114. return frames;
  115. }
  116. void createDecoder(const std::string & codec, int width = 0, int height = 0) {
  117. webrtc::VideoCodec codec_settings;
  118. codec_settings.width=width;
  119. codec_settings.height=height;
  120. if (codec == "H264") {
  121. m_decoder=m_factory->CreateVideoDecoder(webrtc::SdpVideoFormat(cricket::kH264CodecName));
  122. codec_settings.codecType = webrtc::VideoCodecType::kVideoCodecH264;
  123. }
  124. if (m_decoder.get() != NULL) {
  125. m_decoder->InitDecode(&codec_settings,2);
  126. m_decoder->RegisterDecodeCompleteCallback(this);
  127. }
  128. }
  129. void destroyDecoder() {
  130. m_decoder.reset(NULL);
  131. }
  132. bool hasDecoder() {
  133. return (m_decoder.get() != NULL);
  134. }
  135. void PostFrame(const rtc::scoped_refptr<webrtc::EncodedImageBuffer>& content, uint64_t ts, webrtc::VideoFrameType frameType) {
  136. Frame frame(content, ts, frameType);
  137. {
  138. std::unique_lock<std::mutex> lock(m_queuemutex);
  139. m_queue.push(frame);
  140. }
  141. m_queuecond.notify_all();
  142. }
  143. // overide webrtc::DecodedImageCallback
  144. virtual int32_t Decoded(webrtc::VideoFrame& decodedImage) override {
  145. int64_t ts = std::chrono::high_resolution_clock::now().time_since_epoch().count()/1000/1000;
  146. RTC_LOG(LS_VERBOSE) << "VideoDecoder::Decoded size:" << decodedImage.size()
  147. << " decode ts:" << decodedImage.ntp_time_ms()
  148. << " source ts:" << ts;
  149. // waiting
  150. if ( (m_wait) && (m_prevts != 0) ) {
  151. int64_t periodSource = decodedImage.timestamp() - m_previmagets;
  152. int64_t periodDecode = ts-m_prevts;
  153. RTC_LOG(LS_VERBOSE) << "VideoDecoder::Decoded interframe decode:" << periodDecode << " source:" << periodSource;
  154. int64_t delayms = periodSource-periodDecode;
  155. if ( (delayms > 0) && (delayms < 1000) ) {
  156. std::this_thread::sleep_for(std::chrono::milliseconds(delayms));
  157. }
  158. } else {
  159. std::this_thread::sleep_for(std::chrono::milliseconds(5));
  160. }
  161. m_broadcaster.OnFrame(decodedImage);
  162. m_previmagets = decodedImage.timestamp();
  163. m_prevts = std::chrono::high_resolution_clock::now().time_since_epoch().count()/1000/1000;
  164. return 1;
  165. }
  166. rtc::VideoBroadcaster& m_broadcaster;
  167. std::unique_ptr<webrtc::VideoDecoderFactory>& m_factory;
  168. std::unique_ptr<webrtc::VideoDecoder> m_decoder;
  169. std::queue<Frame> m_queue;
  170. std::mutex m_queuemutex;
  171. std::condition_variable m_queuecond;
  172. std::thread m_decoderthread;
  173. bool m_stop;
  174. bool m_wait;
  175. int64_t m_previmagets;
  176. int64_t m_prevts;
  177. };