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:
parent
3ee13e4ac2
commit
e001b57d84
@ -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,
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user