1 /*******************************************************************************
2 stsc.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
quicktime_stsc_init(quicktime_stsc_t * stsc)28 void quicktime_stsc_init(quicktime_stsc_t *stsc)
29 {
30 stsc->version = 0;
31 stsc->flags = 0;
32 stsc->total_entries = 0;
33 stsc->entries_allocated = 0;
34 }
35
quicktime_stsc_init_table(quicktime_t * file,quicktime_stsc_t * stsc)36 void quicktime_stsc_init_table(quicktime_t *file, quicktime_stsc_t *stsc)
37 {
38 if(!stsc->entries_allocated)
39 {
40 stsc->total_entries = 1;
41 stsc->entries_allocated = 2048;
42 stsc->table = (quicktime_stsc_table_t*)calloc(1, sizeof(quicktime_stsc_table_t) * stsc->entries_allocated);
43 }
44 }
45
quicktime_stsc_init_video(quicktime_t * file,quicktime_stsc_t * stsc)46 void quicktime_stsc_init_video(quicktime_t *file, quicktime_stsc_t *stsc)
47 {
48 quicktime_stsc_table_t *table;
49 quicktime_stsc_init_table(file, stsc);
50 table = &stsc->table[0];
51 table->chunk = 1;
52 table->samples = 1;
53 table->id = 1;
54 }
55
quicktime_stsc_init_audio(quicktime_t * file,quicktime_stsc_t * stsc,int sample_rate)56 void quicktime_stsc_init_audio(quicktime_t *file, quicktime_stsc_t *stsc, int sample_rate)
57 {
58 quicktime_stsc_table_t *table;
59 quicktime_stsc_init_table(file, stsc);
60 table = &stsc->table[0];
61 table->chunk = 1;
62 table->samples = 0; /* set this after completion or after every audio chunk is written */
63 table->id = 1;
64 }
65
quicktime_stsc_delete(quicktime_stsc_t * stsc)66 void quicktime_stsc_delete(quicktime_stsc_t *stsc)
67 {
68 if(stsc->total_entries) free(stsc->table);
69 stsc->total_entries = 0;
70 }
71
quicktime_stsc_dump(quicktime_stsc_t * stsc)72 void quicktime_stsc_dump(quicktime_stsc_t *stsc)
73 {
74 int i;
75 lqt_dump(" sample to chunk (stsc)\n");
76 lqt_dump(" version %d\n", stsc->version);
77 lqt_dump(" flags %ld\n", stsc->flags);
78 lqt_dump(" total_entries %ld\n", stsc->total_entries);
79 for(i = 0; i < stsc->total_entries; i++)
80 {
81 lqt_dump(" chunk %ld samples %lx id %ld\n",
82 stsc->table[i].chunk, stsc->table[i].samples, stsc->table[i].id);
83 }
84 }
85
quicktime_read_stsc(quicktime_t * file,quicktime_stsc_t * stsc)86 void quicktime_read_stsc(quicktime_t *file, quicktime_stsc_t *stsc)
87 {
88 int i;
89 stsc->version = quicktime_read_char(file);
90 stsc->flags = quicktime_read_int24(file);
91 stsc->total_entries = quicktime_read_int32(file);
92
93 stsc->entries_allocated = stsc->total_entries;
94 stsc->table = (quicktime_stsc_table_t*)malloc(sizeof(quicktime_stsc_table_t) * stsc->total_entries);
95 for(i = 0; i < stsc->total_entries; i++)
96 {
97 stsc->table[i].chunk = quicktime_read_int32(file);
98 stsc->table[i].samples = quicktime_read_int32(file);
99 stsc->table[i].id = quicktime_read_int32(file);
100 }
101 }
102
quicktime_compress_stsc(quicktime_stsc_t * stsc)103 void quicktime_compress_stsc(quicktime_stsc_t *stsc)
104 {
105 int i, last_same;
106
107 /* This can happen, if a stream was created, but no
108 samples have been written. The resulting file will be
109 invalid anyway, just don't let us crash */
110
111 if(!stsc->table)
112 return;
113
114 for(i = 1, last_same = 0; i < stsc->total_entries; i++)
115 {
116 if(stsc->table[i].samples != stsc->table[last_same].samples)
117 {
118 /* An entry has a different sample count. */
119 last_same++;
120 if(last_same < i)
121 {
122 /* Move it up the list. */
123 stsc->table[last_same] = stsc->table[i];
124 }
125 }
126 }
127 last_same++;
128 stsc->total_entries = last_same;
129 }
130
quicktime_write_stsc(quicktime_t * file,quicktime_stsc_t * stsc)131 void quicktime_write_stsc(quicktime_t *file, quicktime_stsc_t *stsc)
132 {
133 int i;
134 quicktime_atom_t atom;
135
136 quicktime_atom_write_header(file, &atom, "stsc");
137
138 quicktime_write_char(file, stsc->version);
139 quicktime_write_int24(file, stsc->flags);
140 quicktime_write_int32(file, stsc->total_entries);
141 for(i = 0; i < stsc->total_entries; i++)
142 {
143 quicktime_write_int32(file, stsc->table[i].chunk);
144 quicktime_write_int32(file, stsc->table[i].samples);
145 quicktime_write_int32(file, stsc->table[i].id);
146 }
147
148 quicktime_atom_write_footer(file, &atom);
149 }
150
quicktime_update_stsc(quicktime_stsc_t * stsc,long chunk,long samples)151 int quicktime_update_stsc(quicktime_stsc_t *stsc, long chunk, long samples)
152 {
153 chunk++;
154 if(chunk > stsc->entries_allocated)
155 {
156 stsc->entries_allocated = chunk * 2;
157 stsc->table =(quicktime_stsc_table_t*)realloc(stsc->table, sizeof(quicktime_stsc_table_t) * stsc->entries_allocated);
158 }
159
160 stsc->table[chunk - 1].samples = samples;
161 stsc->table[chunk - 1].chunk = chunk;
162 stsc->table[chunk - 1].id = 1;
163 if(chunk > stsc->total_entries) stsc->total_entries = chunk;
164 return 0;
165 }
166
167 /* Optimizing while writing doesn't allow seeks during recording so */
168 /* entries are created for every chunk and only optimized during */
169 /* writeout. Unfortunately there's no way to keep audio synchronized */
170 /* after overwriting a recording as the fractional audio chunk in the */
171 /* middle always overwrites the previous location of a larger chunk. On */
172 /* writing, the table must be optimized. RealProducer requires an */
173 /* optimized table. */
174
175