Пример #1
0
GF_Err flxs_Write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_AdobeFlashAccessParamsBox *ptr = (GF_AdobeFlashAccessParamsBox *)s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_box_write_header(s, bs);
	if (e) return e;
	if (ptr->metadata) {
		gf_bs_write_data(bs, ptr->metadata, (u32)strlen(ptr->metadata));
		gf_bs_write_u8(bs, 0); //string end
	}
	return GF_OK;
}
Пример #2
0
GF_Err tenc_Write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_TrackEncryptionBox *ptr = (GF_TrackEncryptionBox *) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_int(bs, ptr->IsEncrypted, 24);
	gf_bs_write_u8(bs, ptr->IV_size);
	gf_bs_write_data(bs, (char *) ptr->KID, 16);
	return GF_OK;
}
Пример #3
0
GF_Err avcc_Write(GF_Box *s, GF_BitStream *bs)
{
	u32 i, count;
	GF_Err e;
	GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *) s;
	if (!s) return GF_BAD_PARAM;
	if (!ptr->config) return GF_OK;
	e = gf_isom_box_write_header(s, bs);
	if (e) return e;

	gf_bs_write_u8(bs, ptr->config->configurationVersion);
	gf_bs_write_u8(bs, ptr->config->AVCProfileIndication);
	gf_bs_write_u8(bs, ptr->config->profile_compatibility);
	gf_bs_write_u8(bs, ptr->config->AVCLevelIndication);
	if (ptr->type==GF_ISOM_BOX_TYPE_AVCC) {
		gf_bs_write_int(bs, 0x3F, 6);
	} else {
		gf_bs_write_int(bs, ptr->config->complete_representation, 1);
		gf_bs_write_int(bs, 0x1F, 5);
	}
	gf_bs_write_int(bs, ptr->config->nal_unit_size - 1, 2);
	gf_bs_write_int(bs, 0x7, 3);
	count = gf_list_count(ptr->config->sequenceParameterSets);
	gf_bs_write_int(bs, count, 5);
	for (i=0; i<count; i++) {
		GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *) gf_list_get(ptr->config->sequenceParameterSets, i);
		gf_bs_write_u16(bs, sl->size);
		gf_bs_write_data(bs, sl->data, sl->size);
	}

	count = gf_list_count(ptr->config->pictureParameterSets);
	gf_bs_write_u8(bs, count);
	for (i=0; i<count; i++) {
		GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *) gf_list_get(ptr->config->pictureParameterSets, i);
		gf_bs_write_u16(bs, sl->size);
		gf_bs_write_data(bs, sl->data, sl->size);
	}
	return GF_OK;
}
Пример #4
0
GF_Err piff_psec_Write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u32 sample_count;
	GF_SampleEncryptionBox *ptr = (GF_SampleEncryptionBox *) s;
	if (!s) return GF_BAD_PARAM;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;
	gf_bs_write_u8(bs, ptr->version);
	gf_bs_write_u24(bs, ptr->flags);

	if (ptr->flags & 1) {
		gf_bs_write_int(bs, ptr->AlgorithmID, 24);
		gf_bs_write_u8(bs, ptr->IV_size);
		gf_bs_write_data(bs, (char *) ptr->KID, 16);
	}
	sample_count = gf_list_count(ptr->samp_aux_info);
	gf_bs_write_u32(bs, sample_count);
	if (sample_count) {
		u32 i, j;
		e = store_senc_info((GF_SampleEncryptionBox *)ptr, bs);
		if (e) return e;

		for (i = 0; i < sample_count; i++) {
			GF_CENCSampleAuxInfo *sai = (GF_CENCSampleAuxInfo *)gf_list_get(ptr->samp_aux_info, i);
			if (! sai->IV_size) continue;
			gf_bs_write_data(bs, (char *)sai->IV, sai->IV_size);
			gf_bs_write_u16(bs, sai->subsample_count);
			for (j = 0; j < sai->subsample_count; j++) {
				gf_bs_write_u16(bs, sai->subsamples[j].bytes_clear_data);
				gf_bs_write_u32(bs, sai->subsamples[j].bytes_encrypted_data);
			}
		}
	}
	return GF_OK;
}
Пример #5
0
GF_Err tenc_Write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_TrackEncryptionBox *ptr = (GF_TrackEncryptionBox *) s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	gf_bs_write_u8(bs, 0x0); //reserved
	if (!ptr->version) {
		gf_bs_write_u8(bs, 0x0); //reserved
	} else {
		gf_bs_write_int(bs, ptr->crypt_byte_block, 4);
		gf_bs_write_int(bs, ptr->skip_byte_block, 4);
	}
	gf_bs_write_u8(bs, ptr->isProtected);
	gf_bs_write_u8(bs, ptr->Per_Sample_IV_Size);
	gf_bs_write_data(bs, (char *) ptr->KID, 16);
	if ((ptr->isProtected == 1) && !ptr->Per_Sample_IV_Size) {
		gf_bs_write_u8(bs, ptr->constant_IV_size);
		gf_bs_write_data(bs,(char *) ptr->constant_IV, ptr->constant_IV_size);
	}
	return GF_OK;
}
Пример #6
0
GF_Err ohdr_Write(GF_Box *s, GF_BitStream *bs)
{
	u16 cid_len, ri_len;
	GF_Err e;
	GF_OMADRMCommonHeaderBox *ptr = (GF_OMADRMCommonHeaderBox *)s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	gf_bs_write_u8(bs, ptr->EncryptionMethod);
	gf_bs_write_u8(bs, ptr->PaddingScheme);
	gf_bs_write_u64(bs, ptr->PlaintextLength);
	
	cid_len = ptr->ContentID ? strlen(ptr->ContentID) : 0;
	gf_bs_write_u16(bs, cid_len);
	ri_len = ptr->RightsIssuerURL ? strlen(ptr->RightsIssuerURL) : 0;
	gf_bs_write_u16(bs, ri_len);
	gf_bs_write_u16(bs, ptr->TextualHeadersLen);

	if (cid_len) gf_bs_write_data(bs, ptr->ContentID, strlen(ptr->ContentID));
	if (ri_len) gf_bs_write_data(bs, ptr->RightsIssuerURL, strlen(ptr->RightsIssuerURL));
	if (ptr->TextualHeadersLen) gf_bs_write_data(bs, ptr->TextualHeaders, ptr->TextualHeadersLen);
	ptr->size -= cid_len+ri_len+ptr->TextualHeadersLen;
	return GF_OK;
}
Пример #7
0
GF_Err grpi_Write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	u16 gid_len;
	GF_OMADRMGroupIDBox *ptr = (GF_OMADRMGroupIDBox *)s;
	if (!s) return GF_BAD_PARAM;
	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	gid_len = ptr->GroupID ? (u16) strlen(ptr->GroupID) : 0;
	gf_bs_write_u16(bs, gid_len);
	gf_bs_write_u8(bs, ptr->GKEncryptionMethod);
	gf_bs_write_u16(bs, ptr->GKLength);
	gf_bs_write_data(bs, ptr->GroupID, gid_len);
	gf_bs_write_data(bs, ptr->GroupKey, ptr->GKLength);
	return GF_OK;
}
Пример #8
0
GF_Err piff_pssh_Write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_PIFFProtectionSystemHeaderBox *ptr = (GF_PIFFProtectionSystemHeaderBox *) s;
	if (!s) return GF_BAD_PARAM;

	e = gf_isom_box_write_header(s, bs);
	if (e) return e;
	gf_bs_write_u8(bs, ptr->version);
	gf_bs_write_u24(bs, ptr->flags);

	gf_bs_write_data(bs, (char *) ptr->SystemID, 16);
	gf_bs_write_u32(bs, ptr->private_data_size);
	gf_bs_write_data(bs, (char *) ptr->private_data, ptr->private_data_size);
	return GF_OK;
}
Пример #9
0
GF_Err gf_isom_rewrite_text_sample(GF_ISOSample *samp, u32 sampleDescriptionIndex, u32 sample_dur)
{
	GF_BitStream *bs;
	u32 pay_start, txt_size;
	Bool is_utf_16 = 0;
	if (!samp || !samp->data || !samp->dataLength) return GF_OK;

	bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
	txt_size = gf_bs_read_u16(bs);
	gf_bs_del(bs);

	/*remove BOM*/
	pay_start = 2;
	if (txt_size>2) {
		/*seems 3GP only accepts BE UTF-16 (no LE, no UTF32)*/
		if (((u8) samp->data[2]==(u8) 0xFE) && ((u8)samp->data[3]==(u8) 0xFF)) {
			is_utf_16 = 1;
			pay_start = 4;
			txt_size -= 2;
		}
	}

	/*rewrite as TTU(1)*/
	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
	gf_bs_write_int(bs, is_utf_16, 1);
	gf_bs_write_int(bs, 0, 4);
	gf_bs_write_int(bs, 1, 3);
	gf_bs_write_u16(bs, 8 + samp->dataLength - pay_start);
	gf_bs_write_u8(bs, sampleDescriptionIndex + SAMPLE_INDEX_OFFSET);
	gf_bs_write_u24(bs, sample_dur);
	/*write text size*/
	gf_bs_write_u16(bs, txt_size);
	if (txt_size) gf_bs_write_data(bs, samp->data + pay_start, samp->dataLength - pay_start);

	gf_free(samp->data);
	samp->data = NULL;
	gf_bs_get_content(bs, &samp->data, &samp->dataLength);
	gf_bs_del(bs);
	return GF_OK;
}
Пример #10
0
GF_Err gf_isom_get_ttxt_esd(GF_MediaBox *mdia, GF_ESD **out_esd)
{
	GF_BitStream *bs;
	u32 count, i;
	Bool has_v_info;
	GF_List *sampleDesc;
	GF_ESD *esd;
	GF_TrackBox *tk;

	*out_esd = NULL;
	sampleDesc = mdia->information->sampleTable->SampleDescription->boxList;
	count = gf_list_count(sampleDesc);
	if (!count) return GF_ISOM_INVALID_MEDIA;
	
	esd = gf_odf_desc_esd_new(2);
	esd->decoderConfig->streamType = GF_STREAM_TEXT;
	esd->decoderConfig->objectTypeIndication = 0x08;

	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);


	/*Base3GPPFormat*/
	gf_bs_write_u8(bs, 0x10);
	/*MPEGExtendedFormat*/
	gf_bs_write_u8(bs, 0x10);
	/*profileLevel*/
	gf_bs_write_u8(bs, 0x10);
	gf_bs_write_u24(bs, mdia->mediaHeader->timeScale);
	gf_bs_write_int(bs, 0, 1);	/*no alt formats*/
	gf_bs_write_int(bs, 2, 2);	/*only out-of-band-band sample desc*/
	gf_bs_write_int(bs, 1, 1);	/*we will write sample desc*/

	/*write v info if any visual track in this movie*/
	has_v_info = 0;
	i=0;
	while ((tk = (GF_TrackBox*)gf_list_enum(mdia->mediaTrack->moov->trackList, &i))) {
		if (tk->Media->handler && (tk->Media->handler->handlerType == GF_ISOM_MEDIA_VISUAL)) {
			has_v_info = 1;
		}
	}
	gf_bs_write_int(bs, has_v_info, 1);

	gf_bs_write_int(bs, 0, 3);	/*reserved, spec doesn't say the values*/
	gf_bs_write_u8(bs, mdia->mediaTrack->Header->layer);
	gf_bs_write_u16(bs, mdia->mediaTrack->Header->width>>16);
	gf_bs_write_u16(bs, mdia->mediaTrack->Header->height>>16);

	/*write desc*/
	gf_bs_write_u8(bs, count);
	for (i=0; i<count; i++) {
		GF_Tx3gSampleEntryBox *a;
		a = (GF_Tx3gSampleEntryBox *) gf_list_get(sampleDesc, i);
		if ((a->type != GF_ISOM_BOX_TYPE_TX3G) && (a->type != GF_ISOM_BOX_TYPE_TEXT) ) continue;
		gf_isom_write_tx3g(a, bs, i+1, SAMPLE_INDEX_OFFSET);
	}
	if (has_v_info) {
		u32 trans;
		/*which video shall we pick for MPEG-4, and how is the associations indicated in 3GP ???*/
		gf_bs_write_u16(bs, 0);
		gf_bs_write_u16(bs, 0);
		trans = mdia->mediaTrack->Header->matrix[6]; trans >>= 16;
		gf_bs_write_u16(bs, trans);
		trans = mdia->mediaTrack->Header->matrix[7]; trans >>= 16;
		gf_bs_write_u16(bs, trans);
	}

	gf_bs_get_content(bs, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
	gf_bs_del(bs);
	*out_esd = esd;
	return GF_OK;
}
Пример #11
0
static GF_Err gf_seng_encode_dims_au(GF_SceneEngine *seng, u16 ESID, GF_List *commands, char **data, u32 *size)
{
#ifndef GPAC_DISABLE_SCENE_DUMP
	GF_SceneDumper *dumper = NULL;
#endif
	GF_Err e;
	char rad_name[4096];
	char file_name[4096];
	FILE *file = NULL;
	u64 fsize;
	char *buffer = NULL;
	GF_BitStream *bs = NULL;
	u8 dims_header;
	Bool compress_dims;
#ifdef DUMP_DIMS_LOG_WITH_TIME
	u32 do_dump_with_time = 1;
#endif
	u32 buffer_len;
	char *cache_dir, *dump_name;

	if (!data) return GF_BAD_PARAM;

	e = GF_OK;

	if (!seng->dump_path) cache_dir = gf_get_default_cache_directory();
	else cache_dir = seng->dump_path;

	dump_name = "gpac_scene_engine_dump";
	compress_dims = 1;

#ifdef DUMP_DIMS_LOG_WITH_TIME
start:    
#endif
	
	if (commands && gf_list_count(commands)) {
        sprintf(rad_name, "%s%c%s%s", cache_dir, GF_PATH_SEPARATOR, dump_name, "_update");
	} else {
#ifndef DUMP_DIMS_LOG_WITH_TIME
		sprintf(rad_name, "%s%c%s%s", cache_dir, GF_PATH_SEPARATOR, "rap_", dump_name);
#else
        char date_str[100], time_str[100];
        time_t now;
        struct tm *tm_tot;
        now = time(NULL);        
        tm_tot = localtime(&now);
        strftime(date_str, 100, "%Yy%mm%dd", tm_tot);
		strftime(time_str, 100, "%Hh%Mm%Ss", tm_tot);            
        sprintf(rad_name, "%s%c%s-%s-%s%s", cache_dir, GF_PATH_SEPARATOR, date_str, time_str, "rap_", dump_name);
#endif
	}

#ifndef GPAC_DISABLE_SCENE_DUMP
	dumper = gf_sm_dumper_new(seng->ctx->scene_graph, rad_name, ' ', GF_SM_DUMP_SVG);
	if (!dumper) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[SceneEngine] Cannot create SVG dumper for %s.svg\n", rad_name)); 
		e = GF_IO_ERR;
		goto exit;
	}

	if (commands && gf_list_count(commands)) {
		e = gf_sm_dump_command_list(dumper, commands, 0, 0);
	}
	else {
		e = gf_sm_dump_graph(dumper, 0, 0);
	}
	gf_sm_dumper_del(dumper);

    if(seng->dump_rap){
        GF_SceneDumper *dumper = NULL;
                 
        sprintf(rad_name, "%s%c%s%s", cache_dir, GF_PATH_SEPARATOR, "rap_", dump_name);

        dumper = gf_sm_dumper_new(seng->ctx->scene_graph, rad_name, ' ', GF_SM_DUMP_SVG);
	    if (!dumper) {
		    GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[SceneEngine] Cannot create SVG dumper for %s.svg\n", rad_name)); 
		    e = GF_IO_ERR;
		    goto exit;
        }
        e = gf_sm_dump_graph(dumper, 0, 0);
        gf_sm_dumper_del(dumper);
    }

	if (e) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[SceneEngine] Cannot dump DIMS Commands\n")); 
		goto exit;
	}
