예제 #1
0
파일: webvtt.c 프로젝트: dragonlucian/gpac
GF_Err gf_webvtt_dump_iso_sample(FILE *dump, u32 timescale, GF_ISOSample *iso_sample)
{
	GF_Err e;
	GF_BitStream *bs;

	bs = gf_bs_new(iso_sample->data, iso_sample->dataLength, GF_BITSTREAM_READ);
	while(gf_bs_available(bs))
	{
		GF_Box *box;
		GF_WebVTTTimestamp ts;
		e = gf_isom_parse_box(&box, bs);
		if (e) return e;
		if (box->type == GF_ISOM_BOX_TYPE_VTCU) {
			GF_VTTCueBox *cuebox = (GF_VTTCueBox *)box;
			if (cuebox->id) fprintf(dump, "%s", cuebox->id->string);
			gf_webvtt_timestamp_set(&ts, (iso_sample->DTS * 1000) / timescale);
			gf_webvtt_timestamp_dump(&ts, dump, GF_FALSE);
			fprintf(dump, " --> NEXT");
			if (cuebox->settings) fprintf(dump, " %s", cuebox->settings->string);
			fprintf(dump, "\n");
			if (cuebox->payload) fprintf(dump, "%s", cuebox->payload->string);
			fprintf(dump, "\n");
		} else if (box->type == GF_ISOM_BOX_TYPE_VTTE) {
			gf_webvtt_timestamp_set(&ts, (iso_sample->DTS * 1000) / timescale);
			gf_webvtt_timestamp_dump(&ts, dump, GF_FALSE);
			fprintf(dump, " --> NEXT\n\n");
		} else if (box->type == GF_ISOM_BOX_TYPE_VTTA) {
			fprintf(dump, "%s\n\n", ((GF_StringBox *)box)->string);
		}
		gf_isom_box_del(box);
	}
	gf_bs_del(bs);
	return GF_OK;
}
예제 #2
0
파일: webvtt.c 프로젝트: erelh/gpac
GF_List *gf_webvtt_parse_iso_cues(GF_ISOSample *iso_sample, u64 start)
{
    GF_List         *cues;
    GF_WebVTTCue    *cue;
    GF_VTTCueBox    *cuebox;
    GF_BitStream    *bs;
    cues = gf_list_new();
    bs = gf_bs_new(iso_sample->data, iso_sample->dataLength, GF_BITSTREAM_READ);
    while(gf_bs_available(bs))
    {
        GF_Err  e;
        GF_Box  *box;
        e = gf_isom_parse_box(&box, bs);
        if (e) return NULL;
        if (box->type == GF_ISOM_BOX_TYPE_VTCU) {
            cuebox = (GF_VTTCueBox *)box;
            cue   = gf_webvtt_cue_new();
            gf_list_add(cues, cue);
            gf_webvtt_timestamp_set(&cue->start, start);
            if (cuebox->id) {
                gf_webvtt_cue_add_property(cue, WEBVTT_ID, cuebox->id->string, (u32) strlen(cuebox->id->string));
            }
            if (cuebox->settings) {
                gf_webvtt_cue_add_property(cue, WEBVTT_SETTINGS, cuebox->settings->string, (u32) strlen(cuebox->settings->string));
            }
            if (cuebox->payload) {
                gf_webvtt_cue_add_property(cue, WEBVTT_PAYLOAD, cuebox->payload->string, (u32) strlen(cuebox->payload->string));
            }
        }
        gf_isom_box_del(box);
    }
    gf_bs_del(bs);
    return cues;
}
예제 #3
0
파일: webvtt.c 프로젝트: porcelijn/gpac
GF_Err gf_webvtt_dump_iso_sample(FILE *dump, u32 timescale, GF_ISOSample *iso_sample, Bool box_mode)
{
	GF_Err e;
	GF_BitStream *bs;

	if (box_mode) {
		fprintf(dump, "<WebVTTSample decodingTimeStamp=\""LLU"\" compositionTimeStamp=\""LLD"\" RAP=\"%d\" dataLength=\"%d\" >\n", iso_sample->DTS, (s64)iso_sample->DTS + iso_sample->CTS_Offset, iso_sample->IsRAP, iso_sample->dataLength);
	}
	bs = gf_bs_new(iso_sample->data, iso_sample->dataLength, GF_BITSTREAM_READ);
	while(gf_bs_available(bs))
	{
		GF_Box *box;
		GF_WebVTTTimestamp ts;
		e = gf_isom_box_parse(&box, bs);
		if (e) return e;

		if (box_mode) {
			gf_isom_box_dump(box, dump);
		} else if (box->type == GF_ISOM_BOX_TYPE_VTCC_CUE) {
			GF_VTTCueBox *cuebox = (GF_VTTCueBox *)box;
			if (cuebox->id) fprintf(dump, "%s", cuebox->id->string);
			gf_webvtt_timestamp_set(&ts, (iso_sample->DTS * 1000) / timescale);
			gf_webvtt_timestamp_dump(&ts, dump, GF_FALSE);
			fprintf(dump, " --> NEXT");
			if (cuebox->settings) fprintf(dump, " %s", cuebox->settings->string);
			fprintf(dump, "\n");
			if (cuebox->payload) fprintf(dump, "%s", cuebox->payload->string);
			fprintf(dump, "\n");
		} else if (box->type == GF_ISOM_BOX_TYPE_VTTE) {
			gf_webvtt_timestamp_set(&ts, (iso_sample->DTS * 1000) / timescale);
			gf_webvtt_timestamp_dump(&ts, dump, GF_FALSE);
			fprintf(dump, " --> NEXT\n\n");
		} else if (box->type == GF_ISOM_BOX_TYPE_VTTA) {
			fprintf(dump, "%s\n\n", ((GF_StringBox *)box)->string);
		}
		gf_isom_box_del(box);
	}
	gf_bs_del(bs);
	if (box_mode) {
		fprintf(dump, "</WebVTTSample>\n");
	}
	return GF_OK;
}
예제 #4
0
파일: webvtt.c 프로젝트: dragonlucian/gpac
GF_EXPORT
GF_List *gf_webvtt_parse_cues_from_data(const char *data, u32 dataLength, u64 start)
{
	GF_List         *cues;
	GF_WebVTTCue    *cue;
	GF_VTTCueBox    *cuebox;
	GF_BitStream    *bs;
	char			*pre_text;
	cue = NULL;
	pre_text = NULL;
	cues = gf_list_new();
	bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ);
	while(gf_bs_available(bs))
	{
		GF_Err  e;
		GF_Box  *box;
		e = gf_isom_parse_box(&box, bs);
		if (e) return NULL;
		if (box->type == GF_ISOM_BOX_TYPE_VTCU) {
			cuebox = (GF_VTTCueBox *)box;
			cue   = gf_webvtt_cue_new();
			if (pre_text) {
				gf_webvtt_cue_add_property(cue, WEBVTT_PRECUE_TEXT, pre_text, (u32) strlen(pre_text));
				gf_free(pre_text);
				pre_text = NULL;
			}
			gf_list_add(cues, cue);
			gf_webvtt_timestamp_set(&cue->start, start);
			if (cuebox->id) {
				gf_webvtt_cue_add_property(cue, WEBVTT_ID, cuebox->id->string, (u32) strlen(cuebox->id->string));
			}
			if (cuebox->settings) {
				gf_webvtt_cue_add_property(cue, WEBVTT_SETTINGS, cuebox->settings->string, (u32) strlen(cuebox->settings->string));
			}
			if (cuebox->payload) {
				gf_webvtt_cue_add_property(cue, WEBVTT_PAYLOAD, cuebox->payload->string, (u32) strlen(cuebox->payload->string));
			}
		} else if (box->type == GF_ISOM_BOX_TYPE_VTTA) {
			GF_StringBox *sbox = (GF_StringBox *)box;
			if (cue) {
				gf_webvtt_cue_add_property(cue, WEBVTT_POSTCUE_TEXT, sbox->string, (u32) strlen(sbox->string));
			} else {
				pre_text = gf_strdup(sbox->string);
			}
		}
		gf_isom_box_del(box);
	}
	gf_bs_del(bs);
	return cues;
}
예제 #5
0
파일: webvtt.c 프로젝트: dragonlucian/gpac
static GF_Err gf_webvtt_parser_dump_finalize(GF_WebVTTParser *parser, u64 duration)
{
	GF_WebVTTSample *sample;
	assert(gf_list_count(parser->samples) <= 1);
	sample = (GF_WebVTTSample *)gf_list_get(parser->samples, 0);
	if (sample) {
		while (gf_list_count(sample->cues)) {
			GF_WebVTTCue *cue = (GF_WebVTTCue *)gf_list_get(sample->cues, 0);
			gf_list_rem(sample->cues, 0);
			if (gf_webvtt_timestamp_is_zero(&cue->end)) {
				gf_webvtt_timestamp_set(&cue->end, duration);
			}
			parser->on_cue_read(parser->user, cue);
		}
		gf_webvtt_sample_del(sample);
		gf_list_rem(parser->samples, 0);
	}
	return GF_OK;
}
예제 #6
0
파일: webvtt.c 프로젝트: dragonlucian/gpac
GF_Err gf_webvtt_merge_cues(GF_WebVTTParser *parser, u64 start, GF_List *cues)
{
	GF_WebVTTSample *wsample;
	GF_WebVTTSample *prev_wsample;
	Bool            has_continuation_cue = GF_FALSE;

	assert(gf_list_count(parser->samples) <= 1);

	wsample = gf_webvtt_sample_new();
	wsample->start = start;

	prev_wsample = (GF_WebVTTSample *)gf_list_last(parser->samples);
	while (gf_list_count(cues)) {
		GF_WebVTTCue *cue = (GF_WebVTTCue *)gf_list_get(cues, 0);
		gf_list_rem(cues, 0);
		/* add the cue to the current sample */
		gf_list_add(wsample->cues, cue);
		/* update with the previous sample */
		if (prev_wsample) {
			Bool  found = GF_FALSE;
			while (!found && gf_list_count(prev_wsample->cues)) {
				GF_WebVTTCue *old_cue = (GF_WebVTTCue *)gf_list_get(prev_wsample->cues, 0);
				gf_list_rem(prev_wsample->cues, 0);
				if (
				    ((!cue->id && !old_cue->id) || (old_cue->id && cue->id && !strcmp(old_cue->id, cue->id))) &&
				    ((!cue->settings && !old_cue->settings) || (old_cue->settings && cue->settings && !strcmp(old_cue->settings, cue->settings))) &&
				    ((!cue->text && !old_cue->text) || (old_cue->text && cue->text && !strcmp(old_cue->text, cue->text)))
				) {
					/* if it is the same cue, update its start with the initial start */
					cue->start = old_cue->start;
					has_continuation_cue = GF_TRUE;
					found = GF_TRUE;
					if (old_cue->pre_text) {
						cue->pre_text = old_cue->pre_text;
						old_cue->pre_text = NULL;
					}
					if (old_cue->post_text) {
						cue->post_text = old_cue->post_text;
						old_cue->post_text = NULL;
					}
					/* delete the old cue */
					gf_webvtt_cue_del(old_cue);
				} else {
					/* finalize the end cue time */
					if (gf_webvtt_timestamp_is_zero(&old_cue->end)) {
						gf_webvtt_timestamp_set(&old_cue->end, wsample->start);
					}
					/* transfer the cue */
					if (!has_continuation_cue) {
						/* the cue can be safely serialized while keeping the order */
						parser->on_cue_read(parser->user, old_cue);
					} else {
						/* keep the cue in the current sample to respect cue start ordering */
						gf_list_add(wsample->cues, old_cue);
					}
				}
			}
		}
	}
	/* No cue in the current sample */
	if (prev_wsample) {
		while (gf_list_count(prev_wsample->cues)) {
			GF_WebVTTCue *cue = (GF_WebVTTCue *)gf_list_get(prev_wsample->cues, 0);
			gf_list_rem(prev_wsample->cues, 0);
			/* finalize the end cue time */
			if (gf_webvtt_timestamp_is_zero(&cue->end)) {
				gf_webvtt_timestamp_set(&cue->end, wsample->start);
			}
			/* transfer the cue */
			if (!has_continuation_cue) {
				/* the cue can be safely serialized while keeping the order */
				parser->on_cue_read(parser->user, cue);
			} else {
				/* keep the cue in the current sample to respect cue start ordering */
				gf_list_add(wsample->cues, cue);
			}
		}
		gf_webvtt_sample_del(prev_wsample);
		gf_list_rem_last(parser->samples);
		prev_wsample = NULL;
	} else {
		/* nothing to do */
	}
	if (gf_list_count(wsample->cues)) {
		gf_list_add(parser->samples, wsample);
	} else {
		gf_webvtt_sample_del(wsample);
	}
	return GF_OK;
}