Mercurial > mplayer.hg
comparison libmpdemux/demux_viv.c @ 2687:8c75a9a639c1
vivo demuxer
author | arpi |
---|---|
date | Sun, 04 Nov 2001 16:57:09 +0000 |
parents | |
children | af8b2c0e4dad |
comparison
equal
deleted
inserted
replaced
2686:44ff6b5c7cea | 2687:8c75a9a639c1 |
---|---|
1 // VIVO file parser by A'rpi | |
2 | |
3 #include <stdio.h> | |
4 #include <stdlib.h> | |
5 #include <unistd.h> | |
6 | |
7 #include "config.h" | |
8 #include "mp_msg.h" | |
9 #include "help_mp.h" | |
10 | |
11 #include "stream.h" | |
12 #include "demuxer.h" | |
13 #include "stheader.h" | |
14 | |
15 #include "bswap.h" | |
16 | |
17 typedef struct { | |
18 float fps; | |
19 } vivo_priv_t; | |
20 | |
21 int vivo_check_file(demuxer_t* demuxer){ | |
22 int flags=0; | |
23 int i=0; | |
24 int len; | |
25 int len2; | |
26 int c; | |
27 unsigned char buf[2048+256]; | |
28 vivo_priv_t* priv; | |
29 | |
30 mp_msg(MSGT_DEMUX,MSGL_V,"Checking for VIVO\n"); | |
31 | |
32 c=stream_read_char(demuxer->stream); | |
33 if(c) return 0; | |
34 len=0; | |
35 while((c=stream_read_char(demuxer->stream))>=0x80){ | |
36 len+=0x80*(c-0x80); | |
37 if(len>1024) return 0; | |
38 } | |
39 len+=c; | |
40 printf("header block 1 size: %d\n",len); | |
41 //stream_skip(demuxer->stream,len); | |
42 stream_read(demuxer->stream,buf,len); | |
43 buf[len]=0; | |
44 // printf("VIVO header: '%s'\n",buf); | |
45 | |
46 // parse header: | |
47 i=0; | |
48 while(i<len && buf[i]==0x0D && buf[i+1]==0x0A) i+=2; // skip empty lines | |
49 if(strncmp(buf+i,"Version:Vivo/1",14)) return 0; // bad version/type! | |
50 | |
51 priv=malloc(sizeof(vivo_priv_t)); | |
52 memset(priv,0,sizeof(vivo_priv_t)); | |
53 demuxer->priv=priv; | |
54 | |
55 // TODO: parse FPS and other info (display title/author etc) | |
56 priv->fps=10.0; // FIXME (parse from header) | |
57 | |
58 c=stream_read_char(demuxer->stream); | |
59 if(c) return 0; | |
60 len2=0; | |
61 while((c=stream_read_char(demuxer->stream))>=0x80){ | |
62 len2+=0x80*(c-0x80); | |
63 if(len+len2>2048) return 0; | |
64 } | |
65 len2+=c; | |
66 printf("header block 2 size: %d\n",len2); | |
67 stream_skip(demuxer->stream,len2); | |
68 // stream_read(demuxer->stream,buf+len,len2); | |
69 | |
70 // c=stream_read_char(demuxer->stream); | |
71 // printf("first packet: %02X\n",c); | |
72 | |
73 return 1; | |
74 } | |
75 | |
76 | |
77 // return value: | |
78 // 0 = EOF or no stream found | |
79 // 1 = successfully read a packet | |
80 int demux_vivo_fill_buffer(demuxer_t *demux){ | |
81 demux_stream_t *ds=NULL; | |
82 int c; | |
83 int len=0; | |
84 int seq; | |
85 demux->filepos=stream_tell(demux->stream); | |
86 | |
87 c=stream_read_char(demux->stream); | |
88 switch(c&0xF0){ | |
89 case 0x00: // header - skip it! | |
90 len=stream_read_char(demux->stream); | |
91 break; | |
92 case 0x10: // video packet | |
93 len=128; | |
94 ds=demux->video; | |
95 break; | |
96 case 0x20: // video packet | |
97 len=stream_read_char(demux->stream); | |
98 ds=demux->video; | |
99 break; | |
100 case 0x40: // audio packet | |
101 len=24; | |
102 ds=demux->audio; | |
103 break; | |
104 default: | |
105 mp_msg(MSGT_DEMUX,MSGL_WARN,"VIVO - unknown ID found: %02X contact author!\n",c); | |
106 } | |
107 | |
108 if(!ds){ | |
109 if(len) stream_skip(demux->stream,len); | |
110 return 1; | |
111 } | |
112 | |
113 seq=c&0x0F; | |
114 | |
115 if(ds->asf_packet){ | |
116 if(ds->asf_seq!=seq){ | |
117 // closed segment, finalize packet: | |
118 ds_add_packet(ds,ds->asf_packet); | |
119 ds->asf_packet=NULL; | |
120 } else { | |
121 // append data to it! | |
122 demux_packet_t* dp=ds->asf_packet; | |
123 dp->buffer=realloc(dp->buffer,dp->len+len); | |
124 //memcpy(dp->buffer+dp->len,data,len); | |
125 stream_read(demux->stream,dp->buffer+dp->len,len); | |
126 mp_dbg(MSGT_DEMUX,MSGL_DBG4,"data appended! %d+%d\n",dp->len,len); | |
127 dp->len+=len; | |
128 // we are ready now. | |
129 return 1; | |
130 } | |
131 } | |
132 // create new packet: | |
133 { demux_packet_t* dp; | |
134 dp=new_demux_packet(len); | |
135 //memcpy(dp->buffer,data,len); | |
136 stream_read(demux->stream,dp->buffer,len); | |
137 // dp->pts=time*0.001f; | |
138 // dp->flags=keyframe; | |
139 // if(ds==demux->video) printf("ASF time: %8d dur: %5d \n",time,dur); | |
140 dp->pos=demux->filepos; | |
141 ds->asf_packet=dp; | |
142 ds->asf_seq=seq; | |
143 // we are ready now. | |
144 return 1; | |
145 } | |
146 | |
147 } | |
148 | |
149 static const short h263_format[8][2] = { | |
150 { 0, 0 }, | |
151 { 128, 96 }, | |
152 { 176, 144 }, | |
153 { 352, 288 }, | |
154 { 704, 576 }, | |
155 { 1408, 1152 }, | |
156 }; | |
157 | |
158 static unsigned char* buffer; | |
159 static int bufptr=0; | |
160 static int bitcnt=0; | |
161 static unsigned char buf=0; | |
162 static int format, width, height; | |
163 | |
164 static unsigned int x_get_bits(int n){ | |
165 unsigned int x=0; | |
166 while(n-->0){ | |
167 if(!bitcnt){ | |
168 // fill buff | |
169 buf=buffer[bufptr++]; | |
170 bitcnt=8; | |
171 } | |
172 //x=(x<<1)|(buf&1);buf>>=1; | |
173 x=(x<<1)|(buf>>7);buf<<=1; | |
174 --bitcnt; | |
175 } | |
176 return x; | |
177 } | |
178 | |
179 #define get_bits(xxx,n) x_get_bits(n) | |
180 #define get_bits1(xxx) x_get_bits(1) | |
181 #define skip_bits(xxx,n) x_get_bits(n) | |
182 #define skip_bits1(xxx) x_get_bits(1) | |
183 | |
184 /* most is hardcoded. should extend to handle all h263 streams */ | |
185 static int h263_decode_picture_header(unsigned char *b_ptr) | |
186 { | |
187 | |
188 buffer=b_ptr; | |
189 bufptr=bitcnt=buf=0; | |
190 | |
191 /* picture header */ | |
192 if (get_bits(&s->gb, 22) != 0x20) | |
193 return -1; | |
194 skip_bits(&s->gb, 8); /* picture timestamp */ | |
195 | |
196 if (get_bits1(&s->gb) != 1) | |
197 return -1; /* marker */ | |
198 if (get_bits1(&s->gb) != 0) | |
199 return -1; /* h263 id */ | |
200 skip_bits1(&s->gb); /* split screen off */ | |
201 skip_bits1(&s->gb); /* camera off */ | |
202 skip_bits1(&s->gb); /* freeze picture release off */ | |
203 | |
204 format = get_bits(&s->gb, 3); | |
205 | |
206 if (format != 7) { | |
207 printf("h263_plus = 0 format = %d\n",format); | |
208 /* H.263v1 */ | |
209 width = h263_format[format][0]; | |
210 height = h263_format[format][1]; | |
211 printf("%d x %d\n",width,height); | |
212 if (!width) | |
213 return -1; | |
214 | |
215 printf("pict_type=%d\n",get_bits1(&s->gb)); | |
216 printf("unrestricted_mv=%d\n",get_bits1(&s->gb)); | |
217 #if 1 | |
218 printf("SAC: %d\n",get_bits1(&s->gb)); | |
219 printf("advanced prediction mode: %d\n",get_bits1(&s->gb)); | |
220 printf("PB frame: %d\n",get_bits1(&s->gb)); | |
221 #else | |
222 if (get_bits1(&s->gb) != 0) | |
223 return -1; /* SAC: off */ | |
224 if (get_bits1(&s->gb) != 0) | |
225 return -1; /* advanced prediction mode: off */ | |
226 if (get_bits1(&s->gb) != 0) | |
227 return -1; /* not PB frame */ | |
228 #endif | |
229 printf("qscale=%d\n",get_bits(&s->gb, 5)); | |
230 skip_bits1(&s->gb); /* Continuous Presence Multipoint mode: off */ | |
231 } else { | |
232 printf("h263_plus = 1\n"); | |
233 /* H.263v2 */ | |
234 if (get_bits(&s->gb, 3) != 1) | |
235 return -1; | |
236 if (get_bits(&s->gb, 3) != 6) /* custom source format */ | |
237 return -1; | |
238 skip_bits(&s->gb, 12); | |
239 skip_bits(&s->gb, 3); | |
240 printf("pict_type=%d\n",get_bits(&s->gb, 3) + 1); | |
241 // if (s->pict_type != I_TYPE && | |
242 // s->pict_type != P_TYPE) | |
243 // return -1; | |
244 skip_bits(&s->gb, 7); | |
245 skip_bits(&s->gb, 4); /* aspect ratio */ | |
246 width = (get_bits(&s->gb, 9) + 1) * 4; | |
247 skip_bits1(&s->gb); | |
248 height = get_bits(&s->gb, 9) * 4; | |
249 printf("%d x %d\n",width,height); | |
250 if (height == 0) | |
251 return -1; | |
252 printf("qscale=%d\n",get_bits(&s->gb, 5)); | |
253 } | |
254 | |
255 /* PEI */ | |
256 while (get_bits1(&s->gb) != 0) { | |
257 skip_bits(&s->gb, 8); | |
258 } | |
259 // s->f_code = 1; | |
260 // s->width = width; | |
261 // s->height = height; | |
262 return 0; | |
263 } | |
264 | |
265 | |
266 void demux_open_vivo(demuxer_t* demuxer){ | |
267 vivo_priv_t* priv=demuxer->priv; | |
268 | |
269 if(!ds_fill_buffer(demuxer->video)){ | |
270 mp_msg(MSGT_DEMUX,MSGL_ERR,"VIVO: " MSGTR_MissingVideoStreamBug); | |
271 return; | |
272 } | |
273 | |
274 h263_decode_picture_header(demuxer->video->buffer); | |
275 | |
276 | |
277 { sh_video_t* sh=new_sh_video(demuxer,0); | |
278 | |
279 sh->format=0x6f766976; // "vivo" | |
280 if(!sh->fps) sh->fps=priv->fps; | |
281 sh->frametime=1.0f/sh->fps; | |
282 sh->disp_w=width; // FIXME | |
283 sh->disp_h=height; | |
284 | |
285 // emulate BITMAPINFOHEADER: | |
286 sh->bih=malloc(sizeof(BITMAPINFOHEADER)); | |
287 memset(sh->bih,0,sizeof(BITMAPINFOHEADER)); | |
288 sh->bih->biSize=40; | |
289 sh->bih->biWidth=sh->disp_w; | |
290 sh->bih->biHeight=sh->disp_h; | |
291 sh->bih->biPlanes=1; | |
292 sh->bih->biBitCount=24; | |
293 sh->bih->biCompression=sh->format; | |
294 sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight*3; | |
295 demuxer->video->sh=sh; sh->ds=demuxer->video; | |
296 demuxer->video->id=0; | |
297 } | |
298 | |
299 if(!ds_fill_buffer(demuxer->audio)){ | |
300 mp_msg(MSGT_DEMUX,MSGL_ERR,"VIVO: " MSGTR_MissingAudioStream); | |
301 } else | |
302 { sh_audio_t* sh=new_sh_audio(demuxer,1); | |
303 sh->format=0x111; // 0x112 | |
304 // Emulate WAVEFORMATEX struct: | |
305 sh->wf=malloc(sizeof(WAVEFORMATEX)); | |
306 memset(sh->wf,0,sizeof(WAVEFORMATEX)); | |
307 sh->wf->nChannels=1; | |
308 sh->wf->wBitsPerSample=16; | |
309 sh->wf->nSamplesPerSec=22050; | |
310 sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8; | |
311 demuxer->audio->sh=sh; sh->ds=demuxer->audio; | |
312 demuxer->audio->id=1; | |
313 } | |
314 | |
315 | |
316 } | |
317 |