#endif

#ifdef DUMP_DIMS_LOG_WITH_TIME
    if (do_dump_with_time) {
        do_dump_with_time = 0;
        goto start;        
    }
#endif
	
	sprintf(file_name, "%s.svg", rad_name);
	file = gf_f64_open(file_name, "rb");
	if (!file) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[SceneEngine] Cannot open SVG dump file %s\n", file_name)); 
		e = GF_IO_ERR;
		goto exit;
	}
	gf_f64_seek(file, 0, SEEK_END);
	fsize = gf_f64_tell(file);
	
	if (fsize == 0) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[SceneEngine] SVG dump %s is empty\n", file_name)); 
		goto exit;
	}

	/* First, read the dump in a buffer */
	buffer = gf_malloc((size_t)fsize * sizeof(char));
	gf_f64_seek(file, 0, SEEK_SET);
	fsize = fread(buffer, sizeof(char), (size_t)fsize, file);
	fclose(file);
    file = NULL;

	/* Then, set DIMS unit header - TODO: notify redundant units*/
	dims_header = 0;
    if (commands && gf_list_count(commands)) {
		dims_header = GF_DIMS_UNIT_P; /* streamer->all_non_rap_critical ? 0 : GF_DIMS_UNIT_P;*/
	} else {
		/*redundant RAP with complete scene*/
		dims_header = GF_DIMS_UNIT_M | GF_DIMS_UNIT_S | GF_DIMS_UNIT_I | GF_DIMS_UNIT_P;
	}

	/* Then, if compression is asked, we do it */
	buffer_len = (u32)fsize;
	assert(fsize < 1<<31);
	GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[SceneEngine] Sending DIMS data - sizes: raw (%d)", buffer_len)); 
	if (compress_dims) {
		dims_header |= GF_DIMS_UNIT_C;
		e = gf_gz_compress_payload(&buffer, buffer_len, &buffer_len);
		GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("/ compressed (%d)", buffer_len)); 
		if (e) goto exit;
	}
    GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("\n")); 

	/* Then,  prepare the DIMS data using a bitstream instead of direct manipulation for endianness
           The new bitstream size should be:
		the size of the (compressed) data 
		+ 1 bytes for the header
		+ 2 bytes for the size
		+ 4 bytes if the size is greater than 65535
	 */
	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); 
	if (buffer_len > 65535) {
		GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[SceneEngine] Warning: DIMS Unit size too big !!!\n")); 
		gf_bs_write_u16(bs, 0); /* internal GPAC hack to indicate that the size is larger than 65535 */
		gf_bs_write_u32(bs, buffer_len+1);
	} else {
		gf_bs_write_u16(bs, buffer_len+1);
	}
	gf_bs_write_u8(bs, dims_header);
	gf_bs_write_data(bs, buffer, buffer_len);

	gf_free(buffer);
	buffer = NULL;

	gf_bs_get_content(bs, data, size);
	gf_bs_del(bs);

