Coverage Report

Created: 2024-02-11 06:48

/src/gpac/src/isomedia/tx3g.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 *      GPAC - Multimedia Framework C SDK
3
 *
4
 *      Authors: Jean Le Feuvre
5
 *      Copyright (c) Telecom ParisTech 2000-2023
6
 *          All rights reserved
7
 *
8
 *  This file is part of GPAC / ISO Media File Format sub-project
9
 *
10
 *  GPAC is free software; you can redistribute it and/or modify
11
 *  it under the terms of the GNU Lesser General Public License as published by
12
 *  the Free Software Foundation; either version 2, or (at your option)
13
 *  any later version.
14
 *
15
 *  GPAC is distributed in the hope that it will be useful,
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 *  GNU Lesser General Public License for more details.
19
 *
20
 *  You should have received a copy of the GNU Lesser General Public
21
 *  License along with this library; see the file COPYING.  If not, write to
22
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23
 *
24
 */
25
26
#include <gpac/internal/isomedia_dev.h>
27
#include <gpac/constants.h>
28
29
#ifndef GPAC_DISABLE_ISOM
30
31
static u32 rgb_48_to_32(char *val)
32
0
{
33
0
  u32 res = 0x0;
34
0
  u32 i;
35
36
0
  for (i=0; i<3; i++) {
37
0
    u32 v = val[2*i];
38
0
    v<<=8;
39
0
    v|=val[2*i + 1];
40
0
    v/=0xFF;
41
42
0
    res <<= 8;
43
0
    res |= v;
44
0
  }
45
0
  return res;
46
0
}
47
48
GF_EXPORT
49
GF_Err gf_isom_get_text_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, GF_TextSampleDescriptor **out_desc)
50
0
{
51
0
  GF_TrackBox *trak;
52
0
  u32 i;
53
0
  GF_Tx3gSampleEntryBox *txt = NULL;
54
0
  GF_TextSampleEntryBox *qt_txt = NULL;
55
0
  if (!descriptionIndex || !out_desc) return GF_BAD_PARAM;
56
57
0
  trak = gf_isom_get_track_from_file(movie, trackNumber);
58
0
  if (!trak || !trak->Media) return GF_BAD_PARAM;
59
60
0
  switch (trak->Media->handler->handlerType) {
61
0
  case GF_ISOM_MEDIA_TEXT:
62
0
  case GF_ISOM_MEDIA_SUBT:
63
0
  case GF_ISOM_MEDIA_MPEG_SUBT:
64
0
    break;
65
0
  default:
66
0
    return GF_BAD_PARAM;
67
0
  }
68
69
0
  txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, descriptionIndex - 1);
70
0
  if (!txt) return GF_BAD_PARAM;
71
0
  switch (txt->type) {
72
0
  case GF_ISOM_BOX_TYPE_TX3G:
73
0
    break;
74
0
  case GF_ISOM_BOX_TYPE_TEXT:
75
0
    qt_txt = (GF_TextSampleEntryBox *)txt;
76
0
    txt = NULL;
77
0
    break;
78
0
  default:
79
0
    return GF_BAD_PARAM;
80
0
  }
81
82
0
  (*out_desc) = (GF_TextSampleDescriptor *) gf_odf_desc_new(GF_ODF_TX3G_TAG);
83
0
  if (! (*out_desc) ) return GF_OUT_OF_MEM;
84
85
0
  if (qt_txt) {
86
0
    (*out_desc)->back_color = rgb_48_to_32(qt_txt->background_color);
87
0
    (*out_desc)->default_pos = qt_txt->default_box;
88
0
    (*out_desc)->default_style.style_flags = 0; //todo, expose qt_txt->fontFace;
89
0
    (*out_desc)->default_style.text_color = rgb_48_to_32(qt_txt->foreground_color);
90
0
    (*out_desc)->displayFlags = qt_txt->displayFlags;
91
0
    (*out_desc)->vert_justif = -1;
92
0
    (*out_desc)->horiz_justif = qt_txt->textJustification;
93
0
    if (qt_txt->textName) {
94
0
      (*out_desc)->font_count = 1;
95
0
      (*out_desc)->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord));
96
0
      (*out_desc)->fonts[0].fontName = gf_strdup(qt_txt->textName);
97
0
    }
98
0
  } else {
99
0
    (*out_desc)->back_color = txt->back_color;
100
0
    (*out_desc)->default_pos = txt->default_box;
101
0
    (*out_desc)->default_style = txt->default_style;
102
0
    (*out_desc)->displayFlags = txt->displayFlags;
103
0
    (*out_desc)->vert_justif = txt->vertical_justification;
104
0
    (*out_desc)->horiz_justif = txt->horizontal_justification;
105
0
    if (txt->font_table && txt->font_table->entry_count) {
106
0
      (*out_desc)->font_count = txt->font_table->entry_count;
107
0
      (*out_desc)->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord) * txt->font_table->entry_count);
108
0
      for (i=0; i<txt->font_table->entry_count; i++) {
109
0
        (*out_desc)->fonts[i].fontID = txt->font_table->fonts[i].fontID;
110
0
        if (txt->font_table->fonts[i].fontName)
111
0
          (*out_desc)->fonts[i].fontName = gf_strdup(txt->font_table->fonts[i].fontName);
112
0
      }
113
0
    }
114
0
  }
115
0
  return GF_OK;
116
0
}
117
118
#ifndef GPAC_DISABLE_ISOM_WRITE
119
120
#if 0 //unused
121
/*! updates text sample description
122
\param isom_file the target ISO file
123
\param trackNumber the target track
124
\param sampleDescriptionIndex the target sample description index
125
\param desc the text sample descriptor to use
126
\return error if any
127
*/
128
GF_Err gf_isom_update_text_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, GF_TextSampleDescriptor *desc)
129
{
130
  GF_TrackBox *trak;
131
  GF_Err e;
132
  Bool is_qt_text = GF_FALSE;
133
  u32 i;
134
  GF_Tx3gSampleEntryBox *txt;
135
136
  if (!descriptionIndex || !desc) return GF_BAD_PARAM;
137
  e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
138
  if (e) return e;
139
140
  trak = gf_isom_get_track_from_file(movie, trackNumber);
141
  if (!trak || !trak->Media || !desc->font_count) return GF_BAD_PARAM;
142
143
  switch (trak->Media->handler->handlerType) {
144
  case GF_ISOM_MEDIA_TEXT:
145
  case GF_ISOM_MEDIA_SUBT:
146
  case GF_ISOM_MEDIA_MPEG_SUBT:
147
    break;
148
  default:
149
    return GF_BAD_PARAM;
150
  }
151
152
  txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, descriptionIndex - 1);
