@@ -66,13 +66,17 @@ class DroidVideoDecoder : public GMPVideoDecoder
66
66
err = g_platform_api->createmutex (&m_stop_lock);
67
67
if (GMP_FAILED (err))
68
68
Error (err);
69
+ err = g_platform_api->createmutex (&m_drain_lock);
70
+ if (GMP_FAILED (err))
71
+ Error (err);
69
72
}
70
73
71
74
virtual ~DroidVideoDecoder ()
72
75
{
73
76
// Destroy the Mutex
74
77
m_codec_lock->Destroy ();
75
78
m_stop_lock->Destroy ();
79
+ m_drain_lock->Destroy ();
76
80
}
77
81
78
82
// GMPVideoDecoder methods
@@ -240,32 +244,43 @@ class DroidVideoDecoder : public GMPVideoDecoder
240
244
void SubmitBufferThread (DroidMediaCodecData cdata,
241
245
DroidMediaBufferCallbacks cb)
242
246
{
243
-
247
+ m_drain_lock-> Acquire ();
244
248
if (m_draining || (!m_codec && !CreateCodec ())) {
249
+ LOG (ERROR, " Buffer submitted while draining" );
245
250
cb.unref (cb.data );
251
+ m_drain_lock->Release ();
246
252
return ;
247
253
}
254
+ m_drain_lock->Release ();
255
+
256
+ // This blocks when the input Source is full
248
257
droid_media_codec_queue (m_codec, &cdata, &cb);
249
258
259
+ m_drain_lock->Acquire ();
250
260
if (!m_draining && m_callback && g_platform_api) {
251
261
g_platform_api->runonmainthread (WrapTask (m_callback,
252
262
&GMPVideoDecoderCallback::InputDataExhausted));
253
263
}
264
+ m_drain_lock->Release ();
254
265
}
255
266
256
267
virtual void Reset ()
257
268
{
258
269
m_stop_lock->Acquire ();
259
270
if (m_resetting) {
260
- m_stop_lock->Release ();
261
- return ;
271
+ m_stop_lock->Release ();
272
+ return ;
262
273
}
263
274
m_resetting = true ;
264
275
m_stop_lock->Release ();
265
276
266
277
if (m_codec) {
267
278
ResetCodec ();
268
279
}
280
+ m_drain_lock->Acquire ();
281
+ m_draining = false ;
282
+ m_drain_lock->Release ();
283
+ m_resetting = false ;
269
284
m_callback->ResetComplete ();
270
285
}
271
286
@@ -276,11 +291,14 @@ class DroidVideoDecoder : public GMPVideoDecoder
276
291
}
277
292
278
293
// TODO: This never happens because the codec never really drains, except for EOS
294
+ m_drain_lock->Acquire ();
279
295
if (!m_codec || m_dur.size () == 0 ) {
280
296
m_callback->DrainComplete ();
297
+ m_draining = false ;
281
298
} else {
282
- m_draining = true ;
299
+ m_draining = true ;
283
300
}
301
+ m_drain_lock->Release ();
284
302
}
285
303
286
304
virtual void DecodingComplete ()
@@ -316,9 +334,10 @@ class DroidVideoDecoder : public GMPVideoDecoder
316
334
cb.data_available = DataAvailable;
317
335
droid_media_codec_set_data_callbacks (m_codec, &cb, this );
318
336
}
319
-
320
337
// Reset state
338
+ m_drain_lock->Acquire ();
321
339
m_draining = false ;
340
+ m_drain_lock->Release ();
322
341
323
342
if (!droid_media_codec_start (m_codec)) {
324
343
droid_media_codec_destroy (m_codec);
@@ -382,7 +401,6 @@ class DroidVideoDecoder : public GMPVideoDecoder
382
401
m_dur.clear ();
383
402
RequestNewConverter ();
384
403
m_codec_lock->Release ();
385
- m_resetting = false ;
386
404
}
387
405
388
406
void ProcessFrameLock (DroidMediaCodecData * decoded)
@@ -460,12 +478,15 @@ class DroidVideoDecoder : public GMPVideoDecoder
460
478
// Send the new frame back to Gecko
461
479
m_callback->Decoded (frame);
462
480
LOG (DEBUG, " ProcessFrame: Returning frame ts: " << ts << " dur: " << dur);
481
+ m_drain_lock->Acquire ();
463
482
if (m_dur.size () == 0 && m_draining) {
464
- // TODO: we never get the buffers down to 0 with the current SimpleDecodingSource, but EOS will do it
465
- m_callback->DrainComplete ();
483
+ // TODO: we never get the buffers down to 0 with the current SimpleDecodingSource, but EOS will do it
484
+ m_callback->DrainComplete ();
485
+ m_draining = false ;
466
486
} else {
467
487
LOG (DEBUG, " Buffers still out " << m_dur.size ());
468
488
}
489
+ m_drain_lock->Release ();
469
490
}
470
491
471
492
virtual void EOS ()
@@ -494,6 +515,8 @@ class DroidVideoDecoder : public GMPVideoDecoder
494
515
// Stop lock prevents a deadlock when droid_media_codec_loop can't quit during
495
516
// shutdown because it's waiting to get a frame processed on the main thread.
496
517
GMPMutex *m_stop_lock = nullptr ;
518
+ // Drain lock protects the m_draining flag
519
+ GMPMutex *m_drain_lock = nullptr ;
497
520
GMPThread *m_submit_thread = nullptr ;
498
521
DroidMediaCodecDecoderMetaData m_metadata;
499
522
DroidMediaCodec *m_codec = nullptr ;
@@ -558,8 +581,7 @@ GMPErr GMPInit (GMPPlatformAPI * platformAPI)
558
581
GMPErr GMPGetAPI (const char *apiName, void *hostAPI, void **pluginApi)
559
582
{
560
583
if (!strcmp (apiName, " decode-video" )) {
561
- *pluginApi =
562
- new DroidVideoDecoder (static_cast <GMPVideoHost *>(hostAPI));
584
+ *pluginApi = new DroidVideoDecoder (static_cast <GMPVideoHost *>(hostAPI));
563
585
return GMPNoErr;
564
586
}
565
587
return GMPGenericErr;
0 commit comments