1 /*******************************************************************************
2  avi_idx1.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 
29 typedef struct
30   {
31   char tag[4];
32   int32_t flags;
33   int32_t offset;
34   int32_t size;
35   } avi_tag_t;
36 
37 
38 
quicktime_delete_idx1(quicktime_idx1_t * idx1)39 void quicktime_delete_idx1(quicktime_idx1_t *idx1)
40   {
41   if(idx1->table) free(idx1->table);
42   }
43 
quicktime_idx1_dump(quicktime_idx1_t * idx1)44 void quicktime_idx1_dump(quicktime_idx1_t *idx1)
45   {
46   int i;
47   lqt_dump("idx1\n");
48   for(i = 0; i < idx1->table_size; i++)
49     {
50     quicktime_idx1table_t *idx1table = idx1->table + i;
51     lqt_dump("  T: %c%c%c%c, F: %08x, O: %d, S: %d\n",
52              idx1table->tag[0],
53              idx1table->tag[1],
54              idx1table->tag[2],
55              idx1table->tag[3],
56              idx1table->flags,
57              idx1table->offset,
58              idx1table->size);
59     }
60 
61   }
62 
63 
quicktime_read_idx1(quicktime_t * file,quicktime_riff_t * riff,quicktime_atom_t * parent_atom)64 void quicktime_read_idx1(quicktime_t *file,
65                          quicktime_riff_t *riff,
66                          quicktime_atom_t *parent_atom)
67   {
68   int i;
69   quicktime_idx1_t *idx1 = &riff->idx1;
70 
71 
72   // Allocate table.
73   idx1->table_size = (parent_atom->end - quicktime_position(file)) / 16;
74 
75   if(idx1->table_size <= 0)
76     {
77     idx1->table_size = 0;
78     return;
79     }
80   idx1->table_allocation = idx1->table_size;
81   idx1->table = calloc(sizeof(quicktime_idx1table_t), idx1->table_size);
82 
83   // Store it in idx1 table now.
84   // Wait for full ix table discovery before converting to stco.
85   for(i = 0; i < idx1->table_size; i++)
86     {
87     quicktime_idx1table_t *idx1table = idx1->table + i;
88 
89     quicktime_read_data(file, (uint8_t*)(idx1table->tag), 4);
90     idx1table->flags = quicktime_read_int32_le(file);
91     idx1table->offset = quicktime_read_int32_le(file);
92     idx1table->size = quicktime_read_int32_le(file);
93     }
94 
95 
96 
97   }
98 
quicktime_write_idx1(quicktime_t * file,quicktime_idx1_t * idx1)99 void quicktime_write_idx1(quicktime_t *file,
100                           quicktime_idx1_t *idx1)
101   {
102   int i;
103   quicktime_idx1table_t *table = idx1->table;
104   int table_size = idx1->table_size;
105 
106 
107   // Write table
108   quicktime_atom_write_header(file, &idx1->atom, "idx1");
109 
110   for(i = 0; i < table_size; i++)
111     {
112     quicktime_idx1table_t *entry = &table[i];
113     quicktime_write_char32(file, entry->tag);
114     quicktime_write_int32_le(file, entry->flags);
115     quicktime_write_int32_le(file, entry->offset);
116     quicktime_write_int32_le(file, entry->size);
117     }
118 
119 
120   quicktime_atom_write_footer(file, &idx1->atom);
121   }
122 
quicktime_set_idx1_keyframe(quicktime_t * file,quicktime_trak_t * trak,int new_keyframe)123 void quicktime_set_idx1_keyframe(quicktime_t *file,
124                                  quicktime_trak_t *trak,
125                                  int new_keyframe)
126   {
127   quicktime_riff_t *riff = file->riff[0];
128   quicktime_hdrl_t *hdrl = &riff->hdrl;
129   quicktime_strl_t *strl = hdrl->strl[trak->tkhd.track_id - 1];
130   char *tag = strl->tag;
131   quicktime_idx1_t *idx1 = &riff->idx1;
132   int i;
133   int counter = -1;
134   // Search through entire index for right numbered tag.
135   // Since all the tracks are combined in the same index, this is unavoidable.
136   for(i = 0; i < idx1->table_size; i++)
137     {
138     quicktime_idx1table_t *idx1_table = &idx1->table[i];
139     if(!memcmp(idx1_table->tag, tag, 4))
140       {
141       counter++;
142       if(counter == new_keyframe)
143         {
144         idx1_table->flags |= AVI_KEYFRAME;
145         break;
146         }
147       }
148     }
149   }
150 
quicktime_update_idx1table(quicktime_t * file,quicktime_trak_t * trak,int offset,int size)151 void quicktime_update_idx1table(quicktime_t *file,
152                                 quicktime_trak_t *trak,
153                                 int offset,
154                                 int size)
155   {
156   quicktime_riff_t *riff = file->riff[0];
157   quicktime_strl_t *strl = trak->strl;
158   char *tag = strl->tag;
159   quicktime_idx1_t *idx1 = &riff->idx1;
160   quicktime_movi_t *movi = &riff->movi;
161   quicktime_idx1table_t *idx1_table;
162 #if 0
163   int keyframe_frame = idx1->table_size + 1;
164 
165   // Set flag for keyframe
166   for(i = stss->total_entries - 1; i >= 0; i--)
167     {
168     if(stss->table[i].sample == keyframe_frame)
169       {
170       flags |= AVI_KEYFRAME;
171       break;
172       }
173     else
174       if(stss->table[i].sample < keyframe_frame)
175         {
176         break;
177         }
178     }
179 #endif
180 
181   // Allocation
182   if(idx1->table_size >= idx1->table_allocation)
183     {
184     idx1->table_allocation += 1024;
185 
186     idx1->table = realloc(idx1->table, sizeof(*idx1->table) * idx1->table_allocation);
187     memset(idx1->table + idx1->table_size, 0,
188            sizeof(*idx1->table) * (idx1->table_allocation - idx1->table_size));
189     }
190 
191   // Appendage
192   idx1_table = &idx1->table[idx1->table_size];
193   memcpy(idx1_table->tag, tag, 4);
194 
195   if(trak->mdia.minf.is_audio ||
196      !trak->mdia.minf.stbl.stss.total_entries)
197     idx1_table->flags = AVI_KEYFRAME;
198   else
199     idx1_table->flags = 0;
200 
201   idx1_table->offset = offset - 8 - movi->atom.start;
202   idx1_table->size = size;
203   idx1->table_size++;
204   }
205 
206 
207 
208 
209