exit:
	if (!seng->dump_path) gf_free(cache_dir);
	if (buffer) gf_free(buffer);
	if (file) fclose(file);
	return e;
}
Пример #12
0
static GF_Err CENC_ProcessData(ISMAEAPriv *priv, GF_IPMPEvent *evt)
{
	GF_Err e;
	GF_BitStream *pleintext_bs, *cyphertext_bs, *sai_bs;
	char IV[17];
	bin128 KID;
	char *buffer;
	u32 max_size, i, subsample_count;
	u64 BSO;
	GF_CENCSampleAuxInfo *sai;

	e = GF_OK;
	pleintext_bs = cyphertext_bs = sai_bs = NULL;
	buffer = NULL;
	max_size = 4096;

	if (!priv->crypt) return GF_SERVICE_ERROR;
	
	if (!evt->is_encrypted || !evt->IV_size) return GF_OK;

	cyphertext_bs = gf_bs_new(evt->data, evt->data_size, GF_BITSTREAM_READ);
	sai_bs = gf_bs_new(evt->sai, evt->saiz, GF_BITSTREAM_READ);
	pleintext_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
	buffer = (char*)gf_malloc(sizeof(char) * max_size);

	sai = (GF_CENCSampleAuxInfo *)gf_malloc(sizeof(GF_CENCSampleAuxInfo));
	if (!sai) {
		e = GF_IO_ERR;
		goto exit;
	}
	memset(sai, 0, sizeof(GF_CENCSampleAuxInfo));
	sai->IV_size = evt->IV_size;
	/*read sample auxiliary information from bitstream*/
	gf_bs_read_data(sai_bs,  (char *)KID, 16);
	gf_bs_read_data(sai_bs, (char *)sai->IV, sai->IV_size);
	sai->subsample_count = gf_bs_read_u16(sai_bs);
	if (sai->subsample_count) {
		sai->subsamples = (GF_CENCSubSampleEntry *)gf_malloc(sai->subsample_count*sizeof(GF_CENCSubSampleEntry));
		for (i = 0; i < sai->subsample_count; i++) {
			sai->subsamples[i].bytes_clear_data = gf_bs_read_u16(sai_bs);
			sai->subsamples[i].bytes_encrypted_data = gf_bs_read_u32(sai_bs);
		}
	}


	for (i = 0; i < priv->KID_count; i++) {
		if (!strncmp((const char *)KID, (const char *)priv->KIDs[i], 16)) {
			memmove(priv->key, priv->keys[i], 16);
			break;
		}
	}

	if (priv->first_crypted_samp) {
		memmove(IV, sai->IV, sai->IV_size);
		if (sai->IV_size == 8)
			memset(IV+8, 0, sizeof(char)*8);
		e = gf_crypt_init(priv->crypt, priv->key, 16, IV);
		if (e) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot initialize AES-128 AES-128 %s (%s)\n", priv->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) );
			e = GF_IO_ERR;
			goto exit;
		}
		priv->first_crypted_samp = GF_FALSE;
	} else {
		if (priv->is_cenc) {
			GF_BitStream *bs;
			bs = gf_bs_new(IV, 17, GF_BITSTREAM_WRITE);
			gf_bs_write_u8(bs, 0);	/*begin of counter*/
			gf_bs_write_data(bs,(char *)sai->IV, sai->IV_size);
			if (sai->IV_size == 8)
				gf_bs_write_u64(bs, 0); /*0-padded if IV_size == 8*/
			gf_bs_del(bs);
			gf_crypt_set_state(priv->crypt, IV, 17);
		}
		e = gf_crypt_set_key(priv->crypt, priv->key, 16, IV);
		if (e) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot set key AES-128 %s (%s)\n", priv->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) );
			e = GF_IO_ERR;
			goto exit;
		}
	}

	subsample_count = 0;
	BSO = 0;
	while (gf_bs_available(cyphertext_bs)) {
		assert(subsample_count < sai->subsample_count);

		/*read clear data and write it to pleintext bitstream*/
		if (max_size < sai->subsamples[subsample_count].bytes_clear_data) {
			buffer = (char*)gf_realloc(buffer, sizeof(char)*sai->subsamples[subsample_count].bytes_clear_data);
			max_size = sai->subsamples[subsample_count].bytes_clear_data;
		}
		gf_bs_read_data(cyphertext_bs, buffer, sai->subsamples[subsample_count].bytes_clear_data);
		gf_bs_write_data(pleintext_bs, buffer, sai->subsamples[subsample_count].bytes_clear_data);

		/*now read encrypted data, decrypted it and write to pleintext bitstream*/
		if (max_size < sai->subsamples[subsample_count].bytes_encrypted_data) {
			buffer = (char*)gf_realloc(buffer, sizeof(char)*sai->subsamples[subsample_count].bytes_encrypted_data);
			max_size = sai->subsamples[subsample_count].bytes_encrypted_data;
		}
		gf_bs_read_data(cyphertext_bs, buffer, sai->subsamples[subsample_count].bytes_encrypted_data);
		gf_crypt_decrypt(priv->crypt, buffer, sai->subsamples[subsample_count].bytes_encrypted_data);
		gf_bs_write_data(pleintext_bs, buffer, sai->subsamples[subsample_count].bytes_encrypted_data);

		/*update IV for next subsample*/
		if (priv->is_cenc) {
			BSO += sai->subsamples[subsample_count].bytes_encrypted_data;
			if (gf_bs_available(cyphertext_bs)) {
				char next_IV[17];
				u64 prev_block_count, salt_portion, block_count_portion;
				u32 remain;
				GF_BitStream *bs, *tmp;

				prev_block_count = BSO / 16;
				remain = BSO % 16;
				tmp = gf_bs_new((const char *)sai->IV, 16, GF_BITSTREAM_READ);
				bs = gf_bs_new(next_IV, 17, GF_BITSTREAM_WRITE);
				gf_bs_write_u8(bs, 0);	/*begin of counter*/

				salt_portion = gf_bs_read_u64(tmp);
				block_count_portion = gf_bs_read_u64(tmp);
				/*reset the block counter to zero without affecting the other 64 bits of the IV*/
				if (prev_block_count > 0xFFFFFFFFFFFFFFFFULL - block_count_portion)
					block_count_portion = prev_block_count - (0xFFFFFFFFFFFFFFFFULL - block_count_portion) - 1;
				else
					block_count_portion +=  prev_block_count;
				gf_bs_write_u64(bs, salt_portion);
				gf_bs_write_u64(bs, block_count_portion);

				gf_crypt_set_state(priv->crypt, next_IV, 17);
				/*decrypt remain bytes*/
				if (remain) {
					char dummy[20];
					gf_crypt_decrypt(priv->crypt, dummy, remain);
				}

				gf_bs_del(bs);
				gf_bs_del(tmp);
			}
		}

		subsample_count++;
	}

	if (buffer) gf_free(buffer);
	gf_bs_get_content(pleintext_bs, &buffer, &evt->data_size);
	memmove(evt->data, buffer, evt->data_size);