153
  if (!txt) return GF_BAD_PARAM;
154
  switch (txt->type) {
155
  case GF_ISOM_BOX_TYPE_TX3G:
156
    break;
157
  case GF_ISOM_BOX_TYPE_TEXT:
158
    is_qt_text = GF_TRUE;
159
    break;
160
  default:
161
    return GF_BAD_PARAM;
162
  }
163
164
  if (!movie->keep_utc)
165
    trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
166
167
  txt->back_color = desc->back_color;
168
  txt->default_box = desc->default_pos;
169
  txt->default_style = desc->default_style;
170
  txt->displayFlags = desc->displayFlags;
171
  txt->vertical_justification = desc->vert_justif;
172
  txt->horizontal_justification = desc->horiz_justif;
173
  if (is_qt_text) {
174
    GF_TextSampleEntryBox *qtt = (GF_TextSampleEntryBox *) txt;
175
    if (qtt->textName) gf_free(qtt->textName);
176
    qtt->textName = NULL;
177
    if (desc->font_count) {
178
      qtt->textName = gf_strdup(desc->fonts[0].fontName);
179
    }
180
  } else {
181
    if (txt->font_table) gf_isom_box_del_parent(&txt->child_boxes, (GF_Box*)txt->font_table);
182
183
    txt->font_table = (GF_FontTableBox *)gf_isom_box_new_parent(&txt->child_boxes, GF_ISOM_BOX_TYPE_FTAB);
184
    txt->font_table->entry_count = desc->font_count;
185
    txt->font_table->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord) * desc->font_count);
186
    for (i=0; i<desc->font_count; i++) {
187
      txt->font_table->fonts[i].fontID = desc->fonts[i].fontID;
188
      if (desc->fonts[i].fontName) txt->font_table->fonts[i].fontName = gf_strdup(desc->fonts[i].fontName);
189
    }
190
  }
191
  return e;
192
}
193
#endif //unused
194
195
GF_EXPORT
196
GF_Err gf_isom_new_text_description(GF_ISOFile *movie, u32 trackNumber, GF_TextSampleDescriptor *desc, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
197
0
{
198
0
  GF_TrackBox *trak;
199
0
  GF_Err e;
200
0
  u32 dataRefIndex, i;
201
0
  GF_Tx3gSampleEntryBox *txt;
202
203
0
  e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
204
0
  if (e) return e;
205
206
0
  trak = gf_isom_get_track_from_file(movie, trackNumber);
207
0
  if (!trak || !trak->Media || !desc || !desc->font_count) return GF_BAD_PARAM;
208
209
0
  switch (trak->Media->handler->handlerType) {
210
0
  case GF_ISOM_MEDIA_TEXT:
211
0
  case GF_ISOM_MEDIA_SUBT:
212
0
  case GF_ISOM_MEDIA_MPEG_SUBT:
213
0
    break;
214
0
  default:
215
0
    return GF_BAD_PARAM;
216
0
  }
217
218
  //get or create the data ref
219
0
  e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
220
0
  if (e) return e;
221
0
  if (!dataRefIndex) {
222
0
    e = Media_CreateDataRef(movie, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
223
0
    if (e) return e;
224
0
  }
225
0
  if (!movie->keep_utc)
226
0
    trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
227
228
0
  txt = (GF_Tx3gSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TX3G);
229
0
  if (!txt) return GF_OUT_OF_MEM;
230
0
  txt->dataReferenceIndex = dataRefIndex;
231
0
  gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, txt);
232
0
  if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
233
234
0
  txt->back_color = desc->back_color;
235
0
  txt->default_box = desc->default_pos;
236
0
  txt->default_style = desc->default_style;
237
0
  txt->displayFlags = desc->displayFlags;
238
0
  txt->vertical_justification = desc->vert_justif;
239
0
  txt->horizontal_justification = desc->horiz_justif;
240
0
  txt->font_table = (GF_FontTableBox *)gf_isom_box_new_parent(&txt->child_boxes, GF_ISOM_BOX_TYPE_FTAB);
241
0
  if (!txt->font_table) return GF_OUT_OF_MEM;
242
0
  txt->font_table->entry_count = desc->font_count;
243
244
0
  txt->font_table->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord) * desc->font_count);
245
0
  if (!txt->font_table->fonts) return GF_OUT_OF_MEM;
246
0
  for (i=0; i<desc->font_count; i++) {
247
0
    txt->font_table->fonts[i].fontID = desc->fonts[i].fontID;
248
0
    if (desc->fonts[i].fontName) txt->font_table->fonts[i].fontName = gf_strdup(desc->fonts[i].fontName);
249
0
  }
250
0
  return e;
