Beispiel #1
0
static GF_Err VTT_ProcessData(GF_SceneDecoder *plug, const char *inBuffer, u32 inBufferLength,
                              u16 ES_ID, u32 stream_time, u32 mmlevel)
{
	GF_Err e = GF_OK;
	VTTDec *vttdec = (VTTDec *)plug->privateStack;
	if (!vttdec->has_rendering_script) return GF_BAD_PARAM;

	if (stream_time==(u32)-1) {
		/* TODO */
		return GF_OK;
	}

	switch (vttdec->oti) {
	case GPAC_OTI_PRIVATE_SCENE_VTT:
		/*full parsing*/
		if (vttdec->file_size) {
			/*init step*/
			if (!vttdec->use_progressive) {
				/*not done yet*/
				if (!vtt_check_download(vttdec)) return GF_OK;
				/* TODO: parse */
			} else {
				/* TODO: parse what you can */
			}
		}
		break;

	case GPAC_OTI_SCENE_VTT:
		/* TODO: try to parse a cue from the given string */
		break;

	case GPAC_OTI_SCENE_VTT_MP4:
	{
#ifndef GPAC_DISABLE_MEDIA_IMPORT
		char start[100], end[100];
		GF_List *cues;
		cues = gf_webvtt_parse_cues_from_data(inBuffer, inBufferLength, 0);
		gf_webvtt_js_removeCues(vttdec->sg->RootNode);
		if (gf_list_count(cues)) {
			while (gf_list_count(cues)) {
				GF_WebVTTCue *cue = (GF_WebVTTCue *)gf_list_get(cues, 0);
				gf_list_rem(cues, 0);
				sprintf(start, "%02d:%02d:%02d.%03d", cue->start.hour, cue->start.min, cue->start.sec, cue->start.ms);
				sprintf(end, "%02d:%02d:%02d.%03d", cue->end.hour, cue->end.min, cue->end.sec, cue->end.ms);
				gf_webvtt_js_addCue(vttdec->sg->RootNode, cue->id, start, end, cue->settings, cue->text);

				gf_webvtt_cue_del(cue);
			}
		}
		gf_list_del(cues);
#endif
	}
	break;

	default:
		return GF_BAD_PARAM;
	}

	return e;
}
Beispiel #2
0
void gf_webvtt_sample_del(GF_WebVTTSample * samp)
{
	while (gf_list_count(samp->cues)) {
		GF_WebVTTCue *cue = (GF_WebVTTCue *)gf_list_get(samp->cues, 0);
		gf_list_rem(samp->cues, 0);
		gf_webvtt_cue_del(cue);
	}
	gf_list_del(samp->cues);
	gf_free(samp);
}
Beispiel #3
0
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_cue_del(cue);
		}
		gf_webvtt_sample_del(sample);
		gf_list_rem(parser->samples, 0);
	}
	return GF_OK;
}
Beispiel #4
0
GF_Err gf_webvtt_parser_parse(GF_WebVTTParser *parser, u32 duration)
{
	char            szLine[2048];
	char            *sOK;
	u32             len;
	GF_Err          e;
	Bool            do_parse = GF_TRUE;
	GF_WebVTTCue    *cue = NULL;
	u32             start = 0;
	u32             end = 0;
	char            *prevLine = NULL;
	char            *header = NULL;
	u32             header_len = 0;
	Bool            had_marks = GF_FALSE;

	if (!parser) return GF_BAD_PARAM;
	if (parser->is_srt) {
		parser->on_header_parsed(parser->user, gf_strdup("WEBVTT\n"));
	}
	while (do_parse) {
		sOK = gf_text_get_utf8_line(szLine, 2048, parser->vtt_in, parser->unicode_type);
		REM_TRAIL_MARKS(szLine, "\r\n")
		len = (u32) strlen(szLine);
		switch (parser->state) {
		case WEBVTT_PARSER_STATE_WAITING_SIGNATURE:
			if (!sOK || len < 6 || strnicmp(szLine, "WEBVTT", 6) || (len > 6 && szLine[6] != ' ' && szLine[6] != '\t')) {
				e = GF_CORRUPTED_DATA;
				parser->report_message(parser->user, e, "Bad WEBVTT file signature %s", szLine);
				goto exit;
			} else {
				if (had_marks) {
					szLine[len] = '\n';
					len++;
				}
				header = gf_strdup(szLine);
				header_len = len;
				parser->state = WEBVTT_PARSER_STATE_WAITING_HEADER;
			}
			break; /* proceed to next line */
		case WEBVTT_PARSER_STATE_WAITING_HEADER:
			if (prevLine) {
				u32 prev_len = (u32) strlen(prevLine);
				header = (char *)gf_realloc(header, header_len + prev_len + 1);
				strcpy(header+header_len,prevLine);
				header_len += prev_len;
				gf_free(prevLine);
				prevLine = NULL;
			}
			if (sOK && len) {
				if (strstr(szLine, "-->")) {
					parser->on_header_parsed(parser->user, header);
					/* continue to the next state without breaking */
					parser->state = WEBVTT_PARSER_STATE_WAITING_CUE_TIMESTAMP;
					/* no break, continue to the next state*/
				} else {
					if (had_marks) {
						szLine[len] = '\n';
						len++;
					}
					prevLine = gf_strdup(szLine);
					break; /* proceed to next line */
				}
			} else {
				parser->on_header_parsed(parser->user, header);
				if (!sOK) {
					/* end of file, parsing is done */
					do_parse = GF_FALSE;
					break;
				} else {
					/* empty line means end of header */
					parser->state = WEBVTT_PARSER_STATE_WAITING_CUE;
					/* no break, continue to the next state*/
				}
			}
		case WEBVTT_PARSER_STATE_WAITING_CUE:
			if (sOK && len) {
				if (strstr(szLine, "-->")) {
					parser->state = WEBVTT_PARSER_STATE_WAITING_CUE_TIMESTAMP;
					/* continue to the next state without breaking */
				} else {
					/* discard the previous line */
					/* should we do something with it ? callback ?*/
					if (prevLine) {
						gf_free(prevLine);
						prevLine = NULL;
					}
					/* save this new line */
					if (had_marks) {
						szLine[len] = '\n';
						len++;
					}
					prevLine = gf_strdup(szLine);
					/* stay in the same state */
					break;
				}
			} else {
				/* discard the previous line */
				/* should we do something with it ? callback ?*/
				if (prevLine) {
					gf_free(prevLine);
					prevLine = NULL;
				}
				if (!sOK) {
					do_parse = GF_FALSE;
					break;
				} else {
					/* remove empty lines and stay in the same state */
					break;
				}
			}
		case WEBVTT_PARSER_STATE_WAITING_CUE_TIMESTAMP:
			if (sOK && len) {
				if (cue == NULL) {
					cue   = gf_webvtt_cue_new();
				}
				if (prevLine) {
					gf_webvtt_cue_add_property(cue, WEBVTT_ID, prevLine, (u32) strlen(prevLine));
					gf_free(prevLine);
					prevLine = NULL;
				}
				e = gf_webvtt_parser_parse_timings_settings(parser, cue, szLine, len);
				if (e) {
					if (cue) gf_webvtt_cue_del(cue);
					cue = NULL;
					parser->state = WEBVTT_PARSER_STATE_WAITING_CUE;
				} else {
					start = (u32)gf_webvtt_timestamp_get(&cue->start);
					end   = (u32)gf_webvtt_timestamp_get(&cue->end);
					parser->state = WEBVTT_PARSER_STATE_WAITING_CUE_PAYLOAD;
				}
			} else {
				/* not possible */
				assert(0);
			}
			break;
		case WEBVTT_PARSER_STATE_WAITING_CUE_PAYLOAD:
			if (sOK && len) {
				if (had_marks) {
					szLine[len] = '\n';
					len++;
				}
				gf_webvtt_cue_add_property(cue, WEBVTT_PAYLOAD, szLine, len);
				/* remain in the same state as a cue payload can have multiple lines */
				break;
			} else {
				/* end of the current cue */
				gf_webvtt_add_cue_to_samples(parser, parser->samples, cue);
				cue = NULL;

				gf_set_progress("Importing WebVTT", gf_ftell(parser->vtt_in), parser->file_size);
				if ((duration && (end >= duration)) || !sOK) {
					do_parse = GF_FALSE;
					break;
				} else {
					/* empty line, move to next cue */
					parser->state = WEBVTT_PARSER_STATE_WAITING_CUE;
					break;
				}
			}
		}
		if (duration && (start >= duration)) {
			do_parse = GF_FALSE;
			break;
		}
	}


	/* no more cues to come, flush everything */
	if (cue) {
		gf_webvtt_add_cue_to_samples(parser, parser->samples, cue);
		cue = NULL;
	}
	while (gf_list_count(parser->samples) > 0) {
		GF_WebVTTSample *sample = (GF_WebVTTSample *)gf_list_get(parser->samples, 0);
		parser->last_duration = sample->end - sample->start;
		gf_list_rem(parser->samples, 0);
		parser->on_sample_parsed(parser->user, sample);
	}
	gf_set_progress("Importing WebVTT", parser->file_size, parser->file_size);
	e = GF_OK;
exit:
	if (cue) gf_webvtt_cue_del(cue);
	if (prevLine) gf_free(prevLine);
	if (header) gf_free(header);
	return e;
}
Beispiel #5
0
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;
}