gst/matroska/ebml-read.c: Don't create unnecessary sub-buffers all the time. Dramatic...
[platform/upstream/gst-plugins-good.git] / gst / matroska / ebml-read.c
1 /* GStreamer EBML I/O
2  * (c) 2003 Ronald Bultje <rbultje@ronald.bitfreak.net>
3  *
4  * ebml-read.c: read EBML data from file/stream
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <string.h>
27
28 #include "ebml-read.h"
29 #include "ebml-ids.h"
30
31 GST_DEBUG_CATEGORY_STATIC (ebmlread_debug);
32 #define GST_CAT_DEFAULT ebmlread_debug
33
34 static void gst_ebml_read_class_init (GstEbmlReadClass * klass);
35 static void gst_ebml_read_init (GstEbmlRead * ebml);
36 static GstStateChangeReturn gst_ebml_read_change_state (GstElement * element,
37     GstStateChange transition);
38
39 /* convenience functions */
40 static gboolean gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size,
41     GstBuffer ** p_buf, guint8 ** bytes);
42 static gboolean gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size,
43     GstBuffer ** p_buf, guint8 ** bytes);
44
45
46 static GstElementClass *parent_class;   /* NULL */
47
48 GType
49 gst_ebml_read_get_type (void)
50 {
51   static GType gst_ebml_read_type;      /* 0 */
52
53   if (!gst_ebml_read_type) {
54     static const GTypeInfo gst_ebml_read_info = {
55       sizeof (GstEbmlReadClass),
56       NULL,
57       NULL,
58       (GClassInitFunc) gst_ebml_read_class_init,
59       NULL,
60       NULL,
61       sizeof (GstEbmlRead),
62       0,
63       (GInstanceInitFunc) gst_ebml_read_init,
64     };
65
66     gst_ebml_read_type =
67         g_type_register_static (GST_TYPE_ELEMENT, "GstEbmlRead",
68         &gst_ebml_read_info, 0);
69   }
70
71   return gst_ebml_read_type;
72 }
73
74 static void
75 gst_ebml_read_class_init (GstEbmlReadClass * klass)
76 {
77   GstElementClass *gstelement_class = (GstElementClass *) klass;
78
79   parent_class = g_type_class_peek_parent (klass);
80
81   GST_DEBUG_CATEGORY_INIT (ebmlread_debug, "ebmlread",
82       0, "EBML stream helper class");
83
84   gstelement_class->change_state =
85       GST_DEBUG_FUNCPTR (gst_ebml_read_change_state);
86 }
87
88 static void
89 gst_ebml_read_init (GstEbmlRead * ebml)
90 {
91   ebml->sinkpad = NULL;
92   ebml->level = NULL;
93 }
94
95 static GstStateChangeReturn
96 gst_ebml_read_change_state (GstElement * element, GstStateChange transition)
97 {
98   GstStateChangeReturn ret;
99   GstEbmlRead *ebml = GST_EBML_READ (element);
100
101   switch (transition) {
102     case GST_STATE_CHANGE_READY_TO_PAUSED:
103       if (!ebml->sinkpad) {
104         g_return_val_if_reached (GST_STATE_CHANGE_FAILURE);
105       }
106       break;
107     default:
108       break;
109   }
110
111   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
112
113   switch (transition) {
114     case GST_STATE_CHANGE_PAUSED_TO_READY:
115     {
116       g_list_foreach (ebml->level, (GFunc) g_free, NULL);
117       g_list_free (ebml->level);
118       ebml->level = NULL;
119       if (ebml->cached_buffer) {
120         gst_buffer_unref (ebml->cached_buffer);
121         ebml->cached_buffer = NULL;
122       }
123       ebml->offset = 0;
124       break;
125     }
126     default:
127       break;
128   }
129
130   return ret;
131 }
132
133 /*
134  * Return: the amount of levels in the hierarchy that the
135  * current element lies higher than the previous one.
136  * The opposite isn't done - that's auto-done using master
137  * element reading.
138  */
139
140 static guint
141 gst_ebml_read_element_level_up (GstEbmlRead * ebml)
142 {
143   guint num = 0;
144   guint64 pos = ebml->offset;
145
146   while (ebml->level != NULL) {
147     GList *last = g_list_last (ebml->level);
148     GstEbmlLevel *level = last->data;
149
150     if (pos >= level->start + level->length) {
151       ebml->level = g_list_remove (ebml->level, level);
152       g_free (level);
153       num++;
154     } else {
155       break;
156     }
157   }
158
159   return num;
160 }
161
162 /*
163  * Calls pull_range for (offset,size) without advancing our offset
164  */
165 static gboolean
166 gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
167     guint8 ** bytes)
168 {
169   GstFlowReturn ret;
170
171   /* Caching here actually makes much less difference than one would expect.
172    * We do it mainly to avoid pulling buffers of 1 byte all the time */
173   if (ebml->cached_buffer) {
174     guint64 cache_offset = GST_BUFFER_OFFSET (ebml->cached_buffer);
175     guint cache_size = GST_BUFFER_SIZE (ebml->cached_buffer);
176
177     if (cache_offset <= ebml->offset &&
178         (ebml->offset + size) < (cache_offset + cache_size)) {
179       if (p_buf)
180         *p_buf = gst_buffer_create_sub (ebml->cached_buffer,
181             ebml->offset - cache_offset, size);
182       if (bytes)
183         *bytes =
184             GST_BUFFER_DATA (ebml->cached_buffer) + ebml->offset - cache_offset;
185       return TRUE;
186     }
187     gst_buffer_unref (ebml->cached_buffer);
188     ebml->cached_buffer = NULL;
189   }
190
191   if (gst_pad_pull_range (ebml->sinkpad, ebml->offset, MAX (size, 64 * 1024),
192           &ebml->cached_buffer) == GST_FLOW_OK &&
193       GST_BUFFER_SIZE (ebml->cached_buffer) >= size) {
194     if (p_buf)
195       *p_buf = gst_buffer_create_sub (ebml->cached_buffer, 0, size);
196     if (bytes)
197       *bytes = GST_BUFFER_DATA (ebml->cached_buffer);
198     return TRUE;
199   }
200
201   if (!p_buf)
202     return FALSE;
203
204   ret = gst_pad_pull_range (ebml->sinkpad, ebml->offset, size, p_buf);
205   if (ret != GST_FLOW_OK) {
206     GST_DEBUG ("pull_range returned %d", ret);
207     return FALSE;
208   }
209
210   if (GST_BUFFER_SIZE (*p_buf) < size) {
211     GST_WARNING_OBJECT (ebml, "Dropping short buffer at offset %"
212         G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", ebml->offset,
213         size, GST_BUFFER_SIZE (*p_buf));
214     gst_buffer_unref (*p_buf);
215     *p_buf = NULL;
216     if (bytes)
217       *bytes = NULL;
218     return FALSE;
219   }
220
221   if (bytes)
222     *bytes = GST_BUFFER_DATA (*p_buf);
223
224   return TRUE;
225 }
226
227 /*
228  * Calls pull_range for (offset,size) and advances our offset by size
229  */
230 static gboolean
231 gst_ebml_read_pull_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf,
232     guint8 ** bytes)
233 {
234   if (!gst_ebml_read_peek_bytes (ebml, size, p_buf, bytes))
235     return FALSE;
236
237   ebml->offset += size;
238   return TRUE;
239 }
240
241 /*
242  * Read: the element content data ID.
243  * Return: FALSE on error.
244  */
245
246 static gboolean
247 gst_ebml_read_element_id (GstEbmlRead * ebml, guint32 * id, guint * level_up)
248 {
249   guint8 *buf;
250   gint len_mask = 0x80, read = 1, n = 1;
251   guint32 total;
252   guint8 b;
253
254   if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf))
255     return FALSE;
256
257   b = GST_READ_UINT8 (buf);
258
259   total = (guint32) b;
260
261   while (read <= 4 && !(total & len_mask)) {
262     read++;
263     len_mask >>= 1;
264   }
265   if (read > 4) {
266     guint64 pos = ebml->offset;
267
268     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
269         ("Invalid EBML ID size tag (0x%x) at position %llu (0x%llx)",
270             (guint) b, pos, pos));
271     return FALSE;
272   }
273
274   if (!gst_ebml_read_peek_bytes (ebml, read, NULL, &buf))
275     return FALSE;
276
277   while (n < read) {
278     b = GST_READ_UINT8 (buf + n);
279     total = (total << 8) | b;
280     ++n;
281   }
282
283   *id = total;
284
285   /* level */
286   if (level_up)
287     *level_up = gst_ebml_read_element_level_up (ebml);
288
289   ebml->offset += read;
290   return TRUE;
291 }
292
293 /*
294  * Read: element content length.
295  * Return: the number of bytes read or -1 on error.
296  */
297
298 static gint
299 gst_ebml_read_element_length (GstEbmlRead * ebml, guint64 * length)
300 {
301   guint8 *buf;
302   gint len_mask = 0x80, read = 1, n = 1, num_ffs = 0;
303   guint64 total;
304   guint8 b;
305
306   if (!gst_ebml_read_peek_bytes (ebml, 1, NULL, &buf))
307     return -1;
308
309   b = GST_READ_UINT8 (buf);
310
311   total = (guint64) b;
312
313   while (read <= 8 && !(total & len_mask)) {
314     read++;
315     len_mask >>= 1;
316   }
317   if (read > 8) {
318     guint64 pos = ebml->offset;
319
320     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
321         ("Invalid EBML length size tag (0x%x) at position %llu (0x%llx)",
322             (guint) b, pos, pos));
323     return -1;
324   }
325
326   if ((total &= (len_mask - 1)) == len_mask - 1)
327     num_ffs++;
328
329   if (!gst_ebml_read_peek_bytes (ebml, read, NULL, &buf))
330     return -1;
331
332   while (n < read) {
333     guint8 b = GST_READ_UINT8 (buf + n);
334
335     if (b == 0xff)
336       num_ffs++;
337     total = (total << 8) | b;
338     ++n;
339   }
340
341   if (read == num_ffs)
342     *length = G_MAXUINT64;
343   else
344     *length = total;
345
346   ebml->offset += read;
347
348   return read;
349 }
350
351 /*
352  * Return: the ID of the next element.
353  * Level_up contains the amount of levels that this
354  * next element lies higher than the previous one.
355  */
356
357 gboolean
358 gst_ebml_peek_id (GstEbmlRead * ebml, guint * level_up, guint32 * id)
359 {
360   guint64 off;
361
362   g_assert (level_up);
363
364   off = ebml->offset;           /* save offset */
365
366   if (!gst_ebml_read_element_id (ebml, id, level_up))
367     return FALSE;
368
369   ebml->offset = off;           /* restore offset */
370   return TRUE;
371 }
372
373 /*
374  * Return the length of the stream in bytes
375  */
376
377 gint64
378 gst_ebml_read_get_length (GstEbmlRead * ebml)
379 {
380   GstFormat fmt = GST_FORMAT_BYTES;
381   gint64 end;
382
383   if (!gst_pad_query_duration (GST_PAD_PEER (ebml->sinkpad), &fmt, &end))
384     g_return_val_if_reached (0);        ///// FIXME /////////
385
386   if (fmt != GST_FORMAT_BYTES || end < 0)
387     g_return_val_if_reached (0);        ///// FIXME /////////
388
389   return end;
390 }
391
392 /*
393  * Seek to a given offset.
394  */
395
396 gboolean
397 gst_ebml_read_seek (GstEbmlRead * ebml, guint64 offset)
398 {
399   if (offset >= gst_ebml_read_get_length (ebml))
400     return FALSE;
401
402   ebml->offset = offset;
403
404   return TRUE;
405 }
406
407 /*
408  * Skip the next element.
409  */
410
411 gboolean
412 gst_ebml_read_skip (GstEbmlRead * ebml)
413 {
414   guint64 length;
415   guint32 id;
416
417   if (!gst_ebml_read_element_id (ebml, &id, NULL))
418     return FALSE;
419
420   if (gst_ebml_read_element_length (ebml, &length) < 0)
421     return FALSE;
422
423   ebml->offset += length;
424   return TRUE;
425 }
426
427 /*
428  * Read the next element as a GstBuffer (binary).
429  */
430
431 gboolean
432 gst_ebml_read_buffer (GstEbmlRead * ebml, guint32 * id, GstBuffer ** buf)
433 {
434   guint64 length;
435
436   if (!gst_ebml_read_element_id (ebml, id, NULL))
437     return FALSE;
438
439   if (gst_ebml_read_element_length (ebml, &length) < 0)
440     return FALSE;
441
442   if (length == 0) {
443     *buf = gst_buffer_new ();
444     return TRUE;
445   }
446
447   *buf = NULL;
448   if (!gst_ebml_read_pull_bytes (ebml, (guint) length, buf, NULL))
449     return FALSE;
450
451   return TRUE;
452 }
453
454 /*
455  * Read the next element, return a pointer to it and its size.
456  */
457
458 static gboolean
459 gst_ebml_read_bytes (GstEbmlRead * ebml, guint32 * id, guint8 ** data,
460     guint * size)
461 {
462   guint64 length;
463
464   *size = 0;
465
466   if (!gst_ebml_read_element_id (ebml, id, NULL))
467     return FALSE;
468
469   if (gst_ebml_read_element_length (ebml, &length) < 0)
470     return FALSE;
471
472   if (length == 0) {
473     *data = NULL;
474     return TRUE;
475   }
476
477   *data = NULL;
478   if (!gst_ebml_read_pull_bytes (ebml, (guint) length, NULL, data))
479     return FALSE;
480
481   *size = (guint) length;
482
483   return TRUE;
484 }
485
486 /*
487  * Read the next element as an unsigned int.
488  */
489
490 gboolean
491 gst_ebml_read_uint (GstEbmlRead * ebml, guint32 * id, guint64 * num)
492 {
493   guint8 *data;
494   guint size;
495
496   if (!gst_ebml_read_bytes (ebml, id, &data, &size))
497     return FALSE;
498
499   if (size < 1 || size > 8) {
500     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
501         ("Invalid integer element size %d at position %llu (0x%llu)",
502             size, ebml->offset - size, ebml->offset - size));
503     return FALSE;
504   }
505   *num = 0;
506   while (size > 0) {
507     *num = (*num << 8) | *data;
508     size--;
509     data++;
510   }
511
512   return TRUE;
513 }
514
515 /*
516  * Read the next element as a signed int.
517  */
518
519 gboolean
520 gst_ebml_read_sint (GstEbmlRead * ebml, guint32 * id, gint64 * num)
521 {
522   guint8 *data;
523   guint size;
524   gboolean negative = 0;
525
526   if (!gst_ebml_read_bytes (ebml, id, &data, &size))
527     return FALSE;
528
529   if (size < 1 || size > 8) {
530     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
531         ("Invalid integer element size %d at position %llu (0x%llx)",
532             size, ebml->offset - size, ebml->offset - size));
533     return FALSE;
534   }
535
536   *num = 0;
537   if (*data & 0x80) {
538     negative = 1;
539     *num = *data & ~0x80;
540     size--;
541     data++;
542   }
543
544   while (size > 0) {
545     *num = (*num << 8) | *data;
546     size--;
547     data++;
548   }
549
550   /* make signed */
551   if (negative) {
552     *num = 0 - *num;
553   }
554
555   return TRUE;
556 }
557
558 /*
559  * Read the next element as a float.
560  */
561
562 gboolean
563 gst_ebml_read_float (GstEbmlRead * ebml, guint32 * id, gdouble * num)
564 {
565   guint8 *data;
566   guint size;
567
568   if (!gst_ebml_read_bytes (ebml, id, &data, &size))
569     return FALSE;
570
571   if (size != 4 && size != 8 && size != 10) {
572     GST_ELEMENT_ERROR (ebml, STREAM, DEMUX, (NULL),
573         ("Invalid float element size %d at position %llu (0x%llx)",
574             size, ebml->offset - size, ebml->offset - size));
575     return FALSE;
576   }
577
578   if (size == 10) {
579     GST_ELEMENT_ERROR (ebml, CORE, NOT_IMPLEMENTED, (NULL),
580         ("FIXME! 10-byte floats unimplemented"));
581     return FALSE;
582   }
583
584   if (size == 4) {
585     gfloat f;
586
587 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
588     f = *(gfloat *) data;
589 #else
590     while (size > 0) {
591       ((guint8 *) & f)[size - 1] = data[4 - size];
592       size--;
593     }
594 #endif
595
596     *num = f;
597   } else {
598     gdouble d;
599
600 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
601     d = *(gdouble *) data;
602 #else
603     while (size > 0) {
604       ((guint8 *) & d)[size - 1] = data[8 - size];
605       size--;
606     }
607 #endif
608
609     *num = d;
610   }
611
612   return TRUE;
613 }
614
615 /*
616  * Read the next element as an ASCII string.
617  */
618
619 gboolean
620 gst_ebml_read_ascii (GstEbmlRead * ebml, guint32 * id, gchar ** str)
621 {
622   guint8 *data;
623   guint size;
624
625   if (!gst_ebml_read_bytes (ebml, id, &data, &size))
626     return FALSE;
627
628   *str = g_malloc (size + 1);
629   memcpy (*str, data, size);
630   (*str)[size] = '\0';
631
632   return TRUE;
633 }
634
635 /*
636  * Read the next element as a UTF-8 string.
637  */
638
639 gboolean
640 gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str)
641 {
642   gboolean ret;
643
644 #ifndef GST_DISABLE_GST_DEBUG
645   guint64 oldoff = ebml->offset;
646 #endif
647
648   ret = gst_ebml_read_ascii (ebml, id, str);
649
650   if (str != NULL && *str != NULL && **str != '\0' &&
651       !g_utf8_validate (*str, -1, NULL)) {
652     GST_WARNING ("Invalid UTF-8 string at offset %" G_GUINT64_FORMAT, oldoff);
653   }
654
655   return ret;
656 }
657
658 /*
659  * Read the next element as a date.
660  * Returns the seconds since the unix epoch.
661  */
662
663 gboolean
664 gst_ebml_read_date (GstEbmlRead * ebml, guint32 * id, gint64 * date)
665 {
666   gint64 ebml_date;
667   gboolean res = gst_ebml_read_sint (ebml, id, &ebml_date);
668
669   *date = (ebml_date / GST_SECOND) + GST_EBML_DATE_OFFSET;
670   return res;
671 }
672
673 /*
674  * Read the next element, but only the header. The contents
675  * are supposed to be sub-elements which can be read separately.
676  */
677
678 gboolean
679 gst_ebml_read_master (GstEbmlRead * ebml, guint32 * id)
680 {
681   GstEbmlLevel *level;
682   guint64 length;
683
684   if (!gst_ebml_read_element_id (ebml, id, NULL))
685     return FALSE;
686
687   if (gst_ebml_read_element_length (ebml, &length) < 0)
688     return FALSE;
689
690   /* remember level */
691   level = g_new (GstEbmlLevel, 1);
692   level->start = ebml->offset;
693   level->length = length;
694   ebml->level = g_list_append (ebml->level, level);
695
696   return TRUE;
697 }
698
699 /*
700  * Read the next element as binary data.
701  */
702
703 gboolean
704 gst_ebml_read_binary (GstEbmlRead * ebml,
705     guint32 * id, guint8 ** binary, guint64 * length)
706 {
707   guint8 *data;
708   guint size;
709
710   if (!gst_ebml_read_bytes (ebml, id, &data, &size))
711     return FALSE;
712
713   *length = size;
714   *binary = g_memdup (data, size);
715
716   return TRUE;
717 }
718
719 /*
720  * Read an EBML header.
721  */
722
723 gboolean
724 gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version)
725 {
726   /* this function is the first to be called */
727   guint32 id;
728   guint level_up;
729
730   /* default init */
731   if (doctype)
732     *doctype = NULL;
733   if (version)
734     *version = 1;
735
736   if (!gst_ebml_peek_id (ebml, &level_up, &id))
737     return FALSE;
738
739   GST_DEBUG_OBJECT (ebml, "id: %08x", GST_READ_UINT32_BE (&id));
740
741   if (level_up != 0 || id != GST_EBML_ID_HEADER) {
742     GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL));
743     return FALSE;
744   }
745   if (!gst_ebml_read_master (ebml, &id))
746     return FALSE;
747
748   while (TRUE) {
749     if (!gst_ebml_peek_id (ebml, &level_up, &id))
750       return FALSE;
751
752     /* end-of-header */
753     if (level_up)
754       break;
755
756     switch (id) {
757         /* is our read version uptodate? */
758       case GST_EBML_ID_EBMLREADVERSION:{
759         guint64 num;
760
761         if (!gst_ebml_read_uint (ebml, &id, &num))
762           return FALSE;
763         g_assert (id == GST_EBML_ID_EBMLREADVERSION);
764         if (num != GST_EBML_VERSION)
765           return FALSE;
766         break;
767       }
768
769         /* we only handle 8 byte lengths at max */
770       case GST_EBML_ID_EBMLMAXSIZELENGTH:{
771         guint64 num;
772
773         if (!gst_ebml_read_uint (ebml, &id, &num))
774           return FALSE;
775         g_assert (id == GST_EBML_ID_EBMLMAXSIZELENGTH);
776         if (num != sizeof (guint64))
777           return FALSE;
778         break;
779       }
780
781         /* we handle 4 byte IDs at max */
782       case GST_EBML_ID_EBMLMAXIDLENGTH:{
783         guint64 num;
784
785         if (!gst_ebml_read_uint (ebml, &id, &num))
786           return FALSE;
787         g_assert (id == GST_EBML_ID_EBMLMAXIDLENGTH);
788         if (num != sizeof (guint32))
789           return FALSE;
790         break;
791       }
792
793       case GST_EBML_ID_DOCTYPE:{
794         gchar *text;
795
796         if (!gst_ebml_read_ascii (ebml, &id, &text))
797           return FALSE;
798         g_assert (id == GST_EBML_ID_DOCTYPE);
799         if (doctype) {
800           if (doctype)
801             g_free (*doctype);
802           *doctype = text;
803         } else
804           g_free (text);
805         break;
806       }
807
808       case GST_EBML_ID_DOCTYPEREADVERSION:{
809         guint64 num;
810
811         if (!gst_ebml_read_uint (ebml, &id, &num))
812           return FALSE;
813         g_assert (id == GST_EBML_ID_DOCTYPEREADVERSION);
814         if (version)
815           *version = num;
816         break;
817       }
818
819       default:
820         GST_WARNING ("Unknown data type 0x%x in EBML header (ignored)", id);
821         /* pass-through */
822
823         /* we ignore these two, as they don't tell us anything we care about */
824       case GST_EBML_ID_VOID:
825       case GST_EBML_ID_EBMLVERSION:
826       case GST_EBML_ID_DOCTYPEVERSION:
827         if (!gst_ebml_read_skip (ebml))
828           return FALSE;
829         break;
830     }
831   }
832
833   return TRUE;
834 }