251
0
}
252
253
254
/*blindly adds text - note we don't rely on terminaison characters to handle utf8 and utf16 data
255
in the same way. It is the user responsibility to signal UTF16*/
256
GF_EXPORT
257
GF_Err gf_isom_text_add_text(GF_TextSample *samp, char *text_data, u32 text_len)
258
26.8k
{
259
26.8k
  if (!samp) return GF_BAD_PARAM;
260
26.8k
  if (!text_len) return GF_OK;
261
24.8k
  samp->text = (char*)gf_realloc(samp->text, sizeof(char) * (samp->len + text_len) );
262
24.8k
  memcpy(samp->text + samp->len, text_data, sizeof(char) * text_len);
263
24.8k
  samp->len += text_len;
264
24.8k
  return GF_OK;
265
26.8k
}
266
267
#if 0 //unused
268
/*! sets UTF16 marker for text data. This MUST be called on an empty sample. If text data added later
269
on (cf below) is not formatted as UTF16 data(2 bytes char) the resulting text sample won't be compliant,
270
but this library won't warn
271
\param tx_samp the target text sample
272
\return error if any
273
*/
274
GF_Err gf_isom_text_set_utf16_marker(GF_TextSample *samp)
275
{
276
  /*we MUST have an empty sample*/
277
  if (!samp || samp->text) return GF_BAD_PARAM;
278
  samp->text = (char*)gf_malloc(sizeof(char) * 2);
279
  if (!samp->text) return GF_OUT_OF_MEM;
280
  samp->text[0] = (char) 0xFE;
281
  samp->text[1] = (char) 0xFF;
282
  samp->len = 2;
283
  return GF_OK;
284
}
285
#endif //unused
286
287
GF_EXPORT
288
GF_Err gf_isom_text_add_style(GF_TextSample *samp, GF_StyleRecord *rec)
289
14.9k
{
290
14.9k
  if (!samp || !rec) return GF_BAD_PARAM;
291
292
14.9k
  if (!samp->styles) {
293
538
    samp->styles = (GF_TextStyleBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STYL);
294
538
    if (!samp->styles) return GF_OUT_OF_MEM;
295
538
  }
296
14.9k
  samp->styles->styles = (GF_StyleRecord*)gf_realloc(samp->styles->styles, sizeof(GF_StyleRecord)*(samp->styles->entry_count+1));
297
14.9k
  if (!samp->styles->styles) return GF_OUT_OF_MEM;
298
14.9k
  samp->styles->styles[samp->styles->entry_count] = *rec;
299
14.9k
  samp->styles->entry_count++;
300
14.9k
  return GF_OK;
301
14.9k
}
302
303
GF_EXPORT
304
GF_Err gf_isom_text_add_highlight(GF_TextSample *samp, u16 start_char, u16 end_char)
305
0
{
306
0
  GF_TextHighlightBox *a;
307
0
  if (!samp) return GF_BAD_PARAM;
308
0
  if (start_char == end_char) return GF_BAD_PARAM;
309
310
0
  a = (GF_TextHighlightBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_HLIT);
311
0
  if (!a) return GF_OUT_OF_MEM;
312
0
  a->startcharoffset = start_char;
313
0
  a->endcharoffset = end_char;
314
0
  return gf_list_add(samp->others, a);
315
0
}
316
317
318
GF_EXPORT
319
GF_Err gf_isom_text_set_highlight_color(GF_TextSample *samp, u32 argb)
320
0
{
321
0
  if (!samp) return GF_BAD_PARAM;
322
323
0
  if (!samp->highlight_color) {
324
0
    samp->highlight_color = (GF_TextHighlightColorBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_HCLR);
325
0
    if (!samp->highlight_color) return GF_OUT_OF_MEM;
326
0
  }
327
0
  samp->highlight_color->hil_color = argb;
328
0
  return GF_OK;
329
0
}
330
331
/*3GPP spec is quite obscur here*/
332
GF_EXPORT
333
GF_Err gf_isom_text_add_karaoke(GF_TextSample *samp, u32 start_time)
334
0
{
335
0
  if (!samp) return GF_BAD_PARAM;
336
0
  samp->cur_karaoke = (GF_TextKaraokeBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_KROK);
337
0
  if (!samp->cur_karaoke) return GF_OUT_OF_MEM;
338
0
  samp->cur_karaoke->highlight_starttime = start_time;
339
0
  return gf_list_add(samp->others, samp->cur_karaoke);
340
0
}
341
342
GF_EXPORT
343
GF_Err gf_isom_text_set_karaoke_segment(GF_TextSample *samp, u32 end_time, u16 start_char, u16 end_char)
344
0
{
345
0
  if (!samp || !samp->cur_karaoke) return GF_BAD_PARAM;
346
0
  samp->cur_karaoke->records = (KaraokeRecord*)gf_realloc(samp->cur_karaoke->records, sizeof(KaraokeRecord)*(samp->cur_karaoke->nb_entries+1));
347
0
  if (!samp->cur_karaoke->records) return GF_OUT_OF_MEM;
348
0
  samp->cur_karaoke->records[samp->cur_karaoke->nb_entries].end_charoffset = end_char;
349
0
  samp->cur_karaoke->records[samp->cur_karaoke->nb_entries].start_charoffset = start_char;
350
0
  samp->cur_karaoke->records[samp->cur_karaoke->nb_entries].highlight_endtime = end_time;
351
0
  samp->cur_karaoke->nb_entries++;
352
0
  return GF_OK;
353
0
}
354
355
GF_EXPORT
356
GF_Err gf_isom_text_set_scroll_delay(GF_TextSample *samp, u32 scroll_delay)
357
0
{
358
0
  if (!samp) return GF_BAD_PARAM;
359
0
  if (!samp->scroll_delay) {
360
0
    samp->scroll_delay = (GF_TextScrollDelayBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_DLAY);
361
0
    if (!samp->scroll_delay) return GF_OUT_OF_MEM;
362
0
  }
363
0
  samp->scroll_delay->scroll_delay = scroll_delay;
364
0
  return GF_OK;
365
0
}
366
367
GF_EXPORT
368
GF_Err gf_isom_text_add_hyperlink(GF_TextSample *samp, char *URL, char *altString, u16 start_char, u16 end_char)
369
0
{
370
0
  GF_TextHyperTextBox*a;
371
0
  if (!samp) return GF_BAD_PARAM;
372
0
  a = (GF_TextHyperTextBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_HREF);
373
0
  if (!a) return GF_OUT_OF_MEM;
374
0
  a->startcharoffset = start_char;
375
0
  a->endcharoffset = end_char;
376
0
  a->URL = URL ? gf_strdup(URL) : NULL;
377
0
  a->URL_hint = altString ? gf_strdup(altString) : NULL;
378
0
  return gf_list_add(samp->others, a);
379
0
}
380
381
GF_EXPORT
382
GF_Err gf_isom_text_set_box(GF_TextSample *samp, s16 top, s16 left, s16 bottom, s16 right)
383
0
{
384
0
  if (!samp) return GF_BAD_PARAM;
385
0
  if (!samp->box) {
386
0
    samp->box = (GF_TextBoxBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_TBOX);
387
0
    if (!samp->box) return GF_OUT_OF_MEM;
388
0
  }
389
0
  samp->box->box.top = top;
390
0
  samp->box->box.left = left;
391
0
  samp->box->box.bottom = bottom;
392
0
  samp->box->box.right = right;
393
0
  return GF_OK;
394
0
}
395
396
GF_EXPORT
397
GF_Err gf_isom_text_add_blink(GF_TextSample *samp, u16 start_char, u16 end_char)
398
0
{
399
0
  GF_TextBlinkBox *a;
400
0
  if (!samp) return GF_BAD_PARAM;
401
0
  a = (GF_TextBlinkBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_BLNK);
402
0
  if (!a) return GF_OUT_OF_MEM;
403
0
  a->startcharoffset = start_char;
404
0
  a->endcharoffset = end_char;
405
0
  return gf_list_add(samp->others, a);
406
0
}
407
408
GF_EXPORT
409
GF_Err gf_isom_text_set_wrap(GF_TextSample *samp, u8 wrap_flags)
410
0
{
411
0
  if (!samp) return GF_BAD_PARAM;
412
0
  if (!samp->wrap) {
413
0
    samp->wrap = (GF_TextWrapBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_TWRP);
414
0
    if (!samp->wrap) return GF_OUT_OF_MEM;
415
0
  }
416
0
  samp->wrap->wrap_flag = wrap_flags;
417
0
  return GF_OK;
418
0
}
419
420
GF_EXPORT
421
GF_Err gf_isom_text_set_forced(GF_TextSample *samp, Bool is_forced)
422
438
{
423
438
  if (!samp) return GF_BAD_PARAM;
424
438
  samp->is_forced = is_forced;
425
438
  return GF_OK;
426
438
}
427
428
static GFINLINE GF_Err gpp_write_modifier(GF_BitStream *bs, GF_Box *a)
429
45.3k
{
430
45.3k
  GF_Err e;
431
45.3k
  if (!a) return GF_OK;
432
530
  e = gf_isom_box_size(a);
433
530
  if (!e) e = gf_isom_box_write(a, bs);
434
530
  return e;
435
45.3k
}
436
437
GF_EXPORT
438
GF_Err gf_isom_text_sample_write_bs(const GF_TextSample *samp, GF_BitStream *bs)
439
9.06k
{
440
9.06k
  GF_Err e;
441
9.06k
  u32 i;
442
9.06k
  if (!samp) return GF_BAD_PARAM;
443
444
9.06k
  gf_bs_write_u16(bs, samp->len);
445
9.06k
  if (samp->len) gf_bs_write_data(bs, samp->text, samp->len);
446
447
9.06k
  e = gpp_write_modifier(bs, (GF_Box *)samp->styles);
448
9.06k
  if (!e) e = gpp_write_modifier(bs, (GF_Box *)samp->highlight_color);
449
9.06k
  if (!e) e = gpp_write_modifier(bs, (GF_Box *)samp->scroll_delay);
450
9.06k
  if (!e) e = gpp_write_modifier(bs, (GF_Box *)samp->box);
451
9.06k
  if (!e) e = gpp_write_modifier(bs, (GF_Box *)samp->wrap);
452
453
9.06k
  if (!e && samp->is_forced) {
454
77
    gf_bs_write_u32(bs, 8);
455
77
    gf_bs_write_u32(bs, GF_QT_BOX_TYPE_FRCD);
456
77
  }
457
458
9.06k
  if (!e) {
459
9.06k
    GF_Box *a;
460
9.06k
    i=0;
461
9.06k
    while ((a = (GF_Box*)gf_list_enum(samp->others, &i))) {
462
0
      e = gpp_write_modifier(bs, a);
463
0
      if (e) break;
464
0
    }
465
9.06k
  }
466
9.06k
  return e;
467
9.06k
}
468
469
GF_EXPORT
470
GF_ISOSample *gf_isom_text_to_sample(const GF_TextSample *samp)
471
0
{
472
0
  GF_Err e;
473
0
  GF_ISOSample *res;
474
0
  GF_BitStream *bs;
475
0
  if (!samp) return NULL;
476
477
0
  bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
478
479
0
  e = gf_isom_text_sample_write_bs(samp, bs);
480
481
0
  if (e) {
482
0
    gf_bs_del(bs);
483
0
    return NULL;
484
0
  }
485
0
  res = gf_isom_sample_new();
486
0
  if (!res) {
487
0
    gf_bs_del(bs);
488
0
    return NULL;
489
0
  }
490
0
  gf_bs_get_content(bs, &res->data, &res->dataLength);
491
0
  gf_bs_del(bs);
492
0
  res->IsRAP = RAP;
493
0
  return res;
494
0
}
495
496
u32 gf_isom_text_sample_size(GF_TextSample *samp)
497
9.06k
{
498
9.06k
  GF_Box *a;
499
9.06k
  u32 i, size;
500
9.06k
  if (!samp) return 0;
501
502
9.06k
  size = 2 + samp->len;
503
9.06k
  if (samp->styles) {
504
530
    gf_isom_box_size((GF_Box *)samp->styles);
505
530
    size += (u32) samp->styles->size;
506
530
  }
507
9.06k
  if (samp->highlight_color) {
508
0
    gf_isom_box_size((GF_Box *)samp->highlight_color);
509
0
    size += (u32) samp->highlight_color->size;
510
0
  }
511
9.06k
  if (samp->scroll_delay) {
512
0
    gf_isom_box_size((GF_Box *)samp->scroll_delay);
513
0
    size += (u32) samp->scroll_delay->size;
514
0
  }
515
9.06k
  if (samp->box) {
516
0
    gf_isom_box_size((GF_Box *)samp->box);
517
0
    size += (u32) samp->box->size;
518
0
  }
519
9.06k
  if (samp->wrap) {
520
0
    gf_isom_box_size((GF_Box *)samp->wrap);
521
0
    size += (u32) samp->wrap->size;
522
0
  }
523
9.06k
  i=0;
524
9.06k
  while ((a = (GF_Box*)gf_list_enum(samp->others, &i))) {
525
0
    gf_isom_box_size((GF_Box *)a);
526
0
    size += (u32) a->size;
527
0
  }
528
9.06k
  return size;
529
9.06k
}
530
531
#if 0 //unused
532
/*! checks if this text description is already inserted
533
\param isom_file the target ISO file
534
\param trackNumber the target track
535
\param desc the 3GPP text sample description to check
536
\param outDescIdx set to 0 if not found, or index of the matching sample description
537
\param same_styles indicates if default styles matches
538
\param same_box indicates if default box matches
539
*/
540
GF_Err gf_isom_text_has_similar_description(GF_ISOFile *movie, u32 trackNumber, GF_TextSampleDescriptor *desc, u32 *outDescIdx, Bool *same_box, Bool *same_styles)
541
{
542
  GF_TrackBox *trak;
543
  GF_Err e;
544
  u32 i, j, count;
545
  GF_Tx3gSampleEntryBox *txt;
546
547
  *same_box = *same_styles = 0;
548
  *outDescIdx = 0;
549
550
  if (!desc) return GF_BAD_PARAM;
551
  e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
552
  if (e) return GF_BAD_PARAM;
553
554
  trak = gf_isom_get_track_from_file(movie, trackNumber);
555
  if (!trak || !trak->Media || !desc->font_count) return GF_BAD_PARAM;
556
557
  switch (trak->Media->handler->handlerType) {
558
  case GF_ISOM_MEDIA_TEXT:
559
  case GF_ISOM_MEDIA_SUBT:
560
  case GF_ISOM_MEDIA_MPEG_SUBT:
561
    break;
562
  default:
563
    return GF_BAD_PARAM;
564
  }
565
566
  count = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
567
  for (i=0; i<count; i++) {
568
    Bool same_fonts;
569
    txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, i);
570
    if (!txt) continue;
571
    if ((txt->type != GF_ISOM_BOX_TYPE_TX3G) && (txt->type != GF_ISOM_BOX_TYPE_TEXT)) continue;
572
    if (txt->back_color != desc->back_color) continue;
573
    if (txt->displayFlags != desc->displayFlags) continue;
574
    if (txt->vertical_justification != desc->vert_justif) continue;
575
    if (txt->horizontal_justification != desc->horiz_justif) continue;
576
    if (txt->font_table->entry_count != desc->font_count) continue;
577
578
    same_fonts = 1;
579
    for (j=0; j<desc->font_count; j++) {
580
      if (txt->font_table->fonts[j].fontID != desc->fonts[j].fontID) same_fonts = 0;
581
      else if (strcmp(desc->fonts[j].fontName, txt->font_table->fonts[j].fontName)) same_fonts = 0;
582
    }
583
    if (same_fonts) {
584
      *outDescIdx = i+1;
585
      if (!memcmp(&txt->default_box, &desc->default_pos, sizeof(GF_BoxRecord))) *same_box = 1;
586
      if (!memcmp(&txt->default_style, &desc->default_style, sizeof(GF_StyleRecord))) *same_styles = 1;
587
      return GF_OK;
588
    }
589
  }
590
  return GF_OK;
591
}
592
#endif
593
594
#endif /*GPAC_DISABLE_ISOM_WRITE*/
595
596
GF_EXPORT
597
GF_TextSample *gf_isom_new_text_sample()
598
6.19k
{
599
6.19k
  GF_TextSample *res;
600
6.19k
  GF_SAFEALLOC(res, GF_TextSample);
601
6.19k
  if (!res) return NULL;
602
6.19k
  res->others = gf_list_new();
603
6.19k
  return res;
604
6.19k
}
605
606
GF_EXPORT
607
GF_Err gf_isom_text_reset_styles(GF_TextSample *samp)
608
10.5k
{
609
10.5k
  if (!samp) return GF_BAD_PARAM;
610
10.5k
  if (samp->box) gf_isom_box_del((GF_Box *)samp->box);
611
10.5k
  samp->box = NULL;
612
10.5k
  if (samp->highlight_color) gf_isom_box_del((GF_Box *)samp->highlight_color);
613
10.5k
  samp->highlight_color = NULL;
614
10.5k
  if (samp->scroll_delay) gf_isom_box_del((GF_Box *)samp->scroll_delay);
615
10.5k
  samp->scroll_delay = NULL;
616
10.5k
  if (samp->wrap) gf_isom_box_del((GF_Box *)samp->wrap);
617
10.5k
  samp->wrap = NULL;
618
10.5k
  if (samp->styles) gf_isom_box_del((GF_Box *)samp->styles);
619
10.5k
  samp->styles = NULL;
620
10.5k
  samp->cur_karaoke = NULL;
621
10.5k
  while (gf_list_count(samp->others)) {
622
0
    GF_Box *a = (GF_Box*)gf_list_get(samp->others, 0);
623
0
    gf_list_rem(samp->others, 0);
624
0
    gf_isom_box_del(a);
625
0
  }
626
10.5k
  samp->is_forced = GF_FALSE;
627
10.5k
  return GF_OK;
628
10.5k
}
629
630
GF_EXPORT
631
GF_Err gf_isom_text_reset(GF_TextSample *samp)
632
10.5k
{
633
10.5k
  if (!samp) return GF_BAD_PARAM;
634
10.5k
  if (samp->text) gf_free(samp->text);
635
10.5k
  samp->text = NULL;
636
10.5k
  samp->len = 0;
637
10.5k
  return gf_isom_text_reset_styles(samp);
638
10.5k
}
639
640
GF_EXPORT
641
void gf_isom_delete_text_sample(GF_TextSample * tx_samp)
642
6.19k
{
643
6.19k
  gf_isom_text_reset(tx_samp);
644
6.19k
  gf_list_del(tx_samp->others);
645
6.19k
  gf_free(tx_samp);
646
6.19k
}
647
648
GF_EXPORT
649
GF_TextSample *gf_isom_parse_text_sample(GF_BitStream *bs)
650
0
{
651
0
  GF_TextSample *s = gf_isom_new_text_sample();
652
653
  /*empty sample*/
654
0
  if (!bs || !gf_bs_available(bs)) return s;
655
656
0
  s->len = gf_bs_read_u16(bs);
657
0
  if (s->len) {
658
    /*2 extra bytes for UTF-16 term char just in case (we don't know if a BOM marker is present or
659
    not since this may be a sample carried over RTP*/
660
0
    s->text = (char *) gf_malloc(sizeof(char)*(s->len+2) );
661
0
    if (!s->text) return NULL;
662
0
    s->text[s->len] = 0;
663
0
    s->text[s->len+1] = 0;
664
0
    gf_bs_read_data(bs, s->text, s->len);
665
0
  }
666
667
0
  while (gf_bs_available(bs)) {
668
0
    GF_Box *a = NULL;
669
0
    GF_Err e = gf_isom_box_parse(&a, bs);
670
0
    if (e) {
671
0
      if (a) gf_isom_box_del(a);
672
0
      break;
673
0
    }
674
675
0
    switch (a->type) {
676
0
    case GF_ISOM_BOX_TYPE_STYL:
677
0
      if (s->styles) {
678
0
        GF_TextStyleBox *st2 = (GF_TextStyleBox *)a;
679
0
        if (!s->styles->entry_count) {
680
0
          gf_isom_box_del((GF_Box*)s->styles);
681
0
          s->styles = st2;
682
0
        } else {
683
0
          s->styles->styles = (GF_StyleRecord*)gf_realloc(s->styles->styles, sizeof(GF_StyleRecord) * (s->styles->entry_count + st2->entry_count));
684
0
          memcpy(&s->styles->styles[s->styles->entry_count], st2->styles, sizeof(GF_StyleRecord) * st2->entry_count);
685
0
          s->styles->entry_count += st2->entry_count;
686
0
          gf_isom_box_del(a);
687
0
        }
688
0
      } else {
689
0
        s->styles = (GF_TextStyleBox*)a;
690
0
      }
691
0
      break;
692
0
    case GF_ISOM_BOX_TYPE_KROK:
693
0
      s->cur_karaoke = (GF_TextKaraokeBox*)a;
694
0
    case GF_ISOM_BOX_TYPE_HLIT:
695
0
    case GF_ISOM_BOX_TYPE_HREF:
696
0
    case GF_ISOM_BOX_TYPE_BLNK:
697
0
      gf_list_add(s->others, a);
698
0
      break;
699
0
    case GF_ISOM_BOX_TYPE_HCLR:
700
0
      if (s->highlight_color) gf_isom_box_del(a);
701
0
      else s->highlight_color = (GF_TextHighlightColorBox *) a;
702
0
      break;
703
0
    case GF_ISOM_BOX_TYPE_DLAY:
704
0
      if (s->scroll_delay) gf_isom_box_del(a);
705
0
      else s->scroll_delay= (GF_TextScrollDelayBox*) a;
706
0
      break;
707
0
    case GF_ISOM_BOX_TYPE_TBOX:
708
0
      if (s->box) gf_isom_box_del(a);
709
0
      else s->box= (GF_TextBoxBox *) a;
710
0
      break;
711
0
    case GF_ISOM_BOX_TYPE_TWRP:
712
0
      if (s->wrap) gf_isom_box_del(a);
713
0
      else s->wrap= (GF_TextWrapBox*) a;
714
0
      break;
715
0
    case GF_QT_BOX_TYPE_FRCD:
716
0
      s->is_forced = GF_TRUE;
717
0
      gf_isom_box_del(a);
718
0
      break;
719
0
    default:
720
0
      gf_isom_box_del(a);
721
0
      break;
722
0
    }
723
0
  }
724
0
  return s;
725
0
}
726
727
#if 0 //unused
728
GF_TextSample *gf_isom_parse_text_sample_from_data(u8 *data, u32 dataLength)
729
{
730
  GF_TextSample *s;
731
  GF_BitStream *bs;
732
  /*empty text sample*/
733
  if (!data || !dataLength) {
734
    return gf_isom_new_text_sample();
735
  }
736
737
  bs = gf_bs_new(data, dataLength, GF_BITSTREAM_READ);
738
  s = gf_isom_parse_text_sample(bs);
739
  gf_bs_del(bs);
740
  return s;
741
}
742
#endif
743
744
745
/*out-of-band sample desc (128 and 255 reserved in RFC)*/
746
0
#define SAMPLE_INDEX_OFFSET   129
747
748
749
static void gf_isom_write_tx3g(GF_Tx3gSampleEntryBox *_a, GF_BitStream *bs, u32 sidx, u32 sidx_offset)
750
0
{
751
0
  u32 size, j, fount_count;
752
0
  const char *qt_fontname = NULL;
753
0
  void gpp_write_rgba(GF_BitStream *bs, u32 col);
754
0
  void gpp_write_box(GF_BitStream *bs, GF_BoxRecord *rec);
755
0
  void gpp_write_style(GF_BitStream *bs, GF_StyleRecord *rec);
756
757
0
  GF_TextSampleEntryBox *qt = (_a->type==GF_ISOM_BOX_TYPE_TEXT) ? (GF_TextSampleEntryBox *)_a : NULL;
758
0
  GF_Tx3gSampleEntryBox *ttxt = (_a->type!=GF_ISOM_BOX_TYPE_TEXT) ? (GF_Tx3gSampleEntryBox *)_a : NULL;
759
760
0
  if (sidx_offset) gf_bs_write_u8(bs, sidx + sidx_offset);
761
762
  /*SINCE WINCE HAS A READONLY VERSION OF MP4 WE MUST DO IT BY HAND*/
763
0
  size = 8 + 18 + 8 + 12;
764
0
  size += 8 + 2;
765
0
  fount_count = 0;
766
0
  if (qt && qt->textName) {
767
0
    qt_fontname = qt->textName;
768
0
    fount_count = 1;
769
0
  } else if (ttxt && ttxt->font_table) {
770
0
    fount_count = ttxt->font_table->entry_count;
771
0
    for (j=0; j<fount_count; j++) {
772
0
      size += 3;
773
0
      if (ttxt->font_table->fonts[j].fontName)
774
0
        size += (u32) strlen(ttxt->font_table->fonts[j].fontName);
775
0
    }
776
0
  }
777
  /*write TextSampleEntry box*/
778
0
  gf_bs_write_u32(bs, size);
779
0
  gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_TX3G);
