📄 channel.c
字号:
if (hdr.randomAccessPointFlag) ch->IsRap = 1; /*check OCR*/ if (hdr.OCRflag) { s64 OCR_TS = (s64) (((s64) hdr.objectClockReference) * ch->ocr_scale); gf_clock_set_time(ch->clock, (u32) OCR_TS); ch->IsClockInit = 1; } /*get AU end state*/ OldLength = ch->buffer ? ch->len : 0; EndAU = hdr.accessUnitEndFlag; if (ch->AULength == OldLength + StreamLength) EndAU = 1; if (EndAU) ch->NextIsAUStart = 1; if (!StreamLength && EndAU && ch->buffer) { GF_LOG(GF_LOG_DEBUG, GF_LOG_SYNC, ("[SyncLayer] ES%d: Empty packet, flushing buffer\n", ch->esd->ESID)); Channel_DispatchAU(ch, 0); return; } if (!StreamLength) return; /*missed begining, unusable*/ if (!ch->buffer && !NewAU) { if (ch->esd->slConfig->useAccessUnitStartFlag) { GF_LOG(GF_LOG_ERROR, GF_LOG_SYNC, ("[SyncLayer] ES%d: missed begin of AU\n", ch->esd->ESID)); } return; } /*Write the Packet payload to the buffer*/ if (NewAU) { /*we should NEVER have a bitstream at this stage*/ assert(!ch->buffer); /*ignore length fields*/ size = StreamLength + ch->media_padding_bytes; ch->buffer = (char*)malloc(sizeof(char) * size); if (!ch->buffer) { assert(0); return; } ch->allocSize = size; memset(ch->buffer, 0, sizeof(char) * size); ch->len = 0; } if (!ch->esd->slConfig->usePaddingFlag) hdr.paddingFlag = 0; /*if no bitstream, we missed the AU Start packet. Unusable ...*/ if (!ch->buffer) { GF_LOG(GF_LOG_ERROR, GF_LOG_SYNC, ("[SyncLayer] ES%d: Empty buffer - missed begining of AU\n", ch->esd->ESID)); return; } if (ch->ipmp_tool) { GF_IPMPEvent evt; memset(&evt, 0, sizeof(evt)); evt.event_type=GF_IPMP_TOOL_PROCESS_DATA; evt.channel = ch; evt.data = payload; evt.data_size = StreamLength; evt.is_encrypted = hdr.isma_encrypted; evt.isma_BSO = hdr.isma_BSO; ch->ipmp_tool->process(ch->ipmp_tool, &evt); } if (hdr.paddingFlag && !EndAU) { /*to do - this shouldn't happen anyway */ } else { /*check if enough space*/ size = ch->allocSize; if (size && (StreamLength + ch->len <= size)) { memcpy(ch->buffer+ch->len, payload, StreamLength); ch->len += StreamLength; } else { size = StreamLength + ch->len + ch->media_padding_bytes; ch->buffer = (char*)realloc(ch->buffer, sizeof(char) * size); memcpy(ch->buffer+ch->len, payload, StreamLength); ch->allocSize = size; ch->len += StreamLength; } if (hdr.paddingFlag) ch->padingBits = hdr.paddingBits; } if (EndAU) Channel_DispatchAU(ch, hdr.au_duration);}/*notification of End of stream on this channel*/void gf_es_on_eos(GF_Channel *ch){ if (!ch || ch->IsEndOfStream) return; ch->IsEndOfStream = 1; /*flush buffer*/ ch_buffer_off(ch); ch->clock->has_seen_eos = 1; gf_odm_on_eos(ch->odm, ch);}GF_DBUnit *gf_es_get_au(GF_Channel *ch){ Bool comp, is_new_data; GF_Err e, state; GF_SLHeader slh; if (ch->es_state != GF_ESM_ES_RUNNING) return NULL; if (!ch->is_pulling) { /*we must update buffering before fetching in order to stop buffering for streams with very few updates (especially streams with one update, like most of OD streams)*/ if (ch->BufferOn) Channel_UpdateBuffering(ch, 0); if (ch->first_au_fetched && ch->BufferOn) return NULL; return ch->AU_buffer_first; } /*pull from stream - resume clock if needed*/ ch_buffer_off(ch); e = gf_term_channel_get_sl_packet(ch->service, ch, (char **) &ch->AU_buffer_pull->data, &ch->AU_buffer_pull->dataLength, &slh, &comp, &state, &is_new_data); if (e) state = e; switch (state) { case GF_EOS: gf_es_on_eos(ch); return NULL; case GF_OK: break; default: gf_term_message(ch->odm->term, ch->service->url , "Data reception failure", state); return NULL; } assert(!comp); /*update timing if new stream data but send no data*/ if (is_new_data) { gf_es_receive_sl_packet(ch->service, ch, NULL, 0, &slh, GF_OK); if (ch->ipmp_tool) { GF_IPMPEvent evt; memset(&evt, 0, sizeof(evt)); evt.event_type=GF_IPMP_TOOL_PROCESS_DATA; evt.data = ch->AU_buffer_pull->data; evt.data_size = ch->AU_buffer_pull->dataLength; evt.is_encrypted = slh.isma_encrypted; evt.isma_BSO = slh.isma_BSO; evt.channel = ch; e = ch->ipmp_tool->process(ch->ipmp_tool, &evt); if (e && 0) { gf_term_channel_release_sl_packet(ch->service, ch); return NULL; } } } /*this may happen in file streaming when data has not arrived yet, in which case we discard the AU*/ if (!ch->AU_buffer_pull->data) { gf_term_channel_release_sl_packet(ch->service, ch); return NULL; } ch->AU_buffer_pull->CTS = (u32) ch->CTS; ch->AU_buffer_pull->DTS = (u32) ch->DTS; ch->AU_buffer_pull->PaddingBits = ch->padingBits; ch->AU_buffer_pull->RAP = ch->IsRap; return ch->AU_buffer_pull;}void gf_es_init_dummy(GF_Channel *ch){ GF_SLHeader slh; Bool comp, is_new_data; GF_Err e, state; if (!ch->is_pulling) return; /*pull from stream - resume clock if needed*/ ch_buffer_off(ch); e = gf_term_channel_get_sl_packet(ch->service, ch, (char **) &ch->AU_buffer_pull->data, &ch->AU_buffer_pull->dataLength, &slh, &comp, &state, &is_new_data); if (e) state = e; if ((state==GF_OK) && is_new_data) gf_es_receive_sl_packet(ch->service, ch, NULL, 0, &slh, GF_OK); gf_term_channel_release_sl_packet(ch->service, ch);}void gf_es_drop_au(GF_Channel *ch){ GF_DBUnit *au; if (ch->is_pulling) { assert(ch->AU_buffer_pull); gf_term_channel_release_sl_packet(ch->service, ch); ch->AU_buffer_pull->data = NULL; ch->AU_buffer_pull->dataLength = 0; ch->first_au_fetched = 1; return; } if (!ch->AU_buffer_first) return; /*lock the channel before touching the queue*/ gf_es_lock(ch, 1); ch->first_au_fetched = 1; au = ch->AU_buffer_first; ch->AU_buffer_first = au->next; au->next = NULL; gf_db_unit_del(au); ch->AU_Count -= 1; if (!ch->AU_Count && ch->AU_buffer_first) { ch->AU_buffer_first = NULL; } if (!ch->AU_buffer_first) ch->AU_buffer_last = NULL; Channel_UpdateBufferTime(ch); /*if we get under our limit, rebuffer EXCEPT WHEN EOS is signaled*/ if (!ch->IsEndOfStream && Channel_NeedsBuffering(ch, 1)) { ch_buffer_on(ch); } /*unlock the channel*/ gf_es_lock(ch, 0);}/*(un)locks channel*/void gf_es_lock(GF_Channel *ch, u32 LockIt){ if (LockIt) { gf_mx_p(ch->mx); } else { gf_mx_v(ch->mx); }}/*performs final setup upon connection confirm*/void gf_es_on_connect(GF_Channel *ch){ Bool can_buffer; GF_NetworkCommand com; /*check whether we can work in pull mode or not*/ can_buffer = 1; /*if local interaction streams no buffer nor pull*/ if ((ch->esd->decoderConfig->streamType == GF_STREAM_INTERACT) && !ch->esd->URLString) can_buffer = 0; com.base.on_channel = ch; ch->is_pulling = 0; if (can_buffer) { /*request padding*/ com.command_type = GF_NET_CHAN_SET_PADDING; com.pad.padding_bytes = ch->media_padding_bytes; if (!com.pad.padding_bytes || (gf_term_service_command(ch->service, &com) == GF_OK)) { /*request pull if possible*/ if (ch->service->ifce->ChannelGetSLP && ch->service->ifce->ChannelReleaseSLP) { com.command_type = GF_NET_CHAN_SET_PULL; if (gf_term_service_command(ch->service, &com) == GF_OK) { ch->is_pulling = 1; can_buffer = 0; } } } } /*checks whether the stream is interactive or not*/ com.command_type = GF_NET_CHAN_INTERACTIVE; if (gf_term_service_command(ch->service, &com)!=GF_OK) { ch->clock->no_time_ctrl = 1; ch->odm->flags |= GF_ODM_NO_TIME_CTRL; gf_odm_refresh_uninteractives(ch->odm); } /*signal channel state*/ if (ch->es_state == GF_ESM_ES_WAIT_FOR_ACK) ch->es_state = GF_ESM_ES_CONNECTED; /*signal only once connected to prevent PLAY trigger on connection callback*/ ch->odm->pending_channels--; /*remember channels connected on service*/ if (ch->esd->URLString) ch->service->nb_ch_users++; /*buffer setup*/ ch->MinBuffer = ch->MaxBuffer = 0; if (can_buffer) { const char *sOpt; com.command_type = GF_NET_CHAN_BUFFER; com.base.on_channel = ch; /*set default values*/ com.buffer.max = 1000; sOpt = gf_cfg_get_key(ch->odm->term->user->config, "Network", "BufferLength"); if (sOpt) com.buffer.max = atoi(sOpt); com.buffer.min = 0; sOpt = gf_cfg_get_key(ch->odm->term->user->config, "Network", "RebufferLength"); if (sOpt) com.buffer.min = atoi(sOpt); if (gf_term_service_command(ch->service, &com) == GF_OK) { ch->MinBuffer = com.buffer.min; ch->MaxBuffer = com.buffer.max; } } /*get duration*/ com.command_type = GF_NET_CHAN_DURATION; com.base.on_channel = ch; if (gf_term_service_command(ch->service, &com) == GF_OK) gf_odm_set_duration(ch->odm, ch, (u64) (1000*com.duration.duration));}void gf_es_config_drm(GF_Channel *ch, GF_NetComDRMConfig *drm_cfg){ GF_Terminal *term = ch->odm->term; u32 i, count; GF_Err e; GF_IPMPEvent evt; GF_OMADRM2Config cfg; GF_OMADRM2Config isma_cfg; /*always buffer when fetching keys*/ ch_buffer_on(ch); ch->is_protected = 1; memset(&evt, 0, sizeof(GF_IPMPEvent)); evt.event_type = GF_IPMP_TOOL_SETUP; evt.channel = ch; /*push all cfg data*/ if (drm_cfg->contentID) { evt.config_data_code = GF_4CC('o','d','r','m'); memset(&cfg, 0, sizeof(cfg)); cfg.scheme_version = drm_cfg->scheme_version; cfg.scheme_type = drm_cfg->scheme_type; cfg.scheme_uri = drm_cfg->scheme_uri; cfg.kms_uri = drm_cfg->kms_uri; memcpy(cfg.hash, drm_cfg->hash, sizeof(char)*20); cfg.contentID = drm_cfg->contentID; cfg.oma_drm_crypt_type = drm_cfg->oma_drm_crypt_type; cfg.oma_drm_use_pad = drm_cfg->oma_drm_use_pad; cfg.oma_drm_use_hdr = drm_cfg->oma_drm_use_hdr; cfg.oma_drm_textual_headers = drm_cfg->oma_drm_textual_headers; cfg.oma_drm_textual_headers_len = drm_cfg->oma_drm_textual_headers_len; evt.config_data = &cfg; } else { evt.config_data_code = GF_4CC('i','s','m','a'); memset(&isma_cfg, 0, sizeof(isma_cfg)); isma_cfg.scheme_version = drm_cfg->scheme_version; isma_cfg.scheme_type = drm_cfg->scheme_type; isma_cfg.scheme_uri = drm_cfg->scheme_uri; isma_cfg.kms_uri = drm_cfg->kms_uri; evt.config_data = &isma_cfg; } if (ch->ipmp_tool) { e = ch->ipmp_tool->process(ch->ipmp_tool, &evt); if (e) gf_term_message(ch->odm->term, ch->service->url, "Error setting up DRM tool", e); ch_buffer_off(ch); return; } /*browse all available tools*/ count = gf_modules_get_count(term->user->modules); for (i=0; i< count; i++) { ch->ipmp_tool = (GF_IPMPTool *) gf_modules_load_interface(term->user->modules, i, GF_IPMP_TOOL_INTERFACE); if (!ch->ipmp_tool) continue; GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[IPMP] Checking if IPMP tool %s can handle channel protection scheme\n", ch->ipmp_tool->module_name)); e = ch->ipmp_tool->process(ch->ipmp_tool, &evt); if (e==GF_OK) { GF_LOG(GF_LOG_DEBUG, GF_LOG_MEDIA, ("[IPMP] Associating IPMP tool %s to channel %d\n", ch->ipmp_tool->module_name, ch->esd->ESID)); ch_buffer_off(ch); return; } gf_modules_close_interface((GF_BaseInterface *) ch->ipmp_tool); ch->ipmp_tool = NULL; } gf_term_message(ch->odm->term, ch->service->url, "No IPMP tool suitable to handle channel protection", GF_NOT_SUPPORTED); ch_buffer_off(ch);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -