Fix msvc 2013 compiler errors after the ingenious cleanup in 4ca67869cc7a.
[blender.git] / source / blender / imbuf / intern / indexer_dv.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * Peter Schlaile <peter [at] schlaile [dot] de> 2011
19  *
20  * Contributor(s): none yet.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 /** \file blender/imbuf/intern/indexer_dv.c
26  *  \ingroup imbuf
27  */
28
29 #include "MEM_guardedalloc.h"
30
31 #include "BLI_utildefines.h"
32 #include "BLI_path_util.h"
33
34 #include "IMB_indexer.h"
35 #include <time.h>
36
37 typedef struct indexer_dv_bitstream {
38         unsigned char *buffer;
39         int bit_pos;
40 } indexer_dv_bitstream;
41
42 static indexer_dv_bitstream bitstream_new(unsigned char *buffer_)
43 {
44         indexer_dv_bitstream rv;
45
46         rv.buffer = buffer_;
47         rv.bit_pos = 0;
48
49         return rv;
50 }
51
52 static unsigned long bitstream_get_bits(indexer_dv_bitstream *This, int num)
53 {
54         int byte_pos = This->bit_pos >> 3;
55         unsigned long i = 
56                 This->buffer[byte_pos] | (This->buffer[byte_pos + 1] << 8) |
57                 (This->buffer[byte_pos + 2] << 16) |
58                 (This->buffer[byte_pos + 3] << 24);
59         int rval = (i >> (This->bit_pos & 0x7)) & ((1 << num) - 1);
60         This->bit_pos += num;
61         return rval;
62 }
63
64 static int parse_num(indexer_dv_bitstream *b, int numbits)
65 {
66         return bitstream_get_bits(b, numbits);
67 }
68
69 static int parse_bcd(indexer_dv_bitstream *b, int n)
70 {
71         char s[256];
72         char *p = s + (n + 3) / 4;
73
74         *p-- = 0;
75
76         while (n > 4) {
77                 char a;
78                 int v = bitstream_get_bits(b, 4);
79
80                 n -= 4;
81                 a = '0' + v;
82
83                 if (a > '9') {
84                         bitstream_get_bits(b, n);
85                         return -1;
86                 }
87
88                 *p-- = a;
89         }
90         if (n) {
91                 char a;
92                 int v = bitstream_get_bits(b, n);
93                 a = '0' + v;
94                 if (a > '9') {
95                         return -1;
96                 }
97                 *p-- = a;
98         }
99
100         return atol(s);
101 }
102
103 typedef struct indexer_dv_context {
104         int rec_curr_frame;
105         int rec_curr_second;
106         int rec_curr_minute;
107         int rec_curr_hour;
108
109         int rec_curr_day;
110         int rec_curr_month;
111         int rec_curr_year;
112
113         char got_record_date;
114         char got_record_time;
115
116         time_t ref_time_read;
117         time_t ref_time_read_new;
118         int curr_frame;
119
120         time_t gap_start;
121         int gap_frame;
122
123         int frameno_offset;
124
125         anim_index_entry backbuffer[31];
126         int fsize;
127
128         anim_index_builder *idx;
129 } indexer_dv_context;
130
131 static void parse_packet(indexer_dv_context *This, unsigned char *p)
132 {
133         indexer_dv_bitstream b;
134         int type = p[0];
135
136         b = bitstream_new(p + 1);
137
138         switch (type) {
139                 case 0x62: /* Record date */
140                         parse_num(&b, 8);
141                         This->rec_curr_day = parse_bcd(&b, 6);
142                         parse_num(&b, 2);
143                         This->rec_curr_month = parse_bcd(&b, 5);
144                         parse_num(&b, 3);
145                         This->rec_curr_year = parse_bcd(&b, 8);
146                         if (This->rec_curr_year < 25) {
147                                 This->rec_curr_year += 2000;
148                         }
149                         else {
150                                 This->rec_curr_year += 1900;
151                         }
152                         This->got_record_date = 1;
153                         break;
154                 case 0x63: /* Record time */
155                         This->rec_curr_frame = parse_bcd(&b, 6);
156                         parse_num(&b, 2);
157                         This->rec_curr_second = parse_bcd(&b, 7);
158                         parse_num(&b, 1);
159                         This->rec_curr_minute = parse_bcd(&b, 7);
160                         parse_num(&b, 1);
161                         This->rec_curr_hour = parse_bcd(&b, 6);
162                         This->got_record_time = 1;
163                         break;
164         }
165 }
166
167 static void parse_header_block(indexer_dv_context *This, unsigned char *target)
168 {
169         int i;
170         for (i = 3; i < 80; i += 5) {
171                 if (target[i] != 0xff) {
172                         parse_packet(This, target + i);
173                 }
174         }
175 }
176
177 static void parse_subcode_blocks(
178         indexer_dv_context *This, unsigned char *target)
179 {
180         int i, j;
181
182         for (j = 0; j < 2; j++) {
183                 for (i = 3; i < 80; i += 5) {
184                         if (target[i] != 0xff) {
185                                 parse_packet(This, target + i);
186                         }
187                 }
188         }
189 }
190
191 static void parse_vaux_blocks(
192         indexer_dv_context *This, unsigned char *target)
193 {
194         int i, j;
195
196         for (j = 0; j < 3; j++) {
197                 for (i = 3; i < 80; i += 5) {
198                         if (target[i] != 0xff) {
199                                 parse_packet(This, target + i);
200                         }
201                 }
202                 target += 80;
203         }
204 }
205
206 static void parse_audio_headers(
207         indexer_dv_context *This, unsigned char *target)
208 {
209         int i;
210
211         for (i = 0; i < 9; i++) {
212                 if (target[3] != 0xff) {
213                         parse_packet(This, target + 3);
214                 }
215                 target += 16 * 80;
216         }
217 }
218
219 static void parse_frame(indexer_dv_context *This,
220                         unsigned char *framebuffer, int isPAL)
221 {
222         int numDIFseq = isPAL ? 12 : 10;
223         unsigned char *target = framebuffer;
224         int ds;
225
226         for (ds = 0; ds < numDIFseq; ds++) {
227                 parse_header_block(This, target);
228                 target +=   1 * 80;
229                 parse_subcode_blocks(This, target);
230                 target +=   2 * 80;
231                 parse_vaux_blocks(This, target);
232                 target +=   3 * 80;
233                 parse_audio_headers(This, target);
234                 target += 144 * 80;
235         }
236 }
237
238 static void inc_frame(int *frame, time_t *t, int isPAL)
239 {
240         if ((isPAL && *frame >= 25) || (!isPAL && *frame >= 30)) {
241                 fprintf(stderr, "Ouchie: inc_frame: invalid_frameno: %d\n",
242                         *frame);
243         }
244         (*frame)++;
245         if (isPAL && *frame >= 25) {
246                 (*t)++;
247                 *frame = 0;
248         }
249         else if (!isPAL && *frame >= 30) {
250                 (*t)++;
251                 *frame = 0;
252         }
253 }
254
255 static void write_index(indexer_dv_context *This, anim_index_entry *entry)
256 {
257         IMB_index_builder_add_entry(
258                 This->idx, entry->frameno + This->frameno_offset,
259                 entry->seek_pos, entry->seek_pos_dts, entry->pts);
260 }
261
262 static void fill_gap(indexer_dv_context *This, int isPAL)
263 {
264         int i;
265
266         for (i = 0; i < This->fsize; i++) {
267                 if (This->gap_start == This->ref_time_read &&
268                     This->gap_frame == This->curr_frame)
269                 {
270                         fprintf(stderr,
271                                 "indexer_dv::fill_gap: "
272                                 "can't seek backwards !\n");
273                         break;
274                 }
275                 inc_frame(&This->gap_frame, &This->gap_start, isPAL);
276         }
277
278         while (This->gap_start != This->ref_time_read ||
279                This->gap_frame != This->curr_frame)
280         {
281                 inc_frame(&This->gap_frame, &This->gap_start, isPAL);
282                 This->frameno_offset++;
283         }
284
285         for (i = 0; i < This->fsize; i++) {
286                 write_index(This, This->backbuffer + i);
287         }
288         This->fsize = 0;
289 }
290
291 static void proc_frame(indexer_dv_context *This,
292                        unsigned char *UNUSED(framebuffer), int isPAL)
293 {
294         struct tm recDate;
295         time_t t;
296
297         if (!This->got_record_date || !This->got_record_time) {
298                 return;
299         }
300
301         recDate.tm_sec = This->rec_curr_second;
302         recDate.tm_min = This->rec_curr_minute;
303         recDate.tm_hour = This->rec_curr_hour;
304         recDate.tm_mday = This->rec_curr_day;
305         recDate.tm_mon = This->rec_curr_month - 1;
306         recDate.tm_year = This->rec_curr_year - 1900;
307         recDate.tm_wday = -1;
308         recDate.tm_yday = -1;
309         recDate.tm_isdst = -1;
310         
311         t = mktime(&recDate);
312         if (t == -1) {
313                 return;
314         }
315
316         This->ref_time_read_new = t;
317
318         if (This->ref_time_read < 0) {
319                 This->ref_time_read = This->ref_time_read_new;
320                 This->curr_frame = 0;
321         }
322         else {
323                 if (This->ref_time_read_new - This->ref_time_read == 1) {
324                         This->curr_frame = 0;
325                         This->ref_time_read = This->ref_time_read_new;
326                         if (This->gap_frame >= 0) {
327                                 fill_gap(This, isPAL);
328                                 This->gap_frame = -1;
329                         }
330                 }
331                 else if (This->ref_time_read_new == This->ref_time_read) {
332                         /* do nothing */
333                 }
334                 else {
335                         This->gap_start = This->ref_time_read;
336                         This->gap_frame = This->curr_frame;
337                         This->ref_time_read = This->ref_time_read_new;
338                         This->curr_frame = -1;
339                 }
340         }
341 }
342
343 static void indexer_dv_proc_frame(anim_index_builder *idx,
344                                   unsigned char *buffer,
345                                   int UNUSED(data_size),
346                                   struct anim_index_entry *entry)
347 {
348         int isPAL;
349         
350         indexer_dv_context *This = (indexer_dv_context *) idx->private_data;
351
352         isPAL = (buffer[3] & 0x80);
353
354         This->got_record_date = false;
355         This->got_record_time = false;
356
357         parse_frame(This, buffer, isPAL);
358         proc_frame(This, buffer, isPAL);
359
360         if (This->curr_frame >= 0) {
361                 write_index(This, entry);
362                 inc_frame(&This->curr_frame, &This->ref_time_read, isPAL);
363         }
364         else {
365                 This->backbuffer[This->fsize++] = *entry;
366                 if (This->fsize >= 31) {
367                         int i;
368
369                         fprintf(stderr, "indexer_dv::indexer_dv_proc_frame: "
370                                 "backbuffer overrun, emergency flush");
371
372                         for (i = 0; i < This->fsize; i++) {
373                                 write_index(This, This->backbuffer + i);
374                         }
375                         This->fsize = 0;
376                 }
377         }
378 }
379
380 static void indexer_dv_delete(anim_index_builder *idx)
381 {
382         int i = 0;
383         indexer_dv_context *This = (indexer_dv_context *) idx->private_data;
384
385         for (i = 0; i < This->fsize; i++) {
386                 write_index(This, This->backbuffer + i);
387         }
388
389         MEM_freeN(This);
390 }
391
392 static void UNUSED_FUNCTION(IMB_indexer_dv_new)(anim_index_builder *idx)
393 {
394         indexer_dv_context *rv = MEM_callocN(
395                 sizeof(indexer_dv_context), "index_dv builder context");
396
397         rv->ref_time_read = -1;
398         rv->curr_frame = -1;
399         rv->gap_frame = -1;
400         rv->idx = idx;
401         
402         idx->private_data = rv;
403         idx->proc_frame = indexer_dv_proc_frame;
404         idx->delete_priv_data = indexer_dv_delete;
405 }