780
0
  gf_bs_write_data(bs, _a->reserved, 6);
781
0
  gf_bs_write_u16(bs, _a->dataReferenceIndex);
782
0
  gf_bs_write_u32(bs, _a->displayFlags);
783
0
  if (qt) {
784
0
    GF_StyleRecord sr;
785
0
    memset(&sr, 0, sizeof(GF_StyleRecord));
786
0
    gf_bs_write_u8(bs, qt->textJustification);
787
0
    gf_bs_write_u8(bs, (u8) -1);
788
0
    gpp_write_rgba(bs, rgb_48_to_32(qt->background_color) );
789
0
    gpp_write_box(bs, &qt->default_box);
790
0
    sr.text_color = rgb_48_to_32(qt->foreground_color);
791
0
    sr.style_flags = 0; //todo expose qt->fontFace;
792
0
    gpp_write_style(bs, &sr);
793
0
  } else {
794
0
    gf_bs_write_u8(bs, ttxt->horizontal_justification);
795
0
    gf_bs_write_u8(bs, ttxt->vertical_justification);
796
0
    gpp_write_rgba(bs, ttxt->back_color);
797
0
    gpp_write_box(bs, &ttxt->default_box);
798
0
    gpp_write_style(bs, &ttxt->default_style);
799
0
  }
