diff --git a/talk/media/base/videoframe.h b/talk/media/base/videoframe.h index 56621ad5a4..2e9a01bfc1 100644 --- a/talk/media/base/videoframe.h +++ b/talk/media/base/videoframe.h @@ -132,9 +132,14 @@ class VideoFrame { virtual VideoFrame *Copy() const = 0; // Since VideoFrame supports shallow copy and the internal frame buffer might - // be shared, in case VideoFrame needs exclusive access of the frame buffer, - // user can call MakeExclusive() to make sure the frame buffer is exclusive - // accessable to the current object. This might mean a deep copy of the frame + // be shared, this function can be used to check exclusive ownership. The + // default implementation is conservative and returns false. Subclasses with + // knowledge of implementation specific details can override this. + virtual bool IsExclusive() const { return false; } + + // In case VideoFrame needs exclusive access of the frame buffer, user can + // call MakeExclusive() to make sure the frame buffer is exclusively + // accessible to the current object. This might mean a deep copy of the frame // buffer if it is currently shared by other objects. virtual bool MakeExclusive() = 0; diff --git a/talk/media/base/videoframefactory.cc b/talk/media/base/videoframefactory.cc index b4725cdd8e..147f1faf81 100644 --- a/talk/media/base/videoframefactory.cc +++ b/talk/media/base/videoframefactory.cc @@ -46,9 +46,9 @@ VideoFrame* VideoFrameFactory::CreateAliasedFrame( return cropped_input_frame.release(); } - // Create and stretch the output frame if it has not been created yet or its - // size is not same as the expected. - if (!output_frame_ || + // Create and stretch the output frame if it has not been created yet, is + // still in use by others, or its size is not same as the expected. + if (!output_frame_ || !output_frame_->IsExclusive() || output_frame_->GetWidth() != static_cast(output_width) || output_frame_->GetHeight() != static_cast(output_height)) { output_frame_.reset( diff --git a/talk/media/webrtc/webrtcvideoframe.cc b/talk/media/webrtc/webrtcvideoframe.cc index 9764f31af5..0b1d4a8194 100644 --- a/talk/media/webrtc/webrtcvideoframe.cc +++ b/talk/media/webrtc/webrtcvideoframe.cc @@ -244,7 +244,15 @@ VideoFrame* WebRtcVideoFrame::Copy() const { return ret_val; } +bool WebRtcVideoFrame::IsExclusive() const { + return video_buffer_->HasOneRef(); +} + bool WebRtcVideoFrame::MakeExclusive() { + if (IsExclusive()) + return true; + + // Not exclusive already, need to copy. const size_t length = video_buffer_->length(); RefCountedBuffer* exclusive_buffer = new RefCountedBuffer(length); memcpy(exclusive_buffer->data(), video_buffer_->data(), length); diff --git a/talk/media/webrtc/webrtcvideoframe.h b/talk/media/webrtc/webrtcvideoframe.h index 4de12b224c..2e34d67ee9 100644 --- a/talk/media/webrtc/webrtcvideoframe.h +++ b/talk/media/webrtc/webrtcvideoframe.h @@ -137,6 +137,7 @@ class WebRtcVideoFrame : public VideoFrame { } virtual VideoFrame* Copy() const; + virtual bool IsExclusive() const; virtual bool MakeExclusive(); virtual size_t ConvertToRgbBuffer(uint32 to_fourcc, uint8* buffer, size_t size, int stride_rgb) const;