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 */
32 #include "stream/stream.h"
36 typedef struct FrameInfo
47 #define FRAMETYPE_AUDIO_MPEG1L2 4
48 #define FRAMETYPE_AUDIO_ULAW 5
49 #define FRAMETYPE_AUDIO_ADPCM 6
51 #define PACKET_BLOCK_SIZE 0x00000200
52 #define PACKET_BLOCK_LAST 0x000001FF
53 #define PACKET_BLOCK_MASK 0xFFFFFE00
55 #define MAX_PACKET_SIZE 1048576 // 1 Mb
57 #define STREAM_START_CODE_SIZE 4
61 static unsigned int start_code [] =
63 0xB0010000, // VISUAL_OBJECT_SEQUENCE_START_CODE
64 0xB6010000, // VOP_START_CODE
65 0x04C4FDFF, // MPEG1LAYERII_START_CODE
66 0x00000000 // end of start codes list
70 static int imeHeaderValid(FrameInfo
*frame
)
72 if ( frame
->channelNo
> 7 ||
73 frame
->frameSize
> MAX_PACKET_SIZE
|| frame
->frameSize
<= 0)
75 mp_msg(MSGT_DEMUX
, MSGL_V
, "Invalid packet in LMLM4 stream: ch=%d size=%d\n", frame
->channelNo
, frame
->frameSize
);
78 switch (frame
->frameType
) {
82 case FRAMETYPE_AUDIO_MPEG1L2
:
83 case FRAMETYPE_AUDIO_ULAW
:
84 case FRAMETYPE_AUDIO_ADPCM
:
87 mp_msg(MSGT_DEMUX
, MSGL_V
, "Invalid packet in LMLM4 stream (wrong packet type %d)\n", frame
->frameType
);
94 int searchMPEG4Stream(demuxer_t* demuxer, IME6400Header *imeHeader)
97 ssize_t imeHeaderSize = sizeof(IME6400Header);
98 ssize_t dataSize = sizeof(IME6400Header) * 3;
99 ssize_t ptr = imeHeaderSize * 2;
100 int errNo, startCodeNo;
103 data = malloc(dataSize);
105 imeHeaderSwap(imeHeader);
106 memcpy(data + imeHeaderSize, imeHeader, imeHeaderSize);
108 // printHex(data + imeHeaderSize, imeHeaderSize);
110 while ((errNo = stream_read(demuxer->stream, data + imeHeaderSize * 2 , imeHeaderSize)) == imeHeaderSize)
112 // printHex(data + imeHeaderSize * 2, imeHeaderSize);
114 pos = stream_tell(demuxer->stream);
115 while (dataSize - ptr >= STREAM_START_CODE_SIZE) {
117 while (start_code[startCodeNo])
119 if (memcmp(&start_code[startCodeNo], data + ptr, STREAM_START_CODE_SIZE) == 0) // start code match
121 memcpy(imeHeader, data + ptr - imeHeaderSize, imeHeaderSize);
122 imeHeaderSwap(imeHeader);
123 if (imeHeaderValid(imeHeader))
125 stream_seek(demuxer->stream, pos - (dataSize - ptr));
134 memcpy(data,data + imeHeaderSize, imeHeaderSize * 2);
135 ptr -= imeHeaderSize;
143 static int getFrame(demuxer_t
*demuxer
, FrameInfo
*frameInfo
)
145 unsigned int packetSize
;
147 frameInfo
->channelNo
= stream_read_word(demuxer
->stream
);
148 frameInfo
->frameType
= stream_read_word(demuxer
->stream
);
149 packetSize
=stream_read_dword(demuxer
->stream
);
151 if(stream_eof(demuxer
->stream
)){
152 frameInfo
->frameSize
= 0;
156 frameInfo
->frameSize
= packetSize
- 8; //sizeof(IME6400Header);
157 frameInfo
->paddingSize
= (packetSize
& PACKET_BLOCK_LAST
) ? PACKET_BLOCK_SIZE
- (packetSize
& PACKET_BLOCK_LAST
) : 0;
159 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "typ: %d chan: %d size: %d pad: %d\n",
160 frameInfo
->frameType
,
161 frameInfo
->channelNo
,
162 frameInfo
->frameSize
,
163 frameInfo
->paddingSize
);
165 if(!imeHeaderValid(frameInfo
)){
167 stream_skip(demuxer
->stream
,PACKET_BLOCK_SIZE
-8);
168 frameInfo
->frameSize
= 0;
175 static int lmlm4_check_file(demuxer_t
* demuxer
)
180 mp_msg(MSGT_DEMUX
, MSGL_V
, "Checking for LMLM4 Stream Format\n");
182 if(getFrame(demuxer
, &frameInfo
)!=1){
183 stream_skip(demuxer
->stream
,-8);
184 mp_msg(MSGT_DEMUX
, MSGL_V
, "LMLM4 Stream Format not found\n");
187 first
=stream_read_dword(demuxer
->stream
);
188 stream_skip(demuxer
->stream
,-12);
190 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: first=0x%08X\n",first
);
192 switch(frameInfo
.frameType
){
193 case FRAMETYPE_AUDIO_MPEG1L2
:
194 if( (first
& 0xffe00000) != 0xffe00000 ){
195 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: not mpeg audio\n");
198 if((4-((first
>>17)&3))!=2){
199 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: not layer-2\n");
202 if(((first
>>10)&0x3)==3){
203 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: invalid audio sampelrate\n");
206 mp_msg(MSGT_DEMUXER
,MSGL_V
,"LMLM4: first packet is audio, header checks OK!\n");
208 // TODO: add checks for video header too, for case of disabled audio
212 // stream_reset(demuxer->stream);
213 mp_msg(MSGT_DEMUX
, MSGL_V
, "LMLM4 Stream Format found\n");
215 return DEMUXER_TYPE_LMLM4
;
218 static int video
= 0;
219 static int frames
= 0;
222 // 0 = EOF or no stream found
223 // 1 = successfully read a packet
224 static int demux_lmlm4_fill_buffer(demuxer_t
*demux
, demux_stream_t
*ds
)
232 demux
->filepos
= stream_tell(demux
->stream
);
233 mp_msg(MSGT_DEMUX
, MSGL_DBG2
, "fpos = %"PRId64
"\n", (int64_t)demux
->filepos
);
235 ret
=getFrame(demux
, &frameInfo
);
236 if(ret
<=0) return ret
; // EOF/error
238 pts
=demux
->video
->sh
? frames
*((sh_video_t
*)(demux
->video
->sh
))->frametime
: 0;
240 switch(frameInfo
.frameType
){
241 case FRAMETYPE_AUDIO_MPEG1L2
:
242 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, "Audio Packet\n");
245 stream_skip(demux
->stream
, frameInfo
.frameSize
+ frameInfo
.paddingSize
);
246 mp_msg(MSGT_DEMUX
, MSGL_V
, "Skip Audio Packet\n");
247 return -1; //goto hdr;
249 if(demux
->audio
->id
==-1){
250 if(!demux
->a_streams
[id
]) new_sh_audio(demux
,id
);
252 demux
->audio
->sh
=demux
->a_streams
[id
];
253 ((sh_audio_t
*)(demux
->audio
->sh
))->format
=0x50; // mpeg audio layer 1/2
255 if(demux
->audio
->id
==id
)
256 ds_read_packet(demux
->audio
, demux
->stream
, frameInfo
.frameSize
,
257 pts
, demux
->filepos
, 0);
259 stream_skip(demux
->stream
,frameInfo
.frameSize
);
264 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, "First Video Packet\n");
267 frames
=(frames
+1)&(1024*1024-1); // wrap around at 4 hrs to avoid inaccurate float calculations
270 stream_skip(demux
->stream
, frameInfo
.frameSize
+ frameInfo
.paddingSize
);
271 mp_msg(MSGT_DEMUX
, MSGL_V
, "Skip Video P Packet\n");
272 return -1; //goto hdr;
274 mp_dbg(MSGT_DEMUX
, MSGL_DBG2
, "Video Packet\n");
275 if(demux
->video
->id
==-1){
276 if(!demux
->v_streams
[id
]) new_sh_video(demux
,id
);
278 demux
->video
->sh
=demux
->v_streams
[id
];
279 ((sh_video_t
*)(demux
->video
->sh
))->format
=0x10000004; // mpeg4-ES
281 if(demux
->video
->id
==id
)
282 ds_read_packet(demux
->video
, demux
->stream
, frameInfo
.frameSize
,
283 pts
, demux
->filepos
, 0);
286 stream_skip(demux
->stream
,frameInfo
.frameSize
);
289 stream_skip(demux
->stream
, frameInfo
.paddingSize
);
294 static demuxer_t
* demux_open_lmlm4(demuxer_t
* demuxer
){
295 sh_audio_t
*sh_audio
=NULL
;
296 sh_video_t
*sh_video
=NULL
;
299 sh_video_t
* sh_video
;
300 sh_audio_t
* sh_audio
;
301 unsigned int htype
= 0, hleng
;
304 sh_video
= new_sh_video(demuxer
, 0);
305 demuxer
->video
->sh
= sh_video
;
306 sh_video
->ds
= demuxer
->video
;
307 sh_video
->disp_w
= 640;
308 sh_video
->disp_h
= 480;
309 sh_video
->format
= mmioFOURCC('D','I','V','X');
311 sh_video
->bih
= malloc(sizeof(BITMAPINFOHEADER
));
312 memset(sh_video
->bih
, 0, sizeof(BITMAPINFOHEADER
));
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
= malloc(sizeof(WAVEFORMATEX
));
328 memset(sh_audio
->wf
, 0, sizeof(WAVEFORMATEX
));
330 sh_audio
->samplerate
= 48000;
331 sh_audio
->wf
->wBitsPerSample
= 16;
332 sh_audio
->channels
= 2;
333 sh_audio
->format
= 0x50;
334 sh_audio
->wf
->wFormatTag
= sh_audio
->format
;
335 sh_audio
->wf
->nChannels
= sh_audio
->channels
;
336 sh_audio
->wf
->nSamplesPerSec
= sh_audio
->samplerate
;
337 sh_audio
->wf
->nAvgBytesPerSec
= sh_audio
->wf
->nChannels
*
338 sh_audio
->wf
->wBitsPerSample
*sh_audio
->wf
->nSamplesPerSec
/8;
339 sh_audio
->wf
->nBlockAlign
= sh_audio
->channels
*2;
340 sh_audio
->wf
->cbSize
= 0;
344 demuxer
->seekable
= 0;
346 if(!ds_fill_buffer(demuxer
->video
)){
347 mp_tmsg(MSGT_DEMUXER
,MSGL_INFO
,"LMLM4: " "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_tmsg(MSGT_DEMUXER
,MSGL_INFO
,"LMLM4: " "No audio stream found -> no sound.\n");
355 demuxer
->audio
->sh
=NULL
;
357 sh_audio
=demuxer
->audio
->sh
;sh_audio
->ds
=demuxer
->audio
;
364 static void demux_close_lmlm4(demuxer_t
*demuxer
)
366 // printf("Close LMLM4 Stream\n");
371 const demuxer_desc_t demuxer_desc_lmlm4
= {
372 "LMLM4 MPEG4 Compression Card stream demuxer",
378 0, // unsafe autodetect
380 demux_lmlm4_fill_buffer
,