800
  /*write font table box*/
801
0
  size -= (8 + 18 + 8 + 12);
802
0
  gf_bs_write_u32(bs, size);
803
0
  gf_bs_write_u32(bs, GF_ISOM_BOX_TYPE_FTAB);
804
805
0
  gf_bs_write_u16(bs, fount_count);
806
0
  for (j=0; j<fount_count; j++) {
807
0
    if (qt) {
808
0
      gf_bs_write_u16(bs, 0);
809
0
      if (qt_fontname) {
810
0
        u32 len = (u32) strlen(qt_fontname);
811
0
        gf_bs_write_u8(bs, len);
812
0
        gf_bs_write_data(bs, qt_fontname, len);
813
0
      } else {
814
0
        gf_bs_write_u8(bs, 0);
815
0
      }
816
0
    } else {
817
0
      gf_bs_write_u16(bs, ttxt->font_table->fonts[j].fontID);
818
0
      if (ttxt->font_table->fonts[j].fontName) {
819
0
        u32 len = (u32) strlen(ttxt->font_table->fonts[j].fontName);
820
0
        gf_bs_write_u8(bs, len);
821
0
        gf_bs_write_data(bs, ttxt->font_table->fonts[j].fontName, len);
822
0
      } else {
823
0
        gf_bs_write_u8(bs, 0);
824
0
      }
825
0
    }
826
0
  }
