Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * Peter Schlaile <peter [at] schlaile [dot] de> 2011 00019 * 00020 * Contributor(s): none yet. 00021 * 00022 * ***** END GPL LICENSE BLOCK ***** 00023 */ 00024 00025 #include "IMB_indexer.h" 00026 #include "MEM_guardedalloc.h" 00027 #include "BLI_utildefines.h" 00028 #include <time.h> 00029 00030 typedef struct indexer_dv_bitstream { 00031 unsigned char* buffer; 00032 int bit_pos; 00033 } indexer_dv_bitstream; 00034 00035 static indexer_dv_bitstream bitstream_new(unsigned char* buffer_) 00036 { 00037 indexer_dv_bitstream rv; 00038 00039 rv.buffer = buffer_; 00040 rv.bit_pos = 0; 00041 00042 return rv; 00043 } 00044 00045 static unsigned long bitstream_get_bits(indexer_dv_bitstream * This, int num) 00046 { 00047 int byte_pos = This->bit_pos >> 3; 00048 unsigned long i = 00049 This->buffer[byte_pos] | (This->buffer[byte_pos + 1] << 8) | 00050 (This->buffer[byte_pos + 2] << 16) | 00051 (This->buffer[byte_pos + 3] << 24); 00052 int rval = (i >> (This->bit_pos & 0x7)) & ((1 << num) - 1); 00053 This->bit_pos += num; 00054 return rval; 00055 } 00056 00057 static int parse_num(indexer_dv_bitstream * b, int numbits) 00058 { 00059 return bitstream_get_bits(b, numbits); 00060 } 00061 00062 static int parse_bcd(indexer_dv_bitstream * b, int n) 00063 { 00064 char s[256]; 00065 char * p = s + (n+3)/4; 00066 00067 *p-- = 0; 00068 00069 while (n > 4) { 00070 char a; 00071 int v = bitstream_get_bits(b, 4); 00072 00073 n -= 4; 00074 a = '0' + v; 00075 00076 if (a > '9') { 00077 bitstream_get_bits(b, n); 00078 return -1; 00079 } 00080 00081 *p-- = a; 00082 } 00083 if (n) { 00084 char a; 00085 int v = bitstream_get_bits(b, n); 00086 a = '0' + v; 00087 if (a > '9') { 00088 return -1; 00089 } 00090 *p-- = a; 00091 } 00092 00093 return atol(s); 00094 } 00095 00096 typedef struct indexer_dv_context 00097 { 00098 int rec_curr_frame; 00099 int rec_curr_second; 00100 int rec_curr_minute; 00101 int rec_curr_hour; 00102 00103 int rec_curr_day; 00104 int rec_curr_month; 00105 int rec_curr_year; 00106 00107 char got_record_date; 00108 char got_record_time; 00109 00110 time_t ref_time_read; 00111 time_t ref_time_read_new; 00112 int curr_frame; 00113 00114 time_t gap_start; 00115 int gap_frame; 00116 00117 int frameno_offset; 00118 00119 anim_index_entry backbuffer[31]; 00120 int fsize; 00121 00122 anim_index_builder * idx; 00123 } indexer_dv_context; 00124 00125 static void parse_packet(indexer_dv_context * This, unsigned char * p) 00126 { 00127 indexer_dv_bitstream b; 00128 int type = p[0]; 00129 00130 b = bitstream_new(p + 1); 00131 00132 switch (type) { 00133 case 0x62: // Record date 00134 parse_num(&b, 8); 00135 This->rec_curr_day = parse_bcd(&b, 6); 00136 parse_num(&b, 2); 00137 This->rec_curr_month = parse_bcd(&b, 5); 00138 parse_num(&b, 3); 00139 This->rec_curr_year = parse_bcd(&b, 8); 00140 if (This->rec_curr_year < 25) { 00141 This->rec_curr_year += 2000; 00142 } else { 00143 This->rec_curr_year += 1900; 00144 } 00145 This->got_record_date = 1; 00146 break; 00147 case 0x63: // Record time 00148 This->rec_curr_frame = parse_bcd(&b, 6); 00149 parse_num(&b, 2); 00150 This->rec_curr_second = parse_bcd(&b, 7); 00151 parse_num(&b, 1); 00152 This->rec_curr_minute = parse_bcd(&b, 7); 00153 parse_num(&b, 1); 00154 This->rec_curr_hour = parse_bcd(&b, 6); 00155 This->got_record_time = 1; 00156 break; 00157 } 00158 } 00159 00160 static void parse_header_block(indexer_dv_context * This, unsigned char* target) 00161 { 00162 int i; 00163 for (i = 3; i < 80; i += 5) { 00164 if (target[i] != 0xff) { 00165 parse_packet(This, target + i); 00166 } 00167 } 00168 } 00169 00170 static void parse_subcode_blocks( 00171 indexer_dv_context * This, unsigned char* target) 00172 { 00173 int i,j; 00174 00175 for (j = 0; j < 2; j++) { 00176 for (i = 3; i < 80; i += 5) { 00177 if (target[i] != 0xff) { 00178 parse_packet(This, target + i); 00179 } 00180 } 00181 } 00182 } 00183 00184 static void parse_vaux_blocks( 00185 indexer_dv_context * This, unsigned char* target) 00186 { 00187 int i,j; 00188 00189 for (j = 0; j < 3; j++) { 00190 for (i = 3; i < 80; i += 5) { 00191 if (target[i] != 0xff) { 00192 parse_packet(This, target + i); 00193 } 00194 } 00195 target += 80; 00196 } 00197 } 00198 00199 static void parse_audio_headers( 00200 indexer_dv_context * This, unsigned char* target) 00201 { 00202 int i; 00203 00204 for(i = 0; i < 9; i++) { 00205 if (target[3] != 0xff) { 00206 parse_packet(This, target + 3); 00207 } 00208 target += 16 * 80; 00209 } 00210 } 00211 00212 static void parse_frame(indexer_dv_context * This, 00213 unsigned char * framebuffer, int isPAL) 00214 { 00215 int numDIFseq = isPAL ? 12 : 10; 00216 unsigned char* target = framebuffer; 00217 int ds; 00218 00219 for (ds = 0; ds < numDIFseq; ds++) { 00220 parse_header_block(This, target); 00221 target += 1 * 80; 00222 parse_subcode_blocks(This, target); 00223 target += 2 * 80; 00224 parse_vaux_blocks(This, target); 00225 target += 3 * 80; 00226 parse_audio_headers(This, target); 00227 target += 144 * 80; 00228 } 00229 } 00230 00231 static void inc_frame(int * frame, time_t * t, int isPAL) 00232 { 00233 if ((isPAL && *frame >= 25) || (!isPAL && *frame >= 30)) { 00234 fprintf(stderr, "Ouchie: inc_frame: invalid_frameno: %d\n", 00235 *frame); 00236 } 00237 (*frame)++; 00238 if (isPAL && *frame >= 25) { 00239 (*t)++; 00240 *frame = 0; 00241 } else if (!isPAL && *frame >= 30) { 00242 (*t)++; 00243 *frame = 0; 00244 } 00245 } 00246 00247 static void write_index(indexer_dv_context * This, anim_index_entry * entry) 00248 { 00249 IMB_index_builder_add_entry( 00250 This->idx, entry->frameno + This->frameno_offset, 00251 entry->seek_pos, entry->seek_pos_dts, entry->pts); 00252 } 00253 00254 static void fill_gap(indexer_dv_context * This, int isPAL) 00255 { 00256 int i; 00257 00258 for (i = 0; i < This->fsize; i++) { 00259 if (This->gap_start == This->ref_time_read && 00260 This->gap_frame == This->curr_frame) { 00261 fprintf(stderr, 00262 "indexer_dv::fill_gap: " 00263 "can't seek backwards !\n"); 00264 break; 00265 } 00266 inc_frame(&This->gap_frame, &This->gap_start, isPAL); 00267 } 00268 00269 while (This->gap_start != This->ref_time_read || 00270 This->gap_frame != This->curr_frame) { 00271 inc_frame(&This->gap_frame, &This->gap_start, isPAL); 00272 This->frameno_offset++; 00273 } 00274 00275 for (i = 0; i < This->fsize; i++) { 00276 write_index(This, This->backbuffer + i); 00277 } 00278 This->fsize = 0; 00279 } 00280 00281 static void proc_frame(indexer_dv_context * This, 00282 unsigned char* UNUSED(framebuffer), int isPAL) 00283 { 00284 struct tm recDate; 00285 time_t t; 00286 00287 if (!This->got_record_date || !This->got_record_time) { 00288 return; 00289 } 00290 00291 recDate.tm_sec = This->rec_curr_second; 00292 recDate.tm_min = This->rec_curr_minute; 00293 recDate.tm_hour = This->rec_curr_hour; 00294 recDate.tm_mday = This->rec_curr_day; 00295 recDate.tm_mon = This->rec_curr_month - 1; 00296 recDate.tm_year = This->rec_curr_year - 1900; 00297 recDate.tm_wday = -1; 00298 recDate.tm_yday = -1; 00299 recDate.tm_isdst = -1; 00300 00301 t = mktime(&recDate); 00302 if (t == -1) { 00303 return; 00304 } 00305 00306 This->ref_time_read_new = t; 00307 00308 if (This->ref_time_read < 0) { 00309 This->ref_time_read = This->ref_time_read_new; 00310 This->curr_frame = 0; 00311 } else { 00312 if (This->ref_time_read_new - This->ref_time_read == 1) { 00313 This->curr_frame = 0; 00314 This->ref_time_read = This->ref_time_read_new; 00315 if (This->gap_frame >= 0) { 00316 fill_gap(This, isPAL); 00317 This->gap_frame = -1; 00318 } 00319 } else if (This->ref_time_read_new == This->ref_time_read) { 00320 // do nothing 00321 } else { 00322 This->gap_start = This->ref_time_read; 00323 This->gap_frame = This->curr_frame; 00324 This->ref_time_read = This->ref_time_read_new; 00325 This->curr_frame = -1; 00326 } 00327 } 00328 } 00329 00330 static void indexer_dv_proc_frame(anim_index_builder * idx, 00331 unsigned char * buffer, 00332 int UNUSED(data_size), 00333 struct anim_index_entry * entry) 00334 { 00335 int isPAL; 00336 00337 indexer_dv_context * This = (indexer_dv_context *) idx->private_data; 00338 00339 isPAL = (buffer[3] & 0x80); 00340 00341 This->got_record_date = FALSE; 00342 This->got_record_time = FALSE; 00343 00344 parse_frame(This, buffer, isPAL); 00345 proc_frame(This, buffer, isPAL); 00346 00347 if (This->curr_frame >= 0) { 00348 write_index(This, entry); 00349 inc_frame(&This->curr_frame, &This->ref_time_read, isPAL); 00350 } else { 00351 This->backbuffer[This->fsize++] = *entry; 00352 if (This->fsize >= 31) { 00353 int i; 00354 00355 fprintf(stderr, "indexer_dv::indexer_dv_proc_frame: " 00356 "backbuffer overrun, emergency flush"); 00357 00358 for (i = 0; i < This->fsize; i++) { 00359 write_index(This, This->backbuffer+i); 00360 } 00361 This->fsize = 0; 00362 } 00363 } 00364 } 00365 00366 static void indexer_dv_delete(anim_index_builder * idx) 00367 { 00368 int i = 0; 00369 indexer_dv_context * This = (indexer_dv_context *) idx->private_data; 00370 00371 for (i = 0; i < This->fsize; i++) { 00372 write_index(This, This->backbuffer+i); 00373 } 00374 00375 MEM_freeN(This); 00376 } 00377 00378 void IMB_indexer_dv_new(anim_index_builder * idx) 00379 { 00380 indexer_dv_context * rv = MEM_callocN( 00381 sizeof(indexer_dv_context), "index_dv builder context"); 00382 00383 rv->ref_time_read = -1; 00384 rv->curr_frame = -1; 00385 rv->gap_frame = -1; 00386 rv->idx = idx; 00387 00388 idx->private_data = rv; 00389 idx->proc_frame = indexer_dv_proc_frame; 00390 idx->delete_priv_data = indexer_dv_delete; 00391 }