diff options
Diffstat (limited to 'Swiften/ScreenSharing/VP8Decoder.cpp')
-rw-r--r-- | Swiften/ScreenSharing/VP8Decoder.cpp | 99 |
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; +} + +} |