summaryrefslogtreecommitdiff
path: root/chromium/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc')
-rw-r--r--chromium/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc98
1 files changed, 68 insertions, 30 deletions
diff --git a/chromium/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc b/chromium/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc
index 93d3eb5c4aa..10fcb85d36e 100644
--- a/chromium/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc
+++ b/chromium/media/cast/video_receiver/codecs/vp8/vp8_decoder.cc
@@ -4,22 +4,38 @@
#include "media/cast/video_receiver/codecs/vp8/vp8_decoder.h"
+#include "base/bind.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "media/base/video_frame.h"
+#include "media/base/video_util.h"
#include "third_party/libvpx/source/libvpx/vpx/vp8dx.h"
+#include "ui/gfx/size.h"
namespace media {
namespace cast {
-Vp8Decoder::Vp8Decoder(int number_of_cores) {
- decoder_.reset(new vpx_dec_ctx_t());
- InitDecode(number_of_cores);
+void LogFrameDecodedEvent(CastEnvironment* const cast_environment,
+ uint32 frame_id) {
+// TODO(mikhal): Sort out passing of rtp_timestamp.
+// cast_environment->Logging()->InsertFrameEvent(kVideoFrameDecoded,
+// 0, frame_id);
+}
+
+Vp8Decoder::Vp8Decoder(scoped_refptr<CastEnvironment> cast_environment)
+ : decoder_(new vpx_dec_ctx_t()),
+ cast_environment_(cast_environment) {
+ // Make sure that we initialize the decoder from the correct thread.
+ cast_environment_->PostTask(CastEnvironment::VIDEO_DECODER, FROM_HERE,
+ base::Bind(&Vp8Decoder::InitDecoder, base::Unretained(this)));
}
Vp8Decoder::~Vp8Decoder() {}
-void Vp8Decoder::InitDecode(int number_of_cores) {
- vpx_codec_dec_cfg_t cfg;
- cfg.threads = number_of_cores;
+void Vp8Decoder::InitDecoder() {
+ vpx_codec_dec_cfg_t cfg;
+ // Initializing to use one core.
+ cfg.threads = 1;
vpx_codec_flags_t flags = VPX_CODEC_USE_POSTPROC;
if (vpx_codec_dec_init(decoder_.get(), vpx_codec_vp8_dx(), &cfg, flags)) {
@@ -27,38 +43,60 @@ void Vp8Decoder::InitDecode(int number_of_cores) {
}
}
-bool Vp8Decoder::Decode(const EncodedVideoFrame& input_image,
- I420VideoFrame* decoded_frame) {
- if (input_image.data.empty()) return false;
+bool Vp8Decoder::Decode(const EncodedVideoFrame* encoded_frame,
+ const base::TimeTicks render_time,
+ const VideoFrameDecodedCallback& frame_decoded_cb) {
+ DCHECK(cast_environment_->CurrentlyOn(CastEnvironment::VIDEO_DECODER));
+ const int frame_id_int = static_cast<int>(encoded_frame->frame_id);
+ VLOG(1) << "VP8 decode frame:" << frame_id_int
+ << " sized:" << encoded_frame->data.size();
+
+ if (encoded_frame->data.empty()) return false;
vpx_codec_iter_t iter = NULL;
vpx_image_t* img;
- if (vpx_codec_decode(decoder_.get(),
- input_image.data.data(),
- input_image.data.size(),
- 0,
- 1 /* real time*/)) {
+ if (vpx_codec_decode(
+ decoder_.get(),
+ reinterpret_cast<const uint8*>(encoded_frame->data.data()),
+ static_cast<unsigned int>(encoded_frame->data.size()),
+ 0,
+ 1 /* real time*/)) {
+ VLOG(1) << "Failed to decode VP8 frame.";
return false;
}
img = vpx_codec_get_frame(decoder_.get(), &iter);
- if (img == NULL) return false;
-
- // Populate the decoded image.
- decoded_frame->width = img->d_w;
- decoded_frame->height = img->d_h;
-
- decoded_frame->y_plane.stride = img->stride[VPX_PLANE_Y];
- decoded_frame->y_plane.length = img->stride[VPX_PLANE_Y] * img->d_h;
- decoded_frame->y_plane.data = img->planes[VPX_PLANE_Y];
-
- decoded_frame->u_plane.stride = img->stride[VPX_PLANE_U];
- decoded_frame->u_plane.length = img->stride[VPX_PLANE_U] * img->d_h;
- decoded_frame->u_plane.data = img->planes[VPX_PLANE_U];
+ if (img == NULL) {
+ VLOG(1) << "Skip rendering VP8 frame:" << frame_id_int;
+ return false;
+ }
- decoded_frame->v_plane.stride = img->stride[VPX_PLANE_V];
- decoded_frame->v_plane.length = img->stride[VPX_PLANE_V] * img->d_h;
- decoded_frame->v_plane.data = img->planes[VPX_PLANE_V];
+ gfx::Size visible_size(img->d_w, img->d_h);
+ gfx::Size full_size(img->stride[VPX_PLANE_Y], img->d_h);
+ DCHECK(VideoFrame::IsValidConfig(VideoFrame::I420, visible_size,
+ gfx::Rect(visible_size), full_size));
+ // Temp timing setting - will sort out timing in a follow up cl.
+ scoped_refptr<VideoFrame> decoded_frame =
+ VideoFrame::CreateFrame(VideoFrame::I420, visible_size,
+ gfx::Rect(visible_size), full_size, base::TimeDelta());
+
+ // Copy each plane individually (need to account for stride).
+ // TODO(mikhal): Eliminate copy once http://crbug.com/321856 is resolved.
+ CopyPlane(VideoFrame::kYPlane, img->planes[VPX_PLANE_Y],
+ img->stride[VPX_PLANE_Y], img->d_h, decoded_frame.get());
+ CopyPlane(VideoFrame::kUPlane, img->planes[VPX_PLANE_U],
+ img->stride[VPX_PLANE_U], (img->d_h + 1) / 2, decoded_frame.get());
+ CopyPlane(VideoFrame::kVPlane, img->planes[VPX_PLANE_V],
+ img->stride[VPX_PLANE_V], (img->d_h + 1) / 2, decoded_frame.get());
+
+ // Log:: Decoding complete (should be called from the main thread).
+ cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE, base::Bind(
+ LogFrameDecodedEvent, cast_environment_,encoded_frame->frame_id));
+
+ VLOG(1) << "Decoded frame " << frame_id_int;
+ // Frame decoded - return frame to the user via callback.
+ cast_environment_->PostTask(CastEnvironment::MAIN, FROM_HERE,
+ base::Bind(frame_decoded_cb, decoded_frame, render_time));
return true;
}