📄 tx3g.c
字号:
count = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); for (i=0; i<count; i++) { Bool same_fonts; txt = (GF_TextSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, i); if (!txt|| (txt->type != GF_ISOM_BOX_TYPE_TX3G)) continue; if (txt->back_color != desc->back_color) continue; if (txt->displayFlags != desc->displayFlags) continue; if (txt->vertical_justification != desc->vert_justif) continue; if (txt->horizontal_justification != desc->horiz_justif) continue; if (txt->font_table->entry_count != desc->font_count) continue; same_fonts = 1; for (j=0; j<desc->font_count; j++) { if (txt->font_table->fonts[j].fontID != desc->fonts[j].fontID) same_fonts = 0; else if (strcmp(desc->fonts[j].fontName, txt->font_table->fonts[j].fontName)) same_fonts = 0; } if (same_fonts) { *outDescIdx = i+1; if (!memcmp(&txt->default_box, &desc->default_pos, sizeof(GF_BoxRecord))) *same_box = 1; if (!memcmp(&txt->default_style, &desc->default_style, sizeof(GF_StyleRecord))) *same_styles = 1; return GF_OK; } } return GF_OK;}#endifGF_TextSample *gf_isom_new_text_sample(){ GF_TextSample *res; GF_SAFEALLOC(res, GF_TextSample); if (!res) return NULL; res->others = gf_list_new(); return res;}GF_Err gf_isom_text_reset_styles(GF_TextSample *samp){ if (!samp) return GF_BAD_PARAM; if (samp->box) gf_isom_box_del((GF_Box *)samp->box); samp->box = NULL; if (samp->highlight_color) gf_isom_box_del((GF_Box *)samp->highlight_color); samp->highlight_color = NULL; if (samp->scroll_delay) gf_isom_box_del((GF_Box *)samp->scroll_delay); samp->scroll_delay = NULL; if (samp->wrap) gf_isom_box_del((GF_Box *)samp->wrap); samp->wrap = NULL; if (samp->styles) gf_isom_box_del((GF_Box *)samp->styles); samp->styles = NULL; samp->cur_karaoke = NULL; while (gf_list_count(samp->others)) { GF_Box *a = (GF_Box*)gf_list_get(samp->others, 0); gf_list_rem(samp->others, 0); gf_isom_box_del(a); } return GF_OK;}GF_Err gf_isom_text_reset(GF_TextSample *samp){ if (!samp) return GF_BAD_PARAM; if (samp->text) free(samp->text); samp->text = NULL; samp->len = 0; return gf_isom_text_reset_styles(samp);}GF_EXPORTvoid gf_isom_delete_text_sample(GF_TextSample * tx_samp){ gf_isom_text_reset(tx_samp); gf_list_del(tx_samp->others); free(tx_samp);}GF_EXPORTGF_TextSample *gf_isom_parse_texte_sample(GF_BitStream *bs){ GF_TextSample *s = gf_isom_new_text_sample(); /*empty sample*/ if (!bs || !gf_bs_available(bs)) return s; s->len = gf_bs_read_u16(bs); if (s->len) { /*2 extra bytes for UTF-16 term char just in case (we don't know if a BOM marker is present or not since this may be a sample carried over RTP*/ s->text = (char *) malloc(sizeof(char)*(s->len+2) ); s->text[s->len] = 0; s->text[s->len+1] = 0; gf_bs_read_data(bs, s->text, s->len); } while (gf_bs_available(bs)) { GF_Box *a; GF_Err e = gf_isom_parse_box(&a, bs); if (!e) { switch (a->type) { case GF_ISOM_BOX_TYPE_STYL: if (s->styles) { GF_TextStyleBox *st2 = (GF_TextStyleBox *)a; if (!s->styles->entry_count) { gf_isom_box_del((GF_Box*)s->styles); s->styles = st2; } else { s->styles->styles = (GF_StyleRecord*)realloc(s->styles->styles, sizeof(GF_StyleRecord) * (s->styles->entry_count + st2->entry_count)); memcpy(&s->styles->styles[s->styles->entry_count], st2->styles, sizeof(GF_StyleRecord) * st2->entry_count); s->styles->entry_count += st2->entry_count; gf_isom_box_del(a); } } else { s->styles = (GF_TextStyleBox*)a; } break; case GF_ISOM_BOX_TYPE_KROK: s->cur_karaoke = (GF_TextKaraokeBox*)a; case GF_ISOM_BOX_TYPE_HLIT: case GF_ISOM_BOX_TYPE_HREF: case GF_ISOM_BOX_TYPE_BLNK: gf_list_add(s->others, a); break; case GF_ISOM_BOX_TYPE_HCLR: if (s->highlight_color) gf_isom_box_del(a); else s->highlight_color = (GF_TextHighlightColorBox *) a; break; case GF_ISOM_BOX_TYPE_DLAY: if (s->scroll_delay) gf_isom_box_del(a); else s->scroll_delay= (GF_TextScrollDelayBox*) a; break; case GF_ISOM_BOX_TYPE_TBOX: if (s->box) gf_isom_box_del(a); else s->box= (GF_TextBoxBox *) a; break; case GF_ISOM_BOX_TYPE_TWRP: if (s->wrap) gf_isom_box_del(a); else s->wrap= (GF_TextWrapBox*) a; break; default: gf_isom_box_del(a); break; } } } return s;}GF_TextSample *gf_isom_parse_texte_sample_from_data(char *data, u32 dataLength){ GF_TextSample *s; GF_BitStream *bs; /*empty text sample*/ if (!data || !dataLength) { return gf_isom_new_text_sample(); } bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ); s = gf_isom_parse_texte_sample(bs); gf_bs_del(bs); return s;}/*out-of-band sample desc (128 and 255 reserved in RFC)*/#define SAMPLE_INDEX_OFFSET 129static void gf_isom_write_tx3g(GF_TextSampleEntryBox *a, GF_BitStream *bs, u32 sidx, u32 sidx_offset){ u32 size, j; void gpp_write_rgba(GF_BitStream *bs, u32 col); void gpp_write_box(GF_BitStream *bs, GF_BoxRecord *rec); void gpp_write_style(GF_BitStream *bs, GF_StyleRecord *rec); if (sidx_offset) gf_bs_write_u8(bs, sidx + sidx_offset); /*SINCE WINCE HAS A READONLY VERSION OF MP4 WE MUST DO IT BY HAND*/ size = 8 + 18 + 8 + 12; size += 8 + 2; for (j=0; j<a->font_table->entry_count; j++) { size += 3; if (a->font_table->fonts[j].fontName) size += strlen(a->font_table->fonts[j].fontName); } /*write TextSampleEntry box*/ gf_bs_write_u32(bs, size); gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_TX3G); gf_bs_write_data(bs, a->reserved, 6); gf_bs_write_u16(bs, a->dataReferenceIndex); gf_bs_write_u32(bs, a->displayFlags); gf_bs_write_u8(bs, a->horizontal_justification); gf_bs_write_u8(bs, a->vertical_justification); gpp_write_rgba(bs, a->back_color); gpp_write_box(bs, &a->default_box); gpp_write_style(bs, &a->default_style); /*write font table box*/ size -= (8 + 18 + 8 + 12); gf_bs_write_u32(bs, size); gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_FTAB); gf_bs_write_u16(bs, a->font_table->entry_count); for (j=0; j<a->font_table->entry_count; j++) { gf_bs_write_u16(bs, a->font_table->fonts[j].fontID); if (a->font_table->fonts[j].fontName) { u32 len = strlen(a->font_table->fonts[j].fontName); gf_bs_write_u8(bs, len); gf_bs_write_data(bs, a->font_table->fonts[j].fontName, len); } else { gf_bs_write_u8(bs, 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_TextSampleEntryBox *a; a = (GF_TextSampleEntryBox *) gf_list_get(sampleDesc, i); if (a->type != GF_ISOM_BOX_TYPE_TX3G) 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;}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); free(samp->data); samp->data = NULL; gf_bs_get_content(bs, &samp->data, &samp->dataLength); gf_bs_del(bs); return GF_OK;}GF_Err gf_isom_text_get_encoded_tx3g(GF_ISOFile *file, u32 track, u32 sidx, u32 sidx_offset, char **tx3g, u32 *tx3g_size){ GF_BitStream *bs; GF_TrackBox *trak; GF_TextSampleEntryBox *a; trak = gf_isom_get_track_from_file(file, track); if (!trak) return GF_BAD_PARAM; a = (GF_TextSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, sidx-1); if (!a || (a->type != GF_ISOM_BOX_TYPE_TX3G)) return GF_BAD_PARAM; bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_isom_write_tx3g(a, bs, sidx, sidx_offset); *tx3g = NULL; *tx3g_size = 0; gf_bs_get_content(bs, tx3g, tx3g_size); gf_bs_del(bs); return GF_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -