/* * libjingle * Copyright 2011 Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TALK_MEDIA_BASE_FAKEVIDEORENDERER_H_ #define TALK_MEDIA_BASE_FAKEVIDEORENDERER_H_ #include "talk/media/base/videoframe.h" #include "talk/media/base/videorenderer.h" #include "webrtc/base/logging.h" #include "webrtc/base/sigslot.h" namespace cricket { // Faked video renderer that has a callback for actions on rendering. class FakeVideoRenderer : public VideoRenderer { public: FakeVideoRenderer() : errors_(0), width_(0), height_(0), num_set_sizes_(0), num_rendered_frames_(0), black_frame_(false) { } virtual bool SetSize(int width, int height, int reserved) { rtc::CritScope cs(&crit_); width_ = width; height_ = height; ++num_set_sizes_; SignalSetSize(width, height, reserved); return true; } virtual bool RenderFrame(const VideoFrame* frame) { rtc::CritScope cs(&crit_); // TODO(zhurunz) Check with VP8 team to see if we can remove this // tolerance on Y values. black_frame_ = CheckFrameColorYuv(6, 48, 128, 128, 128, 128, frame); // Treat unexpected frame size as error. if (!frame || frame->GetWidth() != static_cast(width_) || frame->GetHeight() != static_cast(height_)) { if (!frame) { LOG(LS_WARNING) << "RenderFrame expected non-null frame."; } else { LOG(LS_WARNING) << "RenderFrame expected frame of size " << width_ << "x" << height_ << " but received frame of size " << frame->GetWidth() << "x" << frame->GetHeight(); } ++errors_; return false; } ++num_rendered_frames_; SignalRenderFrame(frame); return true; } int errors() const { return errors_; } int width() const { rtc::CritScope cs(&crit_); return width_; } int height() const { rtc::CritScope cs(&crit_); return height_; } int num_set_sizes() const { rtc::CritScope cs(&crit_); return num_set_sizes_; } int num_rendered_frames() const { rtc::CritScope cs(&crit_); return num_rendered_frames_; } bool black_frame() const { rtc::CritScope cs(&crit_); return black_frame_; } sigslot::signal3 SignalSetSize; sigslot::signal1 SignalRenderFrame; private: static bool CheckFrameColorYuv(uint8_t y_min, uint8_t y_max, uint8_t u_min, uint8_t u_max, uint8_t v_min, uint8_t v_max, const cricket::VideoFrame* frame) { if (!frame) { return false; } // Y size_t y_width = frame->GetWidth(); size_t y_height = frame->GetHeight(); const uint8_t* y_plane = frame->GetYPlane(); const uint8_t* y_pos = y_plane; int32_t y_pitch = frame->GetYPitch(); for (size_t i = 0; i < y_height; ++i) { for (size_t j = 0; j < y_width; ++j) { uint8_t y_value = *(y_pos + j); if (y_value < y_min || y_value > y_max) { return false; } } y_pos += y_pitch; } // U and V size_t chroma_width = frame->GetChromaWidth(); size_t chroma_height = frame->GetChromaHeight(); const uint8_t* u_plane = frame->GetUPlane(); const uint8_t* v_plane = frame->GetVPlane(); const uint8_t* u_pos = u_plane; const uint8_t* v_pos = v_plane; int32_t u_pitch = frame->GetUPitch(); int32_t v_pitch = frame->GetVPitch(); for (size_t i = 0; i < chroma_height; ++i) { for (size_t j = 0; j < chroma_width; ++j) { uint8_t u_value = *(u_pos + j); if (u_value < u_min || u_value > u_max) { return false; } uint8_t v_value = *(v_pos + j); if (v_value < v_min || v_value > v_max) { return false; } } u_pos += u_pitch; v_pos += v_pitch; } return true; } int errors_; int width_; int height_; int num_set_sizes_; int num_rendered_frames_; bool black_frame_; mutable rtc::CriticalSection crit_; }; } // namespace cricket #endif // TALK_MEDIA_BASE_FAKEVIDEORENDERER_H_