OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/video_receiver/codecs/vp8/vp8_decoder.h" | 5 #include "media/cast/video_receiver/codecs/vp8/vp8_decoder.h" |
6 | 6 |
| 7 #include "base/bind.h" |
7 #include "base/logging.h" | 8 #include "base/logging.h" |
| 9 #include "base/message_loop/message_loop.h" |
8 #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" | 10 #include "third_party/libvpx/source/libvpx/vpx/vp8dx.h" |
9 | 11 |
10 namespace media { | 12 namespace media { |
11 namespace cast { | 13 namespace cast { |
12 | 14 |
13 Vp8Decoder::Vp8Decoder(int number_of_cores) { | 15 Vp8Decoder::Vp8Decoder(int number_of_cores, |
14 decoder_.reset(new vpx_dec_ctx_t()); | 16 scoped_refptr<CastEnvironment> cast_environment) |
| 17 : decoder_(new vpx_dec_ctx_t()), |
| 18 cast_environment_(cast_environment) { |
15 InitDecode(number_of_cores); | 19 InitDecode(number_of_cores); |
16 } | 20 } |
17 | 21 |
18 Vp8Decoder::~Vp8Decoder() {} | 22 Vp8Decoder::~Vp8Decoder() {} |
19 | 23 |
20 void Vp8Decoder::InitDecode(int number_of_cores) { | 24 void Vp8Decoder::InitDecode(int number_of_cores) { |
21 vpx_codec_dec_cfg_t cfg; | 25 vpx_codec_dec_cfg_t cfg; |
22 cfg.threads = number_of_cores; | 26 cfg.threads = number_of_cores; |
23 vpx_codec_flags_t flags = VPX_CODEC_USE_POSTPROC; | 27 vpx_codec_flags_t flags = VPX_CODEC_USE_POSTPROC; |
24 | 28 |
25 if (vpx_codec_dec_init(decoder_.get(), vpx_codec_vp8_dx(), &cfg, flags)) { | 29 if (vpx_codec_dec_init(decoder_.get(), vpx_codec_vp8_dx(), &cfg, flags)) { |
26 DCHECK(false) << "VP8 decode error"; | 30 DCHECK(false) << "VP8 decode error"; |
27 } | 31 } |
28 } | 32 } |
29 | 33 |
30 bool Vp8Decoder::Decode(const EncodedVideoFrame& input_image, | 34 bool Vp8Decoder::Decode(const EncodedVideoFrame* encoded_frame, |
31 I420VideoFrame* decoded_frame) { | 35 const base::TimeTicks render_time, |
32 VLOG(1) << "VP8 decode frame:" << static_cast<int>(input_image.frame_id) | 36 const VideoFrameDecodedCallback& frame_decoded_cb) { |
33 << " sized:" << input_image.data.size(); | 37 const int frame_id_int = static_cast<int>(encoded_frame->frame_id); |
| 38 VLOG(1) << "VP8 decode frame:" << frame_id_int |
| 39 << " sized:" << encoded_frame->data.size(); |
34 | 40 |
35 if (input_image.data.empty()) return false; | 41 if (encoded_frame->data.empty()) return false; |
36 | 42 |
37 vpx_codec_iter_t iter = NULL; | 43 vpx_codec_iter_t iter = NULL; |
38 vpx_image_t* img; | 44 vpx_image_t* img; |
39 if (vpx_codec_decode(decoder_.get(), | 45 if (vpx_codec_decode(decoder_.get(), |
40 input_image.data.data(), | 46 encoded_frame->data.data(), |
41 static_cast<unsigned int>(input_image.data.size()), | 47 static_cast<unsigned int>(encoded_frame->data.size()), |
42 0, | 48 0, |
43 1 /* real time*/)) { | 49 1 /* real time*/)) { |
44 VLOG(1) << "Failed to decode VP8 frame."; | 50 VLOG(1) << "Failed to decode VP8 frame."; |
45 return false; | 51 return false; |
46 } | 52 } |
47 | 53 |
48 img = vpx_codec_get_frame(decoder_.get(), &iter); | 54 img = vpx_codec_get_frame(decoder_.get(), &iter); |
49 if (img == NULL) { | 55 if (img == NULL) { |
50 VLOG(1) << "Skip rendering VP8 frame:" | 56 VLOG(1) << "Skip rendering VP8 frame:" << frame_id_int; |
51 << static_cast<int>(input_image.frame_id); | |
52 return false; | 57 return false; |
53 } | 58 } |
54 | 59 |
| 60 scoped_ptr<I420VideoFrame> decoded_frame(new I420VideoFrame()); |
| 61 |
55 // The img is only valid until the next call to vpx_codec_decode. | 62 // The img is only valid until the next call to vpx_codec_decode. |
56 // Populate the decoded image. | 63 // Populate the decoded image. |
57 decoded_frame->width = img->d_w; | 64 decoded_frame->width = img->d_w; |
58 decoded_frame->height = img->d_h; | 65 decoded_frame->height = img->d_h; |
59 | 66 |
60 decoded_frame->y_plane.stride = img->stride[VPX_PLANE_Y]; | 67 decoded_frame->y_plane.stride = img->stride[VPX_PLANE_Y]; |
61 decoded_frame->y_plane.length = img->stride[VPX_PLANE_Y] * img->d_h; | 68 decoded_frame->y_plane.length = img->stride[VPX_PLANE_Y] * img->d_h; |
62 decoded_frame->y_plane.data = new uint8[decoded_frame->y_plane.length]; | 69 decoded_frame->y_plane.data = new uint8[decoded_frame->y_plane.length]; |
63 memcpy(decoded_frame->y_plane.data, img->planes[VPX_PLANE_Y], | 70 memcpy(decoded_frame->y_plane.data, img->planes[VPX_PLANE_Y], |
64 decoded_frame->y_plane.length); | 71 decoded_frame->y_plane.length); |
65 | 72 |
66 decoded_frame->u_plane.stride = img->stride[VPX_PLANE_U]; | 73 decoded_frame->u_plane.stride = img->stride[VPX_PLANE_U]; |
67 decoded_frame->u_plane.length = img->stride[VPX_PLANE_U] * (img->d_h + 1) / 2; | 74 decoded_frame->u_plane.length = img->stride[VPX_PLANE_U] * (img->d_h + 1) / 2; |
68 decoded_frame->u_plane.data = new uint8[decoded_frame->u_plane.length]; | 75 decoded_frame->u_plane.data = new uint8[decoded_frame->u_plane.length]; |
69 memcpy(decoded_frame->u_plane.data, img->planes[VPX_PLANE_U], | 76 memcpy(decoded_frame->u_plane.data, img->planes[VPX_PLANE_U], |
70 decoded_frame->u_plane.length); | 77 decoded_frame->u_plane.length); |
71 | 78 |
72 decoded_frame->v_plane.stride = img->stride[VPX_PLANE_V]; | 79 decoded_frame->v_plane.stride = img->stride[VPX_PLANE_V]; |
73 decoded_frame->v_plane.length = img->stride[VPX_PLANE_V] * (img->d_h + 1) / 2; | 80 decoded_frame->v_plane.length = img->stride[VPX_PLANE_V] * (img->d_h + 1) / 2; |
74 decoded_frame->v_plane.data = new uint8[decoded_frame->v_plane.length]; | 81 decoded_frame->v_plane.data = new uint8[decoded_frame->v_plane.length]; |
75 | 82 |
76 memcpy(decoded_frame->v_plane.data, img->planes[VPX_PLANE_V], | 83 memcpy(decoded_frame->v_plane.data, img->planes[VPX_PLANE_V], |
77 decoded_frame->v_plane.length); | 84 decoded_frame->v_plane.length); |
78 | 85 |
| 86 // Return frame. |
| 87 VLOG(1) << "Decoded frame " << frame_id_int; |
| 88 // Frame decoded - return frame to the user via callback. |
| 89 cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, |
| 90 base::Bind(frame_decoded_cb, base::Passed(&decoded_frame), render_time)); |
| 91 |
79 return true; | 92 return true; |
80 } | 93 } |
81 | 94 |
82 } // namespace cast | 95 } // namespace cast |
83 } // namespace media | 96 } // namespace media |
84 | 97 |
OLD | NEW |