Mercurial > mplayer.hg
annotate libmpdemux/demux_lmlm4.c @ 27985:1c77b86d355d
Remove a ColorFill that is not necessary since the surface it is used
on has exactly the same size as the video image and the video will
be copied into it before it is used the first time.
author | reimar |
---|---|
date | Mon, 24 Nov 2008 09:46:23 +0000 |
parents | d4fe6e23283e |
children | d643e4643313 |
rev | line source |
---|---|
11590 | 1 /* |
2 LMLM4 MPEG4 Compression Card stream & file parser by Maxim Yevtyushkin <max@linuxmedialabs.com> | |
3 Based on SMJPEG file parser by Alex Beregszaszi | |
4 | |
5 */ | |
6 | |
7 #include <stdio.h> | |
8 #include <stdlib.h> | |
9 #include <unistd.h> | |
10 #include <string.h> /* strtok */ | |
11 | |
12 #include "config.h" | |
13 #include "mp_msg.h" | |
14 #include "help_mp.h" | |
15 | |
22605
4d81dbdf46b9
Add explicit location for headers from the stream/ directory.
diego
parents:
21421
diff
changeset
|
16 #include "stream/stream.h" |
11590 | 17 #include "demuxer.h" |
18 #include "stheader.h" | |
19 | |
25607
9d0b189ce1b2
Fix illegal identifiers: Names starting with __ or _ and uppercase are reserved
diego
parents:
24357
diff
changeset
|
20 typedef struct FrameInfo |
11590 | 21 { |
22 ssize_t frameSize; | |
23 ssize_t paddingSize; | |
24 int frameType; | |
25 int channelNo; | |
26 } FrameInfo; | |
27 | |
28 #define FRAMETYPE_I 0 | |
29 #define FRAMETYPE_P 1 | |
30 #define FRAMETYPE_B 2 | |
31 #define FRAMETYPE_AUDIO_MPEG1L2 4 | |
32 #define FRAMETYPE_AUDIO_ULAW 5 | |
33 #define FRAMETYPE_AUDIO_ADPCM 6 | |
34 | |
35 #define PACKET_BLOCK_SIZE 0x00000200 | |
36 #define PACKET_BLOCK_LAST 0x000001FF | |
37 #define PACKET_BLOCK_MASK 0xFFFFFE00 | |
38 | |
39 #define MAX_PACKET_SIZE 1048576 // 1 Mb | |
40 | |
41 #define STREAM_START_CODE_SIZE 4 | |
42 | |
43 /* | |
44 // codes in MSB first | |
45 static unsigned int start_code [] = | |
46 { | |
47 0xB0010000, // VISUAL_OBJECT_SEQUENCE_START_CODE | |
48 0xB6010000, // VOP_START_CODE | |
49 0x04C4FDFF, // MPEG1LAYERII_START_CODE | |
50 0x00000000 // end of start codes list | |
51 }; | |
52 */ | |
53 | |
54 static int imeHeaderValid(FrameInfo *frame) | |
55 { | |
56 if ( frame->channelNo > 7 || | |
57 frame->frameSize > MAX_PACKET_SIZE || frame->frameSize <= 0) | |
58 { | |
59 mp_msg(MSGT_DEMUX, MSGL_V, "Invalid packet in LMLM4 stream: ch=%d size=%d\n", frame->channelNo, frame->frameSize); | |
60 return 0; | |
61 } | |
62 switch (frame->frameType) { | |
63 case FRAMETYPE_I: | |
64 case FRAMETYPE_P: | |
65 case FRAMETYPE_B: | |
66 case FRAMETYPE_AUDIO_MPEG1L2: | |
67 case FRAMETYPE_AUDIO_ULAW: | |
68 case FRAMETYPE_AUDIO_ADPCM: | |
69 break; | |
70 default: | |
71 mp_msg(MSGT_DEMUX, MSGL_V, "Invalid packet in LMLM4 stream (wrong packet type %d)\n", frame->frameType); | |
72 return 0; | |
73 } | |
74 return 1; | |
75 } | |
76 | |
77 /* | |
78 int searchMPEG4Stream(demuxer_t* demuxer, IME6400Header *imeHeader) | |
79 { | |
80 void *data; | |
81 ssize_t imeHeaderSize = sizeof(IME6400Header); | |
82 ssize_t dataSize = sizeof(IME6400Header) * 3; | |
83 ssize_t ptr = imeHeaderSize * 2; | |
84 int errNo, startCodeNo; | |
85 off_t pos; | |
86 | |
87 data = malloc(dataSize); | |
88 | |
89 imeHeaderSwap(imeHeader); | |
90 memcpy(data + imeHeaderSize, imeHeader, imeHeaderSize); | |
91 | |
92 // printHex(data + imeHeaderSize, imeHeaderSize); | |
93 | |
94 while ((errNo = stream_read(demuxer->stream, data + imeHeaderSize * 2 , imeHeaderSize)) == imeHeaderSize) | |
95 { | |
96 // printHex(data + imeHeaderSize * 2, imeHeaderSize); | |
97 | |
98 pos = stream_tell(demuxer->stream); | |
99 while (dataSize - ptr >= STREAM_START_CODE_SIZE) { | |
100 startCodeNo = 0; | |
101 while (start_code[startCodeNo]) | |
102 { | |
103 if (memcmp(&start_code[startCodeNo], data + ptr, STREAM_START_CODE_SIZE) == 0) // start code match | |
104 { | |
105 memcpy(imeHeader, data + ptr - imeHeaderSize, imeHeaderSize); | |
106 imeHeaderSwap(imeHeader); | |
107 if (imeHeaderValid(imeHeader)) | |
108 { | |
109 stream_seek(demuxer->stream, pos - (dataSize - ptr)); | |
110 free(data); | |
111 return 0; | |
112 } | |
113 } | |
114 startCodeNo++; | |
115 } | |
116 ptr++; | |
117 } | |
118 memcpy(data,data + imeHeaderSize, imeHeaderSize * 2); | |
119 ptr -= imeHeaderSize; | |
120 } | |
121 | |
122 free(data); | |
123 return errNo; | |
124 } | |
125 */ | |
126 | |
127 static int getFrame(demuxer_t *demuxer, FrameInfo *frameInfo) | |
128 { | |
129 unsigned int packetSize; | |
130 | |
131 frameInfo->channelNo = stream_read_word(demuxer->stream); | |
132 frameInfo->frameType = stream_read_word(demuxer->stream); | |
133 packetSize=stream_read_dword(demuxer->stream); | |
134 | |
135 if(stream_eof(demuxer->stream)){ | |
136 frameInfo->frameSize = 0; | |
137 return 0; | |
138 } | |
139 | |
140 frameInfo->frameSize = packetSize - 8; //sizeof(IME6400Header); | |
141 frameInfo->paddingSize = (packetSize & PACKET_BLOCK_LAST) ? PACKET_BLOCK_SIZE - (packetSize & PACKET_BLOCK_LAST) : 0; | |
142 | |
143 mp_msg(MSGT_DEMUX, MSGL_DBG2, "typ: %d chan: %d size: %d pad: %d\n", | |
144 frameInfo->frameType, | |
145 frameInfo->channelNo, | |
146 frameInfo->frameSize, | |
147 frameInfo->paddingSize); | |
148 | |
149 if(!imeHeaderValid(frameInfo)){ | |
150 // skip this packet | |
151 stream_skip(demuxer->stream,PACKET_BLOCK_SIZE-8); | |
152 frameInfo->frameSize = 0; | |
153 return -1; | |
154 } | |
155 | |
156 return 1; | |
157 } | |
158 | |
16175 | 159 static int lmlm4_check_file(demuxer_t* demuxer) |
11590 | 160 { |
161 FrameInfo frameInfo; | |
162 unsigned int first; | |
163 | |
164 mp_msg(MSGT_DEMUX, MSGL_V, "Checking for LMLM4 Stream Format\n"); | |
165 | |
166 if(getFrame(demuxer, &frameInfo)!=1){ | |
167 stream_skip(demuxer->stream,-8); | |
11790 | 168 mp_msg(MSGT_DEMUX, MSGL_V, "LMLM4 Stream Format not found\n"); |
11590 | 169 return 0; |
170 } | |
171 first=stream_read_dword(demuxer->stream); | |
172 stream_skip(demuxer->stream,-12); | |
173 | |
174 mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: first=0x%08X\n",first); | |
175 | |
176 switch(frameInfo.frameType){ | |
177 case FRAMETYPE_AUDIO_MPEG1L2: | |
178 if( (first & 0xffe00000) != 0xffe00000 ){ | |
179 mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: not mpeg audio\n"); | |
180 return 0; | |
181 } | |
182 if((4-((first>>17)&3))!=2){ | |
183 mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: not layer-2\n"); | |
184 return 0; | |
185 } | |
186 if(((first>>10)&0x3)==3){ | |
187 mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: invalid audio sampelrate\n"); | |
188 return 0; | |
189 } | |
190 mp_msg(MSGT_DEMUXER,MSGL_V,"LMLM4: first packet is audio, header checks OK!\n"); | |
191 break; | |
192 // TODO: add checks for video header too, for case of disabled audio | |
193 } | |
194 | |
195 | |
196 // stream_reset(demuxer->stream); | |
197 mp_msg(MSGT_DEMUX, MSGL_V, "LMLM4 Stream Format found\n"); | |
198 | |
16175 | 199 return DEMUXER_TYPE_LMLM4; |
11590 | 200 } |
201 | |
202 static int video = 0; | |
203 static int frames= 0; | |
204 | |
205 // return value: | |
206 // 0 = EOF or no stream found | |
207 // 1 = successfully read a packet | |
16175 | 208 static int demux_lmlm4_fill_buffer(demuxer_t *demux, demux_stream_t *ds) |
11590 | 209 { |
210 FrameInfo frameInfo; | |
211 double pts; | |
212 int id=1; | |
213 int ret; | |
214 | |
24357 | 215 //hdr: |
11590 | 216 demux->filepos = stream_tell(demux->stream); |
17366 | 217 mp_msg(MSGT_DEMUX, MSGL_DBG2, "fpos = %"PRId64"\n", (int64_t)demux->filepos); |
11590 | 218 |
219 ret=getFrame(demux, &frameInfo); | |
220 if(ret<=0) return ret; // EOF/error | |
221 | |
222 pts=demux->video->sh ? frames*((sh_video_t*)(demux->video->sh))->frametime : 0; | |
223 | |
224 switch(frameInfo.frameType){ | |
225 case FRAMETYPE_AUDIO_MPEG1L2: | |
226 mp_dbg(MSGT_DEMUX, MSGL_DBG2, "Audio Packet\n"); | |
227 if (!video) | |
228 { | |
229 stream_skip(demux->stream, frameInfo.frameSize + frameInfo.paddingSize); | |
230 mp_msg(MSGT_DEMUX, MSGL_V, "Skip Audio Packet\n"); | |
231 return -1; //goto hdr; | |
232 } | |
233 if(demux->audio->id==-1){ | |
234 if(!demux->a_streams[id]) new_sh_audio(demux,id); | |
235 demux->audio->id=id; | |
236 demux->audio->sh=demux->a_streams[id]; | |
237 ((sh_audio_t*)(demux->audio->sh))->format=0x50; // mpeg audio layer 1/2 | |
238 } | |
239 if(demux->audio->id==id) | |
240 ds_read_packet(demux->audio, demux->stream, frameInfo.frameSize, | |
241 pts, demux->filepos, 0); | |
242 else | |
243 stream_skip(demux->stream,frameInfo.frameSize); | |
244 break; | |
245 case FRAMETYPE_I: | |
246 if (!video) { | |
247 video = 1; | |
248 mp_dbg(MSGT_DEMUX, MSGL_DBG2, "First Video Packet\n"); | |
249 } | |
250 case FRAMETYPE_P: | |
251 frames=(frames+1)&(1024*1024-1); // wrap around at 4 hrs to avoid inaccurate float calculations | |
252 if (!video) | |
253 { | |
254 stream_skip(demux->stream, frameInfo.frameSize + frameInfo.paddingSize); | |
255 mp_msg(MSGT_DEMUX, MSGL_V, "Skip Video P Packet\n"); | |
256 return -1; //goto hdr; | |
257 } | |
258 mp_dbg(MSGT_DEMUX, MSGL_DBG2, "Video Packet\n"); | |
259 if(demux->video->id==-1){ | |
260 if(!demux->v_streams[id]) new_sh_video(demux,id); | |
261 demux->video->id=id; | |
262 demux->video->sh=demux->v_streams[id]; | |
263 ((sh_video_t*)(demux->video->sh))->format=0x10000004; // mpeg4-ES | |
264 } | |
265 if(demux->video->id==id) | |
266 ds_read_packet(demux->video, demux->stream, frameInfo.frameSize, | |
267 pts, demux->filepos, 0); | |
268 break; | |
269 default: | |
270 stream_skip(demux->stream,frameInfo.frameSize); | |
271 } | |
272 | |
273 stream_skip(demux->stream, frameInfo.paddingSize); | |
274 | |
275 return 1; | |
276 } | |
277 | |
16175 | 278 static demuxer_t* demux_open_lmlm4(demuxer_t* demuxer){ |
279 sh_audio_t *sh_audio=NULL; | |
280 sh_video_t *sh_video=NULL; | |
11590 | 281 |
282 #if 0 | |
283 sh_video_t* sh_video; | |
284 sh_audio_t* sh_audio; | |
285 unsigned int htype = 0, hleng; | |
286 int i = 0; | |
287 | |
288 sh_video = new_sh_video(demuxer, 0); | |
289 demuxer->video->sh = sh_video; | |
290 sh_video->ds = demuxer->video; | |
291 sh_video->disp_w = 640; | |
292 sh_video->disp_h = 480; | |
293 sh_video->format = mmioFOURCC('D','I','V','X'); | |
294 | |
295 sh_video->bih = malloc(sizeof(BITMAPINFOHEADER)); | |
296 memset(sh_video->bih, 0, sizeof(BITMAPINFOHEADER)); | |
297 | |
298 /* these are false values */ | |
299 sh_video->bih->biSize = 40; | |
300 sh_video->bih->biWidth = sh_video->disp_w; | |
301 sh_video->bih->biHeight = sh_video->disp_h; | |
302 sh_video->bih->biPlanes = 3; | |
303 sh_video->bih->biBitCount = 16; | |
304 sh_video->bih->biCompression = sh_video->format; | |
305 sh_video->bih->biSizeImage = sh_video->disp_w*sh_video->disp_h; | |
306 | |
307 sh_audio = new_sh_audio(demuxer, 0); | |
308 demuxer->audio->sh = sh_audio; | |
309 sh_audio->ds = demuxer->audio; | |
310 | |
311 sh_audio->wf = malloc(sizeof(WAVEFORMATEX)); | |
312 memset(sh_audio->wf, 0, sizeof(WAVEFORMATEX)); | |
313 | |
314 sh_audio->samplerate = 48000; | |
315 sh_audio->wf->wBitsPerSample = 16; | |
316 sh_audio->channels = 2; | |
317 sh_audio->format = 0x50; | |
318 sh_audio->wf->wFormatTag = sh_audio->format; | |
319 sh_audio->wf->nChannels = sh_audio->channels; | |
320 sh_audio->wf->nSamplesPerSec = sh_audio->samplerate; | |
321 sh_audio->wf->nAvgBytesPerSec = sh_audio->wf->nChannels* | |
322 sh_audio->wf->wBitsPerSample*sh_audio->wf->nSamplesPerSec/8; | |
323 sh_audio->wf->nBlockAlign = sh_audio->channels *2; | |
324 sh_audio->wf->cbSize = 0; | |
325 | |
326 #endif | |
327 | |
328 demuxer->seekable = 0; | |
329 | |
16175 | 330 if(!ds_fill_buffer(demuxer->video)){ |
331 mp_msg(MSGT_DEMUXER,MSGL_INFO,"LMLM4: " MSGTR_MissingVideoStream); | |
332 demuxer->video->sh=NULL; | |
333 } else { | |
334 sh_video=demuxer->video->sh;sh_video->ds=demuxer->video; | |
335 } | |
336 if(demuxer->audio->id!=-2) { | |
337 if(!ds_fill_buffer(demuxer->audio)){ | |
338 mp_msg(MSGT_DEMUXER,MSGL_INFO,"LMLM4: " MSGTR_MissingAudioStream); | |
339 demuxer->audio->sh=NULL; | |
340 } else { | |
341 sh_audio=demuxer->audio->sh;sh_audio->ds=demuxer->audio; | |
342 } | |
343 } | |
11590 | 344 |
16175 | 345 return demuxer; |
11590 | 346 } |
347 | |
16175 | 348 static void demux_close_lmlm4(demuxer_t *demuxer) |
11590 | 349 { |
350 // printf("Close LMLM4 Stream\n"); | |
351 return; | |
352 } | |
16175 | 353 |
354 | |
25707
d4fe6e23283e
Make all demuxer_desc_t const, thus moving them to .rodata
reimar
parents:
25607
diff
changeset
|
355 const demuxer_desc_t demuxer_desc_lmlm4 = { |
16175 | 356 "LMLM4 MPEG4 Compression Card stream demuxer", |
357 "lmlm4", | |
358 "RAW LMLM4", | |
359 "Maxim Yevtyushkin", | |
360 "", | |
361 DEMUXER_TYPE_LMLM4, | |
362 0, // unsafe autodetect | |
363 lmlm4_check_file, | |
364 demux_lmlm4_fill_buffer, | |
365 demux_open_lmlm4, | |
366 demux_close_lmlm4, | |
367 NULL, | |
368 NULL | |
369 }; |