示例#1
0
文件: media.c 项目: Brilon314/gpac
GF_Err Media_GetSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample **samp, u32 *sIDX, Bool no_data, u64 *out_offset)
{
	GF_Err e;
	u32 bytesRead;
	u32 dataRefIndex, chunkNumber;
	u64 offset, new_size;
	u8 isEdited;
	GF_SampleEntryBox *entry;

	if (!mdia || !mdia->information->sampleTable) return GF_BAD_PARAM;
	if (!mdia->information->sampleTable->SampleSize)
		return GF_ISOM_INVALID_FILE;

	//OK, here we go....
	if (sampleNumber > mdia->information->sampleTable->SampleSize->sampleCount) return GF_BAD_PARAM;

	//get the DTS
	e = stbl_GetSampleDTS(mdia->information->sampleTable->TimeToSample, sampleNumber, &(*samp)->DTS);
	if (e) return e;
	//the CTS offset
	if (mdia->information->sampleTable->CompositionOffset) {
		e = stbl_GetSampleCTS(mdia->information->sampleTable->CompositionOffset , sampleNumber, &(*samp)->CTS_Offset);
		if (e) return e;
	} else {
		(*samp)->CTS_Offset = 0;
	}
	//the size
	e = stbl_GetSampleSize(mdia->information->sampleTable->SampleSize, sampleNumber, &(*samp)->dataLength);
	if (e) return e;
	//the RAP
	if (mdia->information->sampleTable->SyncSample) {
		e = stbl_GetSampleRAP(mdia->information->sampleTable->SyncSample, sampleNumber, &(*samp)->IsRAP, NULL, NULL);
		if (e) return e;
	} else {
		//if no SyncSample, all samples are sync (cf spec)
		(*samp)->IsRAP = RAP;
	}
	/*overwrite sync sample with sample dep if any*/
	if (mdia->information->sampleTable->SampleDep) {
		u32 isLeading, dependsOn, dependedOn, redundant;
		e = stbl_GetSampleDepType(mdia->information->sampleTable->SampleDep, sampleNumber, &isLeading, &dependsOn, &dependedOn, &redundant);
		if (!e) {
			if (dependsOn==1) (*samp)->IsRAP = RAP_NO;
			else if (dependsOn==2) (*samp)->IsRAP = RAP;
			/*if not depended upon and redundant, mark as carousel sample*/
			if ((dependedOn==2) && (redundant==1)) (*samp)->IsRAP = RAP_REDUNDANT;
			/*TODO FIXME - we must enhance the IsRAP semantics to carry disposable info ... */
		}
	}
	/*get sync shadow*/
	if (Media_IsSampleSyncShadow(mdia->information->sampleTable->ShadowSync, sampleNumber)) (*samp)->IsRAP = RAP_REDUNDANT;

	//the data info
	if (!sIDX && !no_data) return GF_BAD_PARAM;
	if (!sIDX && !out_offset) return GF_OK;

	(*sIDX) = 0;
	e = stbl_GetSampleInfos(mdia->information->sampleTable, sampleNumber, &offset, &chunkNumber, sIDX, &isEdited);
	if (e) return e;

	//then get the DataRef
	e = Media_GetSampleDesc(mdia, *sIDX, &entry, &dataRefIndex);
	if (e) return e;

	// Open the data handler - check our mode, don't reopen in read only if this is
	//the same entry. In other modes we have no choice because the main data map is
	//divided into the original and the edition files
	if (mdia->mediaTrack->moov->mov->openMode == GF_ISOM_OPEN_READ) {
		//same as last call in read mode
		if (!mdia->information->dataHandler) {
			e = gf_isom_datamap_open(mdia, dataRefIndex, isEdited);
			if (e) return e;
		}
		if (mdia->information->dataEntryIndex != dataRefIndex)
			mdia->information->dataEntryIndex = dataRefIndex;
	} else {
		e = gf_isom_datamap_open(mdia, dataRefIndex, isEdited);
		if (e) return e;
	}

	if (out_offset) *out_offset = offset;
	if (no_data) return GF_OK;

	/*and finally get the data, include padding if needed*/
	(*samp)->data = (char *) gf_malloc(sizeof(char) * ( (*samp)->dataLength + mdia->mediaTrack->padding_bytes) );
	if (mdia->mediaTrack->padding_bytes)
		memset((*samp)->data + (*samp)->dataLength, 0, sizeof(char) * mdia->mediaTrack->padding_bytes);

	//check if we can get the sample (make sure we have enougth data...)
	new_size = gf_bs_get_size(mdia->information->dataHandler->bs);
	if (offset + (*samp)->dataLength > new_size) {
		//always refresh the size to avoid wrong info on http/ftp
		new_size = gf_bs_get_refreshed_size(mdia->information->dataHandler->bs);
		if (offset + (*samp)->dataLength > new_size) {
			mdia->BytesMissing = offset + (*samp)->dataLength - new_size;
			return GF_ISOM_INCOMPLETE_FILE;
		}
	}

	bytesRead = gf_isom_datamap_get_data(mdia->information->dataHandler, (*samp)->data, (*samp)->dataLength, offset);
	//if bytesRead != sampleSize, we have an IO err
	if (bytesRead < (*samp)->dataLength) {
		return GF_IO_ERR;
	}
	mdia->BytesMissing = 0;
	//finally rewrite the sample if this is an OD Access Unit
	if (mdia->handler->handlerType == GF_ISOM_MEDIA_OD) {
		e = Media_RewriteODFrame(mdia, *samp);
		if (e) return e;
	}
	/*FIXME: we do NOT rewrite sample if we have a encrypted track*/
	else if (gf_isom_is_nalu_based_entry(mdia, entry) &&
	         !gf_isom_is_track_encrypted(mdia->mediaTrack->moov->mov, gf_isom_get_tracknum_from_id(mdia->mediaTrack->moov, mdia->mediaTrack->Header->trackID))
	        ) {
		e = gf_isom_nalu_sample_rewrite(mdia, *samp, sampleNumber, (GF_MPEGVisualSampleEntryBox *)entry);
		if (e) return e;
	}
	else if (mdia->mediaTrack->moov->mov->convert_streaming_text
	         && ((mdia->handler->handlerType == GF_ISOM_MEDIA_TEXT) || (mdia->handler->handlerType == GF_ISOM_MEDIA_SUBT))
	         && (entry->type == GF_ISOM_BOX_TYPE_TX3G || entry->type == GF_ISOM_BOX_TYPE_TEXT)
	        ) {
		u64 dur;
		if (sampleNumber == mdia->information->sampleTable->SampleSize->sampleCount) {
			dur = mdia->mediaHeader->duration - (*samp)->DTS;
		} else {
			stbl_GetSampleDTS(mdia->information->sampleTable->TimeToSample, sampleNumber+1, &dur);
			dur -= (*samp)->DTS;
		}
		e = gf_isom_rewrite_text_sample(*samp, *sIDX, (u32) dur);
		if (e) return e;
	}
	return GF_OK;
}
示例#2
0
文件: read.c 项目: supperlitt/gpac
GF_Err ISOR_ConnectChannel(GF_InputService *plug, LPNETCHANNEL channel, const char *url, Bool upstream)
{
    u32 ESID;
    ISOMChannel *ch;
    GF_NetworkCommand com;
    u32 track;
    Bool is_esd_url;
    GF_Err e;
    ISOMReader *read;
    if (!plug || !plug->priv) return GF_SERVICE_ERROR;
    read = (ISOMReader *) plug->priv;

    track = 0;
    ch = NULL;
    is_esd_url = 0;
    e = GF_OK;
    if (upstream) {
        e = GF_ISOM_INVALID_FILE;
        goto exit;
    }
    if (!read->mov) return GF_SERVICE_ERROR;

    if (strstr(url, "ES_ID")) {
        sscanf(url, "ES_ID=%ud", &ESID);
    } else {
        /*handle url like mypath/myfile.mp4#trackID*/
        char *track_id = strrchr(url, '.');
        if (track_id) {
            track_id = strchr(url, '#');
            if (track_id) track_id ++;
        }
        is_esd_url = 1;

        ESID = 0;
        /*if only one track ok*/
        if (gf_isom_get_track_count(read->mov)==1) ESID = gf_isom_get_track_id(read->mov, 1);
        else if (track_id) {
            ESID = atoi(track_id);
            track = gf_isom_get_track_by_id(read->mov, (u32) ESID);
            if (!track) ESID = 0;
        }

    }
    if (!ESID) {
        e = GF_NOT_SUPPORTED;
        goto exit;
    }

    /*a channel cannot be open twice, it has to be closed before - NOTE a track is NOT a channel and the user can open
    several times the same track as long as a dedicated channel is used*/
    ch = isor_get_channel(read, channel);
    if (ch) {
        e = GF_SERVICE_ERROR;
        goto exit;
    }
    track = gf_isom_get_track_by_id(read->mov, (u32) ESID);
    if (!track) {
        e = GF_STREAM_NOT_FOUND;
        goto exit;
    }

    GF_SAFEALLOC(ch, ISOMChannel);
    ch->owner = read;
    ch->channel = channel;
    gf_list_add(read->channels, ch);
    ch->track = track;
    switch (gf_isom_get_media_type(ch->owner->mov, ch->track)) {
    case GF_ISOM_MEDIA_OCR:
        ch->streamType = GF_STREAM_OCR;
        break;
    case GF_ISOM_MEDIA_SCENE:
        ch->streamType = GF_STREAM_SCENE;
        break;
    }

    ch->has_edit_list = gf_isom_get_edit_segment_count(ch->owner->mov, ch->track) ? 1 : 0;
    ch->has_rap = (gf_isom_has_sync_points(ch->owner->mov, ch->track)==1) ? 1 : 0;
    ch->time_scale = gf_isom_get_media_timescale(ch->owner->mov, ch->track);

exit:
    gf_term_on_connect(read->service, channel, e);
    /*if esd url reconfig SL layer*/
    if (!e && is_esd_url) {
        GF_ESD *esd;
        memset(&com, 0, sizeof(GF_NetworkCommand));
        com.base.on_channel = channel;
        com.command_type = GF_NET_CHAN_RECONFIG;
        esd = gf_isom_get_esd(read->mov, ch->track, 1);
        if (esd) {
            memcpy(&com.cfg.sl_config, esd->slConfig, sizeof(GF_SLConfig));
            gf_odf_desc_del((GF_Descriptor *)esd);
        } else {
            com.cfg.sl_config.tag = GF_ODF_SLC_TAG;
            com.cfg.sl_config.timestampLength = 32;
            com.cfg.sl_config.timestampResolution = ch->time_scale;
            com.cfg.sl_config.useRandomAccessPointFlag = 1;
        }
        gf_term_on_command(read->service, &com, GF_OK);
    }
    if (!e && track && gf_isom_is_track_encrypted(read->mov, track)) {
        memset(&com, 0, sizeof(GF_NetworkCommand));
        com.base.on_channel = channel;
        com.command_type = GF_NET_CHAN_DRM_CFG;
        ch->is_encrypted = 1;
        if (gf_isom_is_ismacryp_media(read->mov, track, 1)) {
            gf_isom_get_ismacryp_info(read->mov, track, 1, NULL, &com.drm_cfg.scheme_type, &com.drm_cfg.scheme_version, &com.drm_cfg.scheme_uri, &com.drm_cfg.kms_uri, NULL, NULL, NULL);
            gf_term_on_command(read->service, &com, GF_OK);
        } else if (gf_isom_is_omadrm_media(read->mov, track, 1)) {
            gf_isom_get_omadrm_info(read->mov, track, 1, NULL, &com.drm_cfg.scheme_type, &com.drm_cfg.scheme_version, &com.drm_cfg.contentID, &com.drm_cfg.kms_uri, &com.drm_cfg.oma_drm_textual_headers, &com.drm_cfg.oma_drm_textual_headers_len, NULL, &com.drm_cfg.oma_drm_crypt_type, NULL, NULL, NULL);

            gf_media_get_file_hash(gf_isom_get_filename(read->mov), com.drm_cfg.hash);
            gf_term_on_command(read->service, &com, GF_OK);

        }
    }
    return e;
}