diff options
author | dknn <yoann.blein@free.fr> | 2012-08-16 21:52:56 (GMT) |
---|---|---|
committer | dknn <yoann.blein@free.fr> | 2012-09-22 09:32:38 (GMT) |
commit | dce09fe24d55d67f60d7bc691e285897f1d64fc2 (patch) | |
tree | f064c11c7c25a647a73c42d01e2cb836ea601bb3 /Swiften/ScreenSharing/VP8Decoder.cpp | |
parent | 867a950d5b3eb1422051a57c2533509188014b1a (diff) | |
download | swift-contrib-dce09fe24d55d67f60d7bc691e285897f1d64fc2.zip swift-contrib-dce09fe24d55d67f60d7bc691e285897f1d64fc2.tar.bz2 |
Add error resilience on decoder side
Diffstat (limited to 'Swiften/ScreenSharing/VP8Decoder.cpp')
-rw-r--r-- | Swiften/ScreenSharing/VP8Decoder.cpp | 37 |
1 files changed, 33 insertions, 4 deletions
diff --git a/Swiften/ScreenSharing/VP8Decoder.cpp b/Swiften/ScreenSharing/VP8Decoder.cpp index 2634cc5..90f5101 100644 --- a/Swiften/ScreenSharing/VP8Decoder.cpp +++ b/Swiften/ScreenSharing/VP8Decoder.cpp @@ -19,7 +19,7 @@ inline int clamp8(int v) VP8Decoder::VP8Decoder() : VideoDecoder(), - codecInterface(vpx_codec_vp8_dx()), codecFlags(0) + codecInterface(vpx_codec_vp8_dx()), codecFlags(0), refFrame(0) { SWIFT_LOG(debug) << "VP8 Decoder:" << vpx_codec_iface_name(codecInterface) << std::endl; @@ -28,6 +28,11 @@ VP8Decoder::VP8Decoder() VP8Decoder::~VP8Decoder() { + vpx_codec_destroy(&codecContext); + if (refFrame) { + vpx_img_free(&refFrame->img); + delete refFrame; + } } void VP8Decoder::updateCodecConfig() @@ -53,10 +58,34 @@ void VP8Decoder::decodeFrame(const std::vector<uint8_t>& frame, int pictureID) } vpx_codec_iter_t iter = NULL; - vpx_image_t* img; - while ((img = vpx_codec_get_frame(&codecContext, &iter))) { - Image rgbImg = convertYV12toRGB(img); + vpx_image_t* decodedImg; + while ((decodedImg = vpx_codec_get_frame(&codecContext, &iter))) { + Image rgbImg = convertYV12toRGB(decodedImg); onNewImageAvailable(rgbImg); + // Restore ref from last save if corrupted, else save the ref + int corrupted = 0; + vpx_codec_control(&codecContext, VP8D_GET_FRAME_CORRUPTED, &corrupted); + if (corrupted) { + vpx_codec_control(&codecContext, VP8_SET_REFERENCE, refFrame); + } else { + // Re-alloc the image ref if the format has changed + if (refFrame && (decodedImg->d_w != refFrame->img.d_w + || decodedImg->d_h != refFrame->img.d_h + || decodedImg->fmt != refFrame->img.fmt)) { + vpx_img_free(&refFrame->img); + delete refFrame; + refFrame = 0; + } + if (!refFrame) { + refFrame = new vpx_ref_frame_t; + refFrame->frame_type = VP8_LAST_FRAME; + unsigned int align = 1; + if (decodedImg->d_w % 32 == 0) + align = 32; + vpx_img_alloc(&refFrame->img, decodedImg->fmt, decodedImg->d_w, decodedImg->d_h, align); + } + vpx_codec_control(&codecContext, VP8_COPY_REFERENCE, refFrame); + } } } |