MERGING TRUNK
[blender-staging.git] / extern / libredcode / format.c
1 #include <netinet/in.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "format.h"
6
7 struct red_reob {
8         unsigned long len;
9         char head[4];
10
11         unsigned long rdvo;
12         unsigned long rdvs;
13         unsigned long rdao;
14         unsigned long rdas;
15
16         unsigned long unknown1;
17         unsigned long unknown2;
18         unsigned long totlen;
19         
20         unsigned long avgv;
21         unsigned long avgs;
22
23         unsigned long unknown3;
24         unsigned long unknown4;
25         unsigned long unknown5;
26 };
27
28 struct redcode_handle {
29         FILE * fp;
30         struct red_reob * reob;
31         unsigned long * rdvo;
32         unsigned long * rdvs;
33         unsigned long * rdao;
34         unsigned long * rdas;
35         long cfra;
36 };
37
38
39 static unsigned char* read_packet(FILE * fp, char * expect)
40 {
41         unsigned long len;
42         char head[5];
43         unsigned char * rv;
44
45         fread(&len, 4, 1, fp);
46         fread(&head, 4, 1, fp);
47
48         head[4] = 0;
49
50         len = ntohl(len);
51
52         if (strcmp(expect, head) != 0) {
53                 fprintf(stderr, "Read: %s, expect: %s\n", head, expect);
54                 return NULL;
55         }
56
57         rv = (unsigned char*) malloc(len + 8);
58
59         memcpy(rv, &len, 4);
60         memcpy(rv + 4, &head, 4);
61         
62         fread(rv + 8, len, 1, fp);
63
64         return rv;
65 }
66
67 static unsigned long * read_index_packet(FILE * fp, char * expect)
68 {
69         unsigned long * rv = (unsigned long*) read_packet(fp, expect);
70         int i;
71
72         if (!rv) {
73                 return NULL;
74         }
75
76         for (i = 2; i < rv[0]/4; i++) {
77                 rv[i] = ntohl(rv[i]);
78         }
79         return rv;
80 }
81
82 static struct red_reob * read_reob(FILE * fp)
83 {
84         fseek(fp, -0x38, SEEK_END);
85
86         return (struct red_reob *) read_index_packet(fp, "REOB");
87 }
88
89 static unsigned long * read_index(FILE * fp, unsigned long i, char * expect)
90 {
91         fseek(fp, i, SEEK_SET);
92         
93         return (unsigned long*) read_index_packet(fp, expect);
94 }
95
96 static unsigned char * read_data(FILE * fp, unsigned long i, char * expect)
97 {
98         fseek(fp, i, SEEK_SET);
99         
100         return read_packet(fp, expect);
101 }
102
103 struct redcode_handle * redcode_open(const char * fname)
104 {
105         struct redcode_handle * rv = NULL;
106         struct red_reob * reob = NULL;
107
108         FILE * fp = fopen(fname, "rb");
109
110         if (!fp) {
111                 return NULL;
112         }
113
114         reob = read_reob(fp);
115         if (!reob) {
116                 fclose(fp);
117                 return NULL;
118         }
119
120         rv = (struct redcode_handle*) calloc(1, sizeof(struct redcode_handle));
121
122         rv->fp = fp;
123         rv->reob = reob;
124         rv->rdvo = read_index(fp, reob->rdvo, "RDVO");
125         rv->rdvs = read_index(fp, reob->rdvs, "RDVS");
126         rv->rdao = read_index(fp, reob->rdao, "RDAO");
127         rv->rdas = read_index(fp, reob->rdas, "RDAS");
128
129         if (!rv->rdvo || !rv->rdvs || !rv->rdao || !rv->rdas) {
130                 redcode_close(rv);
131                 return NULL;
132         }
133
134         return rv;
135 }
136
137 void redcode_close(struct redcode_handle * handle)
138 {
139         if (handle->reob) {
140                 free(handle->reob);
141         }
142         if (handle->rdvo) {
143                 free(handle->rdvo);
144         }
145         if (handle->rdvs) {
146                 free(handle->rdvs);
147         }
148         if (handle->rdao) {
149                 free(handle->rdao);
150         }
151         if (handle->rdas) {
152                 free(handle->rdas);
153         }
154         fclose(handle->fp);
155         free(handle);
156 }
157
158 long redcode_get_length(struct redcode_handle * handle)
159 {
160         return handle->rdvo[0]/4;
161 }
162
163 struct redcode_frame * redcode_read_video_frame(
164         struct redcode_handle * handle, long frame)
165 {
166         struct redcode_frame * rv;
167         unsigned char * data;
168
169         if (frame > handle->rdvo[0]/4 || handle->rdvo[frame + 2] == 0) {
170                 return NULL;
171         }
172         data = read_data(handle->fp, handle->rdvo[frame + 2], "REDV");
173         if (!data) {
174                 return NULL;
175         }
176
177         rv = (struct redcode_frame*) calloc(1, sizeof(struct redcode_frame));
178
179         rv->offset = 12+8;
180         rv->length = *(unsigned long*)data - rv->offset;
181         rv->data = data;
182
183         return rv;
184 }
185
186 struct redcode_frame * redcode_read_audio_frame(
187         struct redcode_handle * handle, long frame)
188 {
189         struct redcode_frame * rv;
190         unsigned char * data;
191
192         if (frame > handle->rdao[0]/4 || handle->rdao[frame + 2] == 0) {
193                 return NULL;
194         }
195         data = read_data(handle->fp, handle->rdao[frame+2], "REDA");
196         if (!data) {
197                 return NULL;
198         }
199
200         rv = (struct redcode_frame*) calloc(1, sizeof(struct redcode_frame));
201
202         rv->offset = 24+8;
203         rv->length = *(unsigned long*)data - rv->offset;
204         rv->data = data;
205
206         return rv;
207 }
208
209 void redcode_free_frame(struct redcode_frame * frame)
210 {
211         free(frame->data);
212         free(frame);
213 }