Do not hold a lock when calling VCMReceiveCallback::FrameToRender.

DecodedImageCallback is allowed to be called on a thread different from decoding thread. To avoid the deadlock in VCMDecodedFrameCallback::Decoded, VCMDecodedFrameCallback::_critSect  should not be held while calling VCMReceiveCallback::FrameToRender.

BUG=1832
R=stefan@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/1570004

Patch from Wu-Cheng Li <wuchengli@chromium.org>.

git-svn-id: http://webrtc.googlecode.com/svn/trunk@4162 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
fischman@webrtc.org 2013-06-04 03:29:37 +00:00
parent 3ee13e4ac2
commit e001b57d84
2 changed files with 17 additions and 10 deletions

View File

@ -45,9 +45,14 @@ int32_t VCMDecodedFrameCallback::Decoded(I420VideoFrame& decodedImage)
{ {
// TODO(holmer): We should improve this so that we can handle multiple // TODO(holmer): We should improve this so that we can handle multiple
// callbacks from one call to Decode(). // callbacks from one call to Decode().
CriticalSectionScoped cs(_critSect); VCMFrameInformation* frameInfo;
VCMFrameInformation* frameInfo = static_cast<VCMFrameInformation*>( VCMReceiveCallback* callback;
_timestampMap.Pop(decodedImage.timestamp())); {
CriticalSectionScoped cs(_critSect);
frameInfo = static_cast<VCMFrameInformation*>(
_timestampMap.Pop(decodedImage.timestamp()));
callback = _receiveCallback;
}
if (frameInfo == NULL) if (frameInfo == NULL)
{ {
// The map should never be empty or full if this callback is called. // The map should never be empty or full if this callback is called.
@ -59,11 +64,10 @@ int32_t VCMDecodedFrameCallback::Decoded(I420VideoFrame& decodedImage)
frameInfo->decodeStartTimeMs, frameInfo->decodeStartTimeMs,
_clock->TimeInMilliseconds()); _clock->TimeInMilliseconds());
if (_receiveCallback != NULL) if (callback != NULL)
{ {
_frame.SwapFrame(&decodedImage); decodedImage.set_render_time_ms(frameInfo->renderTimeMs);
_frame.set_render_time_ms(frameInfo->renderTimeMs); int32_t callbackReturn = callback->FrameToRender(decodedImage);
int32_t callbackReturn = _receiveCallback->FrameToRender(_frame);
if (callbackReturn < 0) if (callbackReturn < 0)
{ {
WEBRTC_TRACE(webrtc::kTraceDebug, WEBRTC_TRACE(webrtc::kTraceDebug,

View File

@ -48,12 +48,12 @@ public:
int32_t Pop(uint32_t timestamp); int32_t Pop(uint32_t timestamp);
private: private:
// Protect |_receiveCallback| and |_timestampMap|.
CriticalSectionWrapper* _critSect; CriticalSectionWrapper* _critSect;
Clock* _clock; Clock* _clock;
I420VideoFrame _frame; VCMReceiveCallback* _receiveCallback; // Guarded by |_critSect|.
VCMReceiveCallback* _receiveCallback;
VCMTiming& _timing; VCMTiming& _timing;
VCMTimestampMap _timestampMap; VCMTimestampMap _timestampMap; // Guarded by |_critSect|.
uint64_t _lastReceivedPictureID; uint64_t _lastReceivedPictureID;
}; };
@ -98,6 +98,9 @@ public:
int32_t SetCodecConfigParameters(const uint8_t* /*buffer*/, int32_t SetCodecConfigParameters(const uint8_t* /*buffer*/,
int32_t /*size*/); int32_t /*size*/);
/**
* Set decode callback. Deregistering while decoding is illegal.
*/
int32_t RegisterDecodeCompleteCallback(VCMDecodedFrameCallback* callback); int32_t RegisterDecodeCompleteCallback(VCMDecodedFrameCallback* callback);
bool External() const; bool External() const;