static void AAC_OnLiveData(AACReader *read, char *data, u32 data_size) { u32 pos; Bool sync; GF_BitStream *bs; ADTSHeader hdr; read->data = realloc(read->data, sizeof(char)*(read->data_size+data_size) ); memcpy(read->data + read->data_size, data, sizeof(char)*data_size); read->data_size += data_size; if (read->needs_connection) { read->needs_connection = 0; bs = gf_bs_new(read->data, read->data_size, GF_BITSTREAM_READ); sync = ADTS_SyncFrame(bs, 0, &hdr); gf_bs_del(bs); if (!sync) return; read->nb_ch = hdr.nb_ch; read->prof = hdr.profile; read->sr_idx = hdr.sr_idx; read->oti = hdr.is_mp2 ? read->prof+0x66-1 : 0x40; read->sample_rate = GF_M4ASampleRates[read->sr_idx]; read->is_live = 1; memset(&read->sl_hdr, 0, sizeof(GF_SLHeader)); gf_term_on_connect(read->service, NULL, GF_OK); AAC_SetupObject(read); } if (!read->ch) return; /*need a full adts header*/ if (read->data_size<=7) return; bs = gf_bs_new(read->data, read->data_size, GF_BITSTREAM_READ); hdr.frame_size = pos = 0; while (ADTS_SyncFrame(bs, 0, &hdr)) { pos = (u32) gf_bs_get_position(bs); read->sl_hdr.accessUnitStartFlag = 1; read->sl_hdr.accessUnitEndFlag = 1; read->sl_hdr.AU_sequenceNumber++; read->sl_hdr.compositionTimeStampFlag = 1; read->sl_hdr.compositionTimeStamp += 1024; gf_term_on_sl_packet(read->service, read->ch, read->data + pos, hdr.frame_size, &read->sl_hdr, GF_OK); gf_bs_skip_bytes(bs, hdr.frame_size); } pos = (u32) gf_bs_get_position(bs); gf_bs_del(bs); if (pos) { char *d; read->data_size -= pos; d = malloc(sizeof(char) * read->data_size); memcpy(d, read->data + pos, sizeof(char) * read->data_size); free(read->data); read->data = d; } AAC_RegulateDataRate(read); }
static void AC3_OnLiveData(AC3Reader *read, const char *data, u32 data_size) { u64 pos; Bool sync; GF_BitStream *bs; GF_AC3Header hdr; memset(&hdr, 0, sizeof(GF_AC3Header)); read->data = gf_realloc(read->data, sizeof(char)*(read->data_size+data_size) ); memcpy(read->data + read->data_size, data, sizeof(char)*data_size); read->data_size += data_size; if (read->needs_connection) { read->needs_connection = 0; bs = gf_bs_new((char *) read->data, read->data_size, GF_BITSTREAM_READ); sync = gf_ac3_parser_bs(bs, &hdr, GF_TRUE); gf_bs_del(bs); if (!sync) return; read->nb_ch = hdr.channels; read->sample_rate = hdr.sample_rate; read->is_live = 1; memset(&read->sl_hdr, 0, sizeof(GF_SLHeader)); gf_service_connect_ack(read->service, NULL, GF_OK); AC3_SetupObject(read); } if (!read->ch) return; /*need a full ac3 header*/ if (read->data_size<=7) return; bs = gf_bs_new((char *) read->data, read->data_size, GF_BITSTREAM_READ); hdr.framesize = 0; pos = 0; while (gf_ac3_parser_bs(bs, &hdr, GF_FALSE)) { pos = gf_bs_get_position(bs); read->sl_hdr.accessUnitStartFlag = 1; read->sl_hdr.accessUnitEndFlag = 1; read->sl_hdr.AU_sequenceNumber++; read->sl_hdr.compositionTimeStampFlag = 1; read->sl_hdr.compositionTimeStamp += 1536; gf_service_send_packet(read->service, read->ch, (char *) read->data + pos, hdr.framesize, &read->sl_hdr, GF_OK); gf_bs_skip_bytes(bs, hdr.framesize); } pos = gf_bs_get_position(bs); gf_bs_del(bs); if (pos) { u8 *d; read->data_size -= (u32) pos; d = gf_malloc(sizeof(char) * read->data_size); memcpy(d, read->data + pos, sizeof(char) * read->data_size); gf_free(read->data); read->data = d; } AC3_RegulateDataRate(read); }
static Bool ADTS_SyncFrame(GF_BitStream *bs, Bool is_complete, ADTSHeader *hdr) { u32 val, pos, start_pos; start_pos = (u32) gf_bs_get_position(bs); while (gf_bs_available(bs)) { val = gf_bs_read_u8(bs); if (val!=0xFF) continue; val = gf_bs_read_int(bs, 4); if (val != 0x0F) { gf_bs_read_int(bs, 4); continue; } hdr->is_mp2 = gf_bs_read_int(bs, 1); gf_bs_read_int(bs, 2); hdr->no_crc = gf_bs_read_int(bs, 1); pos = (u32) gf_bs_get_position(bs) - 2; hdr->profile = 1 + gf_bs_read_int(bs, 2); hdr->sr_idx = gf_bs_read_int(bs, 4); gf_bs_read_int(bs, 1); hdr->nb_ch = gf_bs_read_int(bs, 3); gf_bs_read_int(bs, 4); hdr->frame_size = gf_bs_read_int(bs, 13); gf_bs_read_int(bs, 11); gf_bs_read_int(bs, 2); hdr->hdr_size = 7; if (!hdr->no_crc) { gf_bs_read_u16(bs); hdr->hdr_size = 9; } if (hdr->frame_size < hdr->hdr_size) { gf_bs_seek(bs, pos+1); continue; } hdr->frame_size -= hdr->hdr_size; if (is_complete && (gf_bs_available(bs) == hdr->frame_size)) return 1; else if (gf_bs_available(bs) <= hdr->frame_size) break; gf_bs_skip_bytes(bs, hdr->frame_size); val = gf_bs_read_u8(bs); if (val!=0xFF) { gf_bs_seek(bs, pos+1); continue; } val = gf_bs_read_int(bs, 4); if (val!=0x0F) { gf_bs_read_int(bs, 4); gf_bs_seek(bs, pos+1); continue; } gf_bs_seek(bs, pos+hdr->hdr_size); return 1; } gf_bs_seek(bs, start_pos); return 0; }
/*special authoring functions*/ GF_EXPORT GF_BIFSConfig *gf_odf_get_bifs_config(GF_DefaultDescriptor *dsi, u8 oti) { Bool hasSize, cmd_stream; GF_BitStream *bs; GF_BIFSConfig *cfg; if (oti>=GPAC_OTI_SCENE_BIFS_EXTENDED) return NULL; if (!dsi || !dsi->data || !dsi->dataLength ) { /* Hack for T-DMB non compliant streams (OnTimeTek ?) */ cfg = (GF_BIFSConfig *) gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG); cfg->pixelMetrics = 1; cfg->version = 1; return cfg; } bs = gf_bs_new(dsi->data, dsi->dataLength, GF_BITSTREAM_READ); cfg = (GF_BIFSConfig *) gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG); if (oti==2) { /*3D Mesh Coding*/ gf_bs_read_int(bs, 1); /*PMF*/ gf_bs_read_int(bs, 1); } cfg->nodeIDbits = gf_bs_read_int(bs, 5); cfg->routeIDbits = gf_bs_read_int(bs, 5); if (oti==2) cfg->protoIDbits = gf_bs_read_int(bs, 5); cmd_stream = gf_bs_read_int(bs, 1); if (!cmd_stream) { cfg->elementaryMasks = gf_list_new(); while (1) { GF_ElementaryMask* em = (GF_ElementaryMask* ) gf_odf_New_ElemMask(); em->node_id = gf_bs_read_int(bs, cfg->nodeIDbits); gf_list_add(cfg->elementaryMasks, em); /*this assumes only FDP, BDP and IFS2D (no elem mask)*/ if (gf_bs_read_int(bs, 1) == 0) break; } gf_bs_align(bs); if (gf_bs_get_size(bs) != gf_bs_get_position(bs)) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[ODF] Reading bifs config: shift in sizes (not supported)\n")); } } else { cfg->pixelMetrics = gf_bs_read_int(bs, 1); hasSize = gf_bs_read_int(bs, 1); if (hasSize) { cfg->pixelWidth = gf_bs_read_int(bs, 16); cfg->pixelHeight = gf_bs_read_int(bs, 16); } gf_bs_align(bs); if (gf_bs_get_size(bs) != gf_bs_get_position(bs)) GF_LOG(GF_LOG_WARNING, GF_LOG_CODEC, ("[ODF] Reading bifs config: shift in sizes (invalid descriptor)\n")); } gf_bs_del(bs); return cfg; }
GF_Err hvcc_Read(GF_Box *s, GF_BitStream *bs) { u64 pos; GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *)s; if (ptr->config) gf_odf_hevc_cfg_del(ptr->config); pos = gf_bs_get_position(bs); ptr->config = gf_odf_hevc_cfg_read_bs(bs); pos = gf_bs_get_position(bs) - pos ; if (pos < ptr->size) ptr->size -= (u32) pos; return GF_OK; }
GF_Err store_senc_info(GF_SampleEncryptionBox *ptr, GF_BitStream *bs) { GF_Err e; u64 pos, new_pos; if (!ptr->cenc_saio) return GF_OK; pos = gf_bs_get_position(bs); if (pos>0xFFFFFFFFULL) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] \"senc\" offset larger than 32-bits , \"saio\" box version must be 1 .\n")); } e = gf_bs_seek(bs, ptr->cenc_saio->offset_first_offset_field); if (e) return e; //force using version 1 for saio box i.e offset has 64 bits #ifndef GPAC_DISABLE_ISOM_FRAGMENTS if (ptr->traf) { new_pos = pos - ptr->traf->moof_start_in_bs; } else #endif { new_pos = pos; } if (ptr->cenc_saio->offsets_large) { u32 i; u64 old_offset = ptr->cenc_saio->offsets_large[0]; for (i=0; i<ptr->cenc_saio->entry_count; i++) { gf_bs_write_u64(bs, new_pos + ptr->cenc_saio->offsets_large[i] - old_offset); ptr->cenc_saio->offsets_large[i] = new_pos + ptr->cenc_saio->offsets_large[i] - old_offset; } } else { gf_bs_write_u64(bs, new_pos); } return gf_bs_seek(bs, pos); }
GF_Err FDM_AddData(GF_FileDataMap *ptr, char *data, u32 dataSize) { u32 ret; u64 orig; if (ptr->mode == GF_ISOM_DATA_MAP_READ) return GF_BAD_PARAM; orig = gf_bs_get_size(ptr->bs); /*last access was read, seek to end of file*/ if (ptr->last_acces_was_read) { gf_bs_seek(ptr->bs, orig); ptr->last_acces_was_read = 0; } //OK, write our stuff to the datamap... //we don't use bs here cause we want to know more about what has been written ret = gf_bs_write_data(ptr->bs, data, dataSize); if (ret != dataSize) { ptr->curPos = orig; gf_bs_seek(ptr->bs, orig); return GF_IO_ERR; } ptr->curPos = gf_bs_get_position(ptr->bs); //flush the stream !! if (ptr->stream) fflush(ptr->stream); return GF_OK; }
GF_Err piff_psec_Read(GF_Box *s, GF_BitStream *bs) { //u32 sample_count; GF_SampleEncryptionBox *ptr = (GF_SampleEncryptionBox *)s; if (ptr->size<4) return GF_ISOM_INVALID_FILE; ptr->version = gf_bs_read_u8(bs); ptr->flags = gf_bs_read_u24(bs); ISOM_DECREASE_SIZE(ptr, 4); if (ptr->flags & 1) { ptr->AlgorithmID = gf_bs_read_int(bs, 24); ptr->IV_size = gf_bs_read_u8(bs); gf_bs_read_data(bs, (char *) ptr->KID, 16); ISOM_DECREASE_SIZE(ptr, 20); } if (ptr->IV_size == 0) ptr->IV_size = 8; //default to 8 ptr->bs_offset = gf_bs_get_position(bs); /*sample_count = */gf_bs_read_u32(bs); ISOM_DECREASE_SIZE(ptr, 4); if (ptr->IV_size != 8 && ptr->IV_size != 16) { GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] PIFF PSEC box incorrect IV size: %u - shall be 8 or 16\n", ptr->IV_size)); return GF_BAD_PARAM; } //as for senc, we skip parsing of the box until we have all saiz/saio info ptr->size = 0; return GF_OK; }
static GF_Err gf_isom_cenc_get_sai_by_saiz_saio(GF_MediaBox *mdia, u32 sampleNumber, u8 IV_size, GF_CENCSampleAuxInfo **sai) { GF_BitStream *bs; u32 prev_sai_size, size, i, j, nb_saio; u64 cur_position, offset; GF_Err e = GF_OK; char *buffer; nb_saio = size = prev_sai_size = 0; offset = 0; for (i = 0; i < gf_list_count(mdia->information->sampleTable->sai_offsets); i++) { GF_SampleAuxiliaryInfoOffsetBox *saio = (GF_SampleAuxiliaryInfoOffsetBox *)gf_list_get(mdia->information->sampleTable->sai_offsets, i); if (saio->aux_info_type == GF_4CC('c', 'e', 'n', 'c')) { if (saio->entry_count == 1) offset = saio->version ? saio->offsets_large[0] : saio->offsets[0]; else offset = saio->version ? saio->offsets_large[sampleNumber-1]: saio->offsets[sampleNumber-1]; nb_saio = saio->entry_count; break; } } for (i = 0; i < gf_list_count(mdia->information->sampleTable->sai_sizes); i++) { GF_SampleAuxiliaryInfoSizeBox *saiz = (GF_SampleAuxiliaryInfoSizeBox *)gf_list_get(mdia->information->sampleTable->sai_sizes, i); if (saiz->aux_info_type == GF_4CC('c', 'e', 'n', 'c')) { for (j = 0; j < sampleNumber-1; j++) prev_sai_size += saiz->default_sample_info_size ? saiz->default_sample_info_size : saiz->sample_info_size[j]; size = saiz->default_sample_info_size ? saiz->default_sample_info_size : saiz->sample_info_size[sampleNumber-1]; break; } } offset += (nb_saio == 1) ? prev_sai_size : 0; cur_position = gf_bs_get_position(mdia->information->dataHandler->bs); gf_bs_seek(mdia->information->dataHandler->bs, offset); buffer = (char *)gf_malloc(size); gf_bs_read_data(mdia->information->dataHandler->bs, buffer, size); gf_bs_seek(mdia->information->dataHandler->bs, cur_position); *sai = (GF_CENCSampleAuxInfo *)gf_malloc(sizeof(GF_CENCSampleAuxInfo)); memset(*sai, 0, sizeof(GF_CENCSampleAuxInfo)); bs = gf_bs_new(buffer, size, GF_BITSTREAM_READ); gf_bs_read_data(bs, (char *)(*sai)->IV, IV_size); if (size > IV_size) { (*sai)->subsample_count = gf_bs_read_u16(bs); (*sai)->subsamples = (GF_CENCSubSampleEntry *)gf_malloc(sizeof(GF_CENCSubSampleEntry)*(*sai)->subsample_count); for (i = 0; i < (*sai)->subsample_count; i++) { (*sai)->subsamples[i].bytes_clear_data = gf_bs_read_u16(bs); (*sai)->subsamples[i].bytes_encrypted_data = gf_bs_read_u32(bs); } } gf_bs_del(bs); return e; }
GF_Err senc_Parse(GF_BitStream *bs, GF_TrackBox *trak, void *traf, GF_SampleEncryptionBox *senc) #endif { GF_Err e; u32 i, j, count; u64 pos = gf_bs_get_position(bs); #ifdef GPAC_DISABLE_ISOM_FRAGMENTS if (!traf) return GF_BAD_PARAM; #endif gf_bs_seek(bs, senc->bs_offset); count = gf_bs_read_u32(bs); if (!senc->samp_aux_info) senc->samp_aux_info = gf_list_new(); for (i=0; i<count; i++) { u32 is_encrypted; u32 samp_count; GF_CENCSampleAuxInfo *sai = (GF_CENCSampleAuxInfo *)gf_malloc(sizeof(GF_CENCSampleAuxInfo)); memset(sai, 0, sizeof(GF_CENCSampleAuxInfo)); samp_count = i+1; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS if (trak) samp_count += trak->sample_count_at_seg_start; #endif if (trak) { e = gf_isom_get_sample_cenc_info_ex(trak, traf, senc, samp_count, &is_encrypted, &sai->IV_size, NULL, NULL, NULL, NULL, NULL); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[isobmf] could not get cenc info for sample %d: %s\n", samp_count, gf_error_to_string(e) )); return e; } } //no init movie setup (segment dump/inspaction, assume default encrypted and 16 bytes IV else { is_encrypted = GF_TRUE; sai->IV_size = 16; } if (is_encrypted) { gf_bs_read_data(bs, (char *)sai->IV, sai->IV_size); if (senc->flags & 0x00000002) { sai->subsample_count = gf_bs_read_u16(bs); sai->subsamples = (GF_CENCSubSampleEntry *)gf_malloc(sai->subsample_count*sizeof(GF_CENCSubSampleEntry)); for (j = 0; j < sai->subsample_count; j++) { sai->subsamples[j].bytes_clear_data = gf_bs_read_u16(bs); sai->subsamples[j].bytes_encrypted_data = gf_bs_read_u32(bs); } } } gf_list_add(senc->samp_aux_info, sai); } gf_bs_seek(bs, pos); return GF_OK; }
static GF_Err ParseConfig(GF_BitStream *bs, BIFSStreamInfo *info, u32 version) { Bool hasSize, cmd_stream; if (info->config.elementaryMasks) gf_list_del(info->config.elementaryMasks); info->config.elementaryMasks = NULL ; if (version==2) { info->config.Use3DMeshCoding = gf_bs_read_int(bs, 1); info->config.UsePredictiveMFField = gf_bs_read_int(bs, 1); } info->config.NodeIDBits = gf_bs_read_int(bs, 5); info->config.RouteIDBits = gf_bs_read_int(bs, 5); if (version==2) { info->config.ProtoIDBits = gf_bs_read_int(bs, 5); } cmd_stream = gf_bs_read_int(bs, 1); if (cmd_stream) { info->config.PixelMetrics = gf_bs_read_int(bs, 1); hasSize = gf_bs_read_int(bs, 1); if (hasSize) { info->config.Width = gf_bs_read_int(bs, 16); info->config.Height = gf_bs_read_int(bs, 16); } gf_bs_align(bs); if (gf_bs_get_size(bs) != gf_bs_get_position(bs)) return GF_ODF_INVALID_DESCRIPTOR; return GF_OK; } else { info->config.BAnimRAP = gf_bs_read_int(bs, 1); info->config.elementaryMasks = gf_list_new(); while (1) { /*u32 node_id = */gf_bs_read_int(bs, info->config.NodeIDBits); /*this assumes only FDP, BDP and IFS2D (no elem mask)*/ if (gf_bs_read_int(bs, 1) == 0) break; } gf_bs_align(bs); if (gf_bs_get_size(bs) != gf_bs_get_position(bs)) return GF_NOT_SUPPORTED; return GF_OK; } }
GF_Err senc_Read(GF_Box *s, GF_BitStream *bs) { GF_SampleEncryptionBox *ptr = (GF_SampleEncryptionBox *)s; //WARNING - PSEC (UUID) IS TYPECASTED TO SENC (FULL BOX) SO WE CANNOT USE USUAL FULL BOX FUNCTIONS ptr->version = gf_bs_read_u8(bs); ptr->flags = gf_bs_read_u24(bs); ISOM_DECREASE_SIZE(ptr, 4); ptr->bs_offset = gf_bs_get_position(bs); gf_bs_skip_bytes(bs, ptr->size); ptr->size = 0; return GF_OK; }
GF_Err meta_Read(GF_Box *s, GF_BitStream *bs) { u64 pos = gf_bs_get_position(bs); u64 size = s->size; GF_Err e = gf_isom_box_array_read(s, bs, meta_AddBox); /*try to hack around QT files which don't use a full box for meta, rewind 4 bytes*/ if (e && (pos>4) ) { gf_bs_seek(bs, pos-4); meta_reset(s); s->size = size+4; e = gf_isom_box_array_read(s, bs, meta_AddBox); } return e; }
GF_EXPORT void gf_sl_depacketize (GF_SLConfig *slConfig, GF_SLHeader *Header, char *PDU, u32 PDULength, u32 *HeaderLen) { GF_BitStream *bs; *HeaderLen = 0; if (!Header) return; //reset the input header memset(Header, 0, sizeof(GF_SLHeader)); bs = gf_bs_new(PDU, PDULength, GF_BITSTREAM_READ); if (!bs) return; if (slConfig->useAccessUnitStartFlag) Header->accessUnitStartFlag = gf_bs_read_int(bs, 1); if (slConfig->useAccessUnitEndFlag) Header->accessUnitEndFlag = gf_bs_read_int(bs, 1); if ( !slConfig->useAccessUnitStartFlag && !slConfig->useAccessUnitEndFlag) { Header->accessUnitStartFlag = 1; Header->accessUnitEndFlag = 1; } if (slConfig->OCRLength > 0) Header->OCRflag = gf_bs_read_int(bs, 1); if (slConfig->useIdleFlag) Header->idleFlag = gf_bs_read_int(bs, 1); if (slConfig->usePaddingFlag) { Header->paddingFlag = gf_bs_read_int(bs, 1); if (Header->paddingFlag) Header->paddingBits = gf_bs_read_int(bs, 3); } if (!Header->idleFlag && (!Header->paddingFlag || Header->paddingBits != 0)) { if (slConfig->packetSeqNumLength > 0) Header->packetSequenceNumber = gf_bs_read_int(bs, slConfig->packetSeqNumLength); if (slConfig->degradationPriorityLength > 0) { Header->degradationPriorityFlag = gf_bs_read_int(bs, 1); if (Header->degradationPriorityFlag) Header->degradationPriority = gf_bs_read_int(bs, slConfig->degradationPriorityLength); } if (Header->OCRflag) Header->objectClockReference = gf_bs_read_int(bs, slConfig->OCRLength); if (Header->accessUnitStartFlag) { if (slConfig->useRandomAccessPointFlag) Header->randomAccessPointFlag = gf_bs_read_int(bs, 1); if (slConfig->AUSeqNumLength > 0) Header->AU_sequenceNumber = gf_bs_read_int(bs, slConfig->AUSeqNumLength); if (slConfig->useTimestampsFlag) { Header->decodingTimeStampFlag = gf_bs_read_int(bs, 1); Header->compositionTimeStampFlag = gf_bs_read_int(bs, 1); } if (slConfig->instantBitrateLength > 0) Header->instantBitrateFlag = gf_bs_read_int(bs, 1); if (Header->decodingTimeStampFlag) Header->decodingTimeStamp = gf_bs_read_long_int(bs, slConfig->timestampLength); if (Header->compositionTimeStampFlag) Header->compositionTimeStamp = gf_bs_read_long_int(bs, slConfig->timestampLength); if (slConfig->AULength > 0) Header->accessUnitLength = gf_bs_read_int(bs, slConfig->AULength); if (Header->instantBitrateFlag) Header->instantBitrate = gf_bs_read_int(bs, slConfig->instantBitrateLength); } } gf_bs_align(bs); *HeaderLen = (u32) gf_bs_get_position(bs); gf_bs_del(bs); }
GF_Err piff_psec_Read(GF_Box *s, GF_BitStream *bs) { u32 sample_count, i, j; GF_PIFFSampleEncryptionBox *ptr = (GF_PIFFSampleEncryptionBox *)s; if (ptr->size<4) return GF_ISOM_INVALID_FILE; ptr->version = gf_bs_read_u8(bs); ptr->flags = gf_bs_read_u24(bs); ptr->size -= 4; if (ptr->flags & 1) { ptr->AlgorithmID = gf_bs_read_int(bs, 24); ptr->IV_size = gf_bs_read_u8(bs); gf_bs_read_data(bs, (char *)ptr->KID, 16); ptr->size -= 20; } if (ptr->IV_size == 0) ptr->IV_size = 8; //default to 8 sample_count = gf_bs_read_u32(bs); ptr->size -= 4; if (ptr->IV_size != 8 && ptr->IV_size != 16) { GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] PIFF PSEC box incorrect IV size: %u - shall be 8 or 16\n", ptr->IV_size)); return GF_BAD_PARAM; } ptr->samp_aux_info = gf_list_new(); for (i = 0; i<sample_count; ++i) { GF_CENCSampleAuxInfo *sai; GF_SAFEALLOC(sai, GF_CENCSampleAuxInfo); if (!sai) return GF_OUT_OF_MEM; sai->IV_size = ptr->IV_size; gf_bs_read_data(bs, (char *)sai->IV, ptr->IV_size); ptr->size -= ptr->IV_size; if (ptr->flags & 2) { sai->subsample_count = gf_bs_read_u16(bs); sai->subsamples = gf_malloc(sai->subsample_count * sizeof(GF_CENCSubSampleEntry)); for (j = 0; j < sai->subsample_count; ++j) { sai->subsamples[j].bytes_clear_data = gf_bs_read_u16(bs); sai->subsamples[j].bytes_encrypted_data = gf_bs_read_u32(bs); } ptr->size -= 2 + sai->subsample_count * 6; } gf_list_add(ptr->samp_aux_info, sai); } ptr->bs_offset = gf_bs_get_position(bs); assert(ptr->size == 0); return GF_OK; }
GF_Err senc_Parse(GF_BitStream *bs, GF_TrackBox *trak, void *traf, GF_SampleEncryptionBox *ptr) #endif { GF_Err e; u32 i, j, count; u64 pos = gf_bs_get_position(bs); #ifdef GPAC_DISABLE_ISOM_FRAGMENTS if (!traf) return GF_BAD_PARAM; #endif gf_bs_seek(bs, ptr->bs_offset); count = gf_bs_read_u32(bs); if (!ptr->samp_aux_info) ptr->samp_aux_info = gf_list_new(); for (i=0; i<count; i++) { u32 is_encrypted; GF_CENCSampleAuxInfo *sai = (GF_CENCSampleAuxInfo *)gf_malloc(sizeof(GF_CENCSampleAuxInfo)); memset(sai, 0, sizeof(GF_CENCSampleAuxInfo)); e = gf_isom_get_sample_cenc_info_ex(trak, traf, (trak ? trak->sample_count_at_seg_start : 0 )+ i+1, &is_encrypted, &sai->IV_size, NULL); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[isobmf] could not get cenc info for sample %d: %s\n", trak->sample_count_at_seg_start + i+1, gf_error_to_string(e) )); return e; } if (is_encrypted) { gf_bs_read_data(bs, (char *)sai->IV, sai->IV_size); if (ptr->flags & 0x00000002) { sai->subsample_count = gf_bs_read_u16(bs); sai->subsamples = (GF_CENCSubSampleEntry *)gf_malloc(sai->subsample_count*sizeof(GF_CENCSubSampleEntry)); for (j = 0; j < sai->subsample_count; j++) { sai->subsamples[j].bytes_clear_data = gf_bs_read_u16(bs); sai->subsamples[j].bytes_encrypted_data = gf_bs_read_u32(bs); } } } gf_list_add(ptr->samp_aux_info, sai); } gf_bs_seek(bs, pos); return GF_OK; }
GF_Err store_senc_info(GF_SampleEncryptionBox *ptr, GF_BitStream *bs) { GF_Err e; u64 pos; if (!ptr->cenc_saio) return GF_OK; pos = gf_bs_get_position(bs); if (pos>0xFFFFFFFFULL) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] \"senc\" offset larger than 32-bits , \"saio\" box version must be 1 .\n")); } e = gf_bs_seek(bs, ptr->cenc_saio->offset_first_offset_field); if (e) return e; //force using version 1 for saio box i.e offset has 64 bits if (ptr->traf) { gf_bs_write_u64(bs, pos - ptr->traf->moof_start_in_bs ); } else { gf_bs_write_u64(bs, pos); } return gf_bs_seek(bs, pos); }
GF_Err piff_psec_Read(GF_Box *s, GF_BitStream *bs) { GF_PIFFSampleEncryptionBox *ptr = (GF_PIFFSampleEncryptionBox *)s; if (ptr->size<4) return GF_ISOM_INVALID_FILE; ptr->version = gf_bs_read_u8(bs); ptr->flags = gf_bs_read_u24(bs); ptr->size -= 4; if (ptr->flags & 1) { ptr->AlgorithmID = gf_bs_read_int(bs, 24); ptr->IV_size = gf_bs_read_u8(bs); gf_bs_read_data(bs, (char *) ptr->KID, 16); ptr->size -= 20; } ptr->bs_offset = gf_bs_get_position(bs); gf_bs_skip_bytes(bs, ptr->size); ptr->size = 0; return GF_OK; }
GF_Err store_senc_info(GF_SampleEncryptionBox *ptr, GF_BitStream *bs) { GF_Err e; u64 pos; if (!ptr->cenc_saio) return GF_OK; pos = gf_bs_get_position(bs); if (pos>0xFFFFFFFFULL) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] \"senc\" offset larger than 32-bits , cannot store.\n")); return GF_NOT_SUPPORTED; } e = gf_bs_seek(bs, ptr->cenc_saio->offset_first_offset_field); if (e) return e; if (ptr->traf) { gf_bs_write_u32(bs, (u32) ( pos - ptr->traf->moof_start_in_bs) ); } else { gf_bs_write_u32(bs, (u32) pos); } return gf_bs_seek(bs, pos); }
GF_Err gf_isom_add_meta_item_extended(GF_ISOFile *file, Bool root_meta, u32 track_num, Bool self_reference, char *resource_path, const char *item_name, u32 item_id, const char *mime_type, const char *content_encoding, GF_ImageItemProperties *image_props, const char *URL, const char *URN, char *data, u32 data_len) { GF_Err e; GF_ItemLocationEntry *location_entry; GF_ItemInfoEntryBox *infe; GF_MetaBox *meta; u32 lastItemID = 0; if (!self_reference && !item_name && !resource_path) return GF_BAD_PARAM; e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE); if (e) return e; meta = gf_isom_get_meta(file, root_meta, track_num); if (!meta) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Trying to add item, but missing meta box")); return GF_BAD_PARAM; } e = FlushCaptureMode(file); if (e) return e; /*check file exists */ if (!URN && !URL && !self_reference && !data) { FILE *src = gf_fopen(resource_path, "rb"); if (!src) return GF_URL_ERROR; gf_fclose(src); } if (meta->item_infos) { u32 i; u32 item_count = gf_list_count(meta->item_infos->item_infos); for (i = 0; i < item_count; i++) { GF_ItemInfoEntryBox *e= (GF_ItemInfoEntryBox *)gf_list_get(meta->item_infos->item_infos, i); if (e->item_ID > lastItemID) lastItemID = e->item_ID; if (item_id == e->item_ID) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[IsoMedia] Item with id %d already exists, ignoring\n", item_id)); item_id = 0; } } } infe = (GF_ItemInfoEntryBox *)infe_New(); if (item_id) { infe->item_ID = item_id; } else { infe->item_ID = ++lastItemID; } /*get relative name*/ if (item_name) { infe->item_name = gf_strdup(item_name); } else if (resource_path) { if (strrchr(resource_path, GF_PATH_SEPARATOR)) { infe->item_name = gf_strdup(strrchr(resource_path, GF_PATH_SEPARATOR) + 1); } else { infe->item_name = gf_strdup(resource_path); } } if (mime_type) { infe->content_type = gf_strdup(mime_type); } else { infe->content_type = gf_strdup("application/octet-stream"); } if (content_encoding) infe->content_encoding = gf_strdup(content_encoding); /*Creation of the ItemLocation */ location_entry = (GF_ItemLocationEntry*)gf_malloc(sizeof(GF_ItemLocationEntry)); if (!location_entry) { gf_isom_box_del((GF_Box *)infe); return GF_OUT_OF_MEM; } memset(location_entry, 0, sizeof(GF_ItemLocationEntry)); location_entry->extent_entries = gf_list_new(); /*Creates an mdat if it does not exist*/ if (!file->mdat) { file->mdat = (GF_MediaDataBox *)mdat_New(); gf_list_add(file->TopBoxes, file->mdat); } /*Creation an ItemLocation Box if it does not exist*/ if (!meta->item_locations) meta->item_locations = (GF_ItemLocationBox *)iloc_New(); gf_list_add(meta->item_locations->location_entries, location_entry); location_entry->item_ID = infe->item_ID; if (!meta->item_infos) meta->item_infos = (GF_ItemInfoBox *) iinf_New(); e = gf_list_add(meta->item_infos->item_infos, infe); if (e) return e; if (image_props) { meta_process_image_properties(meta, infe->item_ID, image_props); } /*0: the current file*/ location_entry->data_reference_index = 0; if (self_reference) { GF_ItemExtentEntry *entry; GF_SAFEALLOC(entry, GF_ItemExtentEntry); gf_list_add(location_entry->extent_entries, entry); if (!infe->item_name) infe->item_name = gf_strdup(""); return GF_OK; } /*file not copied, just referenced*/ if (URL || URN) { u32 dataRefIndex; if (!meta->file_locations) meta->file_locations = (GF_DataInformationBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DINF); if (!meta->file_locations->dref) meta->file_locations->dref = (GF_DataReferenceBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DREF); e = Media_FindDataRef(meta->file_locations->dref, (char *) URL, (char *) URN, &dataRefIndex); if (e) return e; if (!dataRefIndex) { e = Media_CreateDataRef(meta->file_locations->dref, (char *) URL, (char *) URN, &dataRefIndex); if (e) return e; } location_entry->data_reference_index = dataRefIndex; } /*capture mode, write to disk*/ if ((file->openMode == GF_ISOM_OPEN_WRITE) && !location_entry->data_reference_index) { FILE *src; GF_ItemExtentEntry *entry; GF_SAFEALLOC(entry, GF_ItemExtentEntry); location_entry->base_offset = gf_bs_get_position(file->editFileMap->bs); /*update base offset size*/ if (location_entry->base_offset>0xFFFFFFFF) meta->item_locations->base_offset_size = 8; else if (location_entry->base_offset && !meta->item_locations->base_offset_size) meta->item_locations->base_offset_size = 4; entry->extent_length = 0; entry->extent_offset = 0; gf_list_add(location_entry->extent_entries, entry); if (data) { gf_bs_write_data(file->editFileMap->bs, data, data_len); /*update length size*/ if (entry->extent_length>0xFFFFFFFF) meta->item_locations->length_size = 8; else if (entry->extent_length && !meta->item_locations->length_size) meta->item_locations->length_size = 4; } else if (resource_path) { src = gf_fopen(resource_path, "rb"); if (src) { char cache_data[4096]; u64 remain; gf_fseek(src, 0, SEEK_END); entry->extent_length = gf_ftell(src); gf_fseek(src, 0, SEEK_SET); remain = entry->extent_length; while (remain) { u32 size_cache = (remain>4096) ? 4096 : (u32) remain; size_t read = fread(cache_data, 1, size_cache, src); if (read==(size_t)-1) break; gf_bs_write_data(file->editFileMap->bs, cache_data, (u32) read); remain -= (u32) read; } gf_fclose(src); /*update length size*/ if (entry->extent_length>0xFFFFFFFF) meta->item_locations->length_size = 8; else if (entry->extent_length && !meta->item_locations->length_size) meta->item_locations->length_size = 4; } } } /*store full path for info*/ else if (!location_entry->data_reference_index) { if (data) { infe->full_path = (char *)gf_malloc(sizeof(char) * data_len); memcpy(infe->full_path, data, sizeof(char) * data_len); infe->data_len = data_len; } else { infe->full_path = gf_strdup(resource_path); infe->data_len = 0; } } return GF_OK; }
static GF_Err SVG_ProcessData(GF_SceneDecoder *plug, const char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 stream_time, u32 mmlevel) { GF_Err e = GF_OK; SVGIn *svgin = (SVGIn *)plug->privateStack; if (stream_time==(u32)-1) { if (svgin->src) gzclose(svgin->src); svgin->src = NULL; gf_sm_load_done(&svgin->loader); svgin->loader.fileName = NULL; svgin->file_pos = 0; gf_sg_reset(svgin->scene->graph); return GF_OK; } switch (svgin->oti) { /*!OTI for SVG dummy stream (dsi = file name) - GPAC internal*/ case GPAC_OTI_PRIVATE_SCENE_SVG: /*full doc parsing*/ if ((svgin->sax_max_duration==(u32) -1) && svgin->file_size) { /*init step*/ if (!svgin->loader.fileName) { /*not done yet*/ if (!svg_check_download(svgin)) return GF_OK; svgin->loader.fileName = svgin->file_name; e = gf_sm_load_init(&svgin->loader); } else { e = gf_sm_load_run(&svgin->loader); } } /*chunk parsing*/ else { u32 entry_time; char file_buf[SVG_PROGRESSIVE_BUFFER_SIZE+2]; /*initial load*/ if (!svgin->src && !svgin->file_pos) { svgin->src = gzopen(svgin->file_name, "rb"); if (!svgin->src) return GF_URL_ERROR; svgin->loader.fileName = svgin->file_name; gf_sm_load_init(&svgin->loader); } e = GF_OK; entry_time = gf_sys_clock(); while (1) { u32 diff; s32 nb_read; nb_read = gzread(svgin->src, file_buf, SVG_PROGRESSIVE_BUFFER_SIZE); /*we may have read nothing but we still need to call parse in case the parser got suspended*/ if (nb_read<=0) { nb_read = 0; if ((e==GF_EOS) && gzeof(svgin->src)) { gf_set_progress("SVG Parsing", svgin->file_pos, svgin->file_size); gzclose(svgin->src); svgin->src = NULL; gf_sm_load_done(&svgin->loader); } goto exit; } file_buf[nb_read] = file_buf[nb_read+1] = 0; e = gf_sm_load_string(&svgin->loader, file_buf, 0); svgin->file_pos += nb_read; /*handle decompression*/ if (svgin->file_pos > svgin->file_size) svgin->file_size = svgin->file_pos + 1; if (e) break; gf_set_progress("SVG Parsing", svgin->file_pos, svgin->file_size); diff = gf_sys_clock() - entry_time; if (diff > svgin->sax_max_duration) { break; } } } break; /*!OTI for streaming SVG - GPAC internal*/ case GPAC_OTI_SCENE_SVG: e = gf_sm_load_string(&svgin->loader, inBuffer, 0); break; /*!OTI for streaming SVG + gz - GPAC internal*/ case GPAC_OTI_SCENE_SVG_GZ: e = svgin_deflate(svgin, inBuffer, inBufferLength); break; /*!OTI for DIMS (dsi = 3GPP DIMS configuration) - GPAC internal*/ case GPAC_OTI_SCENE_DIMS: { u8 prev, dims_hdr; u32 nb_bytes, size; u64 pos; char * buf2 = gf_malloc(inBufferLength); GF_BitStream *bs = gf_bs_new(inBuffer, inBufferLength, GF_BITSTREAM_READ); memcpy(buf2, inBuffer, inBufferLength); // FILE *f = gf_f64_open("dump.svg", "wb"); // while (gf_bs_available(bs)) { pos = gf_bs_get_position(bs); size = gf_bs_read_u16(bs); nb_bytes = 2; /*GPAC internal hack*/ if (!size) { size = gf_bs_read_u32(bs); nb_bytes = 6; } // gf_fwrite( inBuffer + pos + nb_bytes + 1, 1, size - 1, f ); dims_hdr = gf_bs_read_u8(bs); prev = buf2[pos + nb_bytes + size]; buf2[pos + nb_bytes + size] = 0; if (dims_hdr & GF_DIMS_UNIT_C) { e = svgin_deflate(svgin, buf2 + pos + nb_bytes + 1, size - 1); } else { e = gf_sm_load_string(&svgin->loader, buf2 + pos + nb_bytes + 1, 0); } buf2[pos + nb_bytes + size] = prev; gf_bs_skip_bytes(bs, size-1); } // fclose(f); gf_bs_del(bs); } break; default: return GF_BAD_PARAM; } exit: if ((e>=GF_OK) && (svgin->scene->graph_attached!=1) && (gf_sg_get_root_node(svgin->loader.scene_graph)!=NULL) ) { gf_scene_attach_to_compositor(svgin->scene); } /*prepare for next playback*/ if (e) { gf_sm_load_done(&svgin->loader); svgin->loader.fileName = NULL; e = GF_EOS; } return e; }
//write the file track by track, with moov box before or after the mdat GF_Err WriteFlat(MovieWriter *mw, u8 moovFirst, GF_BitStream *bs) { GF_Err e; u32 i; u64 offset, finalOffset, totSize, begin, firstSize, finalSize; GF_Box *a; GF_List *writers = gf_list_new(); GF_ISOFile *movie = mw->movie; begin = totSize = 0; //first setup the writers e = SetupWriters(mw, writers, 0); if (e) goto exit; if (!moovFirst) { if (movie->openMode == GF_ISOM_OPEN_WRITE) { begin = 0; totSize = gf_isom_datamap_get_offset(movie->editFileMap); /*start boxes have not been written yet, do it*/ if (!totSize) { if (movie->is_jp2) { gf_bs_write_u32(movie->editFileMap->bs, 12); gf_bs_write_u32(movie->editFileMap->bs, GF_4CC('j','P',' ',' ')); gf_bs_write_u32(movie->editFileMap->bs, 0x0D0A870A); totSize += 12; begin += 12; } if (movie->brand) { e = gf_isom_box_size((GF_Box *)movie->brand); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->brand, movie->editFileMap->bs); if (e) goto exit; totSize += movie->brand->size; begin += movie->brand->size; } if (movie->pdin) { e = gf_isom_box_size((GF_Box *)movie->pdin); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->pdin, movie->editFileMap->bs); if (e) goto exit; totSize += movie->pdin->size; begin += movie->pdin->size; } } else { if (movie->is_jp2) begin += 12; if (movie->brand) begin += movie->brand->size; if (movie->pdin) begin += movie->pdin->size; } totSize -= begin; } else { if (movie->is_jp2) { gf_bs_write_u32(bs, 12); gf_bs_write_u32(bs, GF_4CC('j','P',' ',' ')); gf_bs_write_u32(bs, 0x0D0A870A); } if (movie->brand) { e = gf_isom_box_size((GF_Box *)movie->brand); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->brand, bs); if (e) goto exit; } /*then progressive download*/ if (movie->pdin) { e = gf_isom_box_size((GF_Box *)movie->pdin); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->pdin, bs); if (e) goto exit; } } //if the moov is at the end, write directly i=0; while ((a = (GF_Box*)gf_list_enum(movie->TopBoxes, &i))) { switch (a->type) { /*written by hand*/ case GF_ISOM_BOX_TYPE_MOOV: case GF_ISOM_BOX_TYPE_META: case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_PDIN: break; case GF_ISOM_BOX_TYPE_MDAT: //in case we're capturing if (movie->openMode == GF_ISOM_OPEN_WRITE) { //emulate a write to recreate our tables (media data already written) e = DoWrite(mw, writers, bs, 1, begin); if (e) goto exit; continue; } //to avoid computing the size each time write always 4 + 4 + 8 bytes before begin = gf_bs_get_position(bs); gf_bs_write_u64(bs, 0); gf_bs_write_u64(bs, 0); e = DoWrite(mw, writers, bs, 0, gf_bs_get_position(bs)); if (e) goto exit; totSize = gf_bs_get_position(bs) - begin; break; default: e = gf_isom_box_size(a); if (e) goto exit; e = gf_isom_box_write(a, bs); if (e) goto exit; break; } } //OK, write the movie box. e = WriteMoovAndMeta(movie, writers, bs); if (e) goto exit; /*if data has been written, update mdat size*/ if (totSize) { offset = gf_bs_get_position(bs); e = gf_bs_seek(bs, begin); if (e) goto exit; if (totSize > 0xFFFFFFFF) { gf_bs_write_u32(bs, 1); } else { gf_bs_write_u32(bs, (u32) totSize); } gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_MDAT); if (totSize > 0xFFFFFFFF) gf_bs_write_u64(bs, totSize); e = gf_bs_seek(bs, offset); } movie->mdat->size = totSize; goto exit; } //nope, we have to write the moov first. The pb is that //1 - we don't know its size till the mdat is written //2 - we don't know the ofset at which the mdat will start... //3 - once the mdat is written, the chunkOffset table can have changed... if (movie->is_jp2) { gf_bs_write_u32(bs, 12); gf_bs_write_u32(bs, GF_4CC('j','P',' ',' ')); gf_bs_write_u32(bs, 0x0D0A870A); } if (movie->brand) { e = gf_isom_box_size((GF_Box *)movie->brand); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->brand, bs); if (e) goto exit; } /*then progressive dnload*/ if (movie->pdin) { e = gf_isom_box_size((GF_Box *)movie->pdin); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->pdin, bs); if (e) goto exit; } //What we will do is first emulate the write from the begining... //note: this will set the size of the mdat e = DoWrite(mw, writers, bs, 1, gf_bs_get_position(bs)); if (e) goto exit; firstSize = GetMoovAndMetaSize(movie, writers); //offset = (firstSize > 0xFFFFFFFF ? firstSize + 8 : firstSize) + 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); offset = firstSize + 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); e = ShiftOffset(movie, writers, offset); if (e) goto exit; //get the size and see if it has changed (eg, we moved to 64 bit offsets) finalSize = GetMoovAndMetaSize(movie, writers); if (firstSize != finalSize) { //we need to remove our offsets ResetWriters(writers); //finalOffset = (finalSize > 0xFFFFFFFF ? finalSize + 8 : finalSize) + 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); finalOffset = finalSize + 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); //OK, now we're sure about the final size. //we don't need to re-emulate, as the only thing that changed is the offset //so just shift the offset e = ShiftOffset(movie, writers, finalOffset - offset); if (e) goto exit; } //now write our stuff e = WriteMoovAndMeta(movie, writers, bs); if (e) goto exit; e = gf_isom_box_size((GF_Box *)movie->mdat); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->mdat, bs); if (e) goto exit; //we don't need the offset as the moov is already written... ResetWriters(writers); e = DoWrite(mw, writers, bs, 0, 0); if (e) goto exit; //then the rest i=0; while ((a = (GF_Box*)gf_list_enum(movie->TopBoxes, &i))) { switch (a->type) { case GF_ISOM_BOX_TYPE_MOOV: case GF_ISOM_BOX_TYPE_META: case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_PDIN: case GF_ISOM_BOX_TYPE_MDAT: break; default: e = gf_isom_box_size(a); if (e) goto exit; e = gf_isom_box_write(a, bs); if (e) goto exit; } } exit: CleanWriters(writers); gf_list_del(writers); return e; }
GF_EXPORT void gf_img_parse(GF_BitStream *bs, u8 *OTI, u32 *mtype, u32 *width, u32 *height, char **dsi, u32 *dsi_len) { u8 b1, b2, b3; u32 size, type; u64 pos; pos = gf_bs_get_position(bs); gf_bs_seek(bs, 0); *mtype = *width = *height = 0; *OTI = 0; if (dsi) { *dsi = NULL; *dsi_len = 0; } b1 = gf_bs_read_u8(bs); b2 = gf_bs_read_u8(bs); b3 = gf_bs_read_u8(bs); /*JPEG*/ if ((b1==0xFF) && (b2==0xD8) && (b3==0xFF)) { u32 offset = 0; u32 Xdens, Ydens, nb_comp; gf_bs_read_u8(bs); gf_bs_skip_bytes(bs, 10); /*2 size, 5 JFIF\0, 2 version, 1 units*/ Xdens = gf_bs_read_int(bs, 16); Ydens = gf_bs_read_int(bs, 16); nb_comp = 0; /*get frame header FFC0*/ while (gf_bs_available(bs)) { u32 type, w, h; if (gf_bs_read_u8(bs) != 0xFF) continue; if (!offset) offset = (u32)gf_bs_get_position(bs) - 1; type = gf_bs_read_u8(bs); /*process all Start of Image markers*/ switch (type) { case 0xC0: case 0xC1: case 0xC2: case 0xC3: case 0xC5: case 0xC6: case 0xC7: case 0xC9: case 0xCA: case 0xCB: case 0xCD: case 0xCE: case 0xCF: gf_bs_skip_bytes(bs, 3); h = gf_bs_read_int(bs, 16); w = gf_bs_read_int(bs, 16); if ((w > *width) || (h > *height)) { *width = w; *height = h; } nb_comp = gf_bs_read_int(bs, 8); break; } } *OTI = GPAC_OTI_IMAGE_JPEG; *mtype = GF_4CC('j','p','e','g'); if (dsi) { GF_BitStream *bs_dsi = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_u16(bs_dsi, offset); gf_bs_write_u16(bs_dsi, Xdens); gf_bs_write_u16(bs_dsi, Ydens); gf_bs_write_u8(bs_dsi, nb_comp); gf_bs_get_content(bs_dsi, dsi, dsi_len); gf_bs_del(bs_dsi); } } /*PNG*/ else if ((b1==0x89) && (b2==0x50) && (b3==0x4E)) { /*check for PNG sig*/ if ( (gf_bs_read_u8(bs) != 0x47) || (gf_bs_read_u8(bs) != 0x0D) || (gf_bs_read_u8(bs) != 0x0A) || (gf_bs_read_u8(bs) != 0x1A) || (gf_bs_read_u8(bs) != 0x0A) ) goto exit; gf_bs_read_u32(bs); /*check for PNG IHDR*/ if ( (gf_bs_read_u8(bs) != 'I') || (gf_bs_read_u8(bs) != 'H') || (gf_bs_read_u8(bs) != 'D') || (gf_bs_read_u8(bs) != 'R')) goto exit; *width = gf_bs_read_u32(bs); *height = gf_bs_read_u32(bs); *OTI = GPAC_OTI_IMAGE_PNG; *mtype = GF_4CC('p','n','g',' '); } size = gf_bs_read_u8(bs); type = gf_bs_read_u32(bs); if ( ((size==12) && (type==GF_4CC('j','P',' ',' ') )) || (type==GF_4CC('j','p','2','h') ) ) { if (type==GF_4CC('j','p','2','h')) { *OTI = GPAC_OTI_IMAGE_JPEG_2000; *mtype = GF_4CC('j','p','2',' '); goto j2k_restart; } type = gf_bs_read_u32(bs); if (type!=0x0D0A870A) goto exit; *OTI = GPAC_OTI_IMAGE_JPEG_2000; *mtype = GF_4CC('j','p','2',' '); while (gf_bs_available(bs)) { j2k_restart: size = gf_bs_read_u32(bs); type = gf_bs_read_u32(bs); switch (type) { case GF_4CC('j','p','2','h'): goto j2k_restart; case GF_4CC('i','h','d','r'): { u16 nb_comp; u8 BPC, C, UnkC, IPR; *height = gf_bs_read_u32(bs); *width = gf_bs_read_u32(bs); nb_comp = gf_bs_read_u16(bs); BPC = gf_bs_read_u8(bs); C = gf_bs_read_u8(bs); UnkC = gf_bs_read_u8(bs); IPR = gf_bs_read_u8(bs); if (dsi) { GF_BitStream *bs_dsi = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_u32(bs_dsi, *height); gf_bs_write_u32(bs_dsi, *width); gf_bs_write_u16(bs_dsi, nb_comp); gf_bs_write_u8(bs_dsi, BPC); gf_bs_write_u8(bs_dsi, C); gf_bs_write_u8(bs_dsi, UnkC); gf_bs_write_u8(bs_dsi, IPR); gf_bs_get_content(bs_dsi, dsi, dsi_len); gf_bs_del(bs_dsi); } goto exit; } break; default: gf_bs_skip_bytes(bs, size-8); break; } } } exit: gf_bs_seek(bs, pos); }
static GF_Err WriteInterleaved(MovieWriter *mw, GF_BitStream *bs, Bool drift_inter) { GF_Err e; u32 i; GF_Box *a; u64 firstSize, finalSize, offset, finalOffset; GF_List *writers = gf_list_new(); GF_ISOFile *movie = mw->movie; //first setup the writers e = SetupWriters(mw, writers, 1); if (e) goto exit; if (movie->is_jp2) { gf_bs_write_u32(bs, 12); gf_bs_write_u32(bs, GF_4CC('j','P',' ',' ')); gf_bs_write_u32(bs, 0x0D0A870A); } if (movie->brand) { e = gf_isom_box_size((GF_Box *)movie->brand); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->brand, bs); if (e) goto exit; } if (movie->pdin) { e = gf_isom_box_size((GF_Box *)movie->pdin); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->pdin, bs); if (e) goto exit; } e = DoInterleave(mw, writers, bs, 1, gf_bs_get_position(bs), drift_inter); if (e) goto exit; firstSize = GetMoovAndMetaSize(movie, writers); offset = firstSize; if (movie->mdat && movie->mdat->dataSize) offset += 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); e = ShiftOffset(movie, writers, offset); if (e) goto exit; //get the size and see if it has changed (eg, we moved to 64 bit offsets) finalSize = GetMoovAndMetaSize(movie, writers); if (firstSize != finalSize) { //we need to remove our offsets ResetWriters(writers); finalOffset = finalSize; if (movie->mdat->dataSize) finalOffset += 8 + (movie->mdat->dataSize > 0xFFFFFFFF ? 8 : 0); //OK, now we're sure about the final size -> shift the offsets //we don't need to re-emulate, as the only thing that changed is the offset //so just shift the offset e = ShiftOffset(movie, writers, finalOffset - offset); if (e) goto exit; firstSize = GetMoovAndMetaSize(movie, writers); } //now write our stuff e = WriteMoovAndMeta(movie, writers, bs); if (e) goto exit; /*we have 8 extra bytes for large size (not computed in gf_isom_box_size) */ if (movie->mdat && movie->mdat->dataSize) { if (movie->mdat->dataSize > 0xFFFFFFFF) movie->mdat->dataSize += 8; e = gf_isom_box_size((GF_Box *)movie->mdat); if (e) goto exit; e = gf_isom_box_write((GF_Box *)movie->mdat, bs); if (e) goto exit; } //we don't need the offset as we are writing... ResetWriters(writers); e = DoInterleave(mw, writers, bs, 0, 0, drift_inter); if (e) goto exit; //then the rest i=0; while ((a = (GF_Box*)gf_list_enum(movie->TopBoxes, &i))) { switch (a->type) { case GF_ISOM_BOX_TYPE_MOOV: case GF_ISOM_BOX_TYPE_META: case GF_ISOM_BOX_TYPE_FTYP: case GF_ISOM_BOX_TYPE_PDIN: case GF_ISOM_BOX_TYPE_MDAT: break; default: e = gf_isom_box_size(a); if (e) goto exit; e = gf_isom_box_write(a, bs); if (e) goto exit; } } exit: CleanWriters(writers); gf_list_del(writers); return e; }
GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing, Bool progressive_mode) { GF_Box *a; u64 totSize; GF_Err e = GF_OK; totSize = 0; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS /*restart from where we stopped last*/ totSize = mov->current_top_box_start; gf_bs_seek(mov->movieFileMap->bs, mov->current_top_box_start); #endif /*while we have some data, parse our boxes*/ while (gf_bs_available(mov->movieFileMap->bs)) { *bytesMissing = 0; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS mov->current_top_box_start = gf_bs_get_position(mov->movieFileMap->bs); #endif e = gf_isom_parse_root_box(&a, mov->movieFileMap->bs, bytesMissing, progressive_mode); if (e >= 0) { e = GF_OK; } else if (e == GF_ISOM_INCOMPLETE_FILE) { /*our mdat is uncomplete, only valid for READ ONLY files...*/ if (mov->openMode != GF_ISOM_OPEN_READ) { return GF_ISOM_INVALID_FILE; } return e; } else { return e; } switch (a->type) { /*MOOV box*/ case GF_ISOM_BOX_TYPE_MOOV: if (mov->moov) return GF_ISOM_INVALID_FILE; mov->moov = (GF_MovieBox *)a; /*set our pointer to the movie*/ mov->moov->mov = mov; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS if (mov->moov->mvex) mov->moov->mvex->mov = mov; #endif e = gf_list_add(mov->TopBoxes, a); if (e) return e; totSize += a->size; break; /*META box*/ case GF_ISOM_BOX_TYPE_META: if (mov->meta) return GF_ISOM_INVALID_FILE; mov->meta = (GF_MetaBox *)a; e = gf_list_add(mov->TopBoxes, a); if (e) return e; totSize += a->size; break; /*we only keep the MDAT in READ for dump purposes*/ case GF_ISOM_BOX_TYPE_MDAT: totSize += a->size; if (mov->openMode == GF_ISOM_OPEN_READ) { if (!mov->mdat) { mov->mdat = (GF_MediaDataBox *) a; e = gf_list_add(mov->TopBoxes, mov->mdat); if (e) return e; } #ifndef GPAC_DISABLE_ISOM_FRAGMENTS else if (mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG) gf_list_add(mov->TopBoxes, a); #endif else gf_isom_box_del(a); } /*if we don't have any MDAT yet, create one (edit-write mode) We only work with one mdat, but we're puting it at the place of the first mdat found when opening a file for editing*/ else if (!mov->mdat && (mov->openMode != GF_ISOM_OPEN_READ) && (mov->openMode != GF_ISOM_OPEN_CAT_FRAGMENTS)) { gf_isom_box_del(a); mov->mdat = (GF_MediaDataBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MDAT); e = gf_list_add(mov->TopBoxes, mov->mdat); if (e) return e; } else { gf_isom_box_del(a); } break; case GF_ISOM_BOX_TYPE_FTYP: /*ONE AND ONLY ONE FTYP*/ if (mov->brand) { gf_isom_box_del(a); return GF_ISOM_INVALID_FILE; } mov->brand = (GF_FileTypeBox *)a; totSize += a->size; e = gf_list_add(mov->TopBoxes, a); break; case GF_ISOM_BOX_TYPE_PDIN: /*ONE AND ONLY ONE PDIN*/ if (mov->pdin) { gf_isom_box_del(a); return GF_ISOM_INVALID_FILE; } mov->pdin = (GF_ProgressiveDownloadBox *) a; totSize += a->size; e = gf_list_add(mov->TopBoxes, a); break; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS case GF_ISOM_BOX_TYPE_STYP: if (((GF_SegmentTypeBox *)a)->majorBrand == GF_4CC('i', 's', 's', 's') || ((GF_SegmentTypeBox *)a)->majorBrand == GF_4CC('i', 'm', 's', 's')) mov->is_index_segment = 1; case GF_ISOM_BOX_TYPE_SIDX: totSize += a->size; if (mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG) { e = gf_list_add(mov->TopBoxes, a); } else { gf_isom_box_del(a); } break; case GF_ISOM_BOX_TYPE_MOOF: ((GF_MovieFragmentBox *)a)->mov = mov; totSize += a->size; mov->moof = (GF_MovieFragmentBox *) a; /*read & debug: store at root level*/ if (mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG) { gf_list_add(mov->TopBoxes, a); } else if (mov->openMode==GF_ISOM_OPEN_CAT_FRAGMENTS) { mov->NextMoofNumber = mov->moof->mfhd->sequence_number+1; mov->moof = NULL; gf_isom_box_del(a); } else { /*merge all info*/ e = MergeFragment((GF_MovieFragmentBox *)a, mov); gf_isom_box_del(a); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Error merging fragment: %s\n", gf_error_to_string(e) )); } } break; #endif case GF_4CC('j','P',' ',' '): { GF_UnknownBox *box = (GF_UnknownBox*)a; u8 *c = box->data; if ((box->dataSize==4) && (GF_4CC(c[0],c[1],c[2],c[3])==(u32)0x0D0A870A)) mov->is_jp2 = 1; gf_isom_box_del(a); } break; default: totSize += a->size; e = gf_list_add(mov->TopBoxes, a); break; } #ifndef GPAC_DISABLE_ISOM_FRAGMENTS // mov->current_top_box_start = gf_bs_get_position(mov->movieFileMap->bs); #endif } /*we need at least moov or meta*/ if (!mov->moov && !mov->meta #ifndef GPAC_DISABLE_ISOM_FRAGMENTS && !mov->moof && !mov->is_index_segment #endif ) return GF_ISOM_INVALID_FILE; /*we MUST have movie header*/ if (mov->moov && !mov->moov->mvhd) return GF_ISOM_INVALID_FILE; /*we MUST have meta handler*/ if (mov->meta && !mov->meta->handler) return GF_ISOM_INVALID_FILE; #ifndef GPAC_DISABLE_ISOM_WRITE if (mov->moov) { /*set the default interleaving time*/ mov->interleavingTime = mov->moov->mvhd->timeScale; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS /*in edit mode with successfully loaded fragments, delete all fragment signaling since file is no longer fragmented*/ if ((mov->openMode > GF_ISOM_OPEN_READ) && (mov->openMode != GF_ISOM_OPEN_CAT_FRAGMENTS) && mov->moov->mvex) { gf_isom_box_del((GF_Box *)mov->moov->mvex); mov->moov->mvex = NULL; } #endif } #endif /*GPAC_DISABLE_ISOM_WRITE*/ return GF_OK; }
GF_Err gp_rtp_builder_do_mpeg4(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize) { char *sl_buffer, *payl_buffer; u32 sl_buffer_size, payl_buffer_size; u32 auh_size_tmp, bytesLeftInPacket, infoSize, pckSize; u64 pos; u8 flush_pck, no_split; flush_pck = 0; bytesLeftInPacket = data_size; /*flush everything*/ if (!data) { if (builder->payload) goto flush_packet; return GF_OK; } if (builder->payload && builder->force_flush) goto flush_packet; //go till done while (bytesLeftInPacket) { no_split = 0; if (builder->sl_header.accessUnitStartFlag) { //init SL if (builder->sl_header.compositionTimeStamp != builder->sl_header.decodingTimeStamp) { builder->sl_header.decodingTimeStampFlag = 1; } builder->sl_header.compositionTimeStampFlag = 1; builder->sl_header.accessUnitLength = FullAUSize; //init some vars - based on the available size and the TS //we decide if we go with the same RTP TS serie or not if (builder->payload) { //don't store more than what we can (that is 2^slMap->CTSDelta - 1) if ( (builder->flags & GP_RTP_PCK_SIGNAL_TS) && (builder->sl_header.compositionTimeStamp - builder->rtp_header.TimeStamp >= (u32) ( 1 << builder->slMap.CTSDeltaLength) ) ) { goto flush_packet; } //don't split AU if # TS , start a new RTP pck if (builder->sl_header.compositionTimeStamp != builder->rtp_header.TimeStamp) no_split = 1; } } /*new RTP Packet*/ if (!builder->payload) { /*first SL in RTP*/ builder->first_sl_in_rtp = 1; /*if this is the end of an AU we will set it to 0 as soon as an AU is splited*/ builder->rtp_header.Marker = 1; builder->rtp_header.PayloadType = builder->PayloadType; builder->rtp_header.SequenceNumber += 1; builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp; /*prepare the mapped headers*/ builder->pck_hdr = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); builder->payload = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); pckSize = infoSize = 0; builder->bytesInPacket = 0; /*in multiSL there is a MSLHSize structure on 2 bytes*/ builder->auh_size = 0; if (builder->has_AU_header) { builder->auh_size = 16; gf_bs_write_int(builder->pck_hdr, 0, 16); } flush_pck = 0; /*and create packet*/ builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header); } //make sure we are not interleaving too much - this should never happen actually if (builder->slMap.IndexDeltaLength && !builder->first_sl_in_rtp && (builder->sl_header.AU_sequenceNumber - builder->last_au_sn >= (u32) 1<<builder->slMap.IndexDeltaLength)) { //we cannot write this packet here goto flush_packet; } /*check max ptime*/ if (builder->max_ptime && ( (u32) builder->sl_header.compositionTimeStamp >= builder->rtp_header.TimeStamp + builder->max_ptime) ) goto flush_packet; auh_size_tmp = gf_rtp_build_au_hdr_size(builder, &builder->sl_header); infoSize = auh_size_tmp + builder->auh_size; infoSize /= 8; /*align*/ if ( (builder->auh_size + auh_size_tmp) % 8) infoSize += 1; if (bytesLeftInPacket + infoSize + builder->bytesInPacket <= builder->Path_MTU) { //End of our data chunk pckSize = bytesLeftInPacket; builder->sl_header.accessUnitEndFlag = IsAUEnd; builder->auh_size += auh_size_tmp; builder->sl_header.paddingFlag = builder->sl_header.paddingBits ? 1 : 0; } else { //AU cannot fit in packet. If no split, start a new packet if (no_split) goto flush_packet; builder->auh_size += auh_size_tmp; pckSize = builder->Path_MTU - (infoSize + builder->bytesInPacket); //that's the end of the rtp packet flush_pck = 1; //but not of the AU -> marker is 0 builder->rtp_header.Marker = 0; } gf_rtp_build_au_hdr_write(builder, pckSize, builder->rtp_header.TimeStamp); //notify the user of our data structure if (builder->OnDataReference) builder->OnDataReference(builder->cbk_obj, pckSize, data_size - bytesLeftInPacket); else gf_bs_write_data(builder->payload, data + (data_size - bytesLeftInPacket), pckSize); bytesLeftInPacket -= pckSize; builder->bytesInPacket += pckSize; /*update IV*/ builder->IV += pckSize; builder->sl_header.paddingFlag = 0; builder->sl_header.accessUnitStartFlag = 0; //we are splitting a payload, auto increment SL seq num if (bytesLeftInPacket) { builder->sl_header.packetSequenceNumber += 1; } else if (! (builder->flags & GP_RTP_PCK_USE_MULTI) ) { builder->rtp_header.Marker = 1; flush_pck = 1; } //first SL in RTP is done builder->first_sl_in_rtp = 0; //store current sl builder->last_au_sn = builder->sl_header.AU_sequenceNumber; if (!flush_pck) continue; //done with the packet flush_packet: gf_bs_align(builder->pck_hdr); /*no aux data yet*/ if (builder->slMap.AuxiliaryDataSizeLength) { //write RSLH after the MSLH gf_bs_write_int(builder->pck_hdr, 0, builder->slMap.AuxiliaryDataSizeLength); } /*rewrite the size header*/ if (builder->has_AU_header) { pos = gf_bs_get_position(builder->pck_hdr); gf_bs_seek(builder->pck_hdr, 0); builder->auh_size -= 16; gf_bs_write_int(builder->pck_hdr, builder->auh_size, 16); gf_bs_seek(builder->pck_hdr, pos); } sl_buffer = NULL; gf_bs_get_content(builder->pck_hdr, &sl_buffer, &sl_buffer_size); //delete our bitstream gf_bs_del(builder->pck_hdr); builder->pck_hdr = NULL; payl_buffer = NULL; payl_buffer_size = 0; if (!builder->OnDataReference) gf_bs_get_content(builder->payload, &payl_buffer, &payl_buffer_size); gf_bs_del(builder->payload); builder->payload = NULL; /*notify header*/ builder->OnData(builder->cbk_obj, sl_buffer, sl_buffer_size, 1); /*notify payload*/ if (payl_buffer) { builder->OnData(builder->cbk_obj, payl_buffer, payl_buffer_size, 0); gf_free(payl_buffer); } /*flush packet*/ builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); gf_free(sl_buffer); } //packet is done, update AU markers if (IsAUEnd) { builder->sl_header.accessUnitStartFlag = 1; builder->sl_header.accessUnitEndFlag = 0; } return GF_OK; }
static GF_Err gf_m2ts_decode_ait(GF_M2TS_AIT *ait, char *data, u32 data_size, u32 table_id) { GF_BitStream *bs; u8 temp_descriptor_tag; u32 data_shift, app_desc_data_shift, ait_app_data_shift; u32 nb_of_protocol; data_shift = 0; temp_descriptor_tag = 0; ait_app_data_shift = 0; bs = gf_bs_new(data,data_size,GF_BITSTREAM_READ); ait->common_descriptors = gf_list_new(); if(ait->common_descriptors == NULL){ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Error during common_descriptors list initialization, abording processing \n")); return GF_CORRUPTED_DATA; } ait->application_decoded = gf_list_new(); if(ait->application_decoded == NULL){ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Error during application list initialization, abording processing \n")); return GF_CORRUPTED_DATA; } ait->table_id = gf_bs_read_int(bs,8); ait->section_syntax_indicator = gf_bs_read_int(bs,1); gf_bs_read_int(bs,3); ait->section_length = gf_bs_read_int(bs,12); if( (data[1] & 0x0C) != 0){ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] section length is not correct abroding \n")); }else if( ait->section_length > AIT_SECTION_LENGTH_MAX){ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] section length should not exceed 1021. Wrong section, abording processing \n")); } ait->test_application_flag = gf_bs_read_int(bs,1); if(ait->test_application_flag == 1){ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] test application flag is at 1. API transmitted for testing, abording processing \n")); return GF_CORRUPTED_DATA; } ait->application_type = gf_bs_read_int(bs,15); if(ait->application_type != APPLICATION_TYPE_HTTP_APPLICATION){ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] application type should 0x10. Wrong section, abording processing \n")); return GF_CORRUPTED_DATA; } gf_bs_read_int(bs,2); ait->version_number = gf_bs_read_int(bs,5); ait->current_next_indicator = gf_bs_read_int(bs,1); if(!ait->current_next_indicator){ GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] current next indicator should be at 1 \n")); return GF_CORRUPTED_DATA; } ait->section_number = gf_bs_read_int(bs,8); ait->last_section_number = gf_bs_read_int(bs,8); gf_bs_read_int(bs,4);/* bit shifting */ ait->common_descriptors_length = gf_bs_read_int(bs,12); gf_bs_read_int(bs,(unsigned int)ait->common_descriptors_length/8); gf_bs_read_int(bs,4);/* bit shifting */ ait->application_loop_length = gf_bs_read_int(bs,12); data_shift = (u32)(gf_bs_get_position(bs)) + ait->common_descriptors_length/8; while (ait_app_data_shift < ait->application_loop_length) { GF_M2TS_AIT_APPLICATION_DECODE* application; GF_SAFEALLOC(application,GF_M2TS_AIT_APPLICATION_DECODE); application->application_descriptors = gf_list_new(); application->index_app_desc_id = 0; /* application loop */ application->organisation_id = gf_bs_read_int(bs,32); application->application_id= gf_bs_read_int(bs,16); application->application_control_code= gf_bs_read_int(bs,8); gf_bs_read_int(bs,4);/* bit shifting */ application->application_descriptors_loop_length= gf_bs_read_int(bs,12); ait_app_data_shift += 9; app_desc_data_shift = 0; nb_of_protocol = 0; while (app_desc_data_shift< application->application_descriptors_loop_length) { temp_descriptor_tag = gf_bs_read_int(bs,8); switch (temp_descriptor_tag) { case APPLICATION_DESCRIPTOR: { u64 pre_processing_pos; u8 i; GF_M2TS_APPLICATION_DESCRIPTOR *application_descriptor; GF_SAFEALLOC(application_descriptor, GF_M2TS_APPLICATION_DESCRIPTOR); application_descriptor->descriptor_tag = temp_descriptor_tag; application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag; application->index_app_desc_id++; application_descriptor->descriptor_length = gf_bs_read_int(bs,8); pre_processing_pos = gf_bs_get_position(bs); application_descriptor->application_profiles_length = gf_bs_read_int(bs,8); application_descriptor->application_profile = gf_bs_read_int(bs,16); application_descriptor->version_major = gf_bs_read_int(bs,8); application_descriptor->version_minor = gf_bs_read_int(bs,8); application_descriptor->version_micro = gf_bs_read_int(bs,8); application_descriptor->service_bound_flag = gf_bs_read_int(bs,1); application_descriptor->visibility = gf_bs_read_int(bs,2); gf_bs_read_int(bs,5); /*bit shift*/ application_descriptor->application_priority = gf_bs_read_int(bs,8); if (nb_of_protocol > 0) { for (i=0; i<nb_of_protocol; i++) { application_descriptor->transport_protocol_label[i] = gf_bs_read_int(bs,8); } } else { application_descriptor->transport_protocol_label[0] = gf_bs_read_int(bs,8); } if (pre_processing_pos+application_descriptor->descriptor_length != gf_bs_get_position(bs) || application_descriptor->application_profile == 2 /* PVR feature */) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) - pre_processing_pos),application_descriptor->descriptor_length)); gf_free(application_descriptor); return GF_CORRUPTED_DATA; } gf_list_add(application->application_descriptors,application_descriptor); app_desc_data_shift += (2+ application_descriptor->descriptor_length); break; } case APPLICATION_NAME_DESCRIPTOR: { u64 pre_processing_pos; GF_M2TS_APPLICATION_NAME_DESCRIPTOR* name_descriptor; GF_SAFEALLOC(name_descriptor, GF_M2TS_APPLICATION_NAME_DESCRIPTOR); application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag; application->index_app_desc_id++; name_descriptor->descriptor_tag = temp_descriptor_tag; name_descriptor->descriptor_length = gf_bs_read_int(bs,8); pre_processing_pos = gf_bs_get_position(bs); name_descriptor->ISO_639_language_code = gf_bs_read_int(bs,24); name_descriptor->application_name_length = gf_bs_read_int(bs,8); name_descriptor->application_name_char = (char*) gf_calloc(name_descriptor->application_name_length+1,sizeof(char)); gf_bs_read_data(bs,name_descriptor->application_name_char,name_descriptor->application_name_length); name_descriptor->application_name_char[name_descriptor->application_name_length] = 0 ; if (pre_processing_pos+name_descriptor->descriptor_length != gf_bs_get_position(bs)) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) - pre_processing_pos),name_descriptor->descriptor_length)); gf_free(name_descriptor->application_name_char); gf_free(name_descriptor); return GF_CORRUPTED_DATA; } gf_list_add(application->application_descriptors,name_descriptor); app_desc_data_shift += (2+ name_descriptor->descriptor_length); break; } case TRANSPORT_PROTOCOL_DESCRIPTOR: { u64 pre_processing_pos; GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR* protocol_descriptor; GF_SAFEALLOC(protocol_descriptor, GF_M2TS_TRANSPORT_PROTOCOL_DESCRIPTOR); application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag; application->index_app_desc_id++; nb_of_protocol++; protocol_descriptor->descriptor_tag = temp_descriptor_tag; protocol_descriptor->descriptor_length = gf_bs_read_int(bs,8); pre_processing_pos = gf_bs_get_position(bs); protocol_descriptor->protocol_id = gf_bs_read_int(bs,16); protocol_descriptor->transport_protocol_label = gf_bs_read_int(bs,8); switch (protocol_descriptor->protocol_id) { case CAROUSEL: { GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE* Carousel_selector_byte; GF_SAFEALLOC(Carousel_selector_byte, GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE); Carousel_selector_byte->remote_connection = gf_bs_read_int(bs,1); gf_bs_read_int(bs,7); /* bit shifting */ if (Carousel_selector_byte->remote_connection) { Carousel_selector_byte->original_network_id = gf_bs_read_int(bs,16); Carousel_selector_byte->transport_stream_id = gf_bs_read_int(bs,16); Carousel_selector_byte->service_id = gf_bs_read_int(bs,16); } Carousel_selector_byte->component_tag = gf_bs_read_int(bs,8); protocol_descriptor->selector_byte = Carousel_selector_byte; break; } case TRANSPORT_HTTP: { u32 i; GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE* Transport_http_selector_byte; GF_SAFEALLOC(Transport_http_selector_byte, GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE); Transport_http_selector_byte->URL_base_length = gf_bs_read_int(bs,8); //fprintf(stderr, "Transport_http_selector_byte->URL_base_length %d \n",Transport_http_selector_byte->URL_base_length); Transport_http_selector_byte->URL_base_byte = (char*)gf_calloc(Transport_http_selector_byte->URL_base_length+1,sizeof(char)); gf_bs_read_data(bs,Transport_http_selector_byte->URL_base_byte ,(u32)(Transport_http_selector_byte->URL_base_length)); Transport_http_selector_byte->URL_base_byte[Transport_http_selector_byte->URL_base_length] = 0; Transport_http_selector_byte->URL_extension_count = gf_bs_read_int(bs,8); if (Transport_http_selector_byte->URL_extension_count) { Transport_http_selector_byte->URL_extentions = (GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION*) gf_calloc(Transport_http_selector_byte->URL_extension_count,sizeof(GF_M2TS_TRANSPORT_HTTP_URL_EXTENTION)); for (i=0; i < Transport_http_selector_byte->URL_extension_count;i++) { Transport_http_selector_byte->URL_extentions[i].URL_extension_length = gf_bs_read_int(bs,8); Transport_http_selector_byte->URL_extentions[i].URL_extension_byte = (char*)gf_calloc(Transport_http_selector_byte->URL_extentions[i].URL_extension_length+1,sizeof(char)); gf_bs_read_data(bs,Transport_http_selector_byte->URL_extentions[i].URL_extension_byte,(u32)(Transport_http_selector_byte->URL_extentions[i].URL_extension_length)); Transport_http_selector_byte->URL_extentions[i].URL_extension_byte[Transport_http_selector_byte->URL_extentions[i].URL_extension_length] = 0; } } protocol_descriptor->selector_byte = Transport_http_selector_byte; break; } default: { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Protocol ID %d unsupported, ignoring the selector byte \n",protocol_descriptor->protocol_id)); } } if (pre_processing_pos+protocol_descriptor->descriptor_length != gf_bs_get_position(bs)) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) - pre_processing_pos),protocol_descriptor->descriptor_length)); if (protocol_descriptor->protocol_id == CAROUSEL) { GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE* Carousel_selector_byte = (GF_M2TS_OBJECT_CAROUSEL_SELECTOR_BYTE*) protocol_descriptor->selector_byte; gf_free(Carousel_selector_byte); } else if(protocol_descriptor->protocol_id ==TRANSPORT_HTTP) { u32 i; GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE* Transport_http_selector_byte = (GF_M2TS_TRANSPORT_HTTP_SELECTOR_BYTE*) protocol_descriptor->selector_byte; gf_free(Transport_http_selector_byte->URL_base_byte); for(i = 0; i < Transport_http_selector_byte->URL_extension_count;i++){ gf_free(Transport_http_selector_byte->URL_extentions[i].URL_extension_byte); } gf_free(Transport_http_selector_byte); } gf_free(protocol_descriptor); return GF_CORRUPTED_DATA; } gf_list_add(application->application_descriptors,protocol_descriptor); app_desc_data_shift += (2+ protocol_descriptor->descriptor_length); break; } case SIMPLE_APPLICATION_LOCATION_DESCRIPTOR: { u64 pre_processing_pos; GF_M2TS_SIMPLE_APPLICATION_LOCATION* Simple_application_location; GF_SAFEALLOC(Simple_application_location, GF_M2TS_SIMPLE_APPLICATION_LOCATION); application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag; application->index_app_desc_id++; Simple_application_location->descriptor_tag = temp_descriptor_tag; Simple_application_location->descriptor_length = gf_bs_read_int(bs,8); pre_processing_pos = gf_bs_get_position(bs); Simple_application_location->initial_path_bytes = (char*)gf_calloc(Simple_application_location->descriptor_length+1,sizeof(char)); gf_bs_read_data(bs,Simple_application_location->initial_path_bytes ,(u32)(Simple_application_location->descriptor_length)); Simple_application_location->initial_path_bytes[Simple_application_location->descriptor_length] = 0; if (pre_processing_pos+Simple_application_location->descriptor_length != gf_bs_get_position(bs)) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) - pre_processing_pos),Simple_application_location->descriptor_length)); gf_free(Simple_application_location->initial_path_bytes); gf_free(Simple_application_location); return GF_CORRUPTED_DATA; } gf_list_add(application->application_descriptors,Simple_application_location); app_desc_data_shift += (2+ Simple_application_location->descriptor_length); break; } case APPLICATION_USAGE_DESCRIPTOR: { u64 pre_processing_pos; GF_M2TS_APPLICATION_USAGE* Application_usage; GF_SAFEALLOC(Application_usage, GF_M2TS_APPLICATION_USAGE); application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag; application->index_app_desc_id++; Application_usage->descriptor_tag = temp_descriptor_tag; Application_usage->descriptor_length = gf_bs_read_int(bs,8); pre_processing_pos = gf_bs_get_position(bs); Application_usage->usage_type = gf_bs_read_int(bs,8); if (pre_processing_pos+Application_usage->descriptor_length != gf_bs_get_position(bs)) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) - pre_processing_pos),Application_usage->descriptor_length)); gf_free(Application_usage); return GF_CORRUPTED_DATA; } gf_list_add(application->application_descriptors,Application_usage); app_desc_data_shift += (2+ Application_usage->descriptor_length); break; } case APPLICATION_BOUNDARY_DESCRIPTOR: { u64 pre_processing_pos; u32 i; GF_M2TS_APPLICATION_BOUNDARY_DESCRIPTOR* boundary_descriptor; GF_SAFEALLOC(boundary_descriptor, GF_M2TS_APPLICATION_BOUNDARY_DESCRIPTOR); application->application_descriptors_id[application->index_app_desc_id] = temp_descriptor_tag; application->index_app_desc_id++; boundary_descriptor->descriptor_tag = temp_descriptor_tag; boundary_descriptor->descriptor_length = gf_bs_read_int(bs,8); pre_processing_pos = gf_bs_get_position(bs); boundary_descriptor->boundary_extension_count = gf_bs_read_int(bs,8); if (boundary_descriptor->boundary_extension_count > 0) { boundary_descriptor->boundary_extension_info = (GF_M2TS_APPLICATION_BOUNDARY_EXTENSION_INFO*)gf_calloc(boundary_descriptor->boundary_extension_count,sizeof(GF_M2TS_APPLICATION_BOUNDARY_EXTENSION_INFO)); for (i=0;i<boundary_descriptor->boundary_extension_count;i++) { boundary_descriptor->boundary_extension_info[i].boundary_extension_length = gf_bs_read_int(bs,8); if (boundary_descriptor->boundary_extension_info[i].boundary_extension_length > 0) { boundary_descriptor->boundary_extension_info[i].boundary_extension_byte = (char*)gf_calloc(boundary_descriptor->boundary_extension_info[i].boundary_extension_length+1,sizeof(char)); gf_bs_read_data(bs,boundary_descriptor->boundary_extension_info[i].boundary_extension_byte ,(u32)(boundary_descriptor->boundary_extension_info[i].boundary_extension_length)); boundary_descriptor->boundary_extension_info[i].boundary_extension_byte[boundary_descriptor->boundary_extension_info[i].boundary_extension_length] = 0; } } } if (pre_processing_pos+boundary_descriptor->descriptor_length != gf_bs_get_position(bs)) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor data processed length error. Difference between byte shifting %d and descriptor length %d \n",(gf_bs_get_position(bs) - pre_processing_pos),boundary_descriptor->descriptor_length)); if (boundary_descriptor->boundary_extension_count > 0) { u32 i; for (i=0;i<boundary_descriptor->boundary_extension_count;i++) { if (boundary_descriptor->boundary_extension_info[i].boundary_extension_length > 0) { gf_free(boundary_descriptor->boundary_extension_info[i].boundary_extension_byte); } } gf_free(boundary_descriptor->boundary_extension_info); } gf_free(boundary_descriptor); return GF_CORRUPTED_DATA; } gf_list_add(application->application_descriptors,boundary_descriptor); app_desc_data_shift += (2+ boundary_descriptor->descriptor_length); break; } default: { u8 length; GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] Descriptor tag %d unknown, ignoring the descriptor \n",temp_descriptor_tag)); /* get descriptor's length */ length = gf_bs_read_int(bs,8); /* bit shifting (eq descriptor's length)*/ gf_bs_read_int(bs,8*length); } } } ait_app_data_shift += application->application_descriptors_loop_length; gf_list_add(ait->application_decoded,application); } data_shift +=ait->application_loop_length; ait->CRC_32 = gf_bs_read_int(bs,32); data_shift += 4; if (data_shift != data_size) { GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[Process AIT] AIT processed length error. Difference between byte shifting %d and data size %d \n",data_shift,data_size)); return GF_CORRUPTED_DATA; } return GF_OK; }
void RS_Deinterleaver(GF_BitStream *bs, char *out_name) { u8 rs0[204], rs1[204], rs2[204], rs3[204], rs4[204], rs5[204], rs6[204], rs7[204], rs8[204], rs9[204], rs10[204], rs11[204]; u8 *rs[12] = { rs0, rs1, rs2, rs3, rs4, rs5, rs6, rs7, rs8, rs9, rs10, rs11 }; u8 *tmp; u8 buf[204]; u32 i; u64 bs_data; u32 k = 0; memset(rs[0], 0, 204); memset(rs[1], 0, 204); memset(rs[2], 0, 204); memset(rs[3], 0, 204); memset(rs[4], 0, 204); memset(rs[5], 0, 204); memset(rs[6], 0, 204); memset(rs[7], 0, 204); memset(rs[8], 0, 204); memset(rs[9], 0, 204); memset(rs[10], 0, 204); memset(rs[11], 0, 204); bs_data = gf_bs_available(bs); while (bs_data > 204) { u64 pos; k++; // printf("TS Packet Number: %d\r", k); pos = gf_bs_get_position(bs); gf_bs_read_data(bs, buf, 204); bs_data = gf_bs_available(bs); while ((buf[0] != 0x47) && (bs_data > 0)) { printf("error in input TS %d\n", k); //return; pos++; gf_bs_seek(bs, pos); gf_bs_read_data(bs, buf, 204); bs_data = gf_bs_available(bs); } for (i=0; i<(17*12); i+=12) { // 1 paquet rs[0][i] = buf[i]; rs[1][i+1] = buf[i+1]; rs[2][i+2] = buf[i+2]; rs[3][i+3] = buf[i+3]; rs[4][i+4] = buf[i+4]; rs[5][i+5] = buf[i+5]; rs[6][i+6] = buf[i+6]; rs[7][i+7] = buf[i+7]; rs[8][i+8] = buf[i+8]; rs[9][i+9] = buf[i+9]; rs[10][i+10] = buf[i+10]; rs[11][i+11] = buf[i+11]; } if (k >= 12) { if (rs[11][0] != 0x47) { printf("error in output TS\n"); } else { save_ts(out_name, rs[11]); } } tmp = rs[11]; rs[11] = rs[10]; rs[10] = rs[9]; rs[9] = rs[8]; rs[8] = rs[7]; rs[7] = rs[6]; rs[6] = rs[5]; rs[5] = rs[4]; rs[4] = rs[3]; rs[3] = rs[2]; rs[2] = rs[1]; rs[1] = rs[0]; rs[0] = tmp; } }
GF_Err gf_isom_parse_movie_boxes(GF_ISOFile *mov, u64 *bytesMissing, Bool progressive_mode) { GF_Box *a; u64 totSize; GF_Err e = GF_OK; totSize = 0; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS if (mov->single_moof_mode && mov->single_moof_state == 2) { return e; } /*restart from where we stopped last*/ totSize = mov->current_top_box_start; gf_bs_seek(mov->movieFileMap->bs, mov->current_top_box_start); #endif /*while we have some data, parse our boxes*/ while (gf_bs_available(mov->movieFileMap->bs)) { *bytesMissing = 0; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS mov->current_top_box_start = gf_bs_get_position(mov->movieFileMap->bs); GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[iso file] Current top box start before parsing %d\n", mov->current_top_box_start)); #endif e = gf_isom_parse_root_box(&a, mov->movieFileMap->bs, bytesMissing, progressive_mode); if (e >= 0) { e = GF_OK; } else if (e == GF_ISOM_INCOMPLETE_FILE) { /*our mdat is uncomplete, only valid for READ ONLY files...*/ if (mov->openMode != GF_ISOM_OPEN_READ) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Incomplete MDAT while file is not read-only\n")); return GF_ISOM_INVALID_FILE; } return e; } else { return e; } switch (a->type) { /*MOOV box*/ case GF_ISOM_BOX_TYPE_MOOV: if (mov->moov) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Duplicate MOOV detected!\n")); return GF_ISOM_INVALID_FILE; } mov->moov = (GF_MovieBox *)a; /*set our pointer to the movie*/ mov->moov->mov = mov; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS if (mov->moov->mvex) mov->moov->mvex->mov = mov; #endif e = gf_list_add(mov->TopBoxes, a); if (e) { return e; } totSize += a->size; break; /*META box*/ case GF_ISOM_BOX_TYPE_META: if (mov->meta) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Duplicate META detected!\n")); return GF_ISOM_INVALID_FILE; } mov->meta = (GF_MetaBox *)a; e = gf_list_add(mov->TopBoxes, a); if (e) { return e; } totSize += a->size; break; /*we only keep the MDAT in READ for dump purposes*/ case GF_ISOM_BOX_TYPE_MDAT: totSize += a->size; if (mov->openMode == GF_ISOM_OPEN_READ) { if (!mov->mdat) { mov->mdat = (GF_MediaDataBox *) a; e = gf_list_add(mov->TopBoxes, mov->mdat); if (e) { return e; } } #ifndef GPAC_DISABLE_ISOM_FRAGMENTS else if (mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG) gf_list_add(mov->TopBoxes, a); #endif else gf_isom_box_del(a); } /*if we don't have any MDAT yet, create one (edit-write mode) We only work with one mdat, but we're puting it at the place of the first mdat found when opening a file for editing*/ else if (!mov->mdat && (mov->openMode != GF_ISOM_OPEN_READ) && (mov->openMode != GF_ISOM_OPEN_CAT_FRAGMENTS)) { gf_isom_box_del(a); mov->mdat = (GF_MediaDataBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MDAT); e = gf_list_add(mov->TopBoxes, mov->mdat); if (e) { return e; } } else { gf_isom_box_del(a); } break; case GF_ISOM_BOX_TYPE_FTYP: /*ONE AND ONLY ONE FTYP*/ if (mov->brand) { gf_isom_box_del(a); GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Duplicate FTYP detected!\n")); return GF_ISOM_INVALID_FILE; } mov->brand = (GF_FileTypeBox *)a; totSize += a->size; e = gf_list_add(mov->TopBoxes, a); break; case GF_ISOM_BOX_TYPE_PDIN: /*ONE AND ONLY ONE PDIN*/ if (mov->pdin) { gf_isom_box_del(a); GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Duplicate PDIN detected!\n")); return GF_ISOM_INVALID_FILE; } mov->pdin = (GF_ProgressiveDownloadBox *) a; totSize += a->size; e = gf_list_add(mov->TopBoxes, a); break; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS case GF_ISOM_BOX_TYPE_STYP: { u32 brand = ((GF_SegmentTypeBox *)a)->majorBrand; switch (brand) { case GF_4CC('s', 'i', 's', 'x'): case GF_4CC('r', 'i', 's', 'x'): case GF_4CC('s', 's', 's', 's'): mov->is_index_segment = GF_TRUE; break; default: break; } } /*fall-through*/ case GF_ISOM_BOX_TYPE_SIDX: totSize += a->size; if (mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG) { e = gf_list_add(mov->TopBoxes, a); } else { gf_isom_box_del(a); } break; case GF_ISOM_BOX_TYPE_MOOF: if (!mov->moov) { GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] Movie fragment but no moov (yet) - possibly broken parsing!\n")); } if (mov->single_moof_mode) { mov->single_moof_state++; if (mov->single_moof_state > 1) { gf_isom_box_del(a); return GF_OK; } } ((GF_MovieFragmentBox *)a)->mov = mov; totSize += a->size; mov->moof = (GF_MovieFragmentBox *) a; /*read & debug: store at root level*/ if (mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG) { u32 k; gf_list_add(mov->TopBoxes, a); /*also update pointers to trex for debug*/ if (mov->moov) { for (k=0; k<gf_list_count(mov->moof->TrackList); k++) { GF_TrackFragmentBox *traf = gf_list_get(mov->moof->TrackList, k); if (traf->tfhd) { GF_TrackBox *trak = gf_isom_get_track_from_id(mov->moov, traf->tfhd->trackID); u32 j=0; while ((traf->trex = (GF_TrackExtendsBox*)gf_list_enum(mov->moov->mvex->TrackExList, &j))) { if (traf->trex->trackID == traf->tfhd->trackID) { if (!traf->trex->track) traf->trex->track = trak; break; } traf->trex = NULL; } } //we should only parse senc/psec when no saiz/saio is present, otherwise we fetch the info directly if (traf->trex && traf->trex->track && (traf->piff_sample_encryption || traf->sample_encryption)) { GF_TrackBox *trak = GetTrackbyID(mov->moov, traf->tfhd->trackID); e = senc_Parse(mov->movieFileMap->bs, trak, traf, traf->piff_sample_encryption ? (GF_SampleEncryptionBox *) traf->piff_sample_encryption : traf->sample_encryption); } } } } else if (mov->openMode==GF_ISOM_OPEN_CAT_FRAGMENTS) { mov->NextMoofNumber = mov->moof->mfhd->sequence_number+1; mov->moof = NULL; gf_isom_box_del(a); } else { /*merge all info*/ e = MergeFragment((GF_MovieFragmentBox *)a, mov); gf_isom_box_del(a); } break; #endif case GF_4CC('j','P',' ',' '): { GF_UnknownBox *box = (GF_UnknownBox*)a; u8 *c = (u8 *) box->data; if ((box->dataSize==4) && (GF_4CC(c[0],c[1],c[2],c[3])==(u32)0x0D0A870A)) mov->is_jp2 = 1; gf_isom_box_del(a); } break; case GF_ISOM_BOX_TYPE_PRFT: #ifndef GPAC_DISABLE_ISOM_FRAGMENTS if (!(mov->FragmentsFlags & GF_ISOM_FRAG_READ_DEBUG)) { //keep the last one read if (mov->last_producer_ref_time) gf_isom_box_del(a); else mov->last_producer_ref_time = (GF_ProducerReferenceTimeBox *)a; break; } #endif //fallthrough default: totSize += a->size; e = gf_list_add(mov->TopBoxes, a); break; } #ifndef GPAC_DISABLE_ISOM_FRAGMENTS /*remember where we left, in case we append an entire number of movie fragments*/ mov->current_top_box_start = gf_bs_get_position(mov->movieFileMap->bs); #endif } /*we need at least moov or meta*/ if (!mov->moov && !mov->meta #ifndef GPAC_DISABLE_ISOM_FRAGMENTS && !mov->moof && !mov->is_index_segment #endif ) { return GF_ISOM_INCOMPLETE_FILE; } /*we MUST have movie header*/ if (mov->moov && !mov->moov->mvhd) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Missing MVHD in MOOV!\n")); return GF_ISOM_INVALID_FILE; } /*we MUST have meta handler*/ if (mov->meta && !mov->meta->handler) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Missing handler in META!\n")); return GF_ISOM_INVALID_FILE; } #ifndef GPAC_DISABLE_ISOM_WRITE if (mov->moov) { /*set the default interleaving time*/ mov->interleavingTime = mov->moov->mvhd->timeScale; #ifndef GPAC_DISABLE_ISOM_FRAGMENTS /*in edit mode with successfully loaded fragments, delete all fragment signaling since file is no longer fragmented*/ if ((mov->openMode > GF_ISOM_OPEN_READ) && (mov->openMode != GF_ISOM_OPEN_CAT_FRAGMENTS) && mov->moov->mvex) { gf_isom_box_del((GF_Box *)mov->moov->mvex); mov->moov->mvex = NULL; } #endif } //create a default mdat if none was found if (!mov->mdat && (mov->openMode != GF_ISOM_OPEN_READ) && (mov->openMode != GF_ISOM_OPEN_CAT_FRAGMENTS)) { mov->mdat = (GF_MediaDataBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MDAT); e = gf_list_add(mov->TopBoxes, mov->mdat); if (e) return e; } #endif /*GPAC_DISABLE_ISOM_WRITE*/ return GF_OK; }
int main(int argc, char **argv) { /********************/ /* declarations */ /********************/ char *input, *output, tmpstr[GF_MAX_PATH]; GF_ISOFile *isom_file_in; GF_MediaImporter import; AdobeHDSCtx ctx; GF_Err e; u32 i; /*****************/ /* gpac init */ /*****************/ gf_sys_init(GF_MemTrackerNone); gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING); /***********************/ /* initialisations */ /***********************/ input = NULL; output = NULL; isom_file_in = NULL; memset(&import, 0, sizeof(GF_MediaImporter)); e = GF_OK; memset(&ctx, 0, sizeof(ctx)); ctx.curr_time = 0; ctx.segnum = 1; /*********************************************/ /* parse arguments and build HDS context */ /*********************************************/ if (GF_OK != parse_args(argc, argv, &input, &output, &ctx.curr_time, &ctx.segnum)) { usage(argv[0]); goto exit; } ctx.multirate_manifest = adobe_alloc_multirate_manifest(output); #if 0 /*'moov' conversion tests*/ { char metamoov64[GF_MAX_PATH]; u32 metamoov64_len; unsigned char metamoov[GF_MAX_PATH]; u32 metamoov_len=GF_MAX_PATH; FILE *f = gf_fopen("metamoov64"/*input*/, "rt"); gf_fseek(f, 0, SEEK_END); metamoov64_len = (u32)gf_ftell(f); gf_fseek(f, 0, SEEK_SET); fread(metamoov64, metamoov64_len, 1, f); metamoov_len = gf_base64_decode(metamoov64, metamoov64_len, metamoov, metamoov_len); gf_fclose(f); f = gf_fopen("metamoov", "wb"); fwrite(metamoov, metamoov_len, 1, f); gf_fclose(f); return 0; } #endif #if 0 /*'abst'conversion tests*/ { char bootstrap64[GF_MAX_PATH]; u32 bootstrap64_len; unsigned char bootstrap[GF_MAX_PATH]; u32 bootstrap_len=GF_MAX_PATH; GF_AdobeBootstrapInfoBox *abst = (GF_AdobeBootstrapInfoBox *)abst_New(); GF_BitStream *bs; #if 1 //64 FILE *f = gf_fopen("bootstrap64"/*input*/, "rt"); gf_fseek(f, 0, SEEK_END); bootstrap64_len = (u32)gf_ftell(f); gf_fseek(f, 0, SEEK_SET); fread(bootstrap64, bootstrap64_len, 1, f); bootstrap_len = gf_base64_decode(bootstrap64, bootstrap64_len, bootstrap, bootstrap_len); #else //binary bootstrap FILE *f = gf_fopen("bootstrap.bin"/*input*/, "rb"); gf_fseek(f, 0, SEEK_END); bootstrap_len = (u32)gf_ftell(f); gf_fseek(f, 0, SEEK_SET); fread(bootstrap, bootstrap_len, 1, f); #endif bs = gf_bs_new(bootstrap+8, bootstrap_len-8, GF_BITSTREAM_READ); abst->size = bootstrap[2]*256+bootstrap[3]; assert(abst->size<GF_MAX_PATH); abst_Read((GF_Box*)abst, bs); gf_bs_del(bs); //then rewrite with just one 'afrt' memset(bootstrap, 0, bootstrap_len); bs = gf_bs_new(bootstrap, bootstrap_len, GF_BITSTREAM_WRITE); abst_Write((GF_Box*)abst, bs); bootstrap_len = (u32)gf_bs_get_position(bs); gf_bs_del(bs); gf_fclose(f); f = gf_fopen("bootstrap", "wt"); bootstrap64_len = gf_base64_encode(bootstrap, bootstrap_len, bootstrap64, GF_MAX_PATH); fwrite(bootstrap64, bootstrap64_len, 1, f); fprintf(f, "\n\n"); abst_dump((GF_Box*)abst, f); gf_fclose(f); abst_del((GF_Box*)abst); return 0; } #endif /*****************/ /* main loop */ /*****************/ import.trackID = 0; import.in_name = input; import.flags = GF_IMPORT_PROBE_ONLY; //create output or open when recovering from a saved state sprintf(tmpstr, "%s_import.mp4", input); isom_file_in = gf_isom_open(tmpstr, GF_ISOM_WRITE_EDIT, NULL); if (!isom_file_in) { fprintf(stderr, "Error opening output file %s: %s\n", tmpstr, gf_error_to_string(e)); assert(0); goto exit; } import.dest = isom_file_in; //probe input e = gf_media_import(&import); if (e) { fprintf(stderr, "Error while importing input file %s: %s\n", input, gf_error_to_string(e)); assert(0); goto exit; } //import input data import.flags = 0; for (i=0; i<import.nb_tracks; i++) { import.trackID = import.tk_info[i].track_num; e = gf_media_import(&import); if (e) { fprintf(stderr, "Error while importing track number %u, input file %s: %s\n", import.trackID, input, gf_error_to_string(e)); assert(0); goto exit; } } //Adobe specific stuff e = adobize_segment(isom_file_in, &ctx); if (e) { fprintf(stderr, "Couldn't turn the ISOM fragmented file into an Adobe f4v segment: %s\n", gf_error_to_string(e)); assert(0); goto exit; } //interleave data and remove imported file //FIXME: set multiple fragments: sprintf(tmpstr, "%s_HD_100_Seg%u-Frag1", output, ctx.segnum); //FIXME: "HD", "100" and fragnum: pass as arg //e = gf_media_fragment_file(isom_file_in, tmpstr, 1.0); e = gf_media_fragment_file(isom_file_in, tmpstr, 1.0+gf_isom_get_duration(isom_file_in)/gf_isom_get_timescale(isom_file_in)); if (e) { fprintf(stderr, "Error while fragmenting file to output %s: %s\n", output, gf_error_to_string(e)); assert(0); goto exit; } gf_isom_delete(isom_file_in); isom_file_in = NULL; e = adobe_gen_multirate_manifest(ctx.multirate_manifest, ctx.bootstrap, ctx.bootstrap_size); if (e) { fprintf(stderr, "Couldn't generate Adobe f4m manifest: %s\n", gf_error_to_string(e)); assert(0); goto exit; } exit: //delete intermediate mp4 file if (isom_file_in) gf_isom_delete(isom_file_in); if (ctx.multirate_manifest) adobe_free_multirate_manifest(ctx.multirate_manifest); if (ctx.bootstrap) { gf_free(ctx.bootstrap); //ctx.bootstrap = NULL; //ctx.bootstrap_size = 0; } gf_sys_close(); return !e ? 0 : 1; }