exit:
	if (pleintext_bs) gf_bs_del(pleintext_bs);
	if (sai_bs) gf_bs_del(sai_bs);
	if (cyphertext_bs) gf_bs_del(cyphertext_bs);
	if (buffer) gf_free(buffer);
	if (sai && sai->subsamples) gf_free(sai->subsamples);
	if (sai) gf_free(sai);
	return e;
}
Пример #13
0
static GF_Err gf_isom_get_3gpp_audio_esd(GF_SampleTableBox *stbl, GF_GenericAudioSampleEntryBox *entry, GF_ESD **out_esd)
{
	GF_BitStream *bs;
	char szName[80];

	(*out_esd) = gf_odf_desc_esd_new(2);
	(*out_esd)->decoderConfig->streamType = GF_STREAM_AUDIO;
	/*official mapping to MPEG-4*/
	switch (entry->type) {
	case GF_ISOM_SUBTYPE_3GP_EVRC: 
		(*out_esd)->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_EVRC_VOICE;
		return GF_OK;
	case GF_ISOM_SUBTYPE_3GP_QCELP:
	{
		u32 block_size, sample_rate, sample_size, i;
		GF_SttsEntry *ent;
		/*only map CBR*/
		sample_size = stbl->SampleSize->sampleSize;
		(*out_esd)->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_13K_VOICE;
		bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
		gf_bs_write_data(bs, "QLCMfmt ", 8);
		gf_bs_write_u32_le(bs, 150);/*fmt chunk size*/
		gf_bs_write_u8(bs, 1);
		gf_bs_write_u8(bs, 0);
		/*QCELP GUID*/
		gf_bs_write_data(bs, "\x41\x6D\x7F\x5E\x15\xB1\xD0\x11\xBA\x91\x00\x80\x5F\xB4\xB9\x7E", 16);
		gf_bs_write_u16_le(bs, 1);
		memset(szName, 0, 80);
		strcpy(szName, "QCELP-13K(GPAC-emulated)");
		gf_bs_write_data(bs, szName, 80);
		ent = &stbl->TimeToSample->entries[0];
		sample_rate = entry->samplerate_hi;
		block_size = ent ? ent->sampleDelta : 160;
		gf_bs_write_u16_le(bs, 8*sample_size*sample_rate/block_size);
		gf_bs_write_u16_le(bs, sample_size);
		gf_bs_write_u16_le(bs, block_size);
		gf_bs_write_u16_le(bs, sample_rate);
		gf_bs_write_u16_le(bs, entry->bitspersample);
		gf_bs_write_u32_le(bs, sample_size ? 0 : 7);
		/**/
		for (i=0; i<7; i++) {
			static const u32 qcelp_r2s [] = {0, 1, 1, 4, 2, 8, 3, 17, 4, 35, 5, 8, 14, 1};
			if (sample_size) {
				gf_bs_write_u16(bs, 0);
			} else {
				gf_bs_write_u8(bs, qcelp_r2s[2*i+1]);
				gf_bs_write_u8(bs, qcelp_r2s[2*i]);
			}
		}
		gf_bs_write_u16(bs, 0);
		memset(szName, 0, 80);
		gf_bs_write_data(bs, szName, 20);/*reserved*/
		gf_bs_get_content(bs, & (*out_esd)->decoderConfig->decoderSpecificInfo->data, & (*out_esd)->decoderConfig->decoderSpecificInfo->dataLength);
		gf_bs_del(bs);
	}
		return GF_OK;
	case GF_ISOM_SUBTYPE_3GP_SMV:
		(*out_esd)->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_SMV_VOICE;
		return GF_OK;
	default:
		break;
	}
	/*this is a user-reserved used in gpac - we need a std OTI for AMR/AMRWB*/
	(*out_esd)->decoderConfig->objectTypeIndication = GPAC_OTI_MEDIA_GENERIC;
	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
	gf_bs_write_u32(bs, entry->type);
	gf_bs_write_u16(bs, entry->samplerate_hi);
	gf_bs_write_u16(bs, (entry->type == GF_ISOM_SUBTYPE_3GP_AMR) ? 160 : 320);
	gf_bs_write_u8(bs, entry->channel_count);
	gf_bs_write_u8(bs, entry->bitspersample);
	gf_bs_write_u8(bs, 0);
	gf_bs_get_content(bs, & (*out_esd)->decoderConfig->decoderSpecificInfo->data, & (*out_esd)->decoderConfig->decoderSpecificInfo->dataLength);
	gf_bs_del(bs);
	return GF_OK;
}
Пример #14
0
GF_Err gp_rtp_builder_do_tx3g(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize, u32 duration, u8 descIndex)
{
	GF_BitStream *bs;
	char *hdr;
	u32 samp_size, txt_size, pay_start, hdr_size, txt_done, cur_frag, nb_frag;
	Bool is_utf_16 = 0;

	if (!data) {
		/*flush packet*/
		if (builder->bytesInPacket) {
			builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
			builder->bytesInPacket = 0;
		}
		return GF_OK;
	}
	/*cfg packet*/
	txt_size = data[0]; txt_size <<= 8; txt_size |= (unsigned char) data[1];
	/*remove BOM*/
	pay_start = 2;
	if (txt_size>2) {
		/*seems 3GP only accepts BE UTF-16 (no LE, no UTF32)*/
		if (((u8) data[2]==(u8) 0xFE) && ((u8) data[3]==(u8) 0xFF)) {
			is_utf_16 = 1;
			pay_start = 4;
			txt_size -= 2;
		}
	}
	samp_size = data_size - pay_start;

	/*if TTU does not fit in packet flush packet*/
	if (builder->bytesInPacket && (builder->bytesInPacket + 3 + 6 + samp_size > builder->Path_MTU)) {
		builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
		builder->bytesInPacket = 0;
	}

	/*first TTU in packet*/
	if (!builder->bytesInPacket) {
		builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
		builder->rtp_header.Marker = 1;
		builder->rtp_header.SequenceNumber += 1;
		builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
	}
	/*fits entirely*/
	if (builder->bytesInPacket + 3 + 6 + samp_size <= builder->Path_MTU) {
		bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
		gf_bs_write_int(bs, is_utf_16, 1);
		gf_bs_write_int(bs, 0, 4);
		gf_bs_write_int(bs, 1, 3);
		gf_bs_write_u16(bs, 8 + samp_size);
		gf_bs_write_u8(bs, descIndex);
		gf_bs_write_u24(bs, duration);
		gf_bs_write_u16(bs, txt_size);
		gf_bs_get_content(bs, &hdr, &hdr_size);
		gf_bs_del(bs);
		builder->OnData(builder->cbk_obj, (char *) hdr, hdr_size, 0);
		builder->bytesInPacket += hdr_size;
		gf_free(hdr);

		if (txt_size) {
			if (builder->OnDataReference) {
				builder->OnDataReference(builder->cbk_obj, samp_size, pay_start);
			} else {
				builder->OnData(builder->cbk_obj, data + pay_start, samp_size, 0);
			}
			builder->bytesInPacket += samp_size;
		}
		/*disable aggregation*/
		if (!(builder->flags & GP_RTP_PCK_USE_MULTI)) {
			builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
			builder->bytesInPacket = 0;
		}
		return GF_OK;
	}
	/*doesn't fit and already data, flush packet*/
	if (builder->bytesInPacket) {
		builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
		builder->rtp_header.TimeStamp = (u32) builder->sl_header.compositionTimeStamp;
		/*split unit*/
		builder->rtp_header.Marker = 0;
		builder->rtp_header.SequenceNumber += 1;
		builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
		builder->bytesInPacket = 0;
	}
	/*write all type2 units (text only) - FIXME: split at char boundaries, NOT SUPPORTED YET*/
	txt_done = 0;
	nb_frag = 1;
	/*all fragments needed for Type2 units*/
	while (txt_done + (builder->Path_MTU-10) < txt_size) {
		txt_done += (builder->Path_MTU-10);
		nb_frag += 1;
	}
	/*all fragments needed for Type3/4 units*/
	txt_done = txt_size;
	while (txt_done + (builder->Path_MTU-7) < samp_size) {
		txt_done += (builder->Path_MTU-7);
		nb_frag += 1;
	}


	cur_frag = 0;
	txt_done = 0;
	while (txt_done<txt_size) {
		u32 size;
		if (txt_done + (builder->Path_MTU-10) < txt_size) {
			size = builder->Path_MTU-10;
		} else {
			size = txt_size - txt_done;
		}

		bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
		gf_bs_write_int(bs, is_utf_16, 1);
		gf_bs_write_int(bs, 0, 4);
		gf_bs_write_int(bs, 2, 3);
		gf_bs_write_u16(bs, 9 + size);
		gf_bs_write_int(bs, nb_frag, 4);
		gf_bs_write_int(bs, cur_frag, 4);
		gf_bs_write_u24(bs, duration);
		gf_bs_write_u8(bs, descIndex);
		/*SLEN is the full original length minus text len and BOM (put here for buffer allocation purposes)*/
		gf_bs_write_u16(bs, samp_size);
		gf_bs_get_content(bs, &hdr, &hdr_size);
		gf_bs_del(bs);
		builder->OnData(builder->cbk_obj, (char *) hdr, hdr_size, 0);
		builder->bytesInPacket += hdr_size;
		gf_free(hdr);

		if (builder->OnDataReference) {
			builder->OnDataReference(builder->cbk_obj, size, pay_start + txt_done);
		} else {
			builder->OnData(builder->cbk_obj, data + pay_start + txt_done, size, 0);
		}
		builder->bytesInPacket += size;
		cur_frag++;

		/*flush packet*/
		if (cur_frag == nb_frag) {
			txt_done = txt_size;
			if (pay_start + txt_done == data_size) {
				builder->rtp_header.Marker = 1;
				builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
				builder->bytesInPacket = 0;
			}
		} else {
			txt_done += size;
			builder->rtp_header.Marker = 0;
			builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
			builder->rtp_header.SequenceNumber += 1;
			builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
			builder->bytesInPacket = 0;
		}
	}

	txt_done = txt_size;

	/*write all modifiers - OPT: split at modifiers boundaries*/
	while (txt_done<samp_size) {
		u32 size, type;
		type = (txt_done == txt_size) ? 3 : 4;

		if (txt_done + (builder->Path_MTU-7) < samp_size) {
			size = builder->Path_MTU-10;
		} else {
			size = samp_size - txt_done;
		}

		bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
		gf_bs_write_int(bs, is_utf_16, 1);
		gf_bs_write_int(bs, 0, 4);
		gf_bs_write_int(bs, type, 3);
		gf_bs_write_u16(bs, 6 + size);
		gf_bs_write_int(bs, nb_frag, 4);
		gf_bs_write_int(bs, cur_frag, 4);
		gf_bs_write_u24(bs, duration);

		gf_bs_get_content(bs, &hdr, &hdr_size);
		gf_bs_del(bs);
		builder->OnData(builder->cbk_obj, (char *) hdr, hdr_size, 0);
		builder->bytesInPacket += hdr_size;
		gf_free(hdr);

		if (builder->OnDataReference) {
			builder->OnDataReference(builder->cbk_obj, size, pay_start + txt_done);
		} else {
			builder->OnData(builder->cbk_obj, data + pay_start + txt_done, size, 0);
		}
		builder->bytesInPacket += size;
		cur_frag++;
		if (cur_frag==nb_frag) {
			builder->rtp_header.Marker = 1;
			builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
			builder->bytesInPacket = 0;
		} else {
			builder->rtp_header.Marker = 0;
			builder->OnPacketDone(builder->cbk_obj, &builder->rtp_header);
			builder->rtp_header.SequenceNumber += 1;
			builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
			builder->bytesInPacket = 0;
		}
		txt_done += size;
	}
	return GF_OK;
}
Пример #15
0
GF_Err gp_rtp_builder_do_smv(GP_RTPPacketizer *builder, char *data, u32 data_size, u8 IsAUEnd, u32 FullAUSize)
{
	u32 offset, rtp_ts;

	if (!data) {
		rtp_evrc_smv_flush(builder);
		return GF_OK;
	}

	rtp_ts = (u32) builder->sl_header.compositionTimeStamp;

	offset = 0;
	while (data_size>offset) {
		u8 frame_type = data[offset];
		u8 size = qes_get_rate_size(frame_type, GF_SMV_EVRC_RATE_TO_SIZE, GF_SMV_EVRC_RATE_TO_SIZE_NB);

		/*reserved, not sent)*/
		if (frame_type>=5) {
			offset += size;
			continue;
		}
		/*packet full or too long*/
		if (builder->bytesInPacket + size > builder->Path_MTU)
			rtp_evrc_smv_flush(builder);

		/*need new*/
		if (!builder->bytesInPacket) {
			builder->rtp_header.TimeStamp = rtp_ts;
			builder->rtp_header.Marker = 0;	/*never set*/
			builder->rtp_header.SequenceNumber += 1;
			builder->OnNewPacket(builder->cbk_obj, &builder->rtp_header);
			assert(builder->pck_hdr==NULL);

			if (builder->auh_size>1) {
				builder->pck_hdr = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
				/*RRLLLNNN (all 0, no interleaving)*/
				gf_bs_write_u8(builder->pck_hdr, 0);
				/*MMM + count-1 : overriden when flushing*/
				gf_bs_write_u8(builder->pck_hdr, 0);
				builder->bytesInPacket = 2;
			}
		}

		/*bundle mode: cat rate byte to TOC, on 4 bits*/
		if (builder->auh_size>1) {
			gf_bs_write_int(builder->pck_hdr, data[offset], 4);
			if (!(builder->last_au_sn % 2)) builder->bytesInPacket += 1;
		}
		/*note that EVEN in header-free format the rate_type byte is removed*/
		offset++;
		size--;

		/*add frame data without rate_type byte header*/
		if (builder->OnDataReference) {
			builder->OnDataReference(builder->cbk_obj, size, offset);
		} else {
			builder->OnData(builder->cbk_obj, data+offset, size, 0);
		}
		builder->last_au_sn++;
		builder->bytesInPacket += size;
		offset += size;
		rtp_ts += 160;
		assert(builder->bytesInPacket<=builder->Path_MTU);
		/*take care of aggregation, flush if needed*/
		if (builder->last_au_sn==builder->auh_size) rtp_evrc_smv_flush(builder);
	}
	return GF_OK;
}
Пример #16
0
/* 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);
		}
	}
Пример #17
0
static GF_ESD *FFD_GetESDescriptor(FFDemux *ffd, Bool for_audio)
{
	GF_BitStream *bs;
	Bool dont_use_sl;
	GF_ESD *esd = (GF_ESD *) gf_odf_desc_esd_new(0);
	esd->ESID = 1 + (for_audio ? ffd->audio_st : ffd->video_st);
	esd->decoderConfig->streamType = for_audio ? GF_STREAM_AUDIO : GF_STREAM_VISUAL;
	esd->decoderConfig->avgBitrate = esd->decoderConfig->maxBitrate = 0;

	/*remap std object types - depending on input formats, FFMPEG may not have separate DSI from initial frame.
	In this case we have no choice but using FFMPEG decoders*/
	if (for_audio) {
		AVCodecContext *dec = ffd->ctx->streams[ffd->audio_st]->codec;
		esd->slConfig->timestampResolution = ffd->audio_tscale.den;
		switch (dec->codec_id) {
		case CODEC_ID_MP2:
			esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG1;
			break;
		case CODEC_ID_MP3:
			esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_MPEG2_PART3;
			break;
		case CODEC_ID_AAC:
			if (!dec->extradata_size) goto opaque_audio;
			esd->decoderConfig->objectTypeIndication = GPAC_OTI_AUDIO_AAC_MPEG4;
			esd->decoderConfig->decoderSpecificInfo->dataLength = dec->extradata_size;
			esd->decoderConfig->decoderSpecificInfo->data = gf_malloc(sizeof(char)*dec->extradata_size);
			memcpy(esd->decoderConfig->decoderSpecificInfo->data,
			       dec->extradata,
			       sizeof(char)*dec->extradata_size);
			break;
		default:
opaque_audio:
			esd->decoderConfig->objectTypeIndication = GPAC_OTI_MEDIA_FFMPEG;
			bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
			gf_bs_write_u32(bs, dec->codec_id);
			gf_bs_write_u32(bs, dec->sample_rate);
			gf_bs_write_u16(bs, dec->channels);
			gf_bs_write_u16(bs, dec->frame_size);
			gf_bs_write_u8(bs, 16);
			gf_bs_write_u8(bs, 0);
			/*ffmpeg specific*/
			gf_bs_write_u16(bs, dec->block_align);
			gf_bs_write_u32(bs, dec->bit_rate);
			gf_bs_write_u32(bs, dec->codec_tag);
			if (dec->extradata_size) {
				gf_bs_write_data(bs, (char *) dec->extradata, dec->extradata_size);
			}
			gf_bs_get_content(bs, (char **) &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
			gf_bs_del(bs);
			break;
		}
		dont_use_sl = ffd->unreliable_audio_timing;
	} else {
		AVCodecContext *dec = ffd->ctx->streams[ffd->video_st]->codec;
		esd->slConfig->timestampResolution = ffd->video_tscale.den;
		switch (dec->codec_id) {
		case CODEC_ID_MPEG4:
			/*there is a bug in fragmentation of raw H264 in ffmpeg, the NALU startcode (0x00000001) is split across
			two frames - we therefore force internal ffmpeg codec ID to avoid NALU size recompute
			at the decoder level*/
//		case CODEC_ID_H264:
			/*if dsi not detected force use ffmpeg*/
			if (!dec->extradata_size) goto opaque_video;
			/*otherwise use any MPEG-4 Visual*/
			esd->decoderConfig->objectTypeIndication = (dec->codec_id==CODEC_ID_H264) ? GPAC_OTI_VIDEO_AVC : GPAC_OTI_VIDEO_MPEG4_PART2;
			esd->decoderConfig->decoderSpecificInfo->dataLength = dec->extradata_size;
			esd->decoderConfig->decoderSpecificInfo->data = gf_malloc(sizeof(char)*dec->extradata_size);
			memcpy(esd->decoderConfig->decoderSpecificInfo->data,
			       dec->extradata,
			       sizeof(char)*dec->extradata_size);
			break;
		case CODEC_ID_MPEG1VIDEO:
			esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG1;
			break;
		case CODEC_ID_MPEG2VIDEO:
			esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_MPEG2_422;
			break;
		default:
opaque_video:
			esd->decoderConfig->objectTypeIndication = GPAC_OTI_MEDIA_FFMPEG;
			bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
			gf_bs_write_u32(bs, dec->codec_id);
			gf_bs_write_u16(bs, dec->width);
			gf_bs_write_u16(bs, dec->height);
			/*ffmpeg specific*/
			gf_bs_write_u32(bs, dec->bit_rate);
			gf_bs_write_u32(bs, dec->codec_tag);
			gf_bs_write_u32(bs, dec->pix_fmt);

			if (dec->extradata_size) {
				gf_bs_write_data(bs, (char *) dec->extradata, dec->extradata_size);
			}
			gf_bs_get_content(bs, (char **) &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
			gf_bs_del(bs);
			break;
		}
		dont_use_sl = 0;
	}

	if (dont_use_sl) {
		esd->slConfig->predefined = SLPredef_SkipSL;
	} else {
		/*only send full AUs*/
		esd->slConfig->useAccessUnitStartFlag = esd->slConfig->useAccessUnitEndFlag = 0;
		if (for_audio) {
			esd->slConfig->hasRandomAccessUnitsOnlyFlag = 1;
		} else {
			esd->slConfig->useRandomAccessPointFlag = 1;
		}
		esd->slConfig->useTimestampsFlag = 1;
	}

	return esd;
}
Пример #18
0
static GF_Err CENC_ProcessData(ISMAEAPriv *priv, GF_IPMPEvent *evt)
{
	GF_Err e;
	GF_BitStream *pleintext_bs, *cyphertext_bs, *sai_bs;
	char IV[17];
	bin128 KID;
	char *buffer;
	u32 max_size, i, subsample_count;
	GF_CENCSampleAuxInfo *sai;

	pleintext_bs = cyphertext_bs = sai_bs = NULL;
	buffer = NULL;
	max_size = 4096;

	if (!priv->crypt) return GF_SERVICE_ERROR;

	if (!evt->is_encrypted || !evt->IV_size || !evt->saiz) return GF_OK;

	cyphertext_bs = gf_bs_new(evt->data, evt->data_size, GF_BITSTREAM_READ);
	sai_bs = gf_bs_new(evt->sai, evt->saiz, GF_BITSTREAM_READ);
	pleintext_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
	buffer = (char*)gf_malloc(sizeof(char) * max_size);

	sai = (GF_CENCSampleAuxInfo *)gf_malloc(sizeof(GF_CENCSampleAuxInfo));
	if (!sai) {
		e = GF_IO_ERR;
		goto exit;
	}
	memset(sai, 0, sizeof(GF_CENCSampleAuxInfo));
	sai->IV_size = evt->IV_size;
	/*read sample auxiliary information from bitstream*/
	gf_bs_read_data(sai_bs,  (char *)KID, 16);
	gf_bs_read_data(sai_bs, (char *)sai->IV, sai->IV_size);
	sai->subsample_count = gf_bs_read_u16(sai_bs);
	if (sai->subsample_count) {
		sai->subsamples = (GF_CENCSubSampleEntry *)gf_malloc(sai->subsample_count*sizeof(GF_CENCSubSampleEntry));
		for (i = 0; i < sai->subsample_count; i++) {
			sai->subsamples[i].bytes_clear_data = gf_bs_read_u16(sai_bs);
			sai->subsamples[i].bytes_encrypted_data = gf_bs_read_u32(sai_bs);
		}
	}


	for (i = 0; i < priv->KID_count; i++) {
		if (!strncmp((const char *)KID, (const char *)priv->KIDs[i], 16)) {
			memmove(priv->key, priv->keys[i], 16);
			break;
		}
	}

	if (priv->first_crypted_samp) {
		memmove(IV, sai->IV, sai->IV_size);
		if (sai->IV_size == 8)
			memset(IV+8, 0, sizeof(char)*8);
		e = gf_crypt_init(priv->crypt, priv->key, 16, IV);
		if (e) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot initialize AES-128 AES-128 %s (%s)\n", priv->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) );
			e = GF_IO_ERR;
			goto exit;
		}
		priv->first_crypted_samp = GF_FALSE;
	} else {
		if (priv->is_cenc) {
			GF_BitStream *bs;
			bs = gf_bs_new(IV, 17, GF_BITSTREAM_WRITE);
			gf_bs_write_u8(bs, 0);	/*begin of counter*/
			gf_bs_write_data(bs,(char *)sai->IV, sai->IV_size);
			if (sai->IV_size == 8)
				gf_bs_write_u64(bs, 0); /*0-padded if IV_size == 8*/
			gf_bs_del(bs);
			gf_crypt_set_state(priv->crypt, IV, 17);
		}
		e = gf_crypt_set_key(priv->crypt, priv->key, 16, IV);
		if (e) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot set key AES-128 %s (%s)\n", priv->is_cenc ? "CTR" : "CBC", gf_error_to_string(e)) );
			e = GF_IO_ERR;
			goto exit;
		}
	}

	//sub-sample encryption
	if (sai->subsample_count) {
		subsample_count = 0;
		while (gf_bs_available(cyphertext_bs)) {
			if (subsample_count >= sai->subsample_count)
				break;

			/*read clear data and write it to pleintext bitstream*/
			if (max_size < sai->subsamples[subsample_count].bytes_clear_data) {
				buffer = (char*)gf_realloc(buffer, sizeof(char)*sai->subsamples[subsample_count].bytes_clear_data);
				max_size = sai->subsamples[subsample_count].bytes_clear_data;
			}
			gf_bs_read_data(cyphertext_bs, buffer, sai->subsamples[subsample_count].bytes_clear_data);
			gf_bs_write_data(pleintext_bs, buffer, sai->subsamples[subsample_count].bytes_clear_data);

			/*now read encrypted data, decrypted it and write to pleintext bitstream*/
			if (max_size < sai->subsamples[subsample_count].bytes_encrypted_data) {
				buffer = (char*)gf_realloc(buffer, sizeof(char)*sai->subsamples[subsample_count].bytes_encrypted_data);
				max_size = sai->subsamples[subsample_count].bytes_encrypted_data;
			}
			gf_bs_read_data(cyphertext_bs, buffer, sai->subsamples[subsample_count].bytes_encrypted_data);
			gf_crypt_decrypt(priv->crypt, buffer, sai->subsamples[subsample_count].bytes_encrypted_data);
			gf_bs_write_data(pleintext_bs, buffer, sai->subsamples[subsample_count].bytes_encrypted_data);

			subsample_count++;
		}
		if (buffer) gf_free(buffer);
		gf_bs_get_content(pleintext_bs, &buffer, &evt->data_size);
	}
	//full sample encryption
	else {
		if (max_size < evt->data_size) {
			buffer = (char*)gf_realloc(buffer, sizeof(char)*evt->data_size);
		}
		gf_bs_read_data(cyphertext_bs, buffer, evt->data_size);
		gf_crypt_decrypt(priv->crypt, buffer, evt->data_size);
	}
	memmove(evt->data, buffer, evt->data_size);

