2 * LMLM4 MPEG4 Compression Card stream & file parser
3 * Copyright (C) 2003 Maxim Yevtyushkin <max@linuxmedialabs.com>
4 * based on SMJPEG file parser by Alex Beregszaszi
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <string.h> /* strtok */
31 #include "stream/stream.h"
35 typedef struct FrameInfo
46 #define FRAMETYPE_AUDIO_MPEG1L2 4
47 #define FRAMETYPE_AUDIO_ULAW 5
48 #define FRAMETYPE_AUDIO_ADPCM 6
50 #define PACKET_BLOCK_SIZE 0x00000200
51 #define PACKET_BLOCK_LAST 0x000001FF
52 #define PACKET_BLOCK_MASK 0xFFFFFE00
54 #define MAX_PACKET_SIZE 1048576 // 1 Mb
56 #define STREAM_START_CODE_SIZE 4
60 static unsigned int start_code [] =
62 0xB0010000, // VISUAL_OBJECT_SEQUENCE_START_CODE
63 0xB6010000, // VOP_START_CODE
64 0x04C4FDFF, // MPEG1LAYERII_START_CODE
65 0x00000000 // end of start codes list
69 static int imeHeaderValid(FrameInfo
*frame
)
71 if ( frame
->channelNo
> 7 ||
72 frame
->frameSize
> MAX_PACKET_SIZE
|| frame
->frameSize
<= 0)
74 mp_msg(MSGT_DEMUX
, MSGL_V
, "Invalid packet in LMLM4 stream: ch=%d size=%d\n", frame
->channelNo
, frame
->frameSize
);
77 switch (frame
->frameType
) {
81 case FRAMETYPE_AUDIO_MPEG1L2
:
82 case FRAMETYPE_AUDIO_ULAW
:
83 case FRAMETYPE_AUDIO_ADPCM
:
86 mp_msg(MSGT_DEMUX
, MSGL_V
, "Invalid packet in LMLM4 stream (wrong packet type %d)\n", frame
->frameType
);
93 int searchMPEG4Stream(demuxer_t* demuxer, IME6400Header *imeHeader)
96 ssize_t imeHeaderSize = sizeof(IME6400Header);
97 ssize_t dataSize = sizeof(IME6400Header) * 3;
98 ssize_t ptr = imeHeaderSize * 2;
99 int errNo, startCodeNo;
102 data = malloc(dataSize);
104 imeHeaderSwap(imeHeader);
105 memcpy(data + imeHeaderSize, imeHeader, imeHeaderSize);
107 // printHex(data + imeHeaderSize, imeHeaderSize);
109 while ((errNo = stream_read(demuxer->stream, data + imeHeaderSize * 2 , imeHeaderSize)) == imeHeaderSize)
111 // printHex(data + imeHeaderSize * 2, imeHeaderSize);
113 pos = stream_tell(demuxer->stream);
114 while (dataSize - ptr >= STREAM_START_CODE_SIZE) {
116 while (start_code[startCodeNo])
118 if (memcmp(&start_code[startCodeNo], data + ptr, STREAM_START_CODE_SIZE) == 0) // start code match
120 memcpy(imeHeader, data + ptr - imeHeaderSize, imeHeaderSize);
121 imeHeaderSwap(imeHeader);
122 if (imeHeaderValid(imeHeader))
124 stream_seek(demuxer->stream, pos - (dataSize - ptr));
133 memcpy(data,data + imeHeaderSize, imeHeaderSize * 2);
134 ptr -= imeHeaderSize;
142 static int getFrame(demuxer_t
*demuxer
, FrameInfo
*frameInfo
)
144 unsigned int packetSize
;
146 frameInfo
->channelNo
= stream_read_word(demuxer
->stream
);
147 frameInfo
->frameType
= stream_read_word(demuxer
->stream
);
148 packetSize
=stream_read_dword(demuxer
->stream
);
150 if(stream_eof(demuxer
->stream
)){
151 frameInfo
->frameSize
= 0;
155 frameInfo
->frameSize
= packetSize
- 8; //sizeof(IME6400Header);
156 frameInfo
->paddingSize
= (packetSize
& PACKET_BLOCK_LAST
) ? PACKET_BLOCK_SIZE
- (packetSize
& PACKET_BLOCK_LAST
) : 0;
158 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "typ: %d chan: %d size: %d pad: %d\n",
159 frameInfo
->frameType
,
160 frameInfo
->channelNo
,
161 frameInfo
->frameSize
,
162 frameInfo
->paddingSize
);
164 if(!imeHeaderValid(frameInfo
)){
166 stream_skip(demuxer
->stream
,PACKET_BLOCK_SIZE
-8);
167 frameInfo
->frameSize
= 0;
174 static int lmlm4_check_file(demuxer_t
* demuxer
)
179 mp_msg(MSGT_DEMUX
, MSGL_V
, "Checking for LMLM4 Stream Format\n");
181 if(getFrame(demuxer
, &frameInfo
)!=1){
182 stream_skip(demuxer
->stream
,-8);
183 mp_msg(MSGT_DEMUX
, MSGL_V
, "LMLM4 Stream Format not found\n");
186 first
=stream_read_dword(demuxer
->stream
);
187 stream_skip(demuxer
->stream
,-12);
189 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: first=0x%08X\n",first
);
191 switch(frameInfo
.frameType
){
192 case FRAMETYPE_AUDIO_MPEG1L2
:
193 if( (first
& 0xffe00000) != 0xffe00000 ){
194 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: not mpeg audio\n");
197 if((4-((first
>>17)&3))!=2){
198 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: not layer-2\n");
201 if(((first
>>10)&0x3)==3){
202 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: invalid audio sampelrate\n");
205 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: first packet is audio, header checks OK!\n");
207 // TODO: add checks for video header too, for case of disabled audio
211 // stream_reset(demuxer->stream);
212 mp_msg(MSGT_DEMUX
, MSGL_V
, "LMLM4 Stream Format found\n");
214 return DEMUXER_TYPE_LMLM4
;
217 static int video
= 0;
218 static int frames
= 0;
221 // 0 = EOF or no stream found
222 // 1 = successfully read a packet
223 static int demux_lmlm4_fill_buffer(demuxer_t
*demux
, demux_stream_t
*ds
)
231 demux
->filepos
= stream_tell(demux
->stream
);
232 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "fpos = %"PRId64
"\n", (int64_t)demux
->filepos
);
234 ret
=getFrame(demux
, &frameInfo
);
235 if(ret
<=0) return ret
; // EOF/error
237 pts
=demux
->video
->sh
? frames
*((sh_video_t
*)(demux
->video
->sh
))->frametime
: 0;
239 switch(frameInfo
.frameType
){
240 case FRAMETYPE_AUDIO_MPEG1L2
:
241 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, "Audio Packet\n");
244 stream_skip(demux
->stream
, frameInfo
.frameSize
+ frameInfo
.paddingSize
);
245 mp_msg(MSGT_DEMUX
, MSGL_V
, "Skip Audio Packet\n");
246 return -1; //goto hdr;
248 if(demux
->audio
->id
==-1){
249 if(!demux
->a_streams
[id
]) new_sh_audio(demux
,id
);
251 demux
->audio
->sh
=demux
->a_streams
[id
];
252 ((sh_audio_t
*)(demux
->audio
->sh
))->format
=0x50; // mpeg audio layer 1/2
254 if(demux
->audio
->id
==id
)
255 ds_read_packet(demux
->audio
, demux
->stream
, frameInfo
.frameSize
,
256 pts
, demux
->filepos
, 0);
258 stream_skip(demux
->stream
,frameInfo
.frameSize
);
263 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, "First Video Packet\n");
266 frames
=(frames
+1)&(1024*1024-1); // wrap around at 4 hrs to avoid inaccurate float calculations
269 stream_skip(demux
->stream
, frameInfo
.frameSize
+ frameInfo
.paddingSize
);
270 mp_msg(MSGT_DEMUX
, MSGL_V
, "Skip Video P Packet\n");
271 return -1; //goto hdr;
273 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, "Video Packet\n");
274 if(demux
->video
->id
==-1){
275 if(!demux
->v_streams
[id
]) new_sh_video(demux
,id
);
277 demux
->video
->sh
=demux
->v_streams
[id
];
278 ((sh_video_t
*)(demux
->video
->sh
))->format
=0x10000004; // mpeg4-ES
280 if(demux
->video
->id
==id
)
281 ds_read_packet(demux
->video
, demux
->stream
, frameInfo
.frameSize
,
282 pts
, demux
->filepos
, 0);
285 stream_skip(demux
->stream
,frameInfo
.frameSize
);
288 stream_skip(demux
->stream
, frameInfo
.paddingSize
);
293 static demuxer_t
* demux_open_lmlm4(demuxer_t
* demuxer
){
294 sh_audio_t
*sh_audio
=NULL
;
295 sh_video_t
*sh_video
=NULL
;
298 sh_video_t
* sh_video
;
299 sh_audio_t
* sh_audio
;
300 unsigned int htype
= 0, hleng
;
303 sh_video
= new_sh_video(demuxer
, 0);
304 demuxer
->video
->sh
= sh_video
;
305 sh_video
->ds
= demuxer
->video
;
306 sh_video
->disp_w
= 640;
307 sh_video
->disp_h
= 480;
308 sh_video
->format
= mmioFOURCC('D','I','V','X');
310 sh_video
->bih
= malloc(sizeof(BITMAPINFOHEADER
));
311 memset(sh_video
->bih
, 0, sizeof(BITMAPINFOHEADER
));
313 /* these are false values */
314 sh_video
->bih
->biSize
= 40;
315 sh_video
->bih
->biWidth
= sh_video
->disp_w
;
316 sh_video
->bih
->biHeight
= sh_video
->disp_h
;
317 sh_video
->bih
->biPlanes
= 3;
318 sh_video
->bih
->biBitCount
= 16;
319 sh_video
->bih
->biCompression
= sh_video
->format
;
320 sh_video
->bih
->biSizeImage
= sh_video
->disp_w
*sh_video
->disp_h
;
322 sh_audio
= new_sh_audio(demuxer
, 0);
323 demuxer
->audio
->sh
= sh_audio
;
324 sh_audio
->ds
= demuxer
->audio
;
326 sh_audio
->wf
= malloc(sizeof(WAVEFORMATEX
));
327 memset(sh_audio
->wf
, 0, sizeof(WAVEFORMATEX
));
329 sh_audio
->samplerate
= 48000;
330 sh_audio
->wf
->wBitsPerSample
= 16;
331 sh_audio
->channels
= 2;
332 sh_audio
->format
= 0x50;
333 sh_audio
->wf
->wFormatTag
= sh_audio
->format
;
334 sh_audio
->wf
->nChannels
= sh_audio
->channels
;
335 sh_audio
->wf
->nSamplesPerSec
= sh_audio
->samplerate
;
336 sh_audio
->wf
->nAvgBytesPerSec
= sh_audio
->wf
->nChannels
*
337 sh_audio
->wf
->wBitsPerSample
*sh_audio
->wf
->nSamplesPerSec
/8;
338 sh_audio
->wf
->nBlockAlign
= sh_audio
->channels
*2;
339 sh_audio
->wf
->cbSize
= 0;
343 demuxer
->seekable
= 0;
345 if(!ds_fill_buffer(demuxer
->video
)){
346 mp_msg(MSGT_DEMUXER
, MSGL_INFO
, "LMLM4: %s",
347 mp_gtext("No video stream found.\n"));
348 demuxer
->video
->sh
=NULL
;
350 sh_video
=demuxer
->video
->sh
;sh_video
->ds
=demuxer
->video
;
352 if(demuxer
->audio
->id
!=-2) {
353 if(!ds_fill_buffer(demuxer
->audio
)){
354 mp_msg(MSGT_DEMUXER
, MSGL_INFO
, "LMLM4: %s",
355 mp_gtext("No audio stream found -> no sound.\n"));
356 demuxer
->audio
->sh
=NULL
;
358 sh_audio
=demuxer
->audio
->sh
;sh_audio
->ds
=demuxer
->audio
;
365 static void demux_close_lmlm4(demuxer_t
*demuxer
)
367 // printf("Close LMLM4 Stream\n");
372 const demuxer_desc_t demuxer_desc_lmlm4
= {
373 "LMLM4 MPEG4 Compression Card stream demuxer",
379 0, // unsafe autodetect
381 demux_lmlm4_fill_buffer
,