📄 text_import.c
字号:
break; case 1: if (sscanf(szLine, "%d:%d:%d,%d --> %d:%d:%d,%d", &sh, &sm, &ss, &sms, &eh, &em, &es, &ems) != 8) { e = gf_import_message(import, GF_CORRUPTED_DATA, "Error scanning SRT frame %d timing", curLine); goto exit; } start = (3600*sh + 60*sm + ss)*1000 + sms; if (start<end) { gf_import_message(import, GF_OK, "WARNING: corrupted SRT frame %d - starts (at %d ms) before end of previous one (%d ms) - adjusting time stamps", curLine, start, end); start = end; } end = (3600*eh + 60*em + es)*1000 + ems; /*make stream start at 0 by inserting a fake AU*/ if (first_samp && (start>0)) { s = gf_isom_text_to_sample(samp); s->DTS = 0; gf_isom_add_sample(import->dest, track, 1, s); gf_isom_sample_del(&s); nb_samp++; } rec.style_flags = 0; state = 2; break; default: /*reset only when text is present*/ first_samp = 0; /*go to line*/ if (txt_line) { gf_isom_text_add_text(samp, "\n", 1); char_len += 1; } ptr = (char *) szLine; len = gf_utf8_mbstowcs(uniLine, 5000, (const char **) &ptr); if (len == (u32) -1) { e = gf_import_message(import, GF_CORRUPTED_DATA, "Invalid UTF data (line %d)", curLine); goto exit; } char_line = 0; i=j=0; rem_styles = 0; while (i<len) { /*start of new style*/ if ( (uniLine[i]=='<') && (uniLine[i+2]=='>')) { /*store prev style*/ if (set_end_char) { assert(set_start_char); gf_isom_text_add_style(samp, &rec); set_end_char = set_start_char = 0; rec.style_flags &= ~rem_styles; rem_styles = 0; } if (set_start_char && (rec.startCharOffset != j)) { rec.endCharOffset = char_len + j; if (rec.style_flags) gf_isom_text_add_style(samp, &rec); } switch (uniLine[i+1]) { case 'b': case 'B': rec.style_flags |= GF_TXT_STYLE_BOLD; set_start_char = 1; rec.startCharOffset = char_len + j; break; case 'i': case 'I': rec.style_flags |= GF_TXT_STYLE_ITALIC; set_start_char = 1; rec.startCharOffset = char_len + j; break; case 'u': case 'U': rec.style_flags |= GF_TXT_STYLE_UNDERLINED; set_start_char = 1; rec.startCharOffset = char_len + j; break; } i+=3; continue; } /*end of prev style*/ if ( (uniLine[i]=='<') && (uniLine[i+1]=='/') && (uniLine[i+3]=='>')) { switch (uniLine[i+2]) { case 'b': case 'B': rem_styles |= GF_TXT_STYLE_BOLD; set_end_char = 1; rec.endCharOffset = char_len + j; break; case 'i': case 'I': rem_styles |= GF_TXT_STYLE_ITALIC; set_end_char = 1; rec.endCharOffset = char_len + j; break; case 'u': case 'U': rem_styles |= GF_TXT_STYLE_UNDERLINED; set_end_char = 1; rec.endCharOffset = char_len + j; break; } i+=4; continue; } /*store style*/ if (set_end_char) { gf_isom_text_add_style(samp, &rec); set_end_char = 0; set_start_char = 1; rec.startCharOffset = char_len + j; rec.style_flags &= ~rem_styles; rem_styles = 0; } uniText[j] = uniLine[i]; j++; i++; } /*store last style*/ if (set_end_char) { gf_isom_text_add_style(samp, &rec); set_end_char = 0; set_start_char = 1; rec.startCharOffset = char_len + j; rec.style_flags &= ~rem_styles; rem_styles = 0; } char_line = j; uniText[j] = 0; sptr = (u16 *) uniText; len = gf_utf8_wcstombs(szText, 5000, (const u16 **) &sptr); gf_isom_text_add_text(samp, szText, len); char_len += char_line; txt_line ++; break; } if (duration && (start >= duration)) break; } /*final flush*/ if (end) { gf_isom_text_reset(samp); s = gf_isom_text_to_sample(samp); s->DTS = (u64) (scale*(s64)end); s->IsRAP = 1; gf_isom_add_sample(import->dest, track, 1, s); gf_isom_sample_del(&s); nb_samp++; } gf_isom_delete_text_sample(samp); gf_isom_set_last_sample_duration(import->dest, track, 0); gf_set_progress("Importing SRT", nb_samp, nb_samp);exit: if (e) gf_isom_remove_track(import->dest, track); fclose(srt_in); return e;}static GF_Err gf_text_import_sub(GF_MediaImporter *import){ FILE *sub_in; u32 track, ID, timescale, i, j, desc_idx, start, end, prev_end, nb_samp, duration, file_size, len, line; GF_TextConfig*cfg; GF_Err e; Double FPS; GF_TextSample * samp; Bool first_samp; s32 unicode_type; char szLine[2048], szTime[20], szText[2048]; GF_ISOSample *s; sub_in = fopen(import->in_name, "rt"); fseek(sub_in, 0, SEEK_END); file_size = ftell(sub_in); fseek(sub_in, 0, SEEK_SET); unicode_type = gf_text_get_utf_type(sub_in); if (unicode_type<0) { fclose(sub_in); return gf_import_message(import, GF_NOT_SUPPORTED, "Unsupported SUB UTF encoding"); } FPS = 25.0; if (import->video_fps) FPS = import->video_fps; cfg = NULL; if (import->esd) { if (!import->esd->slConfig) { import->esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); import->esd->slConfig->predefined = 2; import->esd->slConfig->timestampResolution = 1000; } timescale = import->esd->slConfig->timestampResolution; if (!timescale) timescale = 1000; /*explicit text config*/ if (import->esd->decoderConfig && import->esd->decoderConfig->decoderSpecificInfo->tag == GF_ODF_TEXT_CFG_TAG) { cfg = (GF_TextConfig *) import->esd->decoderConfig->decoderSpecificInfo; import->esd->decoderConfig->decoderSpecificInfo = NULL; } ID = import->esd->ESID; } else { timescale = 1000; ID = 0; } if (cfg && cfg->timescale) timescale = cfg->timescale; track = gf_isom_new_track(import->dest, ID, GF_ISOM_MEDIA_TEXT, timescale); if (!track) { fclose(sub_in); return gf_import_message(import, gf_isom_last_error(import->dest), "Error creating text track"); } gf_isom_set_track_enabled(import->dest, track, 1); if (import->esd && !import->esd->ESID) import->esd->ESID = gf_isom_get_track_id(import->dest, track); gf_text_import_set_language(import, track); file_size = 0; /*setup track*/ if (cfg) { u32 count; char *firstFont = NULL; /*set track info*/ gf_isom_set_track_layout_info(import->dest, track, cfg->text_width<<16, cfg->text_height<<16, 0, 0, cfg->layer); /*and set sample descriptions*/ count = gf_list_count(cfg->sample_descriptions); for (i=0; i<count; i++) { GF_TextSampleDescriptor *sd= (GF_TextSampleDescriptor *)gf_list_get(cfg->sample_descriptions, i); if (!sd->font_count) { sd->fonts = (GF_FontRecord*)malloc(sizeof(GF_FontRecord)); sd->font_count = 1; sd->fonts[0].fontID = 1; sd->fonts[0].fontName = strdup("Serif"); } if (!sd->default_style.fontID) sd->default_style.fontID = sd->fonts[0].fontID; if (!sd->default_style.font_size) sd->default_style.font_size = 16; if (!sd->default_style.text_color) sd->default_style.text_color = 0xFF000000; file_size = sd->default_style.font_size; gf_isom_new_text_description(import->dest, track, sd, NULL, NULL, &desc_idx); if (!firstFont) firstFont = sd->fonts[0].fontName; } gf_import_message(import, GF_OK, "Timed Text (SUB @ %02.2f) import - text track %d x %d, font %s (size %d)", FPS, cfg->text_width, cfg->text_height, firstFont, file_size); gf_odf_desc_del((GF_Descriptor *)cfg); } else { u32 w, h; GF_TextSampleDescriptor *sd; gf_text_get_video_size(import->dest, &w, &h); /*have to work with default - use max size (if only one video, this means the text region is the entire display, and with bottom alignment things should be fine...*/ gf_isom_set_track_layout_info(import->dest, track, w<<16, h<<16, 0, 0, 0); sd = (GF_TextSampleDescriptor*)gf_odf_desc_new(GF_ODF_TX3G_TAG); sd->fonts = (GF_FontRecord*)malloc(sizeof(GF_FontRecord)); sd->font_count = 1; sd->fonts[0].fontID = 1; sd->fonts[0].fontName = strdup("Serif"); sd->back_color = 0x00000000; /*transparent*/ sd->default_style.fontID = 1; sd->default_style.font_size = TTXT_DEFAULT_FONT_SIZE; sd->default_style.text_color = 0xFFFFFFFF; /*white*/ sd->default_style.style_flags = 0; sd->horiz_justif = 1; /*center of scene*/ sd->vert_justif = (s8) -1; /*bottom of scene*/ if (import->flags & GF_IMPORT_SKIP_TXT_BOX) { sd->default_pos.top = sd->default_pos.left = sd->default_pos.right = sd->default_pos.bottom = 0; } else { if ((sd->default_pos.bottom==sd->default_pos.top) || (sd->default_pos.right==sd->default_pos.left)) { sd->default_pos.top = sd->default_pos.left = 0; sd->default_pos.right = w; sd->default_pos.bottom = h; } } gf_isom_new_text_description(import->dest, track, sd, NULL, NULL, &desc_idx); gf_import_message(import, GF_OK, "Timed Text (SUB @ %02.2f) import - text track %d x %d, font %s (size %d)", FPS, w, h, sd->fonts[0].fontName, TTXT_DEFAULT_FONT_SIZE); gf_odf_desc_del((GF_Descriptor *)sd); } duration = (u32) (((Double) import->duration)*timescale/1000.0); e = GF_OK; nb_samp = 0; samp = gf_isom_new_text_sample(); FPS = ((Double) timescale ) / FPS; start = end = prev_end = 0; line = 0; first_samp = 1; while (1) { char *sOK = gf_text_get_utf8_line(szLine, 2048, sub_in, unicode_type); if (!sOK) break; REM_TRAIL_MARKS(szLine, "\r\n\t ") line++; len = strlen(szLine); if (!len) continue; i=0; if (szLine[i] != '{') { e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Bad SUB file (line %d): expecting \"{\" got \"%c\"", line, szLine[i]); goto exit; } while (szLine[i+1] && szLine[i+1]!='}') { szTime[i] = szLine[i+1]; i++; } szTime[i] = 0; start = atoi(szTime); if (start<end) { gf_import_message(import, GF_OK, "WARNING: corrupted SUB frame (line %d) - starts (at %d ms) before end of previous one (%d ms) - adjusting time stamps", line, start, end); start = end; } j=i+2; i=0; if (szLine[i+j] != '{') { e = gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Bad SUB file - expecting \"{\" got \"%c\"", szLine[i]); goto exit; } while (szLine[i+1+j] && szLine[i+1+j]!='}') { szTime[i] = szLine[i+1+j]; i++; } szTime[i] = 0; end = atoi(szTime); j+=i+2; if (start>end) { gf_import_message(import, GF_OK, "WARNING: corrupted SUB frame (line %d) - ends (at %d ms) before start of current frame (%d ms) - skipping", line, end, start); continue; } gf_isom_text_reset(samp); if (start && first_samp) { s = gf_isom_text_to_sample(samp); s->DTS = 0; s->IsRAP = 1; gf_isom_add_sample(import->dest, track, 1, s); gf_isom_sample_del(&s); first_samp = 0; nb_samp++; } for (i=j; i<len; i++) { if (szLine[i]=='|') { szText[i-j] = '\n'; } else { szText[i-j] = szLine[i]; } } szText[i-j] = 0; gf_isom_text_add_text(samp, szText, strlen(szText) ); if (prev_end) { GF_TextSample * empty_samp = gf_isom_new_text_sample(); s = gf_isom_text_to_sample(empty_samp); s->DTS = (u64) (FPS*(s64)prev_end); gf_isom_add_sample(import->dest, track, 1, s); gf_isom_sample_del(&s); nb_samp++; gf_isom_delete_text_sample(empty_samp); } s = gf_isom_text_to_sample(samp); s->DTS = (u64) (FPS*(s64)start); gf_isom_add_sample(import->dest, track, 1, s); gf_isom_sample_del(&s); nb_samp++; gf_isom_text_reset(samp); prev_end = end; gf_set_progress("Importing SUB", ftell(sub_in), file_size); if (duration && (end >= duration)) break; } /*final flush*/ if (end) { gf_isom_text_reset(samp); s = gf_isom_text_to_sample(samp); s->DTS = (u64)(FPS*(s64)end); gf_isom_add_sample(import->dest, track, 1, s); gf_isom_sample_del(&s); nb_samp++; } gf_isom_delete_text_sample(samp); gf_isom_set_last_sample_duration(import->dest, track, 0); gf_set_progress("Importing SUB", nb_samp, nb_samp);exit: if (e) gf_isom_remove_track(import->dest, track); fclose(sub_in); return e;}#define CHECK_STR(__str) \ if (!__str) { \ e = gf_import_message(import, GF_BAD_PARAM, "Invalid XML formatting (line %d)", parser.line); \ goto exit; \ } \u32 ttxt_get_color(GF_MediaImporter *import, char *val){ u32 r, g, b, a, res; r = g = b = a = 0; if (sscanf(val, "%x %x %x %x", &r, &g, &b, &a) != 4) { gf_import_message(import, GF_OK, "Warning: color badly formatted"); } res = (a&0xFF); res<<=8; res |= (r&0xFF); res<<=8; res |= (g&0xFF); res<<=8; res |= (b&0xFF); return res;}void ttxt_parse_text_box(GF_MediaImporter *import, GF_XMLNode *n, GF_BoxRecord *box){ u32 i=0; GF_XMLAttribute *att; memset(box, 0, sizeof(GF_BoxRecord)); while ( (att=(GF_XMLAttribute *)gf_list_enum(n->attributes, &i))) { if (!stricmp(att->name, "top")) box->top = atoi(att->value); else if (!stricmp(att->name, "bottom")) box->bottom = atoi(att->value); else if (!stricmp(att->name, "left")) box->left = atoi(att->value);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -