Blender V2.61 - r43446

indexer_dv.c

Go to the documentation of this file.
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 }