Index: content/common/gpu/client/gpu_video_encode_accelerator_host.cc |
diff --git a/content/common/gpu/client/gpu_video_encode_accelerator_host.cc b/content/common/gpu/client/gpu_video_encode_accelerator_host.cc |
index 36d99e80efb3e571540a808ac981f6fe8bb2916c..edfb7b6349bf9c7fc91157ac7c4e29bcb520a7b4 100644 |
--- a/content/common/gpu/client/gpu_video_encode_accelerator_host.cc |
+++ b/content/common/gpu/client/gpu_video_encode_accelerator_host.cc |
@@ -177,6 +177,12 @@ void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers( |
void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32 frame_id) { |
DVLOG(3) << "OnNotifyInputDone(): frame_id=" << frame_id; |
+ // Fun-fact: std::hash_map is not spec'd to be re-entrant; since freeing a |
+ // frame can trigger a further encode to be kicked off and thus an .insert() |
+ // back into the map, we separate the frame's dtor running from the .erase() |
+ // running by holding on to the frame temporarily. This isn't "just |
+ // theoretical" - Android's std::hash_map crashes if we don't do this. |
+ scoped_refptr<media::VideoFrame> frame = frame_map_[frame_id]; |
if (!frame_map_.erase(frame_id)) { |
DLOG(ERROR) << "OnNotifyInputDone(): " |
"invalid frame_id=" << frame_id; |
@@ -185,6 +191,7 @@ void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32 frame_id) { |
OnNotifyError(kPlatformFailureError); |
return; |
} |
+ frame = NULL; // Not necessary but nice to be explicit; see fun-fact above. |
} |
void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady( |