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