| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. |  | 
| 2 // Use of this source code is governed by a BSD-style license that can be |  | 
| 3 // found in the LICENSE file. |  | 
| 4 |  | 
| 5 #include "media/cast/video_receiver/codecs/vp8/vp8_decoder.h" |  | 
| 6 |  | 
| 7 #include "base/bind.h" |  | 
| 8 #include "base/debug/trace_event.h" |  | 
| 9 #include "base/logging.h" |  | 
| 10 #include "base/message_loop/message_loop.h" |  | 
| 11 #include "media/base/video_frame.h" |  | 
| 12 #include "media/base/video_util.h" |  | 
| 13 #include "media/cast/logging/logging_defines.h" |  | 
| 14 #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" |  | 
| 15 #include "ui/gfx/size.h" |  | 
| 16 |  | 
| 17 namespace { |  | 
| 18 |  | 
| 19 void LogFrameDecodedEvent( |  | 
| 20     const scoped_refptr<media::cast::CastEnvironment>& cast_environment, |  | 
| 21     base::TimeTicks event_time, |  | 
| 22     media::cast::RtpTimestamp rtp_timestamp, |  | 
| 23     uint32 frame_id) { |  | 
| 24   cast_environment->Logging()->InsertFrameEvent( |  | 
| 25       event_time, media::cast::kVideoFrameDecoded, rtp_timestamp, frame_id); |  | 
| 26 } |  | 
| 27 |  | 
| 28 }  // namespace |  | 
| 29 |  | 
| 30 namespace media { |  | 
| 31 namespace cast { |  | 
| 32 |  | 
| 33 Vp8Decoder::Vp8Decoder(scoped_refptr<CastEnvironment> cast_environment) |  | 
| 34     : cast_environment_(cast_environment) { |  | 
| 35   // Make sure that we initialize the decoder from the correct thread. |  | 
| 36   cast_environment_->PostTask( |  | 
| 37       CastEnvironment::VIDEO, |  | 
| 38       FROM_HERE, |  | 
| 39       base::Bind(&Vp8Decoder::InitDecoder, base::Unretained(this))); |  | 
| 40 } |  | 
| 41 |  | 
| 42 Vp8Decoder::~Vp8Decoder() { |  | 
| 43   if (decoder_) { |  | 
| 44     vpx_codec_err_t ret = vpx_codec_destroy(decoder_.get()); |  | 
| 45     CHECK_EQ(VPX_CODEC_OK, ret) << "vpx_codec_destroy() failed."; |  | 
| 46   } |  | 
| 47 } |  | 
| 48 |  | 
| 49 void Vp8Decoder::InitDecoder() { |  | 
| 50   vpx_codec_dec_cfg_t cfg; |  | 
| 51   // Initializing to use one core. |  | 
| 52   cfg.threads = 1; |  | 
| 53   vpx_codec_flags_t flags = VPX_CODEC_USE_POSTPROC; |  | 
| 54 |  | 
| 55   DCHECK(!decoder_); |  | 
| 56   decoder_.reset(new vpx_dec_ctx_t()); |  | 
| 57   vpx_codec_err_t ret = |  | 
| 58       vpx_codec_dec_init(decoder_.get(), vpx_codec_vp8_dx(), &cfg, flags); |  | 
| 59   if (ret != VPX_CODEC_OK) { |  | 
| 60     DCHECK(false) << "vpx_codec_dec_init() failed."; |  | 
| 61     decoder_.reset(); |  | 
| 62   } |  | 
| 63 } |  | 
| 64 |  | 
| 65 bool Vp8Decoder::Decode(const transport::EncodedVideoFrame* encoded_frame, |  | 
| 66                         const base::TimeTicks render_time, |  | 
| 67                         const VideoFrameDecodedCallback& frame_decoded_cb) { |  | 
| 68   DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO)); |  | 
| 69   const int frame_id_int = static_cast<int>(encoded_frame->frame_id); |  | 
| 70   VLOG(2) << "VP8 decode frame:" << frame_id_int |  | 
| 71           << " sized:" << encoded_frame->data.size(); |  | 
| 72 |  | 
| 73   if (encoded_frame->data.empty()) |  | 
| 74     return false; |  | 
| 75 |  | 
| 76   vpx_codec_iter_t iter = NULL; |  | 
| 77   vpx_image_t* img; |  | 
| 78   const int real_time_decoding = 1; |  | 
| 79   if (vpx_codec_decode( |  | 
| 80           decoder_.get(), |  | 
| 81           reinterpret_cast<const uint8*>(encoded_frame->data.data()), |  | 
| 82           static_cast<unsigned int>(encoded_frame->data.size()), |  | 
| 83           0, |  | 
| 84           real_time_decoding)) { |  | 
| 85     VLOG(1) << "Failed to decode VP8 frame:" << frame_id_int; |  | 
| 86     return false; |  | 
| 87   } |  | 
| 88 |  | 
| 89   img = vpx_codec_get_frame(decoder_.get(), &iter); |  | 
| 90   if (img == NULL) { |  | 
| 91     VLOG(1) << "Skip rendering VP8 frame:" << frame_id_int; |  | 
| 92     return false; |  | 
| 93   } |  | 
| 94 |  | 
| 95   gfx::Size visible_size(img->d_w, img->d_h); |  | 
| 96   gfx::Size full_size(img->stride[VPX_PLANE_Y], img->d_h); |  | 
| 97   DCHECK(VideoFrame::IsValidConfig( |  | 
| 98       VideoFrame::I420, visible_size, gfx::Rect(visible_size), full_size)); |  | 
| 99   // Temp timing setting - will sort out timing in a follow up cl. |  | 
| 100   scoped_refptr<VideoFrame> decoded_frame = |  | 
| 101       VideoFrame::CreateFrame(VideoFrame::I420, |  | 
| 102                               visible_size, |  | 
| 103                               gfx::Rect(visible_size), |  | 
| 104                               full_size, |  | 
| 105                               base::TimeDelta()); |  | 
| 106 |  | 
| 107   // Copy each plane individually (need to account for stride). |  | 
| 108   // TODO(mikhal): Eliminate copy once http://crbug.com/321856 is resolved. |  | 
| 109   CopyPlane(VideoFrame::kYPlane, |  | 
| 110             img->planes[VPX_PLANE_Y], |  | 
| 111             img->stride[VPX_PLANE_Y], |  | 
| 112             img->d_h, |  | 
| 113             decoded_frame.get()); |  | 
| 114   CopyPlane(VideoFrame::kUPlane, |  | 
| 115             img->planes[VPX_PLANE_U], |  | 
| 116             img->stride[VPX_PLANE_U], |  | 
| 117             (img->d_h + 1) / 2, |  | 
| 118             decoded_frame.get()); |  | 
| 119   CopyPlane(VideoFrame::kVPlane, |  | 
| 120             img->planes[VPX_PLANE_V], |  | 
| 121             img->stride[VPX_PLANE_V], |  | 
| 122             (img->d_h + 1) / 2, |  | 
| 123             decoded_frame.get()); |  | 
| 124 |  | 
| 125   VLOG(2) << "Decoded frame " << frame_id_int; |  | 
| 126 |  | 
| 127   // Update logging from the main thread. |  | 
| 128   cast_environment_->PostTask(CastEnvironment::MAIN, |  | 
| 129                               FROM_HERE, |  | 
| 130                               base::Bind(&LogFrameDecodedEvent, |  | 
| 131                                          cast_environment_, |  | 
| 132                                          cast_environment_->Clock()->NowTicks(), |  | 
| 133                                          encoded_frame->rtp_timestamp, |  | 
| 134                                          encoded_frame->frame_id)); |  | 
| 135 |  | 
| 136   // Used by chrome/browser/extension/api/cast_streaming/performance_test.cc |  | 
| 137   TRACE_EVENT_INSTANT1( |  | 
| 138       "cast_perf_test", "FrameDecoded", |  | 
| 139       TRACE_EVENT_SCOPE_THREAD, |  | 
| 140       "rtp_timestamp", encoded_frame->rtp_timestamp); |  | 
| 141 |  | 
| 142   // Frame decoded - return frame to the user via callback. |  | 
| 143   cast_environment_->PostTask( |  | 
| 144       CastEnvironment::MAIN, |  | 
| 145       FROM_HERE, |  | 
| 146       base::Bind(frame_decoded_cb, decoded_frame, render_time)); |  | 
| 147 |  | 
| 148   return true; |  | 
| 149 } |  | 
| 150 |  | 
| 151 }  // namespace cast |  | 
| 152 }  // namespace media |  | 
| OLD | NEW | 
|---|