/*NOTE: when starting/stoping a decoder we only lock the decoder mutex, NOT the media manager. This avoids deadlocking in case a system codec waits for the scene graph and the compositor requests a stop/start on a media*/ void gf_term_start_codec(GF_Codec *codec, Bool is_resume) { GF_CodecCapability cap; CodecEntry *ce; GF_Terminal *term = codec->odm->term; if (!gf_list_count(codec->odm->channels)) return; ce = mm_get_codec(term->codecs, codec); if (!ce) return; /*lock dec*/ if (ce->mx) gf_mx_p(ce->mx); /*clean decoder memory and wait for RAP*/ if (codec->CB) gf_cm_reset(codec->CB); if (!is_resume) { cap.CapCode = GF_CODEC_WAIT_RAP; gf_codec_set_capability(codec, cap); if (codec->decio && (codec->decio->InterfaceType == GF_SCENE_DECODER_INTERFACE)) { cap.CapCode = GF_CODEC_SHOW_SCENE; cap.cap.valueInt = 1; gf_codec_set_capability(codec, cap); } } gf_codec_set_status(codec, GF_ESM_CODEC_PLAY); if (!(ce->flags & GF_MM_CE_RUNNING)) { ce->flags |= GF_MM_CE_RUNNING; if (ce->thread) { gf_th_run(ce->thread, RunSingleDec, ce); gf_th_set_priority(ce->thread, term->priority); } else { term->cumulated_priority += ce->dec->Priority+1; } } /*unlock dec*/ if (ce->mx) gf_mx_v(ce->mx); }
void gf_term_stop_codec(GF_Codec *codec, Bool is_pause) { GF_CodecCapability cap; Bool locked = 0; CodecEntry *ce; GF_Terminal *term = codec->odm->term; ce = mm_get_codec(term->codecs, codec); if (!ce) return; if (ce->mx) gf_mx_p(ce->mx); /*We must make sure: 1- media codecs are synchrounously stop otherwise we could destroy the composition memory while the codec writes to it 2- prevent deadlock for other codecs waiting for the scene graph */ else if (codec->CB) { locked = 1; gf_mx_p(term->mm_mx); } else { locked = gf_mx_try_lock(term->mm_mx); } if (!is_pause) { cap.CapCode = GF_CODEC_ABORT; cap.cap.valueInt = 0; gf_codec_set_capability(codec, cap); if (codec->decio && codec->odm->mo && (codec->odm->mo->flags & GF_MO_DISPLAY_REMOVE) ) { cap.CapCode = GF_CODEC_SHOW_SCENE; cap.cap.valueInt = 0; gf_codec_set_capability(codec, cap); codec->odm->mo->flags &= ~GF_MO_DISPLAY_REMOVE; } } /*for audio codec force CB to stop state to discard any pending AU. Not doing so would lead to a wrong estimation of the clock drift when resuming the object*/ if (codec->type==GF_STREAM_AUDIO) { gf_codec_set_status(codec, GF_ESM_CODEC_STOP); } //if video is in a dynamic scene, reset the CB if user stop (eg codec was not in EOS). Otherwise (bifs,svg) we may want to keep the last decoded image else if ((codec->Status<GF_ESM_CODEC_EOS) && codec->odm && codec->odm->parentscene && codec->odm->parentscene->is_dynamic_scene && codec->CB && (codec->CB->Capacity>1)) { gf_codec_set_status(codec, GF_ESM_CODEC_STOP); } /*otherwise set status directly and don't touch CB state*/ else { codec->Status = GF_ESM_CODEC_STOP; } /*don't wait for end of thread since this can be triggered within the decoding thread*/ if (ce->flags & GF_MM_CE_RUNNING) { ce->flags &= ~GF_MM_CE_RUNNING; if (!ce->thread) term->cumulated_priority -= codec->Priority+1; } if (codec->CB) gf_cm_abort_buffering(codec->CB); if (ce->mx) gf_mx_v(ce->mx); /*cf note above*/ else if (locked) gf_mx_v(term->mm_mx); }