1 /*******************************************************************************
2  avi_ix.c
3 
4  libquicktime - A library for reading and writing quicktime/avi/mp4 files.
5  http://libquicktime.sourceforge.net
6 
7  Copyright (C) 2002 Heroine Virtual Ltd.
8  Copyright (C) 2002-2011 Members of the libquicktime project.
9 
10  This library is free software; you can redistribute it and/or modify it under
11  the terms of the GNU Lesser General Public License as published by the Free
12  Software Foundation; either version 2.1 of the License, or (at your option)
13  any later version.
14 
15  This library is distributed in the hope that it will be useful, but WITHOUT
16  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18  details.
19 
20  You should have received a copy of the GNU Lesser General Public License along
21  with this library; if not, write to the Free Software Foundation, Inc., 51
22  Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *******************************************************************************/
24 
25 #include "lqt_private.h"
26 #include <stdlib.h>
27 #include <string.h>
28 
make_tag(int number,char * tag)29 static char* make_tag(int number, char *tag)
30 {
31 	tag[0] = 'i';
32 	tag[1] = 'x';
33 	tag[2] = '0' + (number / 10);
34 	tag[3] = '0' + (number % 10);
35 	return tag;
36 }
37 
quicktime_new_ix(quicktime_t * file,quicktime_trak_t * trak,quicktime_strl_t * strl)38 quicktime_ix_t* quicktime_new_ix(quicktime_t *file,
39 	quicktime_trak_t *trak,
40 	quicktime_strl_t *strl)
41 {
42 	quicktime_ix_t *ix = calloc(1, sizeof(quicktime_ix_t));
43 	ix->base_offset = quicktime_position(file);
44 	make_tag(trak->tkhd.track_id - 1, ix->tag);
45 	ix->longs_per_entry = 2;
46 	ix->index_type = AVI_INDEX_OF_CHUNKS;
47 	memcpy(ix->chunk_id, strl->tag, 4);
48 	return ix;
49 }
50 
51 
quicktime_delete_ix(quicktime_ix_t * ix)52 void quicktime_delete_ix(quicktime_ix_t *ix)
53 {
54 	if(ix->table) free(ix->table);
55 	free(ix);
56 }
57 
quicktime_update_ixtable(quicktime_t * file,quicktime_trak_t * trak,int64_t offset,int size)58 void quicktime_update_ixtable(quicktime_t *file,
59 	quicktime_trak_t *trak,
60 	int64_t offset,
61 	int size)
62 {
63         quicktime_indx_t *indx = &trak->strl->indx;
64 
65         quicktime_ix_t *ix = indx->table[indx->table_size-1].ix;
66         quicktime_ixtable_t *ix_table;
67 
68 
69 /* Allocation */
70 	if(ix->table_size >= ix->table_allocation)
71 	{
72         int new_allocation = ix->table_allocation * 2;
73         if(new_allocation < 1) new_allocation = 1;
74         ix->table = realloc(ix->table, sizeof(quicktime_ixtable_t) * new_allocation);
75         memset(ix->table + ix->table_size, 0,
76                sizeof(quicktime_ixtable_t)*(new_allocation - ix->table_size));
77         ix->table_allocation = new_allocation;
78 	}
79 
80 /* Appendage */
81 	ix_table = &ix->table[ix->table_size++];
82 	ix_table->relative_offset = offset - ix->base_offset;
83         ix_table->size = size;
84 
85         if(!trak->mdia.minf.is_audio &&
86            trak->mdia.minf.stbl.stss.total_entries)
87           {
88           /* If bit 31 of the size is set, we have *no* keyframe */
89           ix_table->size |= 0x80000000;
90           }
91 }
92 
93 
quicktime_write_ix(quicktime_t * file,quicktime_trak_t * trak)94 void quicktime_write_ix(quicktime_t *file,
95                         quicktime_trak_t * trak)
96   {
97 	int i;
98         quicktime_strl_t *strl;
99         quicktime_indx_t *indx;
100         quicktime_ix_t   *ix;
101 
102         strl = trak->strl;
103         indx = &strl->indx;
104         ix = indx->table[indx->table_size-1].ix;
105 
106         quicktime_atom_write_header(file, &ix->atom, ix->tag);
107 
108 /* longs per entry */
109 	quicktime_write_int16_le(file, ix->longs_per_entry);
110 /* index sub type */
111 	quicktime_write_char(file, 0);
112 /* index type */
113 	quicktime_write_char(file, ix->index_type);
114 /* entries in use */
115 	quicktime_write_int32_le(file, ix->table_size);
116 /* chunk ID */
117 	quicktime_write_char32(file, ix->chunk_id);
118 /* base offset */
119 	quicktime_write_int64_le(file, ix->base_offset);
120 /* reserved */
121 	quicktime_write_int32_le(file, 0);
122 
123 /* table */
124 	for(i = 0; i < ix->table_size; i++)
125 	{
126 		quicktime_ixtable_t *table = &ix->table[i];
127 		quicktime_write_int32_le(file, table->relative_offset);
128 		quicktime_write_int32_le(file, table->size);
129 	}
130 
131 	quicktime_atom_write_footer(file, &ix->atom);
132 
133 
134 }
135 
quicktime_read_ix(quicktime_t * file,quicktime_ix_t * ix)136 void quicktime_read_ix(quicktime_t *file,
137 	quicktime_ix_t *ix)
138 {
139 	int i;
140 	quicktime_atom_t leaf_atom;
141 	quicktime_atom_read_header(file, &leaf_atom);
142 
143 	ix->longs_per_entry = quicktime_read_int16_le(file);
144 /* sub type */
145 	quicktime_read_char(file);
146 	ix->index_type = quicktime_read_char(file);
147 	ix->table_size = quicktime_read_int32_le(file);
148 	quicktime_read_char32(file, ix->chunk_id);
149 	ix->base_offset = quicktime_read_int64_le(file);
150 /* reserved */
151 	quicktime_read_int32_le(file);
152 
153 	ix->table = calloc(ix->table_size, sizeof(quicktime_ixtable_t));
154 
155 	for(i = 0; i < ix->table_size; i++)
156 	{
157 		quicktime_ixtable_t *ixtable = &ix->table[i];
158 		ixtable->relative_offset = quicktime_read_int32_le(file);
159 		ixtable->size = quicktime_read_int32_le(file);
160 	}
161 }
162 
quicktime_ix_dump(quicktime_ix_t * ix)163 void quicktime_ix_dump(quicktime_ix_t *ix)
164   {
165   int i;
166   lqt_dump("   table_size:      %d\n", ix->table_size);
167   lqt_dump("   longs_per_entry: %d\n", ix->longs_per_entry);
168   lqt_dump("   index_type:      %d\n", ix->index_type);
169   lqt_dump("   base_offset:     %"PRId64"\n", ix->base_offset);
170   lqt_dump("   tag:             %s\n", ix->tag);
171   lqt_dump("   chunk_id:        %s\n", ix->chunk_id);
172   for(i = 0; i < ix->table_size; i++)
173     {
174     lqt_dump("   off: %d, size: %d, k: %d\n", ix->table[i].relative_offset,
175            (ix->table[i].size & 0x7FFFFFFF),
176            !(ix->table[i].size & 0x80000000));
177     }
178   }
179