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
,
75 "Invalid packet in LMLM4 stream: ch=%d size=%zd\n",
76 frame
->channelNo
, frame
->frameSize
);
79 switch (frame
->frameType
) {
83 case FRAMETYPE_AUDIO_MPEG1L2
:
84 case FRAMETYPE_AUDIO_ULAW
:
85 case FRAMETYPE_AUDIO_ADPCM
:
88 mp_msg(MSGT_DEMUX
, MSGL_V
, "Invalid packet in LMLM4 stream (wrong packet type %d)\n", frame
->frameType
);
95 int searchMPEG4Stream(demuxer_t* demuxer, IME6400Header *imeHeader)
98 ssize_t imeHeaderSize = sizeof(IME6400Header);
99 ssize_t dataSize = sizeof(IME6400Header) * 3;
100 ssize_t ptr = imeHeaderSize * 2;
101 int errNo, startCodeNo;
104 data = malloc(dataSize);
106 imeHeaderSwap(imeHeader);
107 memcpy(data + imeHeaderSize, imeHeader, imeHeaderSize);
109 // printHex(data + imeHeaderSize, imeHeaderSize);
111 while ((errNo = stream_read(demuxer->stream, data + imeHeaderSize * 2 , imeHeaderSize)) == imeHeaderSize)
113 // printHex(data + imeHeaderSize * 2, imeHeaderSize);
115 pos = stream_tell(demuxer->stream);
116 while (dataSize - ptr >= STREAM_START_CODE_SIZE) {
118 while (start_code[startCodeNo])
120 if (memcmp(&start_code[startCodeNo], data + ptr, STREAM_START_CODE_SIZE) == 0) // start code match
122 memcpy(imeHeader, data + ptr - imeHeaderSize, imeHeaderSize);
123 imeHeaderSwap(imeHeader);
124 if (imeHeaderValid(imeHeader))
126 stream_seek(demuxer->stream, pos - (dataSize - ptr));
135 memcpy(data,data + imeHeaderSize, imeHeaderSize * 2);
136 ptr -= imeHeaderSize;
144 static int getFrame(demuxer_t
*demuxer
, FrameInfo
*frameInfo
)
146 unsigned int packetSize
;
148 frameInfo
->channelNo
= stream_read_word(demuxer
->stream
);
149 frameInfo
->frameType
= stream_read_word(demuxer
->stream
);
150 packetSize
=stream_read_dword(demuxer
->stream
);
152 if(stream_eof(demuxer
->stream
)){
153 frameInfo
->frameSize
= 0;
157 frameInfo
->frameSize
= packetSize
- 8; //sizeof(IME6400Header);
158 frameInfo
->paddingSize
= (packetSize
& PACKET_BLOCK_LAST
) ? PACKET_BLOCK_SIZE
- (packetSize
& PACKET_BLOCK_LAST
) : 0;
160 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "typ: %d chan: %d size: %zd pad: %zd\n",
161 frameInfo
->frameType
,
162 frameInfo
->channelNo
,
163 frameInfo
->frameSize
,
164 frameInfo
->paddingSize
);
166 if(!imeHeaderValid(frameInfo
)){
168 stream_skip(demuxer
->stream
,PACKET_BLOCK_SIZE
-8);
169 frameInfo
->frameSize
= 0;
176 static int lmlm4_check_file(demuxer_t
* demuxer
)
181 mp_msg(MSGT_DEMUX
, MSGL_V
, "Checking for LMLM4 Stream Format\n");
183 if(getFrame(demuxer
, &frameInfo
)!=1){
184 stream_skip(demuxer
->stream
,-8);
185 mp_msg(MSGT_DEMUX
, MSGL_V
, "LMLM4 Stream Format not found\n");
188 first
=stream_read_dword(demuxer
->stream
);
189 stream_skip(demuxer
->stream
,-12);
191 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: first=0x%08X\n",first
);
193 switch(frameInfo
.frameType
){
194 case FRAMETYPE_AUDIO_MPEG1L2
:
195 if( (first
& 0xffe00000) != 0xffe00000 ){
196 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: not mpeg audio\n");
199 if((4-((first
>>17)&3))!=2){
200 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: not layer-2\n");
203 if(((first
>>10)&0x3)==3){
204 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: invalid audio sampelrate\n");
207 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: first packet is audio, header checks OK!\n");
209 // TODO: add checks for video header too, for case of disabled audio
213 // stream_reset(demuxer->stream);
214 mp_msg(MSGT_DEMUX
, MSGL_V
, "LMLM4 Stream Format found\n");
216 return DEMUXER_TYPE_LMLM4
;
219 static int video
= 0;
220 static int frames
= 0;
223 // 0 = EOF or no stream found
224 // 1 = successfully read a packet
225 static int demux_lmlm4_fill_buffer(demuxer_t
*demux
, demux_stream_t
*ds
)
233 demux
->filepos
= stream_tell(demux
->stream
);
234 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "fpos = %"PRId64
"\n", (int64_t)demux
->filepos
);
236 ret
=getFrame(demux
, &frameInfo
);
237 if(ret
<=0) return ret
; // EOF/error
239 pts
=demux
->video
->sh
? frames
*((sh_video_t
*)(demux
->video
->sh
))->frametime
: 0;
241 switch(frameInfo
.frameType
){
242 case FRAMETYPE_AUDIO_MPEG1L2
:
243 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, "Audio Packet\n");
246 stream_skip(demux
->stream
, frameInfo
.frameSize
+ frameInfo
.paddingSize
);
247 mp_msg(MSGT_DEMUX
, MSGL_V
, "Skip Audio Packet\n");
248 return -1; //goto hdr;
250 if(demux
->audio
->id
==-1){
251 if(!demux
->a_streams
[id
]) new_sh_audio(demux
,id
);
253 demux
->audio
->sh
=demux
->a_streams
[id
];
254 ((sh_audio_t
*)(demux
->audio
->sh
))->format
=0x50; // mpeg audio layer 1/2
256 if(demux
->audio
->id
==id
)
257 ds_read_packet(demux
->audio
, demux
->stream
, frameInfo
.frameSize
,
258 pts
, demux
->filepos
, 0);
260 stream_skip(demux
->stream
,frameInfo
.frameSize
);
265 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, "First Video Packet\n");
268 frames
=(frames
+1)&(1024*1024-1); // wrap around at 4 hrs to avoid inaccurate float calculations
271 stream_skip(demux
->stream
, frameInfo
.frameSize
+ frameInfo
.paddingSize
);
272 mp_msg(MSGT_DEMUX
, MSGL_V
, "Skip Video P Packet\n");
273 return -1; //goto hdr;
275 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, "Video Packet\n");
276 if(demux
->video
->id
==-1){
277 if(!demux
->v_streams
[id
]) new_sh_video(demux
,id
);
279 demux
->video
->sh
=demux
->v_streams
[id
];
280 ((sh_video_t
*)(demux
->video
->sh
))->format
=0x10000004; // mpeg4-ES
282 if(demux
->video
->id
==id
)
283 ds_read_packet(demux
->video
, demux
->stream
, frameInfo
.frameSize
,
284 pts
, demux
->filepos
, 0);
287 stream_skip(demux
->stream
,frameInfo
.frameSize
);
290 stream_skip(demux
->stream
, frameInfo
.paddingSize
);
295 static demuxer_t
* demux_open_lmlm4(demuxer_t
* demuxer
){
296 sh_audio_t
*sh_audio
=NULL
;
297 sh_video_t
*sh_video
=NULL
;
300 sh_video_t
* sh_video
;
301 sh_audio_t
* sh_audio
;
302 unsigned int htype
= 0, hleng
;
305 sh_video
= new_sh_video(demuxer
, 0);
306 demuxer
->video
->sh
= sh_video
;
307 sh_video
->ds
= demuxer
->video
;
308 sh_video
->disp_w
= 640;
309 sh_video
->disp_h
= 480;
310 sh_video
->format
= mmioFOURCC('D','I','V','X');
312 sh_video
->bih
= calloc(1, sizeof(*sh_video
->bih
));
314 /* these are false values */
315 sh_video
->bih
->biSize
= 40;
316 sh_video
->bih
->biWidth
= sh_video
->disp_w
;
317 sh_video
->bih
->biHeight
= sh_video
->disp_h
;
318 sh_video
->bih
->biPlanes
= 3;
319 sh_video
->bih
->biBitCount
= 16;
320 sh_video
->bih
->biCompression
= sh_video
->format
;
321 sh_video
->bih
->biSizeImage
= sh_video
->disp_w
*sh_video
->disp_h
;
323 sh_audio
= new_sh_audio(demuxer
, 0);
324 demuxer
->audio
->sh
= sh_audio
;
325 sh_audio
->ds
= demuxer
->audio
;
327 sh_audio
->wf
= calloc(1, sizeof(*sh_audio
->wf
));
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
,