📄 decoder.c
字号:
} } /*when using temporal scalability make sure we can decode*/ if (ch->esd->dependsOnESID && (codec->last_unit_dts > AU->DTS)){// printf("SCALABLE STREAM DEAD!!\n"); goto drop; } if (ch->skip_sl) { if (codec->bytes_per_sec) { AU->CTS = codec->last_unit_cts + ch->ts_offset + codec->cur_audio_bytes * 1000 / codec->bytes_per_sec; } else if (codec->fps) { AU->CTS = codec->last_unit_cts + ch->ts_offset + (u32) (codec->cur_video_frames * 1000 / codec->fps); } } if ( LockCompositionUnit(codec, AU->CTS, &cu_buf, &cu_buf_size) == GF_OUT_OF_MEM) return GF_OK; now = gf_term_get_time(codec->odm->term); e = mdec->ProcessData(mdec, AU->data, AU->dataLength, ch->esd->ESID, cu_buf, &cu_buf_size, AU->PaddingBits, mmlevel); now = gf_term_get_time(codec->odm->term) - now; /*input is too small, resize composition memory*/ switch (e) { case GF_BUFFER_TOO_SMALL: /*release but no dispatch*/ UnlockCompositionUnit(codec, AU->CTS, 0); if (ResizeCompositionBuffer(codec, cu_buf_size)==GF_OK) continue; break; case GF_OK: /*in seek don't dispatch any output*/ if (mmlevel == GF_CODEC_LEVEL_SEEK) cu_buf_size = 0; e = UnlockCompositionUnit(codec, AU->CTS, cu_buf_size); codec_update_stats(codec, AU->dataLength, now); if (ch->skip_sl) { if (codec->bytes_per_sec) { codec->cur_audio_bytes += cu_buf_size; while (codec->cur_audio_bytes>codec->bytes_per_sec) { codec->cur_audio_bytes -= codec->bytes_per_sec; codec->last_unit_cts += 1000; } } else if (codec->fps && cu_buf_size) { codec->cur_video_frames += 1; } } GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[Decoder %s] ODM%d: decoded frame TS %d in %d ms\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID, AU->CTS, now)); break; /*this happens a lot when using non-MPEG-4 streams (ex: ffmpeg demuxer)*/ case GF_PACKED_FRAMES: /*in seek don't dispatch any output*/ if (mmlevel == GF_CODEC_LEVEL_SEEK) cu_buf_size = 0; e = UnlockCompositionUnit(codec, AU->CTS, cu_buf_size); if (ch->skip_sl) { if (codec->bytes_per_sec) { codec->cur_audio_bytes += cu_buf_size; } else if (codec->fps && cu_buf_size) { codec->cur_video_frames += 1; } } else { u32 deltaTS = 0; if (codec->bytes_per_sec) { deltaTS = cu_buf_size * 1000 / codec->bytes_per_sec; } else if (codec->fps && cu_buf_size) { deltaTS = (u32) (1000.0f / codec->fps); } //AU->DTS += deltaTS; AU->CTS += deltaTS; } codec_update_stats(codec, 0, now); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[Decoder] ODM%d: decoded packed frame TS %d in %d ms\n", codec->odm->OD->objectDescriptorID, AU->CTS, now)); continue; default: UnlockCompositionUnit(codec, AU->CTS, 0); /*error - if the object is in intitial buffering resume it!!*/ gf_cm_abort_buffering(codec->CB); break; } codec->last_unit_dts = AU->DTS; /*remember base layer timing*/ if (!ch->esd->dependsOnESID && !ch->skip_sl) codec->last_unit_cts = AU->CTS;drop: gf_es_drop_au(ch); if (e) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[Decoder %s] ODM%d: decoded error %s\n", codec->decio->module_name, codec->odm->OD->objectDescriptorID, gf_error_to_string(e) )); return e; } /*escape from decoding loop only if above critical limit - this is to avoid starvation on audio*/ if (codec->CB->UnitCount > codec->CB->Min) { now = gf_term_get_time(codec->odm->term); if (now - entryTime >= TimeAvailable - TIME_CHECK) { return GF_OK; } } Decoder_GetNextAU(codec, &ch, &AU); if (!ch || !AU) return GF_OK; } return GF_OK;}GF_Err gf_codec_process(GF_Codec *codec, u32 TimeAvailable){ if (codec->Status == GF_ESM_CODEC_STOP) return GF_OK; codec->Muted = (codec->odm->media_ctrl && codec->odm->media_ctrl->control->mute) ? 1 : 0; /*OCR: needed for OCR in pull mode (dummy streams used to sync various sources)*/ if (codec->type==GF_STREAM_OCR) { GF_DBUnit *AU; GF_Channel *ch; /*fetch next AU on OCR (empty AUs)*/ Decoder_GetNextAU(codec, &ch, &AU); /*no active channel return*/ if (!AU || !ch) { /*if the codec is in EOS state, move to STOP*/ if (codec->Status == GF_ESM_CODEC_EOS) { gf_term_stop_codec(codec); /*if a mediacontrol is ruling this OCR*/ if (codec->odm->media_ctrl && codec->odm->media_ctrl->control->loop) MC_Restart(codec->odm); } } } /*special case here (we tweak a bit the timing)*/ else if (codec->type==GF_STREAM_PRIVATE_SCENE) { return PrivateScene_Process(codec, TimeAvailable); } else if (codec->decio->InterfaceType==GF_MEDIA_DECODER_INTERFACE) { return MediaCodec_Process(codec, TimeAvailable); } else if (codec->decio->InterfaceType==GF_SCENE_DECODER_INTERFACE) { return SystemCodec_Process(codec, TimeAvailable); } return GF_OK;}GF_Err gf_codec_get_capability(GF_Codec *codec, GF_CodecCapability *cap){ cap->cap.valueInt = 0; if (!codec->decio) return GF_OK; return codec->decio->GetCapabilities(codec->decio, cap);}GF_Err gf_codec_set_capability(GF_Codec *codec, GF_CodecCapability cap){ if (!codec->decio) return GF_OK; return codec->decio->SetCapabilities(codec->decio, cap);}void gf_codec_set_status(GF_Codec *codec, u32 Status){ if (!codec) return; if (Status == GF_ESM_CODEC_PAUSE) codec->Status = GF_ESM_CODEC_STOP; else if (Status == GF_ESM_CODEC_BUFFER) codec->Status = GF_ESM_CODEC_PLAY; else if (Status == GF_ESM_CODEC_PLAY) { codec->last_unit_cts = 0; codec->prev_au_size = 0; codec->Status = Status; codec->last_stat_start = codec->cur_bit_size = codec->max_bit_rate = codec->avg_bit_rate = 0; codec->nb_dec_frames = codec->total_dec_time = codec->max_dec_time = 0; codec->cur_audio_bytes = codec->cur_video_frames = 0; codec->nb_droped = 0; } else codec->Status = Status; if (!codec->CB) return; /*notify CB*/ switch (Status) { case GF_ESM_CODEC_PLAY: gf_cm_set_status(codec->CB, CB_PLAY); return; case GF_ESM_CODEC_PAUSE: gf_cm_set_status(codec->CB, CB_PAUSE); return; case GF_ESM_CODEC_STOP: gf_cm_set_status(codec->CB, CB_STOP); return; case GF_ESM_CODEC_EOS: /*do NOT notify CB yet, wait till last AU is decoded*/ return; case GF_ESM_CODEC_BUFFER: default: return; }}static GF_Err Codec_LoadModule(GF_Codec *codec, GF_ESD *esd, u32 PL){ char szPrefDec[500]; const char *sOpt; GF_BaseDecoder *ifce; u32 i, plugCount; u32 ifce_type; char *cfg; u32 cfg_size; GF_Terminal *term = codec->odm->term; if (esd->decoderConfig->decoderSpecificInfo) { cfg = esd->decoderConfig->decoderSpecificInfo->data; cfg_size = esd->decoderConfig->decoderSpecificInfo->dataLength; } else { cfg = NULL; cfg_size = 0; } ifce_type = GF_SCENE_DECODER_INTERFACE; if ((esd->decoderConfig->streamType==GF_STREAM_AUDIO) || (esd->decoderConfig->streamType==GF_STREAM_VISUAL) || (esd->decoderConfig->streamType==GF_STREAM_ND_SUBPIC) ) ifce_type = GF_MEDIA_DECODER_INTERFACE; /*a bit dirty, if FFMPEG is used for demuxer load it for decoder too*/ if (0 && !stricmp(codec->odm->net_service->ifce->module_name, "FFMPEG demuxer")) { sOpt = "FFMPEG decoder"; } else { /*use user-defined module if any*/ sOpt = NULL; switch (esd->decoderConfig->streamType) { case GF_STREAM_VISUAL: if ((esd->decoderConfig->objectTypeIndication==0x6C) || (esd->decoderConfig->objectTypeIndication==0x6D)) sOpt = gf_cfg_get_key(term->user->config, "Systems", "DefImageDec"); else sOpt = gf_cfg_get_key(term->user->config, "Systems", "DefVideoDec"); break; case GF_STREAM_AUDIO: sOpt = gf_cfg_get_key(term->user->config, "Systems", "DefAudioDec"); break; default: break; } } if (sOpt) { ifce = (GF_BaseDecoder *) gf_modules_load_interface_by_name(term->user->modules, sOpt, ifce_type); if (ifce) { if (ifce->CanHandleStream && ifce->CanHandleStream(ifce, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication, cfg, cfg_size, PL) ) { codec->decio = ifce; return GF_OK; } gf_modules_close_interface((GF_BaseInterface *) ifce); } } /*prefered codec module per streamType/objectType from config*/ sprintf(szPrefDec, "codec_%02x_%02x", esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication); sOpt = gf_cfg_get_key(term->user->config, "Systems", szPrefDec); if (sOpt) { ifce = (GF_BaseDecoder *) gf_modules_load_interface_by_name(term->user->modules, sOpt, ifce_type); if (ifce) { if (ifce->CanHandleStream && ifce->CanHandleStream(ifce, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication, cfg, cfg_size, PL) ) { codec->decio = ifce; return GF_OK; } gf_modules_close_interface((GF_BaseInterface *) ifce); } } /*not found, check all modules*/ plugCount = gf_modules_get_count(term->user->modules); for (i = 0; i < plugCount ; i++) { ifce = (GF_BaseDecoder *) gf_modules_load_interface(term->user->modules, i, ifce_type); if (!ifce) continue; if (ifce->CanHandleStream && ifce->CanHandleStream(ifce, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication, cfg, cfg_size, PL) ) { codec->decio = ifce; return GF_OK; } gf_modules_close_interface((GF_BaseInterface *) ifce); } return GF_CODEC_NOT_FOUND;}GF_Err Codec_Load(GF_Codec *codec, GF_ESD *esd, u32 PL){ switch (esd->decoderConfig->streamType) { /*OCR has no codec, just a channel*/ case GF_STREAM_OCR: codec->decio = NULL; return GF_OK; /*InteractionStream is currently hardcoded*/ case GF_STREAM_INTERACT: codec->decio = (GF_BaseDecoder *) NewISCodec(PL); assert(codec->decio->InterfaceType == GF_SCENE_DECODER_INTERFACE); return GF_OK; /*load decoder module*/ default: return Codec_LoadModule(codec, esd, PL); }}void gf_codec_del(GF_Codec *codec){ if (gf_list_count(codec->inChannels)) return; if (!(codec->flags & GF_ESM_CODEC_IS_USE)) { switch (codec->type) { /*input sensor streams are handled internally for now*/ case GF_STREAM_INTERACT: gf_mx_p(codec->odm->term->net_mx); ISDec_Delete(codec->decio); gf_list_del_item(codec->odm->term->input_streams, codec); gf_mx_v(codec->odm->term->net_mx); break; default: gf_modules_close_interface((GF_BaseInterface *) codec->decio); break; } } if (codec->CB) gf_cm_del(codec->CB); gf_list_del(codec->inChannels); free(codec);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -