GF_Err gf_isom_audio_sample_entry_read(GF_AudioSampleEntryBox *ptr, GF_BitStream *bs) { if (ptr->size<28) return GF_ISOM_INVALID_FILE; gf_bs_read_data(bs, ptr->reserved, 6); ptr->dataReferenceIndex = gf_bs_read_u16(bs); ptr->version = gf_bs_read_u16(bs); ptr->revision = gf_bs_read_u16(bs); ptr->vendor = gf_bs_read_u32(bs); ptr->channel_count = gf_bs_read_u16(bs); ptr->bitspersample = gf_bs_read_u16(bs); ptr->compression_id = gf_bs_read_u16(bs); ptr->packet_size = gf_bs_read_u16(bs); ptr->samplerate_hi = gf_bs_read_u16(bs); ptr->samplerate_lo = gf_bs_read_u16(bs); ptr->size -= 28; if (ptr->version==1) { if (ptr->size<16) return GF_ISOM_INVALID_FILE; gf_bs_skip_bytes(bs, 16); ptr->size-=16; } else if (ptr->version==2) { if (ptr->size<36) return GF_ISOM_INVALID_FILE; gf_bs_skip_bytes(bs, 36); ptr->size -= 36; } return GF_OK; }
static Bool AC3_ConfigureFromFile(AC3Reader *read) { Bool sync; GF_BitStream *bs; GF_AC3Header hdr; memset(&hdr, 0, sizeof(GF_AC3Header)); if (!read->stream) return 0; bs = gf_bs_from_file(read->stream, GF_BITSTREAM_READ); sync = gf_ac3_parser_bs(bs, &hdr, GF_TRUE); if (!sync) { gf_bs_del(bs); return GF_FALSE; } read->nb_ch = hdr.channels; read->sample_rate = hdr.sample_rate; read->duration = 0; if (!read->is_remote) { read->duration = 1536; gf_bs_skip_bytes(bs, hdr.framesize); while (gf_ac3_parser_bs(bs, &hdr, GF_FALSE)) { read->duration += 1536; gf_bs_skip_bytes(bs, hdr.framesize); } } gf_bs_del(bs); gf_f64_seek(read->stream, 0, SEEK_SET); return 1; }
static Bool AAC_ConfigureFromFile(AACReader *read) { Bool sync; GF_BitStream *bs; ADTSHeader hdr; if (!read->stream) return 0; bs = gf_bs_from_file(read->stream, GF_BITSTREAM_READ); sync = ADTS_SyncFrame(bs, !read->is_remote, &hdr); if (!sync) { gf_bs_del(bs); return 0; } read->nb_ch = hdr.nb_ch; read->prof = hdr.profile; read->sr_idx = hdr.sr_idx; read->oti = hdr.is_mp2 ? read->prof+0x66 : 0x40; read->sample_rate = GF_M4ASampleRates[read->sr_idx]; read->duration = 0; if (!read->is_remote) { read->duration = 1024; gf_bs_skip_bytes(bs, hdr.frame_size); while (ADTS_SyncFrame(bs, !read->is_remote, &hdr)) { read->duration += 1024; gf_bs_skip_bytes(bs, hdr.frame_size); } } gf_bs_del(bs); fseek(read->stream, 0, SEEK_SET); return 1; }
GF_Err Read_ImmediateDTE(GF_ImmediateDTE *dte, GF_BitStream *bs) { dte->dataLength = gf_bs_read_u8(bs); if (dte->dataLength > 14) return GF_ISOM_INVALID_FILE; gf_bs_read_data(bs, dte->data, dte->dataLength); if (dte->dataLength < 14) gf_bs_skip_bytes(bs, 14 - dte->dataLength); return GF_OK; }
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 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 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; }
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 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; }
static void SAF_CheckFile(SAFIn *read) { u32 nb_streams, i, cts, au_size, au_type, stream_id, ts_res; GF_BitStream *bs; StreamInfo si[1024]; gf_f64_seek(read->stream, 0, SEEK_SET); bs = gf_bs_from_file(read->stream, GF_BITSTREAM_READ); nb_streams=0; while (gf_bs_available(bs)) { gf_bs_read_u16(bs); gf_bs_read_int(bs, 2); cts = gf_bs_read_int(bs, 30); au_size = gf_bs_read_int(bs, 16); au_type = gf_bs_read_int(bs, 4); stream_id = gf_bs_read_int(bs, 12); au_size-=2; ts_res = 0; for (i=0; i<nb_streams; i++) { if (si[i].stream_id==stream_id) ts_res = si[i].ts_res; } if (!ts_res) { if ((au_type==1) || (au_type==2) || (au_type==7)) { gf_bs_read_u16(bs); ts_res = gf_bs_read_u24(bs); au_size -= 5; si[nb_streams].stream_id = stream_id; si[nb_streams].ts_res = ts_res; nb_streams++; } } if (ts_res && (au_type==4)) { Double ts = cts; ts /= ts_res; if (ts>read->duration) read->duration = ts; } gf_bs_skip_bytes(bs, au_size); } gf_bs_del(bs); gf_f64_seek(read->stream, 0, SEEK_SET); }
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; }
GF_Err gp_rtp_builder_do_dims(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration) { u32 frag_state; GF_BitStream *bs; u32 offset; Bool is_last_du; /*the DIMS hinter doesn't perform inter-sample concatenation*/ if (!data) return GF_OK; offset = 0; builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp; bs = gf_bs_new(data, data_size, GF_BITSTREAM_READ); while (offset < data_size) { u32 du_offset = 0; u32 hdr_offset = 0; u32 orig_size, du_size; orig_size = du_size = 2+gf_bs_read_u16(bs); /*if dims size is >0xFFFF, use our internal hack for large units*/ if (du_size==2) { orig_size = du_size = 2+gf_bs_read_u32(bs); hdr_offset = 4; } gf_bs_skip_bytes(bs, du_size-2); /*prepare M-bit*/ is_last_du = (offset+du_size==data_size) ? 1 : 0; frag_state = 0; while (du_size) { u32 size_offset = 0; u32 size = du_size; /*does not fit, flush required*/ if (builder->bytesInPacket && (du_size + 1 + builder->bytesInPacket > builder->Path_MTU)) { builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); builder->bytesInPacket = 0; } /*fragmentation required*/ if (du_size + 1 > builder->Path_MTU) { size = builder->Path_MTU - 1; /*first fragment*/ if (!frag_state) { /*size field is skipped !!*/ size_offset = 2 + hdr_offset; frag_state = 1; while (du_size - size_offset <= size) { size--; } } /*any middle fragment*/ else frag_state = 2; builder->rtp_header.Marker = 0; } /*last fragment*/ else if (frag_state) { size = du_size; frag_state = 3; builder->rtp_header.Marker = is_last_du; } else { size = du_size; builder->rtp_header.Marker = is_last_du; } if (frag_state && builder->bytesInPacket) { builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); builder->bytesInPacket = 0; } /*need a new packet*/ if (!builder->bytesInPacket) { char dims_rtp_hdr[1]; /*the unit is critical, increase counter (coded on 3 bits)*/ if (! (data[2+hdr_offset] & GF_DIMS_UNIT_P) && (frag_state <= 1) ) { builder->last_au_sn++; builder->last_au_sn %= 8; } /*set CTR value*/ dims_rtp_hdr[0] = builder->last_au_sn; /*if M-bit is set in the dims unit header, replicate it*/ if (data[2+hdr_offset] & (1<<1) ) dims_rtp_hdr[0] |= (1<<6); /*add unit fragmentation type*/ dims_rtp_hdr[0] |= (frag_state<<3); builder->rtp_header.SequenceNumber += 1; builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header); builder->OnData(builder->cbk_obj, (char *) dims_rtp_hdr, 1, 1); builder->bytesInPacket = 1; } /*add payload*/ if (builder->OnDataReference) builder->OnDataReference(builder->cbk_obj, size, offset+du_offset+size_offset); else builder->OnData(builder->cbk_obj, data+offset+du_offset+size_offset, size, 0); /*if fragmentation, force packet flush even on last packet since aggregation unit do not use the same packet format*/ if (frag_state) { builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); builder->bytesInPacket = 0; } else { builder->bytesInPacket += size; } du_offset += size+size_offset; assert(du_size>= size+size_offset); du_size -= size+size_offset; } offset += orig_size; } if (builder->bytesInPacket) { builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header); builder->bytesInPacket = 0; } gf_bs_del(bs); return GF_OK; }
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); }
GF_EXPORT GF_Err gf_odf_parse_descriptor(GF_BitStream *bs, GF_Descriptor **desc, u32 *desc_size) { u32 val, size, sizeHeader; u8 tag; GF_Err err; GF_Descriptor *newDesc; if (!bs) return GF_BAD_PARAM; *desc_size = 0; //tag tag = (u8) gf_bs_read_int(bs, 8); sizeHeader = 1; //size size = 0; do { val = gf_bs_read_int(bs, 8); sizeHeader++; size <<= 7; size |= val & 0x7F; } while ( val & 0x80); *desc_size = size; GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[ODF] Reading descriptor (tag %d size %d)\n", tag, size )); newDesc = gf_odf_create_descriptor(tag); if (! newDesc) { *desc = NULL; *desc_size = sizeHeader; if ( (tag >= GF_ODF_ISO_RES_BEGIN_TAG) && (tag <= GF_ODF_ISO_RES_END_TAG) ) { return GF_ODF_FORBIDDEN_DESCRIPTOR; } else if (!tag || (tag == 0xFF)) { return GF_ODF_INVALID_DESCRIPTOR; } #ifndef GPAC_MINIMAL_ODF return GF_OUT_OF_MEM; #else gf_bs_skip_bytes(bs, size); *desc_size = size + sizeHeader - gf_odf_size_field_size(*desc_size); return GF_OK; #endif } newDesc->tag = tag; err = gf_odf_read_descriptor(bs, newDesc, *desc_size); /*FFMPEG fix*/ if ((tag==GF_ODF_SLC_TAG) && (((GF_SLConfig*)newDesc)->predefined==2)) { if (*desc_size==3) { *desc_size = 1; err = GF_OK; } } //little trick to handle lazy bitstreams that encode //SizeOfInstance on a fix number of bytes //This nb of bytes is added in Read methods *desc_size += sizeHeader - gf_odf_size_field_size(*desc_size); *desc = newDesc; if (err) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODEC, ("[ODF] Error reading descriptor (tag %d size %d): %s\n", tag, size, gf_error_to_string(err) )); gf_odf_delete_descriptor(newDesc); *desc = NULL; } return err; }
static void SAF_NetIO(void *cbk, GF_NETIO_Parameter *param) { GF_Err e; Bool is_rap, go; SAFChannel *ch; u32 cts, au_sn, au_size, type, i, stream_id; u64 bs_pos; GF_BitStream *bs; GF_SLHeader sl_hdr; SAFIn *read = (SAFIn *) cbk; e = param->error; /*done*/ if (param->msg_type==GF_NETIO_DATA_TRANSFERED) { if (read->stream && (read->saf_type==SAF_FILE_REMOTE)) read->saf_type = SAF_FILE_LOCAL; return; } else { /*handle service message*/ gf_service_download_update_stats(read->dnload); if (param->msg_type!=GF_NETIO_DATA_EXCHANGE) { if (e<0) { if (read->needs_connection) { read->needs_connection = 0; gf_service_connect_ack(read->service, NULL, e); } return; } if (read->needs_connection) { u32 total_size; gf_dm_sess_get_stats(read->dnload, NULL, NULL, &total_size, NULL, NULL, NULL); if (!total_size) read->saf_type = SAF_LIVE_STREAM; } return; } } if (!param->size) return; if (!read->run_state) return; if (read->alloc_size < read->saf_size + param->size) { read->saf_data = (char*)gf_realloc(read->saf_data, sizeof(char)*(read->saf_size + param->size) ); read->alloc_size = read->saf_size + param->size; } memcpy(read->saf_data + read->saf_size, param->data, sizeof(char)*param->size); read->saf_size += param->size; /*first AU not complete yet*/ if (read->saf_size<10) return; bs = gf_bs_new(read->saf_data, read->saf_size, GF_BITSTREAM_READ); bs_pos = 0; go = 1; while (go) { u64 avail = gf_bs_available(bs); bs_pos = gf_bs_get_position(bs); if (avail<10) break; is_rap = gf_bs_read_int(bs, 1); au_sn = gf_bs_read_int(bs, 15); gf_bs_read_int(bs, 2); cts = gf_bs_read_int(bs, 30); au_size = gf_bs_read_int(bs, 16); avail-=8; if (au_size > avail) break; assert(au_size>=2); is_rap = 1; type = gf_bs_read_int(bs, 4); stream_id = gf_bs_read_int(bs, 12); au_size -= 2; ch = saf_get_channel(read, stream_id, NULL); switch (type) { case 1: case 2: case 7: if (ch) { gf_bs_skip_bytes(bs, au_size); } else { SAFChannel *first = (SAFChannel *)gf_list_get(read->channels, 0); GF_SAFEALLOC(ch, SAFChannel); ch->stream_id = stream_id; ch->esd = gf_odf_desc_esd_new(0); ch->esd->ESID = stream_id; ch->esd->OCRESID = first ? first->stream_id : stream_id; ch->esd->slConfig->useRandomAccessPointFlag = 1; ch->esd->slConfig->AUSeqNumLength = 0; ch->esd->decoderConfig->objectTypeIndication = gf_bs_read_u8(bs); ch->esd->decoderConfig->streamType = gf_bs_read_u8(bs); ch->ts_res = ch->esd->slConfig->timestampResolution = gf_bs_read_u24(bs); ch->esd->decoderConfig->bufferSizeDB = gf_bs_read_u16(bs); au_size -= 7; if ((ch->esd->decoderConfig->objectTypeIndication == 0xFF) && (ch->esd->decoderConfig->streamType == 0xFF) ) { u16 mimeLen = gf_bs_read_u16(bs); gf_bs_skip_bytes(bs, mimeLen); au_size -= mimeLen+2; } if (type==7) { u16 urlLen = gf_bs_read_u16(bs); ch->esd->URLString = (char*)gf_malloc(sizeof(char)*(urlLen+1)); gf_bs_read_data(bs, ch->esd->URLString, urlLen); ch->esd->URLString[urlLen] = 0; au_size -= urlLen+2; } if (au_size) { ch->esd->decoderConfig->decoderSpecificInfo->dataLength = au_size; ch->esd->decoderConfig->decoderSpecificInfo->data = (char*)gf_malloc(sizeof(char)*au_size); gf_bs_read_data(bs, ch->esd->decoderConfig->decoderSpecificInfo->data, au_size); } if (ch->esd->decoderConfig->streamType==4) ch->buffer_min=100; else if (ch->esd->decoderConfig->streamType==5) ch->buffer_min=400; else ch->buffer_min=0; if (read->needs_connection && (ch->esd->decoderConfig->streamType==GF_STREAM_SCENE)) { gf_list_add(read->channels, ch); read->needs_connection = 0; gf_service_connect_ack(read->service, NULL, GF_OK); } else if (read->needs_connection) { gf_odf_desc_del((GF_Descriptor *) ch->esd); gf_free(ch); ch = NULL; } else { GF_ObjectDescriptor *od; gf_list_add(read->channels, ch); od = (GF_ObjectDescriptor*)gf_odf_desc_new(GF_ODF_OD_TAG); gf_list_add(od->ESDescriptors, ch->esd); ch->esd = NULL; od->objectDescriptorID = ch->stream_id; gf_service_declare_media(read->service, (GF_Descriptor*)od, 0); } } break; case 4: if (ch) { bs_pos = gf_bs_get_position(bs); memset(&sl_hdr, 0, sizeof(GF_SLHeader)); sl_hdr.accessUnitLength = au_size; sl_hdr.AU_sequenceNumber = au_sn; sl_hdr.compositionTimeStampFlag = 1; sl_hdr.compositionTimeStamp = cts; sl_hdr.randomAccessPointFlag = is_rap; if (read->start_range && (read->start_range*ch->ts_res>cts*1000)) { sl_hdr.compositionTimeStamp = read->start_range*ch->ts_res/1000; } gf_service_send_packet(read->service, ch->ch, read->saf_data+bs_pos, au_size, &sl_hdr, GF_OK); } gf_bs_skip_bytes(bs, au_size); break; case 3: if (ch) gf_service_send_packet(read->service, ch->ch, NULL, 0, NULL, GF_EOS); break; case 5: go = 0; read->run_state = 0; i=0; while ((ch = (SAFChannel *)gf_list_enum(read->channels, &i))) { gf_service_send_packet(read->service, ch->ch, NULL, 0, NULL, GF_EOS); } break; } } gf_bs_del(bs); if (bs_pos) { u32 remain = (u32) (read->saf_size - bs_pos); if (remain) memmove(read->saf_data, read->saf_data+bs_pos, sizeof(char)*remain); read->saf_size = remain; } SAF_Regulate(read); }
/* Rewrite mode: * mode = 0: playback * mode = 1: streaming */ GF_Err gf_isom_nalu_sample_rewrite(GF_MediaBox *mdia, GF_ISOSample *sample, u32 sampleNumber, GF_MPEGVisualSampleEntryBox *entry) { Bool is_hevc = 0; GF_Err e = GF_OK; GF_ISOSample *ref_samp; GF_BitStream *src_bs, *ref_bs, *dst_bs; u64 offset; u32 ref_nalu_size, data_offset, data_length, copy_size, nal_size, max_size, di, nal_unit_size_field, cur_extract_mode, extractor_mode; Bool rewrite_ps, rewrite_start_codes; u8 ref_track_ID, ref_track_num; s8 sample_offset, nal_type; u32 nal_hdr; char *buffer; GF_ISOFile *file = mdia->mediaTrack->moov->mov; src_bs = ref_bs = dst_bs = NULL; ref_samp = NULL; buffer = NULL; rewrite_ps = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG) ? 1 : 0; if (! sample->IsRAP) rewrite_ps = 0; rewrite_start_codes = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_ANNEXB_FLAG) ? 1 : 0; extractor_mode = mdia->mediaTrack->extractor_mode&0x0000FFFF; if (extractor_mode == GF_ISOM_NALU_EXTRACT_INSPECT) { if (!rewrite_ps && !rewrite_start_codes) return GF_OK; } if (!entry) return GF_BAD_PARAM; nal_unit_size_field = 0; /*if svc rewrire*/ if (entry->svc_config && entry->svc_config->config) nal_unit_size_field = entry->svc_config->config->nal_unit_size; /*if mvc rewrire*/ /*otherwise do nothing*/ else if (!rewrite_ps && !rewrite_start_codes) { return GF_OK; } if (!nal_unit_size_field) { if (entry->avc_config) nal_unit_size_field = entry->avc_config->config->nal_unit_size; else if (entry->hevc_config) { nal_unit_size_field = entry->hevc_config->config->nal_unit_size; is_hevc = 1; } } if (!nal_unit_size_field) return GF_ISOM_INVALID_FILE; dst_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); src_bs = gf_bs_new(sample->data, sample->dataLength, GF_BITSTREAM_READ); max_size = 4096; /*rewrite start code with NALU delim*/ if (rewrite_start_codes) { gf_bs_write_int(dst_bs, 1, 32); if (is_hevc) { gf_bs_write_int(dst_bs, 0, 1); gf_bs_write_int(dst_bs, GF_HEVC_NALU_ACCESS_UNIT, 6); gf_bs_write_int(dst_bs, 0, 9); /*pic-type - by default we signal all slice types possible*/ gf_bs_write_int(dst_bs, 2, 3); gf_bs_write_int(dst_bs, 0, 5); } else { gf_bs_write_int(dst_bs, (sample->data[0] & 0x60) | GF_AVC_NALU_ACCESS_UNIT, 8); gf_bs_write_int(dst_bs, 0xF0 , 8); /*7 "all supported NALUs" (=111) + rbsp trailing (10000)*/; } } if (rewrite_ps) { if (is_hevc) { u32 i, count; count = gf_list_count(entry->hevc_config->config->param_array); for (i=0; i<count; i++) { GF_HEVCParamArray *ar = gf_list_get(entry->hevc_config->config->param_array, i); rewrite_nalus_list(ar->nalus, dst_bs, rewrite_start_codes, nal_unit_size_field); } /*little optimization if we are not asked to start codes: copy over the sample*/ if (!rewrite_start_codes) { gf_bs_write_data(dst_bs, sample->data, sample->dataLength); gf_free(sample->data); sample->data = NULL; gf_bs_get_content(dst_bs, &sample->data, &sample->dataLength); gf_bs_del(src_bs); gf_bs_del(dst_bs); return GF_OK; } } else { /*this is an SVC track: get all SPS/PPS from this track down to the base layer and rewrite them*/ if (mdia->mediaTrack->has_base_layer) { u32 j; GF_List *nalu_sps = gf_list_new(); GF_List *nalu_pps = gf_list_new(); GF_TrackReferenceTypeBox *dpnd = NULL; Track_FindRef(mdia->mediaTrack, GF_ISOM_REF_SCAL, &dpnd); #if 0 /*get all upper layers with SCAL reference to this track*/ for (j = 0; j < gf_isom_get_track_count(file); j++) { if (gf_isom_has_track_reference(file, j+1, GF_ISOM_REF_SCAL, mdia->mediaTrack->Header->trackID)) { u32 tkID; GF_TrackBox *base_track; GF_MPEGVisualSampleEntryBox *base_entry; gf_isom_get_reference_ID(file, j+1, GF_ISOM_REF_SCAL, 1, &tkID); base_track = GetTrackbyID(mdia->mediaTrack->moov, tkID); base_entry = base_track ? gf_list_get(base_track->Media->information->sampleTable->SampleDescription->other_boxes, 0) : NULL; if (base_entry) merge_nalus(base_entry, nalu_sps, nalu_pps); } } #endif merge_nalus(entry, nalu_sps, nalu_pps); if (dpnd) { for (j=0; j<dpnd->trackIDCount; j++) { GF_TrackBox *base_track = GetTrackbyID(mdia->mediaTrack->moov, dpnd->trackIDs[j]); GF_MPEGVisualSampleEntryBox *base_entry = base_track ? gf_list_get(base_track->Media->information->sampleTable->SampleDescription->other_boxes, 0) : NULL; if (base_entry) merge_nalus(base_entry, nalu_sps, nalu_pps); } } //rewrite nalus rewrite_nalus_list(nalu_sps, dst_bs, rewrite_start_codes, nal_unit_size_field); rewrite_nalus_list(nalu_pps, dst_bs, rewrite_start_codes, nal_unit_size_field); gf_list_del(nalu_sps); gf_list_del(nalu_pps); } else { if (entry->avc_config) { rewrite_nalus_list(entry->avc_config->config->sequenceParameterSets, dst_bs, rewrite_start_codes, nal_unit_size_field); rewrite_nalus_list(entry->avc_config->config->pictureParameterSets, dst_bs, rewrite_start_codes, nal_unit_size_field); rewrite_nalus_list(entry->avc_config->config->sequenceParameterSetExtensions, dst_bs, rewrite_start_codes, nal_unit_size_field); } /*add svc config */ if (entry->svc_config) { rewrite_nalus_list(entry->svc_config->config->sequenceParameterSets, dst_bs, rewrite_start_codes, nal_unit_size_field); rewrite_nalus_list(entry->svc_config->config->pictureParameterSets, dst_bs, rewrite_start_codes, nal_unit_size_field); } /*little optimization if we are not asked to rewrite extractors or start codes: copy over the sample*/ if (!entry->svc_config && !rewrite_start_codes) { gf_bs_write_data(dst_bs, sample->data, sample->dataLength); gf_free(sample->data); sample->data = NULL; gf_bs_get_content(dst_bs, &sample->data, &sample->dataLength); gf_bs_del(src_bs); gf_bs_del(dst_bs); return GF_OK; } } } } buffer = (char *)gf_malloc(sizeof(char)*max_size); while (gf_bs_available(src_bs)) { nal_size = gf_bs_read_int(src_bs, 8*nal_unit_size_field); if (nal_size>max_size) { buffer = (char*) gf_realloc(buffer, sizeof(char)*nal_size); max_size = nal_size; } if (is_hevc) { nal_hdr = gf_bs_read_u16(src_bs); nal_type = (nal_hdr&0x7E00) >> 9; } else { nal_hdr = gf_bs_read_u8(src_bs); nal_type = nal_hdr & 0x1F; } if (is_hevc) { /*we already wrote this stuff*/ if (nal_type==GF_HEVC_NALU_ACCESS_UNIT) { gf_bs_skip_bytes(src_bs, nal_size-2); continue; } /*rewrite nal*/ gf_bs_read_data(src_bs, buffer, nal_size-2); if (rewrite_start_codes) gf_bs_write_u32(dst_bs, 1); else gf_bs_write_int(dst_bs, nal_size, 8*nal_unit_size_field); gf_bs_write_u16(dst_bs, nal_hdr); gf_bs_write_data(dst_bs, buffer, nal_size-2); continue; } /*we already wrote this stuff*/ if (nal_type==GF_AVC_NALU_ACCESS_UNIT) { gf_bs_skip_bytes(src_bs, nal_size-1); continue; } //extractor if (nal_type == 31) { switch (extractor_mode) { case 0: gf_bs_read_int(src_bs, 24); //3 bytes of NALUHeader in extractor ref_track_ID = gf_bs_read_u8(src_bs); sample_offset = (s8) gf_bs_read_int(src_bs, 8); data_offset = gf_bs_read_u32(src_bs); data_length = gf_bs_read_u32(src_bs); ref_track_num = gf_isom_get_track_by_id(file, ref_track_ID); if (!ref_track_num) { e = GF_BAD_PARAM; goto exit; } cur_extract_mode = gf_isom_get_nalu_extract_mode(file, ref_track_num); gf_isom_set_nalu_extract_mode(file, ref_track_num, GF_ISOM_NALU_EXTRACT_INSPECT); ref_samp = gf_isom_get_sample(file, ref_track_num, sampleNumber+sample_offset, &di); if (!ref_samp) { e = GF_IO_ERR; goto exit; } ref_bs = gf_bs_new(ref_samp->data, ref_samp->dataLength, GF_BITSTREAM_READ); offset = 0; while (gf_bs_available(ref_bs)) { if (gf_bs_get_position(ref_bs) < data_offset) { ref_nalu_size = gf_bs_read_int(ref_bs, 8*nal_unit_size_field); offset += ref_nalu_size + nal_unit_size_field; if ((offset > data_offset) || (offset >= gf_bs_get_size(ref_bs))) { e = GF_BAD_PARAM; goto exit; } e = gf_bs_seek(ref_bs, offset); if (e) goto exit; continue; } ref_nalu_size = gf_bs_read_int(ref_bs, 8*nal_unit_size_field); copy_size = data_length ? data_length : ref_nalu_size; assert(copy_size <= ref_nalu_size); nal_hdr = gf_bs_read_u8(ref_bs); //rewrite NAL type if ((copy_size-1)>max_size) { buffer = (char*)gf_realloc(buffer, sizeof(char)*(copy_size-1)); max_size = copy_size-1; } gf_bs_read_data(ref_bs, buffer, copy_size-1); if (rewrite_start_codes) gf_bs_write_u32(dst_bs, 1); else gf_bs_write_int(dst_bs, copy_size, 8*nal_unit_size_field); gf_bs_write_u8(dst_bs, nal_hdr); gf_bs_write_data(dst_bs, buffer, copy_size-1); } gf_isom_sample_del(&ref_samp); ref_samp = NULL; gf_bs_del(ref_bs); ref_bs = NULL; gf_isom_set_nalu_extract_mode(file, ref_track_num, cur_extract_mode); break; default: //skip to end of this NALU gf_bs_skip_bytes(src_bs, nal_size-1); continue; } } else { gf_bs_read_data(src_bs, buffer, nal_size-1); if (rewrite_start_codes) gf_bs_write_u32(dst_bs, 1); else gf_bs_write_int(dst_bs, nal_size, 8*nal_unit_size_field); gf_bs_write_u8(dst_bs, nal_hdr); gf_bs_write_data(dst_bs, buffer, nal_size-1); } }