summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/ScreenSharing/VP8Decoder.cpp')
-rw-r--r--Swiften/ScreenSharing/VP8Decoder.cpp99
1 files changed, 99 insertions, 0 deletions
diff --git a/Swiften/ScreenSharing/VP8Decoder.cpp b/Swiften/ScreenSharing/VP8Decoder.cpp
new file mode 100644
index 0000000..40f631f
--- /dev/null
+++ b/Swiften/ScreenSharing/VP8Decoder.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2012 Yoann Blein
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include <Swiften/ScreenSharing/VP8Decoder.h>
+
+#include <Swiften/ScreenSharing/Image.h>
+#include <Swiften/Base/Log.h>
+#include "vpx/vp8dx.h"
+
+namespace Swift {
+
+inline int clamp8(int v)
+{
+ return std::min(std::max(v, 0), 255);
+}
+
+VP8Decoder::VP8Decoder()
+ : VideoDecoder(),
+ codecInterface(vpx_codec_vp8_dx()), codecFlags(0)
+{
+ SWIFT_LOG(debug) << "VP8 Decoder:" << vpx_codec_iface_name(codecInterface) << std::endl;
+
+ updateCodecConfig();
+}
+
+VP8Decoder::~VP8Decoder()
+{
+}
+
+void VP8Decoder::updateCodecConfig()
+{
+ // TODO: vpx_codec_flags_t flags = VPX_CODEC_USE_INPUT_FRAGMENTS;
+ vpx_codec_err_t err = vpx_codec_dec_init(&codecContext, codecInterface, NULL, codecFlags);
+ if (err) {
+ SWIFT_LOG(debug) << "VP8 Decoder: Failed to initialize decoder, " << vpx_codec_err_to_string(err) << std::endl;
+ // TODO: exception ?
+ }
+}
+
+void VP8Decoder::decodeFrame(const std::vector<uint8_t>& frame)
+{
+ // Decode the frame
+ vpx_codec_err_t err = vpx_codec_decode(&codecContext, &frame[0], frame.size(), NULL, 0);
+ if (err) {
+ SWIFT_LOG(debug) << "VP8 Decoder: Failed to decode frame, " << vpx_codec_err_to_string(err) << std::endl;
+ // TODO: exception ?
+ return;
+ }
+
+ vpx_codec_iter_t iter = NULL;
+ vpx_image_t* img;
+ while ((img = vpx_codec_get_frame(&codecContext, &iter))) {
+ Image rgbImg = convertYV12toRGB(img);
+ onNewImageDecoded(rgbImg);
+ }
+}
+
+Image VP8Decoder::convertYV12toRGB(const vpx_image_t* img)
+{
+ Image rgbImg(img->d_w, img->d_h);
+ std::vector<uint8_t>& data = rgbImg.data;
+
+ uint8_t *yPlane = img->planes[VPX_PLANE_Y];
+ uint8_t *uPlane = img->planes[VPX_PLANE_U];
+ uint8_t *vPlane = img->planes[VPX_PLANE_V];
+
+ int i = 0;
+ for (unsigned int imgY = 0; imgY < img->d_h; imgY++) {
+ for (unsigned int imgX = 0; imgX < img->d_w; imgX++) {
+ int y = yPlane[imgY * img->stride[VPX_PLANE_Y] + imgX];
+ int u = uPlane[(imgY / 2) * img->stride[VPX_PLANE_U] + (imgX / 2)];
+ int v = vPlane[(imgY / 2) * img->stride[VPX_PLANE_V] + (imgX / 2)];
+
+ int c = y - 16;
+ int d = (u - 128);
+ int e = (v - 128);
+
+ // TODO: adjust colors ?
+
+ int r = clamp8((298 * c + 409 * e + 128) >> 8);
+ int g = clamp8((298 * c - 100 * d - 208 * e + 128) >> 8);
+ int b = clamp8((298 * c + 516 * d + 128) >> 8);
+
+ // TODO: cast instead of clamp8
+
+ data[i + 0] = static_cast<uint8_t>(r);
+ data[i + 1] = static_cast<uint8_t>(g);
+ data[i + 2] = static_cast<uint8_t>(b);
+
+ i += 3;
+ }
+ }
+ return rgbImg;
+}
+
+}