GF_Err writegen_process(GF_Filter *filter)
{
	GF_GenDumpCtx *ctx = gf_filter_get_udta(filter);
	GF_FilterPacket *pck, *dst_pck = NULL;
	char *data;
	u32 pck_size;
	Bool do_abort = GF_FALSE;
	Bool split = ctx->split;
	if (!ctx->ipid) return GF_EOS;

	pck = gf_filter_pid_get_packet(ctx->ipid);
	if (!pck || !ctx->codecid) {
		if (gf_filter_pid_is_eos(ctx->ipid)) {
			if (ctx->is_wav) writegen_write_wav_header(ctx);
			else if (ctx->ttml_agg) writegen_flush_ttml(ctx);
			gf_filter_pid_set_eos(ctx->opid);
			return GF_EOS;
		}
		return GF_OK;
	}
	ctx->sample_num++;

	if (ctx->dash_mode && ctx->ttml_agg && gf_filter_pck_get_property(pck, GF_PROP_PCK_FILENUM)) {
		if (ctx->ttml_dash_pck) {
			writegen_flush_ttml(ctx);
			gf_filter_pck_unref(ctx->ttml_dash_pck);
			ctx->ttml_dash_pck = NULL;
		}

		ctx->ttml_dash_pck = pck;
		gf_filter_pck_ref_props(&ctx->ttml_dash_pck);
	}

	if (ctx->sstart) {
		if (ctx->sstart > ctx->sample_num) {
			gf_filter_pid_drop_packet(ctx->ipid);
			return GF_OK;
		}
		if ((ctx->sstart <= ctx->send) && (ctx->sample_num>ctx->send) ) {
			do_abort = GF_TRUE;
		}
	} else if (ctx->dur.num && ctx->dur.den) {
		u64 dts = gf_filter_pck_get_dts(pck);
		if (dts==GF_FILTER_NO_TS)
		dts = gf_filter_pck_get_cts(pck);

		if (!ctx->first_dts_plus_one) {
			ctx->first_dts_plus_one = dts+1;
		} else {
			if (gf_timestamp_greater(dts + 1 - ctx->first_dts_plus_one, gf_filter_pck_get_timescale(pck), ctx->dur.num, ctx->dur.den)) {
				do_abort = GF_TRUE;
			}
		}
	}
	if (do_abort) {
		GF_FilterEvent evt;
		gf_filter_pid_drop_packet(ctx->ipid);
		GF_FEVT_INIT(evt, GF_FEVT_STOP, ctx->ipid);
		gf_filter_pid_send_event(ctx->ipid, &evt);
		return GF_OK;
	}

	//except in dash mode, force a new file if GF_PROP_PCK_FILENUM is set
	if (!ctx->dash_mode && (gf_filter_pck_get_property(pck, GF_PROP_PCK_FILENUM) != NULL)) {
		ctx->cfg_sent = GF_FALSE;
		ctx->first = GF_TRUE;
	}

	if (ctx->frame) {
		split = GF_TRUE;
	} else if (ctx->dcfg_size && gf_filter_pck_get_sap(pck) && !ctx->is_mj2k && (ctx->decinfo!=DECINFO_NO) && !ctx->cfg_sent) {
		if (ctx->codecid==GF_CODECID_FLAC) {
			u8 *dsi_out;
			dst_pck = gf_filter_pck_new_alloc(ctx->opid, ctx->dcfg_size+4, &dsi_out);
			if (!dst_pck) return GF_OUT_OF_MEM;
			dsi_out[0] = 'f';
			dsi_out[1] = 'L';
			dsi_out[2] = 'a';
			dsi_out[3] = 'C';
			memcpy(dsi_out+4, ctx->dcfg, ctx->dcfg_size);
		} else {
			dst_pck = gf_filter_pck_new_shared(ctx->opid, ctx->dcfg, ctx->dcfg_size, NULL);
			if (!dst_pck) return GF_OUT_OF_MEM;
			gf_filter_pck_set_readonly(dst_pck);
		}
		gf_filter_pck_merge_properties(pck, dst_pck);
		gf_filter_pck_set_framing(dst_pck, ctx->first, GF_FALSE);
		ctx->first = GF_FALSE;
		gf_filter_pck_send(dst_pck);
		if ((ctx->decinfo==DECINFO_FIRST) && !ctx->split) {
			ctx->dcfg_size = 0;
			ctx->dcfg = NULL;
		}
		ctx->cfg_sent = GF_TRUE;
		return GF_OK;
	}
	ctx->cfg_sent = GF_FALSE;
	data = (char *) gf_filter_pck_get_data(pck, &pck_size);

	if (ctx->is_mj2k) {
		dst_pck = writegen_write_j2k(ctx, data, pck_size, pck);
	} else if (ctx->is_bmp) {
		dst_pck = writegen_write_bmp(ctx, data, pck_size);
	} else if (ctx->is_y4m) {
		char *y4m_hdr = NULL;
		if (ctx->is_y4m==1) {
			char szInfo[100];
			const GF_PropertyValue *p;
			gf_dynstrcat(&y4m_hdr, "YUV4MPEG2", NULL);
			sprintf(szInfo, " W%d", ctx->w);
			gf_dynstrcat(&y4m_hdr, szInfo, NULL);
			sprintf(szInfo, " H%d", ctx->h);
			gf_dynstrcat(&y4m_hdr, szInfo, NULL);
			p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FPS);
			if (p) {
				sprintf(szInfo, " F%d:%d", p->value.frac.num, p->value.frac.den);
				gf_dynstrcat(&y4m_hdr, szInfo, NULL);
			}
			p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_SAR);
			if (p) {
				sprintf(szInfo, " A%d:%d", p->value.frac.num, p->value.frac.den);
				gf_dynstrcat(&y4m_hdr, szInfo, NULL);
			}
			u32 ilce = gf_filter_pck_get_interlaced(pck);
			sprintf(szInfo, " I%c", (ilce==0) ? 'p' : ((ilce==1) ? 't' : 'b'));
			gf_dynstrcat(&y4m_hdr, szInfo, NULL);

			switch (ctx->target_pfmt) {
			case GF_PIXEL_YUV: gf_dynstrcat(&y4m_hdr, " C420mpeg2", NULL); break;
			case GF_PIXEL_YUV444: gf_dynstrcat(&y4m_hdr, " C444", NULL); break;
			case GF_PIXEL_YUV422: gf_dynstrcat(&y4m_hdr, " C422", NULL); break;
			case GF_PIXEL_GREYSCALE: gf_dynstrcat(&y4m_hdr, " Cmono", NULL); break;
			case GF_PIXEL_YUVA444: gf_dynstrcat(&y4m_hdr, " C444alpha", NULL); break;
			}
			p = gf_filter_pid_get_property_str(ctx->ipid, "yuv4meg_meta");
			if (p) {
				gf_dynstrcat(&y4m_hdr, p->value.string, " X");
			}
			gf_dynstrcat(&y4m_hdr, "\n", NULL);
			ctx->is_y4m=2;
		}
		if (ctx->is_y4m==2) {
			gf_dynstrcat(&y4m_hdr, "FRAME\n", NULL);
		}
		u8 * output;
		u32 len = y4m_hdr ? (u32) strlen(y4m_hdr) : 0;
		dst_pck = gf_filter_pck_new_alloc(ctx->opid, pck_size + len, &output);
		if (!dst_pck) return GF_OUT_OF_MEM;
		if (y4m_hdr) memcpy(output, y4m_hdr, len);
		memcpy(output+len, data, pck_size);
		if (ctx->split)
			ctx->is_y4m=1;

		if (y4m_hdr)
			gf_free(y4m_hdr);

	} else if (ctx->is_wav && ctx->first) {
		u8 * output;
		dst_pck = gf_filter_pck_new_alloc(ctx->opid, 44, &output);
		if (!dst_pck) return GF_OUT_OF_MEM;

		gf_filter_pck_merge_properties(pck, dst_pck);
		gf_filter_pck_set_byte_offset(dst_pck, GF_FILTER_NO_BO);
		gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_FALSE);
		gf_filter_pck_set_corrupted(dst_pck, GF_TRUE);
		ctx->first = GF_FALSE;
		gf_filter_pck_send(dst_pck);
		ctx->nb_bytes += 44;
		return GF_OK;
	} else if (ctx->ttml_agg) {
		GF_Err e = writegen_push_ttml(ctx, data, pck_size, pck);
		ctx->first = GF_FALSE;
		if (e) {
			gf_filter_pid_drop_packet(ctx->ipid);
			return e;
		}
		goto no_output;
	} else if (ctx->trunc_audio) {
		u64 dts = gf_filter_pck_get_dts(pck);
		if (dts==GF_FILTER_NO_TS)
			dts = gf_filter_pck_get_cts(pck);

		if (!ctx->first_dts_plus_one) {
			ctx->first_dts_plus_one = dts+1;
		} else {
			u32 timescale = gf_filter_pck_get_timescale(pck);
			u32 dur = gf_filter_pck_get_duration(pck);
			if (gf_timestamp_greater(dts + dur + 1 - ctx->first_dts_plus_one, timescale, ctx->dur.num, ctx->dur.den)) {
				u32 bpp;
				u8 *odata;
				const GF_PropertyValue *p;
				dur = ctx->dur.num * timescale / ctx->dur.den;
				dur -= (u32) (dts + 1 - ctx->first_dts_plus_one);

				bpp = gf_audio_fmt_bit_depth(ctx->target_afmt);
				p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_NUM_CHANNELS);
				if (p) bpp *= p->value.uint;
				bpp/= 8;

				p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_SAMPLE_RATE);
				if (p && (p->value.uint != timescale)) {
					dur *= p->value.uint;
					dur /= timescale;
				}
				assert(pck_size >= bpp * dur);
				pck_size = bpp * dur;

				dst_pck = gf_filter_pck_new_alloc(ctx->opid, pck_size, &odata);
				if (dst_pck)
					memcpy(odata, data, pck_size);
			}
		}

		if (!dst_pck) {
			dst_pck = gf_filter_pck_new_ref(ctx->opid, 0, 0, pck);
		}

	} else {
		dst_pck = gf_filter_pck_new_ref(ctx->opid, 0, 0, pck);
	}
	if (!dst_pck) return GF_OUT_OF_MEM;
	
	gf_filter_pck_merge_properties(pck, dst_pck);
	//don't keep byte offset
	gf_filter_pck_set_byte_offset(dst_pck, GF_FILTER_NO_BO);

	if (split) {
		gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_FILENUM, &PROP_UINT(ctx->sample_num) );
		gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
	} else {
		gf_filter_pck_set_framing(dst_pck, ctx->first, GF_FALSE);
		ctx->first = GF_FALSE;
	}

	gf_filter_pck_set_seek_flag(dst_pck, 0);
	gf_filter_pck_send(dst_pck);
	ctx->nb_bytes += pck_size;