827
0
}
828
829
GF_Err gf_isom_get_ttxt_esd(GF_MediaBox *mdia, GF_ESD **out_esd)
830
0
{
831
0
  GF_BitStream *bs;
832
0
  u32 count, i;
833
0
  Bool has_v_info;
834
0
  GF_List *sampleDesc;
835
0
  GF_ESD *esd;
836
0
  GF_TrackBox *tk;
837
838
0
  *out_esd = NULL;
839
0
  sampleDesc = mdia->information->sampleTable->SampleDescription->child_boxes;
840
0
  count = gf_list_count(sampleDesc);
841
0
  if (!count) return GF_ISOM_INVALID_MEDIA;
842
843
0
  esd = gf_odf_desc_esd_new(2);
844
0
  esd->decoderConfig->streamType = GF_STREAM_TEXT;
845
0
  esd->decoderConfig->objectTypeIndication = GF_CODECID_TEXT_MPEG4;
846
847
0
  bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
848
849
850
  /*Base3GPPFormat*/
851
0
  gf_bs_write_u8(bs, 0x10);
852
  /*MPEGExtendedFormat*/
853
0
  gf_bs_write_u8(bs, 0x10);
854
  /*profileLevel*/
855
0
  gf_bs_write_u8(bs, 0x10);
856
0
  gf_bs_write_u24(bs, mdia->mediaHeader->timeScale);
857
0
  gf_bs_write_int(bs, 0, 1);  /*no alt formats*/
858
0
  gf_bs_write_int(bs, 2, 2);  /*only out-of-band-band sample desc*/
859
0
  gf_bs_write_int(bs, 1, 1);  /*we will write sample desc*/
860
861
  /*write v info if any visual track in this movie*/
862
0
  has_v_info = 0;
863
0
  i=0;
864
0
  while ((tk = (GF_TrackBox*)gf_list_enum(mdia->mediaTrack->moov->trackList, &i))) {
865
0
    if (tk->Media->handler && (tk->Media->handler->handlerType == GF_ISOM_MEDIA_VISUAL)) {
866
0
      has_v_info = 1;
867
0
    }
868
0
  }
869
0
  gf_bs_write_int(bs, has_v_info, 1);
870
871
0
  gf_bs_write_int(bs, 0, 3);  /*reserved, spec doesn't say the values*/
872
0
  gf_bs_write_u8(bs, mdia->mediaTrack->Header->layer);
873
0
  gf_bs_write_u16(bs, mdia->mediaTrack->Header->width>>16);
874
0
  gf_bs_write_u16(bs, mdia->mediaTrack->Header->height>>16);
875
876
  /*write desc*/
877
0
  gf_bs_write_u8(bs, count);
878
0
  for (i=0; i<count; i++) {
879
0
    GF_Tx3gSampleEntryBox *a;
880
0
    a = (GF_Tx3gSampleEntryBox *) gf_list_get(sampleDesc, i);
881
0
    if ((a->type != GF_ISOM_BOX_TYPE_TX3G) && (a->type != GF_ISOM_BOX_TYPE_TEXT) ) continue;
882
0
    gf_isom_write_tx3g(a, bs, i+1, SAMPLE_INDEX_OFFSET);
883
0
  }
884
0
  if (has_v_info) {
885
0
    u32 trans;
886
    /*which video shall we pick for MPEG-4, and how is the associations indicated in 3GP ???*/
887
0
    gf_bs_write_u16(bs, 0);
888
0
    gf_bs_write_u16(bs, 0);
889
0
    trans = mdia->mediaTrack->Header->matrix[6];
890
0
    trans >>= 16;
891
0
    gf_bs_write_u16(bs, trans);
892
0
    trans = mdia->mediaTrack->Header->matrix[7];
893
0
    trans >>= 16;
894
0
    gf_bs_write_u16(bs, trans);
895
0
  }
896
897
0
  gf_bs_get_content(bs, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
898
0
  gf_bs_del(bs);
899
0
  *out_esd = esd;
900
0
  return GF_OK;
901
0
}
902
903
GF_Err gf_isom_rewrite_text_sample(GF_ISOSample *samp, u32 sampleDescriptionIndex, u32 sample_dur)
904
0
{
905
0
  GF_BitStream *bs;
906
0
  u32 pay_start, txt_size;
907
0
  Bool is_utf_16 = 0;
908
0
  if (!samp || !samp->data || !samp->dataLength) return GF_OK;
909
910
0
  bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
911
0
  txt_size = gf_bs_read_u16(bs);
912
0
  gf_bs_del(bs);
913
914
  /*remove BOM*/
915
0
  pay_start = 2;
916
0
  if (txt_size>2) {
917
    /*seems 3GP only accepts BE UTF-16 (no LE, no UTF32)*/
918
0
    if (((u8) samp->data[2]==(u8) 0xFE) && ((u8)samp->data[3]==(u8) 0xFF)) {
919
0
      is_utf_16 = 1;
920
0
      pay_start = 4;
921
0
      txt_size -= 2;
922
0
    }
923
0
  }
924
925
  /*rewrite as TTU(1)*/
926
0
  bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
927
0
  gf_bs_write_int(bs, is_utf_16, 1);
928
0
  gf_bs_write_int(bs, 0, 4);
929
0
  gf_bs_write_int(bs, 1, 3);
930
0
  gf_bs_write_u16(bs, 8 + samp->dataLength - pay_start);
931
0
  gf_bs_write_u8(bs, sampleDescriptionIndex + SAMPLE_INDEX_OFFSET);
932
0
  gf_bs_write_u24(bs, sample_dur);
933
  /*write text size*/
934
0
  gf_bs_write_u16(bs, txt_size);
935
0
  if (txt_size) gf_bs_write_data(bs, samp->data + pay_start, samp->dataLength - pay_start);
936
937
0
  gf_free(samp->data);
938
0
  samp->data = NULL;
939
0
  gf_bs_get_content(bs, &samp->data, &samp->dataLength);
940
0
  gf_bs_del(bs);
941
0
  return GF_OK;
942
0
}
943
944
945
GF_Err gf_isom_text_get_encoded_tx3g(GF_ISOFile *file, u32 track, u32 sidx, u32 sidx_offset, u8 **tx3g, u32 *tx3g_size)
946
0
{
947
0
  GF_BitStream *bs;
948
0
  GF_TrackBox *trak;
949
0
  GF_Tx3gSampleEntryBox *a;
950
951
0
  *tx3g = NULL;
952
0
  *tx3g_size = 0;
953
0
  trak = gf_isom_get_track_from_file(file, track);
954
0
  if (!trak) return GF_BAD_PARAM;
955
956
0
  a = (GF_Tx3gSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, sidx-1);
957
0
  if (!a) return GF_BAD_PARAM;
958
0
  if ((a->type != GF_ISOM_BOX_TYPE_TX3G) && (a->type != GF_ISOM_BOX_TYPE_TEXT)) return GF_BAD_PARAM;
959
960
0
  bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
961
0
  gf_isom_write_tx3g(a, bs, sidx, sidx_offset);
962
0
  gf_bs_get_content(bs, tx3g, tx3g_size);
963
0
  gf_bs_del(bs);
964
0
  return GF_OK;
965
0
}
966
967
GF_Err gf_isom_set_forced_text(GF_ISOFile *file, u32 track, u32 stsd_idx, u32 flags)
968
0
{
969
0
  GF_TrackBox *trak;
970
0
  GF_Tx3gSampleEntryBox *a;
971
972
0
  trak = gf_isom_get_track_from_file(file, track);
973
0
  if (!trak) return GF_BAD_PARAM;
974
975
0
  a = (GF_Tx3gSampleEntryBox *) gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, stsd_idx-1);
976
0
  if (!a) return GF_BAD_PARAM;
977
0
  if ((a->type != GF_ISOM_BOX_TYPE_TX3G) && (a->type != GF_ISOM_BOX_TYPE_TEXT)) return GF_BAD_PARAM;
978
979
0
  switch (flags) {
980
0
  case 2:
981
0
    a->displayFlags |= GF_TXT_SOME_SAMPLES_FORCED | GF_TXT_ALL_SAMPLES_FORCED;
982
0
    break;
983
0
  case 1:
984
0
    a->displayFlags |= GF_TXT_SOME_SAMPLES_FORCED;
985
0
    a->displayFlags &= ~GF_TXT_ALL_SAMPLES_FORCED;
986
0
    break;
987
0
  default:
988
0
    a->displayFlags &= ~GF_TXT_SOME_SAMPLES_FORCED;
989
0
    a->displayFlags &= ~GF_TXT_ALL_SAMPLES_FORCED;
990
0
    break;
991
0
  }
992
0
  return GF_OK;
993
0
}
994
995
#endif /*GPAC_DISABLE_ISOM*/