exit:
	if (pleintext_bs) gf_bs_del(pleintext_bs);
	if (sai_bs) gf_bs_del(sai_bs);
	if (cyphertext_bs) gf_bs_del(cyphertext_bs);
	if (buffer) gf_free(buffer);
	if (sai && sai->subsamples) gf_free(sai->subsamples);
	if (sai) gf_free(sai);
	return e;
}
Пример #19
0
Файл: saf.c Проект: erelh/gpac
GF_Err gf_saf_mux_for_time(GF_SAFMuxer *mux, u32 time_ms, Bool force_end_of_session, char **out_data, u32 *out_size)
{
	u32 i, count, dlen;
	char *data;
	GF_SAFStream *str;
	GF_SAFSample*au;
	GF_BitStream *bs, *payload;

	*out_data = NULL;
	*out_size = 0;

	gf_mx_p(mux->mx);
	if (!force_end_of_session && (mux->state!=1)) {
		gf_mx_v(mux->mx);
		return GF_OK;
	}

	bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);

	count = gf_list_count(mux->streams);

	/*1: write all stream headers*/
	for (i=0; i<count; i++) {
		str = (GF_SAFStream *)gf_list_get(mux->streams, i);
		if (str->state & 1) continue;

		au = (GF_SAFSample *)gf_list_get(str->aus, 0);

		/*write stream declaration*/
		payload = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
		gf_bs_write_int(payload, str->remote_url ? SAF_REMOTE_STREAM_HEADER : SAF_STREAM_HEADER, 4);
		gf_bs_write_int(payload, str->stream_id, 12);

		gf_bs_write_u8(payload, str->object_type);
		gf_bs_write_u8(payload, str->stream_type);
		gf_bs_write_int(payload, str->ts_resolution, 24);
		gf_bs_write_u16(payload, str->buffersize_db);
		if (str->mime_type) {
			u32 len = (u32) strlen(str->mime_type);
			gf_bs_write_u16(payload, len);
			gf_bs_write_data(payload, str->mime_type, len);
		}
		if (str->remote_url) {
			u32 len = (u32) strlen(str->remote_url);
			gf_bs_write_u16(payload, len);
			gf_bs_write_data(payload, str->remote_url, len);
		}
		if (str->dsi) {
			gf_bs_write_data(payload, str->dsi, str->dsi_len);
		}

		gf_bs_get_content(payload, &data, &dlen);
		gf_bs_del(payload);

		/*write SAF packet header*/
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_int(bs, 0, 15);
		gf_bs_write_int(bs, 0, 1);
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_int(bs, au ? au->ts : 0, 30);
		gf_bs_write_int(bs, dlen, 16);
		gf_bs_write_data(bs, data, dlen);
		gf_free(data);

		/*mark as signaled*/
		str->state |= 1;
	}

	/*write all pending AUs*/
	while (1) {
		GF_SAFStream *src = NULL;
		u32 mux_time = time_ms;

		for (i=0; i<count; i++) {
			str = (GF_SAFStream*)gf_list_get(mux->streams, i);
			au = (GF_SAFSample*)gf_list_get(str->aus, 0);
			if (au && (au->ts*1000 < mux_time*str->ts_resolution)) {
				mux_time = 1000*au->ts/str->ts_resolution;
				src = str;
			}
		}

		if (!src) break;

		au = (GF_SAFSample*)gf_list_get(src->aus, 0);
		gf_list_rem(src->aus, 0);

		/*write stream declaration*/
		gf_bs_write_int(bs, au->is_rap ? 1 : 0, 1);
		gf_bs_write_int(bs, src->last_au_sn, 15);
		gf_bs_write_int(bs, 0, 1);
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_int(bs, au->ts, 30);
		gf_bs_write_u16(bs, 2+au->data_size);
		gf_bs_write_int(bs, SAF_ACCESS_UNIT, 4);
		gf_bs_write_int(bs, src->stream_id, 12);
		gf_bs_write_data(bs, au->data, au->data_size);

		src->last_au_sn ++;
		src->last_au_ts = au->ts;
		gf_free(au->data);
		gf_free(au);
	}

	/*3: write all end of stream*/
	for (i=0; i<count; i++) {
		str = (GF_SAFStream*)gf_list_get(mux->streams, i);
		/*mark as signaled*/
		if (!(str->state & 2)) continue;
		if (gf_list_count(str->aus)) continue;

		/*write stream declaration*/
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_int(bs, str->last_au_sn, 15);
		gf_bs_write_int(bs, 0, 1);
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_int(bs, str->last_au_ts, 30);
		gf_bs_write_int(bs, 2, 16);
		gf_bs_write_int(bs, SAF_END_OF_STREAM, 4);
		gf_bs_write_int(bs, str->stream_id, 12);

		/*remove stream*/
		gf_list_rem(mux->streams, i);
		i--;
		count--;
		saf_stream_del(str);
	}
	mux->state = 0;
	if (force_end_of_session) {
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_int(bs, 0, 15);
		gf_bs_write_int(bs, 0, 1);
		gf_bs_write_int(bs, 1, 1);
		gf_bs_write_int(bs, 0, 30);
		gf_bs_write_int(bs, 2, 16);
		gf_bs_write_int(bs, SAF_END_OF_SESSION, 4);
		gf_bs_write_int(bs, 0, 12);
		mux->state = 2;
	}
	gf_bs_get_content(bs, out_data, out_size);
	gf_bs_del(bs);
	gf_mx_v(mux->mx);
	return GF_OK;
}
Пример #20
0
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);
}