📄 decoder.c
字号:
cap.CapCode = GF_CODEC_MEDIA_NOT_OVER; cap.cap.valueInt = 0; sdec->GetCapabilities(codec->decio, &cap); if (!cap.cap.valueInt) { gf_term_stop_codec(codec); if ((codec->type==GF_STREAM_OD) && (codec->nb_dec_frames==1)) { /*this is just by safety, since seeking is only allowed when a single clock is present in the scene*/ if (gf_list_count(codec->odm->net_service->Clocks)==1) codec->odm->subscene->static_media_ressources=1; } } } goto exit; } /*clock is not started*/// if (ch->first_au_fetched && !gf_clock_is_started(ch->clock)) goto exit; /*check timing based on the input channel and main FPS*/// if ( (AU->DTS > obj_time + codec->odm->term->half_frame_duration) ) goto exit; if ( (AU->DTS > obj_time ) ) goto exit; /*check seeking and update timing - do NOT use the base layer, since BIFS streams may depend on other streams not on the same clock*/ if (codec->last_unit_cts == AU->CTS ) { /*hack for RTSP streaming of systems streams, except InputSensor*/ if (!ch->is_pulling && (codec->type != GF_STREAM_INTERACT) && (AU->dataLength == codec->prev_au_size)) { gf_es_drop_au(ch); GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[Decoder] Same MPEG-4 Systems AU detected - dropping\n")); goto check_unit; } /*seeking for systems is done by not releasing the graph until seek is done*/ check_next_unit = 1; mm_level = GF_CODEC_LEVEL_SEEK; au_time = AU->DTS; } /*set system stream timing*/ else { codec->last_unit_cts = AU->CTS; /*we're droping the frame*/ if (scene_locked) codec->nb_droped ++; mm_level = GF_CODEC_LEVEL_NORMAL; au_time = AU->DTS; } /*lock scene*/ if (!scene_locked) { gf_term_lock_renderer(codec->odm->term, 1); scene_locked = 1; /*if terminal is paused, force step-mode: it won't hurt in regular pause/play and ensures proper frame dumping*/ if (codec->odm->term->play_state) codec->odm->term->renderer->step_mode=1; } /*current media time for system objects is the clock time, since the media is likely to have random updates in time*/ codec->odm->current_time = gf_clock_time(codec->ck); now = gf_term_get_time(codec->odm->term); e = sdec->ProcessData(sdec, AU->data, AU->dataLength, ch->esd->ESID, au_time, mm_level); now = gf_term_get_time(codec->odm->term) - now; GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SysDec] Codec %s Processing AU CTS %d\n", sdec->module_name , AU->CTS)); codec_update_stats(codec, AU->dataLength, now); codec->prev_au_size = AU->dataLength; /*destroy this AU*/ gf_es_drop_au(ch); if (e) { ch->stream_state = 2; goto exit; } /*OD acts as scene codec, regenerate scene*/ if (codec->flags & GF_ESM_CODEC_IS_SCENE_OD) gf_is_regenerate(codec->odm->subscene ? codec->odm->subscene : codec->odm->parentscene); /*in broadcast mode, generate a scene if none is available*/ else if (codec->ck->no_time_ctrl) { GF_InlineScene *is = codec->odm->subscene ? codec->odm->subscene : codec->odm->parentscene; /*static OD resources (embedded in ESD) in broadcast mode, reset time*/ if (codec->flags & GF_ESM_CODEC_IS_STATIC_OD) gf_clock_reset(codec->ck); /*generate a temp scene if none is in place*/ if (is->graph_attached != 1 ) { Bool prev_dyn = is->is_dynamic_scene; is->is_dynamic_scene = 1; gf_is_regenerate(is); is->graph_attached = 2; is->is_dynamic_scene = prev_dyn; GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[Decoder] Got OD resources before scene - generating temporary scene\n")); } } /*if no release restart*/ if (check_next_unit) goto check_unit; exit: if (scene_locked) gf_term_lock_renderer(codec->odm->term, 0); return e;}/*special handling of decoders not using ESM*/static GF_Err PrivateScene_Process(GF_Codec *codec, u32 TimeAvailable){ Bool resume_clock; u32 now; GF_Channel *ch; GF_SceneDecoder *sdec = (GF_SceneDecoder *)codec->decio; GF_Err e = GF_OK; /*muting systems codec means we don't decode until mute is off - likely there will be visible however there is no other way to decode system AUs without modifying the content, which is what mute is about on visual...*/ if (codec->Muted) return GF_OK; if (codec->Status == GF_ESM_CODEC_EOS) { gf_term_stop_codec(codec); return GF_OK; } ch = (GF_Channel*)gf_list_get(codec->inChannels, 0); if (!ch) return GF_OK; resume_clock = 0; /*init channel clock*/ if (!ch->IsClockInit) { gf_es_init_dummy(ch); if (!gf_clock_is_started(ch->clock)) return GF_OK; /*let's be nice to the scene loader (that usually involves quite some parsing), pause clock while parsing*/ gf_clock_pause(ch->clock); codec->last_unit_dts = 0; } codec->odm->current_time = codec->last_unit_cts = gf_clock_time(codec->ck); /*lock scene*/ gf_term_lock_renderer(codec->odm->term, 1); now = gf_term_get_time(codec->odm->term); e = sdec->ProcessData(sdec, NULL, codec->odm->current_time, ch->esd->ESID, codec->odm->current_time, GF_CODEC_LEVEL_NORMAL); now = gf_term_get_time(codec->odm->term) - now; codec->last_unit_dts ++; /*resume on error*/ if (e && (codec->last_unit_dts<2) ) { gf_clock_resume(ch->clock); codec->last_unit_dts = 2; } /*resume clock on 2nd decode (we assume parsing is done in 2 steps, one for first frame display, one for complete parse)*/ else if (codec->last_unit_dts==2) { gf_clock_resume(ch->clock); } codec_update_stats(codec, 0, now); gf_term_lock_renderer(codec->odm->term, 0); if (e==GF_EOS) { /*first end of stream, evaluate duration*/ if (!codec->odm->duration) gf_odm_set_duration(codec->odm, ch, codec->odm->current_time); gf_es_on_eos(ch); return GF_OK; } return e;}/*Get a pointer to the next CU buffer*/static GFINLINE GF_Err LockCompositionUnit(GF_Codec *dec, u32 CU_TS, char **outBuffer, u32 *availableSize){ GF_CMUnit *cu; *outBuffer = NULL; *availableSize = 0; if (!dec->CB) return GF_BAD_PARAM; cu = gf_cm_lock_input(dec->CB, CU_TS); if (!cu ) return GF_OUT_OF_MEM; cu->TS = CU_TS; *outBuffer = cu->data; *availableSize = dec->CB->UnitSize; return GF_OK;}static GFINLINE GF_Err UnlockCompositionUnit(GF_Codec *dec, u32 CTS, u32 NbBytes){ /*temporal scalability disabling: if we already rendered this, no point getting further*/ if (CTS < dec->CB->LastRenderedTS) NbBytes = 0; /*unlock the CB*/ gf_cm_unlock_input(dec->CB, CTS, NbBytes); return GF_OK;}static GF_Err ResizeCompositionBuffer(GF_Codec *dec, u32 NewSize){ if (!dec || !dec->CB) return GF_BAD_PARAM; /*update config*/ MO_UpdateCaps(dec->odm->mo); /*bytes per sec not available: either video or audio not configured*/ if (!dec->bytes_per_sec) { if (NewSize && (NewSize != dec->CB->UnitSize) ) gf_cm_resize(dec->CB, NewSize); } /*audio: make sure we have enough data in CM to entirely fill the HW audio buffer...*/ else { u32 unit_size, audio_buf_len, unit_count; GF_CodecCapability cap; unit_size = NewSize; /*a bit ugly, make some extra provision for speed >1. this is the drawback of working with pre-allocated memory for composition, we may get into cases where there will never be enough data for high speeds... FIXME - WE WILL NEED TO MOVE TO DYNAMIC CU BLOCKS IN ORDER TO SUPPORT ANY SPEED, BUT WHAT IS THE IMPACT FOR LOW RESOURCES DEVICES ??*/// audio_buf_len = 1000; audio_buf_len = 200; cap.CapCode = GF_CODEC_BUFFER_MAX; gf_codec_get_capability(dec, &cap); unit_count = cap.cap.valueInt; /*at least 2 units for dec and render ...*/ if (unit_count<2) unit_count = 2; while (unit_size*unit_count*1000 < dec->bytes_per_sec*audio_buf_len) unit_count++;#ifdef __SYMBIAN32__ /*FIXME - symbian tests*/ unit_count = 10;#endif gf_cm_reinit(dec->CB, unit_size, unit_count); dec->CB->Min = unit_count/3; if (!dec->CB->Min) dec->CB->Min = 1; } if ((dec->type==GF_STREAM_VISUAL) && dec->odm->parentscene->is_dynamic_scene) { gf_is_force_scene_size_video(dec->odm->parentscene, dec->odm->mo); } return GF_OK;}static GF_Err MediaCodec_Process(GF_Codec *codec, u32 TimeAvailable){ GF_DBUnit *AU; GF_Channel *ch; char *cu_buf; u32 cu_buf_size, mmlevel; u32 first, entryTime, now, obj_time; GF_MediaDecoder *mdec = (GF_MediaDecoder*)codec->decio; GF_Err e = GF_OK; /*if video codec muted don't decode (try to saves ressources) if audio codec muted we dispatch to keep sync in place*/ if (codec->Muted && (codec->type==GF_STREAM_VISUAL) ) return GF_OK; entryTime = gf_term_get_time(codec->odm->term); /*fetch next AU in DTS order for this codec*/ Decoder_GetNextAU(codec, &ch, &AU); /*no active channel return*/ if (!AU || !ch) { /*if the codec is in EOS state, assume we're done*/ if (codec->Status == GF_ESM_CODEC_EOS) { /*if codec is reordering, try to flush it*/ if (codec->is_reordering) { if ( LockCompositionUnit(codec, codec->last_unit_cts+1, &cu_buf, &cu_buf_size) == GF_OUT_OF_MEM) return GF_OK; e = mdec->ProcessData(mdec, NULL, 0, 0, cu_buf, &cu_buf_size, 0, 0); if (e==GF_OK) e = UnlockCompositionUnit(codec, codec->last_unit_cts+1, cu_buf_size); } gf_term_stop_codec(codec); if (codec->CB) gf_cm_set_eos(codec->CB); } /*if no data, and channel not buffering, ABORT CB buffer (data timeout or EOS not detectable)*/ else if (ch && !ch->BufferOn) gf_cm_abort_buffering(codec->CB); return GF_OK; } /*get the object time*/ obj_time = gf_clock_time(codec->ck); /*Media Time for media codecs is updated in the CB*/ if (!codec->CB) { gf_es_drop_au(ch); return GF_BAD_PARAM; } /*image codecs - usually only one image is tolerated in the stream, but just in case force reset of CB*/ if ((codec->CB->Capacity==1) && codec->CB->UnitCount && (obj_time>=AU->CTS)) { codec->CB->output->dataLength = 0; codec->CB->UnitCount = 0; } /*try to refill the full buffer*/ first = 1; while (codec->CB->Capacity > codec->CB->UnitCount) { /*set media processing level*/ mmlevel = GF_CODEC_LEVEL_NORMAL; /*SEEK: if the last frame had the same TS, we are seeking. Ask the codec to drop*/ if (!ch->skip_sl && codec->last_unit_cts && (codec->last_unit_cts == AU->CTS) && !ch->esd->dependsOnESID) { mmlevel = GF_CODEC_LEVEL_SEEK; /*object clock is paused by media control or terminal is paused: exact frame seek*/ if ((codec->ck->mc && codec->ck->mc->paused) || (codec->odm->term->play_state)) { gf_cm_rewind_input(codec->CB); mmlevel = GF_CODEC_LEVEL_NORMAL; /*force staying in step-mode*/ codec->odm->term->renderer->step_mode=1; } } /*only perform drop in normal playback*/ else if (codec->CB->Status == CB_PLAY) { /*extremely late, set the level to drop NOTE: the 100 ms safety gard is to avoid discarding audio*/ if (!ch->skip_sl && (AU->CTS + 100 < obj_time) ) { mmlevel = GF_CODEC_LEVEL_DROP; GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[Decoder] ODM%d: frame too late (%d vs %d) - using drop level\n", codec->odm->OD->objectDescriptorID, AU->CTS, obj_time)); } /*we are late according to the media manager*/ else if (codec->PriorityBoost) { mmlevel = GF_CODEC_LEVEL_VERY_LATE; } /*otherwise we must have an idea of the load in order to set the right level use the composition buffer for that, only on the first frame*/ else if (first) { //if the CB is almost empty set to very late if (codec->CB->UnitCount <= codec->CB->Min+1) { mmlevel = GF_CODEC_LEVEL_VERY_LATE; } else if (codec->CB->UnitCount * 2 <= codec->CB->Capacity) { mmlevel = GF_CODEC_LEVEL_LATE; } first = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -