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