1 /*
2 * GPAC - Multimedia Framework C SDK
3 *
4 * Authors: Jean Le Feuvre
5 * Copyright (c) Telecom ParisTech 2005-2019
6 * All rights reserved
7 *
8 * This file is part of GPAC / AVI demuxer filter
9 *
10 * GPAC is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * GPAC is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; see the file COPYING. If not, write to
22 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 */
25
26 #include <gpac/filters.h>
27 #include <gpac/constants.h>
28 #include <gpac/thread.h>
29 #include <gpac/list.h>
30 #include <gpac/bitstream.h>
31
32 #ifndef GPAC_DISABLE_AVILIB
33 #include <gpac/internal/avilib.h>
34 #include <gpac/media_tools.h>
35
36 typedef struct
37 {
38 GF_FilterPid *opid;
39 u32 stream_num;
40 Bool in_use;
41 u32 aud_frame, audio_bps, nb_channels, freq;
42 u64 audio_ts, seek_to_ts;
43 Bool audio_done, is_aac, playing, init_play_done;
44 } AVIAstream;
45
46
47 typedef struct
48 {
49 //opts
50 GF_Fraction fps;
51 Bool importer;
52
53 GF_FilterPid *ipid;
54
55 GF_FilterPid *v_opid;
56 Bool v_in_use;
57 u32 nb_frames, cur_frame, nb_frame_sent;
58 u32 dummy, nvops;
59 const char *src_url;
60 avi_t *avi;
61
62 Bool use_file_fps;
63 GF_Fraction64 duration;
64 Bool v_playing;
65 Bool v_init_play_done;
66
67 GF_List *audios;
68 } GF_AVIDmxCtx;
69
70
avidmx_setup(GF_Filter * filter,GF_AVIDmxCtx * ctx)71 static void avidmx_setup(GF_Filter *filter, GF_AVIDmxCtx *ctx)
72 {
73 u32 sync_id = 0;
74 u32 codecid = 0;
75 Bool unframed;
76 u32 i, count, pfmt=0;
77 GF_Fraction64 dur;
78 char *comp;
79
80 if (ctx->use_file_fps) {
81 Double fps = AVI_frame_rate(ctx->avi);
82 gf_media_get_video_timing(fps, &ctx->fps.num, &ctx->fps.den);
83 }
84
85 dur.den = ctx->fps.num;
86 dur.num = (u64) (ctx->fps.den * AVI_video_frames(ctx->avi));
87
88 unframed = GF_TRUE;
89 comp = AVI_video_compressor(ctx->avi);
90 if (!comp) {
91 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Cannot retrieve video compressor name, ignoring video stream\n"));
92 }
93 /*these are/should be OK*/
94 else if (!stricmp(comp, "DIVX") || !stricmp(comp, "DX50") /*DivX*/
95 || !stricmp(comp, "XVID") /*XviD*/
96 || !stricmp(comp, "3iv2") /*3ivX*/
97 || !stricmp(comp, "fvfw") /*ffmpeg*/
98 || !stricmp(comp, "NDIG") /*nero*/
99 || !stricmp(comp, "MP4V") /*!! not tested*/
100 || !stricmp(comp, "M4CC") /*Divio - not tested*/
101 || !stricmp(comp, "PVMM") /*PacketVideo - not tested*/
102 || !stricmp(comp, "SEDG") /*Samsung - not tested*/
103 || !stricmp(comp, "RMP4") /*Sigma - not tested*/
104 || !stricmp(comp, "MP43") /*not tested*/
105 || !stricmp(comp, "FMP4") /*not tested*/
106 ) {
107 codecid = GF_CODECID_MPEG4_PART2;
108 } else if ( !stricmp(comp, "H264") /*not tested*/
109 || !stricmp(comp, "X264") /*not tested*/
110 ) {
111 codecid = GF_CODECID_AVC;
112 } else if ( !stricmp(comp, "avc1") ) {
113 codecid = GF_CODECID_AVC;
114 unframed = GF_FALSE;
115 } else if (!stricmp(comp, "DIV3") || !stricmp(comp, "DIV4")) {
116 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Video format %s not compliant with MPEG-4 Visual - please recompress the file first\n", comp));
117 } else if (!comp[0]) {
118 codecid = GF_CODECID_RAW;
119 pfmt = GF_PIXEL_BGR;
120 } else {
121 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Video format %s not supported, patch welcome\n", comp));
122 }
123
124 ctx->v_in_use = GF_FALSE;
125 if (codecid) {
126 u32 w, h;
127 if (!ctx->v_opid) {
128 ctx->v_opid = gf_filter_pid_new(filter);
129 }
130 ctx->nb_frames = (u32) AVI_video_frames(ctx->avi);
131 ctx->cur_frame = 0;
132 sync_id = 1;
133 ctx->v_in_use = GF_TRUE;
134
135 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_VISUAL) );
136 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_CODECID, &PROP_UINT(codecid) );
137 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(ctx->fps.num) );
138
139 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_ID, &PROP_UINT( sync_id) );
140 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_CLOCK_ID, &PROP_UINT( sync_id ) );
141 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_FPS, &PROP_FRAC( ctx->fps ) );
142 w = AVI_video_width(ctx->avi);
143 h = AVI_video_height(ctx->avi);
144 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_WIDTH, &PROP_UINT( w ) );
145 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_HEIGHT, &PROP_UINT( h ) );
146 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_DURATION, &PROP_FRAC64( dur ) );
147
148 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_SEEK ) );
149
150 if (pfmt) {
151 u32 stride=0;
152 gf_pixel_get_size_info(pfmt, w, h, NULL, &stride, NULL, NULL, NULL);
153 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_STRIDE, &PROP_UINT( stride ) );
154 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_PIXFMT, &PROP_UINT( pfmt ) );
155 } else if (unframed) {
156 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL(GF_TRUE) );
157 gf_filter_pid_set_property_str(ctx->v_opid, "nocts", &PROP_BOOL( GF_TRUE ) );
158 } else if (ctx->avi->extradata_size && ctx->avi->extradata) {
159 gf_filter_pid_set_property(ctx->v_opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA(ctx->avi->extradata, ctx->avi->extradata_size) );
160
161 }
162 }
163
164 unframed = GF_FALSE;
165 count = AVI_audio_tracks(ctx->avi);
166 for (i=0; i<count; i++) {
167 u32 a_fmt, afmt=0, nb_bits;
168 AVI_set_audio_track(ctx->avi, i);
169
170 codecid = 0;
171 a_fmt = AVI_audio_format(ctx->avi);
172 nb_bits = AVI_audio_bits(ctx->avi);
173 switch (a_fmt) {
174 case WAVE_FORMAT_PCM:
175 case GF_4CC('P','C','M',' '):
176 codecid = GF_CODECID_RAW;
177 switch (nb_bits) {
178 case 8:
179 afmt = GF_AUDIO_FMT_U8;
180 break;
181 case 16:
182 afmt = GF_AUDIO_FMT_S16;
183 break;
184 case 24:
185 afmt = GF_AUDIO_FMT_S24;
186 break;
187 case 32:
188 afmt = GF_AUDIO_FMT_S32;
189 break;
190 default:
191 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Audio bit depth %d not mapped, patch welcome\n", nb_bits));
192 afmt = GF_AUDIO_FMT_S16;
193 break;
194 }
195 break;
196 case WAVE_FORMAT_ADPCM:
197 codecid = GF_CODECID_ADPCM;
198 break;
199 case WAVE_FORMAT_IBM_CVSD:
200 codecid = GF_CODECID_IBM_CVSD;
201 break;
202 case WAVE_FORMAT_ALAW:
203 codecid = GF_CODECID_ALAW;
204 break;
205 case WAVE_FORMAT_MULAW:
206 codecid = GF_CODECID_MULAW;
207 break;
208 case WAVE_FORMAT_OKI_ADPCM:
209 codecid = GF_CODECID_OKI_ADPCM;
210 break;
211 case WAVE_FORMAT_DVI_ADPCM:
212 codecid = GF_CODECID_DVI_ADPCM;
213 break;
214 case WAVE_FORMAT_DIGISTD:
215 codecid = GF_CODECID_DIGISTD;
216 break;
217 case WAVE_FORMAT_YAMAHA_ADPCM:
218 codecid = GF_CODECID_YAMAHA_ADPCM;
219 break;
220 case WAVE_FORMAT_DSP_TRUESPEECH:
221 codecid = GF_CODECID_DSP_TRUESPEECH;
222 break;
223 case WAVE_FORMAT_GSM610:
224 codecid = GF_CODECID_GSM610;
225 break;
226 case IBM_FORMAT_MULAW:
227 codecid = GF_CODECID_IBM_MULAW;
228 break;
229 case IBM_FORMAT_ALAW:
230 codecid = GF_CODECID_IBM_ALAW;
231 break;
232 case IBM_FORMAT_ADPCM:
233 codecid = GF_CODECID_IBM_ADPCM;
234 break;
235 case 0x55:
236 codecid = GF_CODECID_MPEG_AUDIO;
237 unframed = GF_TRUE;
238 break;
239 case 0x0000706d:
240 codecid = GF_CODECID_AAC_MPEG4;
241 unframed = GF_TRUE;
242 break;
243 case 255:
244 codecid = GF_CODECID_AAC_MPEG4;
245 break;
246 default:
247 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[AVIDmx] Audio format %d not supported, patch welcome\n", a_fmt));
248 break;
249 }
250
251 if (codecid) {
252 AVIAstream *st = NULL;
253 u32 brate, j, c = gf_list_count(ctx->audios);
254 for (j=0; j<c; j++) {
255 st = gf_list_get(ctx->audios, j);
256 if (!st->in_use) break;
257 st = NULL;
258 }
259 if (!st) {
260 GF_SAFEALLOC(st, AVIAstream);
261 if (!st) continue;
262 st->opid = gf_filter_pid_new(filter);
263 gf_list_add(ctx->audios, st);
264 }
265 st->in_use = GF_TRUE;
266 st->stream_num = i;
267 if (!sync_id) sync_id = 2 + st->stream_num;
268 st->audio_done = GF_FALSE;
269
270 gf_filter_pid_set_property(st->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_AUDIO) );
271 gf_filter_pid_set_property(st->opid, GF_PROP_PID_CODECID, &PROP_UINT( codecid) );
272 st->freq = AVI_audio_rate(ctx->avi);
273 gf_filter_pid_set_property(st->opid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT( st->freq ) );
274 st->nb_channels = AVI_audio_channels(ctx->avi);
275 gf_filter_pid_set_property(st->opid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT( st->nb_channels ) );
276 brate = AVI_audio_mp3rate(ctx->avi);
277 //for mp3 and aac
278 if (brate && (unframed || (codecid == GF_CODECID_AAC_MPEG4)))
279 gf_filter_pid_set_property(st->opid, GF_PROP_PID_BITRATE, &PROP_UINT( brate ) );
280 gf_filter_pid_set_property(st->opid, GF_PROP_PID_ID, &PROP_UINT( 2 + st->stream_num) );
281 gf_filter_pid_set_property(st->opid, GF_PROP_PID_CLOCK_ID, &PROP_UINT( sync_id ) );
282 gf_filter_pid_set_property(st->opid, GF_PROP_PID_DURATION, &PROP_FRAC64( dur ) );
283
284 gf_filter_pid_set_property(st->opid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_SEEK ) );
285 st->audio_bps = 0;
286 if (unframed) {
287 gf_filter_pid_set_property(st->opid, GF_PROP_PID_UNFRAMED, &PROP_BOOL( GF_TRUE ) );
288 //we don't set timescale, let the reframer handle it
289 } else {
290 if (afmt) {
291 gf_filter_pid_set_property(st->opid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(afmt) );
292 }
293 st->audio_bps = AVI_audio_bits(ctx->avi);
294 gf_filter_pid_set_property(st->opid, GF_PROP_PID_TIMESCALE, &PROP_UINT(st->freq) );
295
296 if (codecid == GF_CODECID_AAC_MPEG4) {
297 #ifndef GPAC_DISABLE_AV_PARSERS
298 GF_M4ADecSpecInfo acfg;
299 u8 *dsi=NULL;
300 u32 dsi_len=0;
301 memset(&acfg, 0, sizeof(GF_M4ADecSpecInfo));
302 acfg.base_object_type = GF_M4A_AAC_LC;
303 acfg.base_sr = st->freq;
304 acfg.nb_chan = st->nb_channels;
305 acfg.sbr_object_type = 0;
306 acfg.audioPL = gf_m4a_get_profile(&acfg);
307 gf_m4a_write_config(&acfg, &dsi, &dsi_len);
308 gf_filter_pid_set_property(st->opid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_len) );
309 #endif
310 st->audio_bps = 0;
311 st->is_aac = GF_TRUE;
312 }
313 }
314
315 }
316 }
317 }
318
avidmx_configure_pid(GF_Filter * filter,GF_FilterPid * pid,Bool is_remove)319 GF_Err avidmx_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
320 {
321 const GF_PropertyValue *p;
322 GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
323
324 if (is_remove) {
325 ctx->ipid = NULL;
326 if (ctx->v_opid) gf_filter_pid_remove(ctx->v_opid);
327 ctx->v_opid = NULL;
328 while (gf_list_count(ctx->audios) ) {
329 AVIAstream *st = gf_list_pop_back(ctx->audios);
330 gf_filter_pid_remove(st->opid);
331 gf_free(st);
332 }
333 return GF_OK;
334 }
335 if (! gf_filter_pid_check_caps(pid))
336 return GF_NOT_SUPPORTED;
337
338 if (!ctx->ipid) {
339 GF_FilterEvent fevt;
340 ctx->ipid = pid;
341
342 //we work with full file only, send a play event on source to indicate that
343 GF_FEVT_INIT(fevt, GF_FEVT_PLAY, pid);
344 fevt.play.start_range = 0;
345 fevt.base.on_pid = ctx->ipid;
346 fevt.play.full_file_only = GF_TRUE;
347 gf_filter_pid_send_event(ctx->ipid, &fevt);
348 }
349
350 p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FILEPATH);
351 if (!p) return GF_NOT_SUPPORTED;
352
353 if (ctx->src_url && !strcmp(ctx->src_url, p->value.string)) return GF_OK;
354
355 if (ctx->avi) {
356 u32 i;
357 AVI_close(ctx->avi);
358 ctx->v_in_use = GF_FALSE;
359 for (i=0; i<gf_list_count(ctx->audios); i++) {
360 AVIAstream *st = gf_list_get(ctx->audios, i);
361 st->in_use = GF_FALSE;
362 }
363 }
364 ctx->avi = NULL;
365
366 ctx->src_url = p->value.string;
367
368 return GF_OK;
369 }
370
avidmx_process_event(GF_Filter * filter,const GF_FilterEvent * evt)371 static Bool avidmx_process_event(GF_Filter *filter, const GF_FilterEvent *evt)
372 {
373 GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
374
375 switch (evt->base.type) {
376 case GF_FEVT_PLAY:
377 gf_filter_post_process_task(filter);
378 if (evt->base.on_pid==ctx->v_opid) {
379 u32 frame_idx = 0;
380 ctx->v_playing = GF_TRUE;
381 if ((evt->play.start_range==0) && !ctx->v_init_play_done) {
382 ctx->v_init_play_done = GF_TRUE;
383 return GF_TRUE;
384 }
385 ctx->v_init_play_done = GF_TRUE;
386 frame_idx = (u32) (ctx->avi->fps * evt->play.start_range);
387 if (frame_idx) {
388 AVI_set_video_position(ctx->avi, frame_idx);
389 } else {
390 AVI_seek_start(ctx->avi);
391 gf_filter_post_process_task(filter);
392 }
393 ctx->cur_frame = frame_idx;
394 } else {
395 u32 i;
396 for (i=0; i<gf_list_count(ctx->audios); i++) {
397 AVIAstream *st = gf_list_get(ctx->audios, i);
398 if (st->opid != evt->base.on_pid) continue;
399 st->playing = GF_TRUE;
400 if ((evt->play.start_range==0) && !st->init_play_done) {
401 st->init_play_done = GF_TRUE;
402 return GF_TRUE;
403 }
404 st->init_play_done = GF_TRUE;
405 AVI_set_audio_position(ctx->avi, 0);
406 st->seek_to_ts = (u32) (evt->play.start_range * st->freq);
407 }
408 }
409
410 //cancel play event, we work with full file
411 return GF_TRUE;
412
413 case GF_FEVT_STOP:
414 if (evt->base.on_pid==ctx->v_opid) {
415 ctx->v_playing = GF_FALSE;
416 } else {
417 u32 i;
418 for (i=0; i<gf_list_count(ctx->audios); i++) {
419 AVIAstream *st = gf_list_get(ctx->audios, i);
420 if (st->opid != evt->base.on_pid) continue;
421 st->playing = GF_TRUE;
422 }
423 }
424 //don't cancel event
425 return GF_FALSE;
426
427 case GF_FEVT_SET_SPEED:
428 //cancel event
429 return GF_TRUE;
430 default:
431 break;
432 }
433 //by default don't cancel event - to rework once we have downloading in place
434 return GF_FALSE;
435 }
436
avidmx_process(GF_Filter * filter)437 GF_Err avidmx_process(GF_Filter *filter)
438 {
439 GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
440 u32 i, count, nb_done, nb_active=0;
441 Bool start, end, video_done;
442
443 if (!ctx->avi) {
444 GF_FilterPacket *pck = gf_filter_pid_get_packet(ctx->ipid);
445 if (!pck) {
446 return GF_OK;
447 }
448 gf_filter_pck_get_framing(pck, &start, &end);
449 gf_filter_pid_drop_packet(ctx->ipid);
450
451 if (!end) {
452 return GF_OK;
453 }
454
455 ctx->avi = AVI_open_input_file((char *)ctx->src_url, 1);
456 if (!ctx->avi) {
457 GF_Err e = GF_NON_COMPLIANT_BITSTREAM;
458 if (! gf_file_exists(ctx->src_url)) e = GF_URL_ERROR;
459 gf_filter_setup_failure(filter, e);
460 return GF_NOT_SUPPORTED;
461 }
462 avidmx_setup(filter, ctx);
463 return GF_OK;
464 }
465 video_done = GF_FALSE;
466 if (ctx->v_in_use && ctx->v_playing && (ctx->cur_frame < ctx->nb_frames) && !gf_filter_pid_would_block(ctx->v_opid) ) {
467 u32 key;
468 u64 file_offset, cts;
469 u8 *pck_data;
470 s32 size = AVI_frame_size(ctx->avi, ctx->cur_frame);
471 if (!size) {
472 AVI_read_frame(ctx->avi, NULL, &key);
473 ctx->dummy++;
474 }
475 //remove dummy frames
476 else {
477 file_offset = (u64) AVI_get_video_position(ctx->avi, ctx->cur_frame);
478 cts = ctx->nb_frame_sent * ctx->fps.den;
479
480 if (size > 4) {
481 GF_FilterPacket *dst_pck = gf_filter_pck_new_alloc(ctx->v_opid, size, &pck_data);
482 AVI_read_frame(ctx->avi, pck_data, &key);
483 gf_filter_pck_set_byte_offset(dst_pck, file_offset);
484 gf_filter_pck_set_cts(dst_pck, cts);
485 gf_filter_pck_set_duration(dst_pck, ctx->fps.den);
486 gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
487 if (key) gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
488 gf_filter_pck_send(dst_pck);
489 ctx->nb_frame_sent++;
490 } else {
491 AVI_read_frame(ctx->avi, NULL, &key);
492 ctx->nvops++;
493 }
494 }
495 nb_active++;
496
497 ctx->cur_frame++;
498 if (ctx->cur_frame < ctx->nb_frames)
499 gf_filter_post_process_task(filter);
500 else
501 video_done = GF_TRUE;
502 } else if (!ctx->v_in_use) {
503 video_done = GF_TRUE;
504 } else if (ctx->cur_frame >= ctx->nb_frames) {
505 video_done = GF_TRUE;
506 }
507
508 nb_done = 0;
509 count = gf_list_count(ctx->audios);
510 for (i=0; i<count; i++) {
511 s32 size;
512 AVIAstream *st = gf_list_get(ctx->audios, i);
513 if (st->audio_done || !st->in_use) {
514 nb_done++;
515 continue;
516 }
517 if (!st->playing || gf_filter_pid_would_block(st->opid) )
518 continue;
519 AVI_set_audio_track(ctx->avi, st->stream_num);
520 nb_active++;
521
522 size = AVI_audio_size(ctx->avi, st->aud_frame);
523
524 if (st->seek_to_ts && size) {
525 if (st->seek_to_ts > st->audio_ts) {
526 st->aud_frame ++;
527 continue;
528 }
529 else
530 st->seek_to_ts = 0;
531 }
532
533 if (size>0) {
534 int continuous;
535 u8 *pck_data;
536 u64 file_offset;
537 GF_FilterPacket *dst_pck = gf_filter_pck_new_alloc(st->opid, size, &pck_data);
538
539 file_offset = gf_ftell(ctx->avi->fdes);
540 AVI_read_audio(ctx->avi, pck_data, size, (int*)&continuous);
541
542 if (st->audio_bps) {
543 u32 nb_samples = (8*size) / (st->audio_bps * st->nb_channels);
544 gf_filter_pck_set_cts(dst_pck, st->audio_ts);
545 gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
546 st->audio_ts += nb_samples;
547 } else if (st->is_aac) {
548 gf_filter_pck_set_cts(dst_pck, st->audio_ts);
549 gf_filter_pck_set_sap(dst_pck, GF_FILTER_SAP_1);
550 st->audio_ts += 1024;
551 }
552
553 if (continuous)
554 gf_filter_pck_set_byte_offset(dst_pck, file_offset);
555
556 gf_filter_pck_send(dst_pck);
557
558 st->aud_frame ++;
559 } else {
560 st->audio_done = GF_TRUE;
561 nb_done++;
562 }
563 }
564 if (!nb_active)
565 return GF_OK;
566 if (video_done && (nb_done==count) ) {
567 if (ctx->v_opid && ctx->v_in_use) gf_filter_pid_set_eos(ctx->v_opid);
568
569 for (i=0; i<count;i++) {
570 AVIAstream *st = gf_list_get(ctx->audios, i);
571 gf_filter_pid_set_eos(st->opid);
572 }
573 return GF_EOS;
574 }
575 gf_filter_post_process_task(filter);
576 return GF_OK;
577 }
578
avidmx_initialize(GF_Filter * filter)579 GF_Err avidmx_initialize(GF_Filter *filter)
580 {
581 GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
582 ctx->use_file_fps = ctx->fps.den ? GF_FALSE : GF_TRUE;
583 ctx->audios = gf_list_new();
584 return GF_OK;
585 }
586
avidmx_finalize(GF_Filter * filter)587 void avidmx_finalize(GF_Filter *filter)
588 {
589 GF_AVIDmxCtx *ctx = gf_filter_get_udta(filter);
590 if (ctx->avi) AVI_close(ctx->avi);
591 while (gf_list_count(ctx->audios)) {
592 AVIAstream *st = gf_list_pop_back(ctx->audios);
593 gf_free(st);
594 }
595 gf_list_del(ctx->audios);
596
597 if (ctx->importer) {
598 GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("AVI Removed Frames: 1 VFW delay frames - 296 N-VOPs\n", ctx->dummy, ctx->nvops));
599 }
600
601 }
602
603
604 static const GF_FilterCapability AVIDmxCaps[] =
605 {
606 CAP_UINT(GF_CAPS_INPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
607 CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_FILE_EXT, "avi"),
608 CAP_STRING(GF_CAPS_INPUT, GF_PROP_PID_MIME, "video/avi|video/x-avi"),
609 CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_AUDIO),
610 CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_VISUAL),
611 };
612
613
614 #define OFFS(_n) #_n, offsetof(GF_AVIDmxCtx, _n)
615 static const GF_FilterArgs AVIDmxArgs[] =
616 {
617 { OFFS(fps), "import frame rate, default is AVI one", GF_PROP_FRACTION, "1/0", NULL, 0},
618 { OFFS(importer), "compatibility with old importer, displays import results", GF_PROP_BOOL, "false", NULL, GF_FS_ARG_HINT_ADVANCED},
619 {0}
620 };
621
622
623 GF_FilterRegister AVIDmxRegister = {
624 .name = "avidmx",
625 GF_FS_SET_DESCRIPTION("AVI demuxer")
626 GF_FS_SET_HELP("This filter demultiplexes AVI files/data to produce media PIDs and frames.")
627 .private_size = sizeof(GF_AVIDmxCtx),
628 .initialize = avidmx_initialize,
629 .finalize = avidmx_finalize,
630 .args = AVIDmxArgs,
631 SETCAPS(AVIDmxCaps),
632 .configure_pid = avidmx_configure_pid,
633 .process = avidmx_process,
634 .process_event = avidmx_process_event,
635 };
636
637 #endif // GPAC_DISABLE_AVILIB
638
avidmx_register(GF_FilterSession * session)639 const GF_FilterRegister *avidmx_register(GF_FilterSession *session)
640 {
641 #ifndef GPAC_DISABLE_AVILIB
642 return &AVIDmxRegister;
643 #else
644 return NULL;
645 #endif
646 }
647
648