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