no_output:
	if (ctx->exporter) {
		u32 timescale = gf_filter_pck_get_timescale(pck);
		u64 ts = gf_filter_pck_get_dts(pck);
		if (ts==GF_FILTER_NO_TS)
			ts = gf_filter_pck_get_cts(pck);
		if (ts!=GF_FILTER_NO_TS) {
			ts += gf_filter_pck_get_duration(pck);
			ts = gf_timestamp_rescale(ts, timescale, ctx->duration.den);
			gf_set_progress("Exporting", ts, ctx->duration.num);
		}
	}

	gf_filter_pid_drop_packet(ctx->ipid);

	return GF_OK;
}
GF_Err writegen_process(GF_Filter *filter)
{
	GF_GenDumpCtx *ctx = gf_filter_get_udta(filter);
	GF_FilterPacket *pck, *dst_pck = NULL;
	char *data;
	u32 pck_size;
	Bool do_abort = GF_FALSE;
	Bool split = ctx->split;
	if (!ctx->ipid) return GF_EOS;

	pck = gf_filter_pid_get_packet(ctx->ipid);
	if (!pck || !ctx->codecid) {
		if (gf_filter_pid_is_eos(ctx->ipid)) {
			if (ctx->is_wav) writegen_write_wav_header(ctx);
			else if (ctx->ttml_agg) writegen_flush_ttml(ctx);
			gf_filter_pid_set_eos(ctx->opid);
			return GF_EOS;
		}
		return GF_OK;
	}
	ctx->sample_num++;

	if (ctx->dash_mode && ctx->ttml_agg && gf_filter_pck_get_property(pck, GF_PROP_PCK_FILENUM)) {
		if (ctx->ttml_dash_pck) {
			writegen_flush_ttml(ctx);
			gf_filter_pck_unref(ctx->ttml_dash_pck);
			ctx->ttml_dash_pck = NULL;
		}

		ctx->ttml_dash_pck = pck;
		gf_filter_pck_ref_props(&ctx->ttml_dash_pck);
	}

	if (ctx->sstart) {
		if (ctx->sstart > ctx->sample_num) {
			gf_filter_pid_drop_packet(ctx->ipid);
			return GF_OK;
		}
		if ((ctx->sstart <= ctx->send) && (ctx->sample_num>ctx->send) ) {
			do_abort = GF_TRUE;
		}
	} else if (ctx->dur.num && ctx->dur.den) {
		u64 dts = gf_filter_pck_get_dts(pck);
		if (dts==GF_FILTER_NO_TS)
		dts = gf_filter_pck_get_cts(pck);

		if (!ctx->first_dts_plus_one) {
			ctx->first_dts_plus_one = dts+1;
		} else {
			if (gf_timestamp_greater(dts + 1 - ctx->first_dts_plus_one, gf_filter_pck_get_timescale(pck), ctx->dur.num, ctx->dur.den)) {
				do_abort = GF_TRUE;
			}
		}
	}
	if (do_abort) {
		GF_FilterEvent evt;
		gf_filter_pid_drop_packet(ctx->ipid);
		GF_FEVT_INIT(evt, GF_FEVT_STOP, ctx->ipid);
		gf_filter_pid_send_event(ctx->ipid, &evt);
		return GF_OK;
	}

	 
	if (!ctx->dash_mode && (gf_filter_pck_get_property(pck, GF_PROP_PCK_FILENUM) != NULL)) {
		ctx->cfg_sent = GF_FALSE;
		ctx->first = GF_TRUE;
	}

	if (ctx->frame) {
		split = GF_TRUE;
	} else if (ctx->dcfg_size && gf_filter_pck_get_sap(pck) && !ctx->is_mj2k && (ctx->decinfo!=DECINFO_NO) && !ctx->cfg_sent) {
		if (ctx->codecid==GF_CODECID_FLAC) {
			u8 *dsi_out;
			dst_pck = gf_filter_pck_new_alloc(ctx->opid, ctx->dcfg_size+4, &dsi_out);
			if (!dst_pck) return GF_OUT_OF_MEM;
			dsi_out[0] = 'f';
			dsi_out[1] = 'L';
			dsi_out[2] = 'a';
			dsi_out[3] = 'C';
			memcpy(dsi_out+4, ctx->dcfg, ctx->dcfg_size);
		} else {
			dst_pck = gf_filter_pck_new_shared(ctx->opid, ctx->dcfg, ctx->dcfg_size, NULL);
			if (!dst_pck) return GF_OUT_OF_MEM;
			gf_filter_pck_set_readonly(dst_pck);
		}
		gf_filter_pck_merge_properties(pck, dst_pck);
		gf_filter_pck_set_framing(dst_pck, ctx->first, GF_FALSE);
		ctx->first = GF_FALSE;
		gf_filter_pck_send(dst_pck);
		if ((ctx->decinfo==DECINFO_FIRST) && !ctx->split) {
			ctx->dcfg_size = 0;
			ctx->dcfg = NULL;
		}
		ctx->cfg_sent = GF_TRUE;
		return GF_OK;
	}
	ctx->cfg_sent = GF_FALSE;
	data = (char *) gf_filter_pck_get_data(pck, &pck_size);

	if (ctx->is_mj2k) {
		dst_pck = writegen_write_j2k(ctx, data, pck_size, pck);
	} else if (ctx->is_bmp) {
		dst_pck = writegen_write_bmp(ctx, data, pck_size);
	} else if (ctx->is_y4m) {
		char *y4m_hdr = NULL;
		if (ctx->is_y4m==1) {
			char szInfo[100];
			const GF_PropertyValue *p;
			gf_dynstrcat(&y4m_hdr, "YUV4MPEG2", NULL);
			sprintf(szInfo, " W%d", ctx->w);
			gf_dynstrcat(&y4m_hdr, szInfo, NULL);
			sprintf(szInfo, " H%d", ctx->h);
			gf_dynstrcat(&y4m_hdr, szInfo, NULL);
			p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_FPS);
			if (p) {
				sprintf(szInfo, " F%d:%d", p->value.frac.num, p->value.frac.den);
				gf_dynstrcat(&y4m_hdr, szInfo, NULL);
			}
			p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_SAR);
			if (p) {
				sprintf(szInfo, " A%d:%d", p->value.frac.num, p->value.frac.den);
				gf_dynstrcat(&y4m_hdr, szInfo, NULL);
			}
			u32 ilce = gf_filter_pck_get_interlaced(pck);
			sprintf(szInfo, " I%c", (ilce==0) ? 'p' : ((ilce==1) ? 't' : 'b'));
			gf_dynstrcat(&y4m_hdr, szInfo, NULL);

			switch (ctx->target_pfmt) {
			case GF_PIXEL_YUV: gf_dynstrcat(&y4m_hdr, " C420mpeg2", NULL); break;
			case GF_PIXEL_YUV444: gf_dynstrcat(&y4m_hdr, " C444", NULL); break;
			case GF_PIXEL_YUV422: gf_dynstrcat(&y4m_hdr, " C422", NULL); break;
			case GF_PIXEL_GREYSCALE: gf_dynstrcat(&y4m_hdr, " Cmono", NULL); break;
			case GF_PIXEL_YUVA444: gf_dynstrcat(&y4m_hdr, " C444alpha", NULL); break;
			}
			p = gf_filter_pid_get_property_str(ctx->ipid, "yuv4meg_meta");
			if (p) {
				gf_dynstrcat(&y4m_hdr, p->value.string, " X");
			}
			gf_dynstrcat(&y4m_hdr, "\n", NULL);
			ctx->is_y4m=2;
		}
		if (ctx->is_y4m==2) {
			gf_dynstrcat(&y4m_hdr, "FRAME\n", NULL);
		}
		u8 * output;
		u32 len = y4m_hdr ? (u32) strlen(y4m_hdr) : 0;
		dst_pck = gf_filter_pck_new_alloc(ctx->opid, pck_size + len, &output);
		if (!dst_pck) return GF_OUT_OF_MEM;
		if (y4m_hdr) memcpy(output, y4m_hdr, len);
		memcpy(output+len, data, pck_size);
		if (ctx->split)
			ctx->is_y4m=1;

		if (y4m_hdr)
			gf_free(y4m_hdr);

	} else if (ctx->is_wav && ctx->first) {
		u8 * output;
		dst_pck = gf_filter_pck_new_alloc(ctx->opid, 44, &output);
		if (!dst_pck) return GF_OUT_OF_MEM;

		gf_filter_pck_merge_properties(pck, dst_pck);
		gf_filter_pck_set_byte_offset(dst_pck, GF_FILTER_NO_BO);
		gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_FALSE);
		gf_filter_pck_set_corrupted(dst_pck, GF_TRUE);
		ctx->first = GF_FALSE;
		gf_filter_pck_send(dst_pck);
		ctx->nb_bytes += 44;
		return GF_OK;
	} else if (ctx->ttml_agg) {
		GF_Err e = writegen_push_ttml(ctx, data, pck_size, pck);
		ctx->first = GF_FALSE;
		if (e) {
			gf_filter_pid_drop_packet(ctx->ipid);
			return e;
		}
		goto no_output;
	} else if (ctx->trunc_audio) {
		u64 dts = gf_filter_pck_get_dts(pck);
		if (dts==GF_FILTER_NO_TS)
			dts = gf_filter_pck_get_cts(pck);

		if (!ctx->first_dts_plus_one) {
			ctx->first_dts_plus_one = dts+1;
		} else {
			u32 timescale = gf_filter_pck_get_timescale(pck);
			u32 dur = gf_filter_pck_get_duration(pck);
			if (gf_timestamp_greater(dts + dur + 1 - ctx->first_dts_plus_one, timescale, ctx->dur.num, ctx->dur.den)) {
				u32 bpp;
				u8 *odata;
				const GF_PropertyValue *p;
				dur = ctx->dur.num * timescale / ctx->dur.den;
				dur -= (u32) (dts + 1 - ctx->first_dts_plus_one);

				bpp = gf_audio_fmt_bit_depth(ctx->target_afmt);
				p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_NUM_CHANNELS);
				if (p) bpp *= p->value.uint;
				bpp/= 8;

				p = gf_filter_pid_get_property(ctx->ipid, GF_PROP_PID_SAMPLE_RATE);
				if (p && (p->value.uint != timescale)) {
					dur *= p->value.uint;
					dur /= timescale;
				}
				assert(pck_size >= bpp * dur);
				pck_size = bpp * dur;

				dst_pck = gf_filter_pck_new_alloc(ctx->opid, pck_size, &odata);
				if (dst_pck)
					memcpy(odata, data, pck_size);
			}
		}

		if (!dst_pck) {
			dst_pck = gf_filter_pck_new_ref(ctx->opid, 0, 0, pck);
		}

	} else {
		dst_pck = gf_filter_pck_new_ref(ctx->opid, 0, 0, pck);
	}
	if (!dst_pck) return GF_OUT_OF_MEM;
	
	gf_filter_pck_merge_properties(pck, dst_pck);
	 
	gf_filter_pck_set_byte_offset(dst_pck, GF_FILTER_NO_BO);

	if (split) {
		gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_FILENUM, &PROP_UINT(ctx->sample_num) );
		gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
	} else {
		gf_filter_pck_set_framing(dst_pck, ctx->first, GF_FALSE);
		ctx->first = GF_FALSE;
	}

	gf_filter_pck_set_seek_flag(dst_pck, 0);
	gf_filter_pck_send(dst_pck);
	ctx->nb_bytes += pck_size;

no_output:
	if (ctx->exporter) {
		u32 timescale = gf_filter_pck_get_timescale(pck);
		u64 ts = gf_filter_pck_get_dts(pck);
		if (ts==GF_FILTER_NO_TS)
			ts = gf_filter_pck_get_cts(pck);
		if (ts!=GF_FILTER_NO_TS) {
			ts += gf_filter_pck_get_duration(pck);
			ts = gf_timestamp_rescale(ts, timescale, ctx->duration.den);
			gf_set_progress("Exporting", ts, ctx->duration.num);
		}
	}

	gf_filter_pid_drop_packet(ctx->ipid);

	return GF_OK;
}