void on_m2ts_import_data()

in src/media_tools/media_import.c [7509:8345]


void on_m2ts_import_data(GF_M2TS_Demuxer *ts, u32 evt_type, void *par)
{
	GF_Err e;
	GF_ISOSample *samp;
	Bool is_au_start;
	u32 i, count, idx;
	GF_M2TS_Program *prog;
	GF_TSImport *tsimp = (GF_TSImport *) ts->user;
	GF_MediaImporter *import= (GF_MediaImporter *)tsimp->import;
	GF_M2TS_ES *es = NULL;
	GF_M2TS_PES *pes = NULL;

	switch (evt_type) {
	case GF_M2TS_EVT_PAT_FOUND:
		break;
//	case GF_M2TS_EVT_PAT_REPEAT:
//	case GF_M2TS_EVT_SDT_REPEAT:
	case GF_M2TS_EVT_PMT_REPEAT:
		/*abort upon first PMT repeat if not using 4on2. Otherwise we must parse the entire
		bitstream to locate ODs sent in OD updates in order to get their stream types...*/
		/*		if (!ts->has_4on2 && (import->flags & GF_IMPORT_PROBE_ONLY) && !import->trackID)
					import->flags |= GF_IMPORT_DO_ABORT;
		*/
		break;
	case GF_M2TS_EVT_PMT_UPDATE:
		gf_import_message(import, GF_OK, "[MPEG-2 TS] PMT Update found - cannot import any further");
		import->flags |= GF_IMPORT_DO_ABORT;
		break;
	case GF_M2TS_EVT_DURATION_ESTIMATED:
		prog = (GF_M2TS_Program*)par;

		if (import->flags & GF_IMPORT_PROBE_ONLY) {
			import->probe_duration = ((GF_M2TS_PES_PCK *) par)->PTS;
		}
		break;

	/*case GF_M2TS_EVT_SDT_FOUND:
		import->nb_progs = gf_list_count(ts->SDTs);
		for (i=0; i<import->nb_progs; i++) {
			GF_M2TS_SDT *sdt = (GF_M2TS_SDT *)gf_list_get(ts->SDTs, i);
			strcpy(import->pg_info[i].name, sdt->service);
			import->pg_info[i].number = sdt->service_id;
		}
		if (!ts->has_4on2 && import->flags & GF_IMPORT_PROBE_ONLY)
			//import->flags |= GF_IMPORT_DO_ABORT;
		break;*/
	case GF_M2TS_EVT_PMT_FOUND:
		prog = (GF_M2TS_Program*)par;

		if (import->flags & GF_IMPORT_PROBE_ONLY) {
			/*
				we scan all the streams declared in this PMT to fill the tk_info structures
				NOTE: in the T-DMB case, we also need to decode ObjectDescriptor Updates see "case GF_M2TS_EVT_SL_PCK"
			*/
			count = gf_list_count(prog->streams);
			for (i=0; i<count; i++) {
				es = (GF_M2TS_ES *)gf_list_get(prog->streams, i);
				if (es->pid == prog->pmt_pid) continue;
				if (es->flags & GF_M2TS_ES_IS_SECTION) {
					//ses = (GF_M2TS_SECTION_ES *)es;
				} else {
					pes = (GF_M2TS_PES *)es;
					gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT);
				}
				idx = import->nb_tracks;
				import->tk_info[idx].track_num = es->pid;
				import->tk_info[idx].prog_num = prog->number;
				import->tk_info[idx].mpeg4_es_id = es->mpeg4_es_id;

				switch (es->stream_type) {
				case GF_M2TS_VIDEO_MPEG1:
					import->tk_info[idx].media_type = GF_4CC('M','P','G','1');
					import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_video++;
					break;
				case GF_M2TS_VIDEO_MPEG2:
					import->tk_info[idx].media_type = GF_4CC('M','P','G','2');
					import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_video++;
					break;
				case GF_M2TS_VIDEO_MPEG4:
					import->tk_info[idx].media_type = GF_4CC('M','P','4','V');
					import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_video++;
					break;
				case GF_M2TS_VIDEO_H264:
				case GF_M2TS_VIDEO_SVC:
					import->tk_info[idx].media_type = (es->stream_type==GF_M2TS_VIDEO_SVC) ? GF_4CC('S','V','C',' ') : GF_4CC('H','2','6','4');
					import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_video++;
					break;
				case GF_M2TS_VIDEO_HEVC:
				case GF_M2TS_VIDEO_SHVC:
					import->tk_info[idx].media_type = (es->stream_type==GF_M2TS_VIDEO_SHVC) ? GF_4CC('S','H','V','C') : GF_4CC('H','E','V','C');
					import->tk_info[idx].type = GF_ISOM_MEDIA_VISUAL;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_video++;
					break;
				case GF_M2TS_AUDIO_MPEG1:
					import->tk_info[idx].media_type = GF_4CC('M','P','G','1');
					import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_audio++;
					break;
				case GF_M2TS_AUDIO_MPEG2:
					import->tk_info[idx].media_type = GF_4CC('M','P','G','2');
					import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_audio++;
					break;
				case GF_M2TS_AUDIO_AAC:
				case GF_M2TS_AUDIO_LATM_AAC:
					import->tk_info[idx].media_type = GF_4CC('M','P','4','A');
					import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_audio++;
					break;
				case GF_M2TS_AUDIO_AC3:
					import->tk_info[idx].media_type = GF_4CC('D','A','C','3');
					import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_audio++;
					break;
				case GF_M2TS_AUDIO_EC3:
					import->tk_info[idx].media_type = GF_4CC('D','E','C','3');
					import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_audio++;
					break;
				case GF_M2TS_AUDIO_DTS:
					import->tk_info[idx].media_type = GF_4CC('D','T','S',' ');
					import->tk_info[idx].type = GF_ISOM_MEDIA_AUDIO;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					tsimp->nb_audio++;
					break;
				case GF_M2TS_SYSTEMS_MPEG4_PES:
				case GF_M2TS_SYSTEMS_MPEG4_SECTIONS:
					if (es->stream_type == GF_M2TS_SYSTEMS_MPEG4_PES) {
						import->tk_info[idx].media_type = GF_4CC('M','4','S','P');
					} else {
						import->tk_info[idx].media_type = GF_4CC('M','4','S','S');
					}
					if (prog->pmt_iod) {
						GF_ESD *esd = gf_m2ts_get_esd(es);
						m2ts_set_track_mpeg4_probe_info(es, esd, &import->tk_info[idx]);
						if (esd && esd->decoderConfig->streamType == GF_STREAM_OD) {
							es->flags |= GF_M2TS_ES_IS_MPEG4_OD;
						}
					} else {
						import->tk_info[idx].type = GF_ISOM_MEDIA_ESM;
					}
					import->nb_tracks++;
					break;
				case GF_M2TS_METADATA_ID3_HLS:
					import->tk_info[idx].media_type = GF_4CC('I','D','3',' ');
					import->tk_info[idx].type = GF_ISOM_MEDIA_META;
					import->tk_info[idx].lang = pes->lang;
					import->nb_tracks++;
					break;
				default:
					gf_import_message(import, GF_OK, "[MPEG-2 TS] Ignoring stream of type %d", es->stream_type);
				}
			}
		} else {
			/* We are not in PROBE mode, we are importing only one stream and don't care about the other streams */
			u32 mtype, stype, oti;
			Bool is_in_iod, found;

			/* Since the GF_M2TS_ES_IS_MPEG4_OD flag is stored at the ES level and ES are reset after probe,
			   we need to set it again as in probe mode */
			found = GF_FALSE;
			count = gf_list_count(prog->streams);
			for (i=0; i<count; i++) {
				GF_ESD *esd;
				es = (GF_M2TS_ES *)gf_list_get(prog->streams, i);
				if (es->pid == prog->pmt_pid) continue;
				if (es->pid == import->trackID) found = GF_TRUE;
				if (es->flags & GF_M2TS_ES_IS_SECTION) {
					//ses = (GF_M2TS_SECTION_ES *)es;
				} else {
					pes = (GF_M2TS_PES *)es;
				}
				esd = gf_m2ts_get_esd(es);
				if (esd && esd->decoderConfig->streamType == GF_STREAM_OD) {
					es->flags |= GF_M2TS_ES_IS_MPEG4_OD;
				}
			}
			/*this PMT is not the one of our stream*/
			if (!found || !ts->ess[import->trackID]) return;

			/*make sure all the streams in this programe are in RAW pes framing mode, so that we get notified of the
			DTS/PTS*/
			for (i=0; i<count; i++) {
				es = (GF_M2TS_ES *)gf_list_get(prog->streams, i);
				if (!(es->flags & GF_M2TS_ES_IS_SECTION)) {
					gf_m2ts_set_pes_framing((GF_M2TS_PES *)es, GF_M2TS_PES_FRAMING_RAW);
				}
			}

			es = ts->ess[import->trackID]; /* import->trackID == pid */

			if (es->flags & GF_M2TS_ES_IS_SECTION) {
				//ses = (GF_M2TS_SECTION_ES *)es;
			} else {
				pes = (GF_M2TS_PES *)es;
				gf_m2ts_set_pes_framing(pes, GF_M2TS_PES_FRAMING_DEFAULT_NAL);
			}

			mtype = stype = oti = 0;
			is_in_iod = GF_FALSE;

			switch (es->stream_type) {
			case GF_M2TS_VIDEO_MPEG1:
				mtype = GF_ISOM_MEDIA_VISUAL;
				stype = GF_STREAM_VISUAL;
				oti = GPAC_OTI_VIDEO_MPEG1;
				break;
			case GF_M2TS_VIDEO_MPEG2:
				mtype = GF_ISOM_MEDIA_VISUAL;
				stype = GF_STREAM_VISUAL;
				oti = GPAC_OTI_VIDEO_MPEG2_422;
				break;
			case GF_M2TS_VIDEO_MPEG4:
				mtype = GF_ISOM_MEDIA_VISUAL;
				stype = GF_STREAM_VISUAL;
				oti = GPAC_OTI_VIDEO_MPEG4_PART2;
				break;
			case GF_M2TS_VIDEO_H264:
				mtype = GF_ISOM_MEDIA_VISUAL;
				stype = GF_STREAM_VISUAL;
				oti = GPAC_OTI_VIDEO_AVC;
				tsimp->avccfg = gf_odf_avc_cfg_new();
				break;
			case GF_M2TS_VIDEO_HEVC:
			case GF_M2TS_VIDEO_SHVC:
				mtype = GF_ISOM_MEDIA_VISUAL;
				stype = GF_STREAM_VISUAL;
				oti = GPAC_OTI_VIDEO_HEVC;
#ifndef GPAC_DISABLE_HEVC
				tsimp->hevccfg = gf_odf_hevc_cfg_new();
#endif //GPAC_DISABLE_HEVC
				break;
			case GF_M2TS_VIDEO_SVC:
				mtype = GF_ISOM_MEDIA_VISUAL;
				stype = GF_STREAM_VISUAL;
				oti = GPAC_OTI_VIDEO_SVC;
				tsimp->avccfg = gf_odf_avc_cfg_new();
				break;
			case GF_M2TS_AUDIO_MPEG1:
				mtype = GF_ISOM_MEDIA_AUDIO;
				stype = GF_STREAM_AUDIO;
				oti = GPAC_OTI_AUDIO_MPEG1;
				break;
			case GF_M2TS_AUDIO_MPEG2:
				mtype = GF_ISOM_MEDIA_AUDIO;
				stype = GF_STREAM_AUDIO;
				oti = GPAC_OTI_AUDIO_MPEG2_PART3;
				break;
			case GF_M2TS_AUDIO_LATM_AAC:
			case GF_M2TS_AUDIO_AAC:
				mtype = GF_ISOM_MEDIA_AUDIO;
				stype = GF_STREAM_AUDIO;
				oti = GPAC_OTI_AUDIO_AAC_MPEG4;
				break;
			case GF_M2TS_AUDIO_AC3:
				mtype = GF_ISOM_MEDIA_AUDIO;
				stype = GF_STREAM_AUDIO;
				oti = GPAC_OTI_AUDIO_AC3;
				break;
			case GF_M2TS_SYSTEMS_MPEG4_PES:
			case GF_M2TS_SYSTEMS_MPEG4_SECTIONS:
				if (prog->pmt_iod && !import->esd) {
					import->esd = gf_m2ts_get_esd(es);
					m2ts_set_track_mpeg4_creation_info(import, &mtype, &stype, &oti);
					is_in_iod = GF_TRUE;
				}
				break;
			}
			m2ts_create_track(tsimp, mtype, stype, oti, es->mpeg4_es_id, is_in_iod);
		}
		break;
	case GF_M2TS_EVT_AAC_CFG:
		if (!(import->flags & GF_IMPORT_PROBE_ONLY) && !tsimp->stream_setup) {
			GF_ESD *esd = gf_isom_get_esd(import->dest, tsimp->track, 1);
			if (esd) {
				if (!esd->decoderConfig->decoderSpecificInfo) esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
				if (esd->decoderConfig->decoderSpecificInfo->data) gf_free(esd->decoderConfig->decoderSpecificInfo->data);
				esd->decoderConfig->decoderSpecificInfo->data = ((GF_M2TS_PES_PCK*)par)->data;
				esd->decoderConfig->decoderSpecificInfo->dataLength = ((GF_M2TS_PES_PCK*)par)->data_len;
				gf_isom_change_mpeg4_description(import->dest, tsimp->track, 1, esd);
				esd->decoderConfig->decoderSpecificInfo->data = NULL;
				gf_odf_desc_del((GF_Descriptor *)esd);
				tsimp->stream_setup = GF_TRUE;
				gf_isom_set_audio_info(import->dest, tsimp->track, 1, ((GF_M2TS_PES_PCK*)par)->stream->aud_sr, ((GF_M2TS_PES_PCK*)par)->stream->aud_nb_ch, 8);
			}
		}
		break;
	case GF_M2TS_EVT_PES_PCK:
	{
		GF_M2TS_PES_PCK *pck = (GF_M2TS_PES_PCK *)par;
		is_au_start = (pck->flags & GF_M2TS_PES_PCK_AU_START);

		if (import->flags & GF_IMPORT_PROBE_ONLY) {
			for (i=0; i<import->nb_tracks; i++) {
				if (import->tk_info[i].track_num == pck->stream->pid) {
					if (pck->stream->aud_sr && ! import->tk_info[i].audio_info.sample_rate) {
						import->tk_info[i].audio_info.sample_rate = pck->stream->aud_sr;
						import->tk_info[i].audio_info.nb_channels = pck->stream->aud_nb_ch;
						if ((pck->stream->stream_type==GF_M2TS_AUDIO_AAC) || (pck->stream->stream_type==GF_M2TS_AUDIO_LATM_AAC)) {
							sprintf(import->tk_info[i].szCodecProfile, "mp4a.40.%02x", (u8) pck->stream->aud_aac_obj_type);
						}
						import->tk_info[i].audio_info.sample_rate = pck->stream->aud_sr;
						import->tk_info[i].audio_info.nb_channels = pck->stream->aud_nb_ch;
						tsimp->nb_audio_configured++;
					}
					/*unpack AVC config*/
					else if (((pck->stream->stream_type==GF_M2TS_VIDEO_H264) || (pck->stream->stream_type==GF_M2TS_VIDEO_SVC)) && !pck->data[0] && !pck->data[1]) {
						u32 nal_type = pck->data[4] & 0x1F;
						if (nal_type == GF_AVC_NALU_SEQ_PARAM) {
							sprintf(import->tk_info[i].szCodecProfile, "avc1.%02x%02x%02x", (u8) pck->data[5], (u8) pck->data[6], (u8) pck->data[7]);
						}
					}
					else if (pck->stream->stream_type==GF_M2TS_VIDEO_HEVC) {
						u32 nal_type = (pck->data[4] & 0x7E) >> 1;
						if (nal_type == GF_HEVC_NALU_SEQ_PARAM) {
							//todo ..;
							sprintf(import->tk_info[i].szCodecProfile, "hvc1");
						}
					}
					else if ((pck->stream->stream_type==GF_M2TS_AUDIO_EC3) || (pck->stream->stream_type==GF_M2TS_AUDIO_AC3) || (pck->stream->stream_type==GF_M2TS_AUDIO_DTS)) {
						if (!import->tk_info[i].audio_info.sample_rate) {
							//todo ...
							import->tk_info[i].audio_info.sample_rate = 44100;
							import->tk_info[i].audio_info.nb_channels = 2;
							tsimp->nb_audio_configured++;
						}
					}

					if (pck->stream->vid_w && ! import->tk_info[i].video_info.width ) {
						import->tk_info[i].video_info.width = pck->stream->vid_w;
						import->tk_info[i].video_info.height = pck->stream->vid_h;
						tsimp->nb_video_configured++;
					}

					/*consider we are done if not using 4 on 2*/
					if (!ts->has_4on2
					        && (tsimp->nb_video_configured == tsimp->nb_video)
					        && (tsimp->nb_audio_configured == tsimp->nb_audio)
					        && import->probe_duration
					   ) {
						import->flags |= GF_IMPORT_DO_ABORT;
					}
					break;
				}
			}
			if (!ts->has_4on2 && (import->trackID==pck->stream->pid) && (pck->stream->vid_h || pck->stream->aud_sr) )
				import->flags |= GF_IMPORT_DO_ABORT;
			return;
		}

		/* Even if we don't import this stream we need to check the first dts of the program */
		if (!(pck->stream->flags & GF_M2TS_ES_FIRST_DTS) && is_au_start) {
			pck->stream->flags |= GF_M2TS_ES_FIRST_DTS;
			pck->stream->first_dts = (pck->PTS!=pck->DTS) ? pck->DTS : pck->PTS;
			if (!pck->stream->program->first_dts || pck->stream->program->first_dts > pck->stream->first_dts) {
				pck->stream->program->first_dts = pck->stream->first_dts;

				if (pck->stream->pid != import->trackID) {
					gf_m2ts_set_pes_framing((GF_M2TS_PES *)pck->stream, GF_M2TS_PES_FRAMING_SKIP);
				}
			}
		}
		if (pck->stream->pid != import->trackID) return;

		/*avc data for the current sample is stored in annex-B, as we don't know the size of each nal
		when called back (depending on PES packetization, the end of the nal could be in following pes)*/
		if (tsimp->avccfg && !pck->data[0] && !pck->data[1]) {
			GF_AVCConfigSlot *slc;
			s32 idx;
			Bool add_sps, is_subseq = GF_FALSE;
			u32 nal_type = pck->data[4] & 0x1F;

			switch (nal_type) {
			case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
				is_subseq = GF_TRUE;
			case GF_AVC_NALU_SEQ_PARAM:
				idx = gf_media_avc_read_sps(pck->data+4, pck->data_len-4, &tsimp->avc, is_subseq, NULL);

				add_sps = GF_FALSE;
				if (idx>=0) {
					if (is_subseq) {
						if ((tsimp->avc.sps[idx].state & AVC_SUBSPS_PARSED) && !(tsimp->avc.sps[idx].state & AVC_SUBSPS_DECLARED)) {
							tsimp->avc.sps[idx].state |= AVC_SUBSPS_DECLARED;
							add_sps = GF_TRUE;
						}
					} else {
						if ((tsimp->avc.sps[idx].state & AVC_SPS_PARSED) && !(tsimp->avc.sps[idx].state & AVC_SPS_DECLARED)) {
							tsimp->avc.sps[idx].state |= AVC_SPS_DECLARED;
							add_sps = GF_TRUE;
						}
					}
					if (add_sps) {
						/*always store nalu size on 4 bytes*/
						tsimp->avccfg->nal_unit_size = 4;
						tsimp->avccfg->configurationVersion = 1;
						tsimp->avccfg->profile_compatibility = tsimp->avc.sps[idx].prof_compat;
						tsimp->avccfg->AVCProfileIndication = tsimp->avc.sps[idx].profile_idc;
						tsimp->avccfg->AVCLevelIndication = tsimp->avc.sps[idx].level_idc;

						if (pck->stream->vid_w < tsimp->avc.sps[idx].width)
							pck->stream->vid_w = tsimp->avc.sps[idx].width;
						if (pck->stream->vid_h < tsimp->avc.sps[idx].height)
							pck->stream->vid_h = tsimp->avc.sps[idx].height;

						if (!(import->flags & GF_IMPORT_FORCE_XPS_INBAND)) {
							slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
							slc->size = pck->data_len-4;
							slc->data = (char*)gf_malloc(sizeof(char)*slc->size);
							memcpy(slc->data, pck->data+4, sizeof(char)*slc->size);
							gf_list_add(tsimp->avccfg->sequenceParameterSets, slc);
						}
					}
				}
				if (import->flags & GF_IMPORT_FORCE_XPS_INBAND) {
					break;
				}
				return;
			case GF_AVC_NALU_PIC_PARAM:
				idx = gf_media_avc_read_pps(pck->data+4, pck->data_len-4, &tsimp->avc);
				if ((idx>=0) && (tsimp->avc.pps[idx].status==1)) {
					tsimp->avc.pps[idx].status = 2;
					if (!(import->flags & GF_IMPORT_FORCE_XPS_INBAND)) {
						slc = (GF_AVCConfigSlot*)gf_malloc(sizeof(GF_AVCConfigSlot));
						slc->size = pck->data_len-4;
						slc->data = (char*)gf_malloc(sizeof(char)*slc->size);
						memcpy(slc->data, pck->data+4, sizeof(char)*slc->size);
						gf_list_add(tsimp->avccfg->pictureParameterSets, slc);
					}
				}
				if (import->flags & GF_IMPORT_FORCE_XPS_INBAND) {
					break;
				}
				/*else discard because of invalid PPS*/
				return;
			/*remove*/
			case GF_AVC_NALU_ACCESS_UNIT:
				tsimp->force_next_au_start = GF_TRUE;
				return;
			case GF_AVC_NALU_FILLER_DATA:
			case GF_AVC_NALU_END_OF_SEQ:
			case GF_AVC_NALU_END_OF_STREAM:
				return;
			case GF_AVC_NALU_SEI:
				break;

			}

			if (tsimp->force_next_au_start) {
				is_au_start = GF_TRUE;
				tsimp->force_next_au_start = GF_FALSE;
			}
		}

		/*avc data for the current sample is stored in annex-B, as we don't know the size of each nal
		when called back (depending on PES packetization, the end of the nal could be in following pes)*/
#ifndef GPAC_DISABLE_HEVC
		else if (tsimp->hevccfg && !pck->data[0] && !pck->data[1]) {
			s32 idx;
			Bool add_sps, is_subseq = GF_FALSE;
			u32 nal_type = (pck->data[4] & 0x7E) >> 1;

			switch (nal_type) {
			case GF_HEVC_NALU_SEQ_PARAM:
				idx = gf_media_hevc_read_sps(pck->data+4, pck->data_len-4, &tsimp->hevc);
				add_sps = GF_FALSE;
				if (idx>=0) {
					if (is_subseq) {
						if ((tsimp->hevc.sps[idx].state & AVC_SUBSPS_PARSED) && !(tsimp->hevc.sps[idx].state & AVC_SUBSPS_DECLARED)) {
							tsimp->hevc.sps[idx].state |= AVC_SUBSPS_DECLARED;
							add_sps = GF_TRUE;
						}
					} else {
						if ((tsimp->hevc.sps[idx].state & AVC_SPS_PARSED) && !(tsimp->hevc.sps[idx].state & AVC_SPS_DECLARED)) {
							tsimp->hevc.sps[idx].state |= AVC_SPS_DECLARED;
							add_sps = GF_TRUE;
						}
					}
					if (add_sps) {
						/*always store nalu size on 4 bytes*/
						tsimp->hevccfg->nal_unit_size = 4;
						tsimp->hevccfg->configurationVersion = 1;

						tsimp->hevccfg->configurationVersion = 1;
						tsimp->hevccfg->profile_space = tsimp->hevc.sps[idx].ptl.profile_space;
						tsimp->hevccfg->profile_idc = tsimp->hevc.sps[idx].ptl.profile_idc;
						tsimp->hevccfg->constraint_indicator_flags = 0;
						tsimp->hevccfg->level_idc = tsimp->hevc.sps[idx].ptl.level_idc;
						tsimp->hevccfg->general_profile_compatibility_flags = tsimp->hevc.sps[idx].ptl.profile_compatibility_flag;
						tsimp->hevccfg->chromaFormat = tsimp->hevc.sps[idx].chroma_format_idc;
						tsimp->hevccfg->luma_bit_depth = tsimp->hevc.sps[idx].bit_depth_luma;
						tsimp->hevccfg->chroma_bit_depth = tsimp->hevc.sps[idx].bit_depth_chroma;

						hevc_cfg_add_nalu(import, tsimp->hevccfg, nal_type, pck->data+4, pck->data_len-4);

						if (pck->stream->vid_w < tsimp->avc.sps[idx].width)
							pck->stream->vid_w = tsimp->avc.sps[idx].width;
						if (pck->stream->vid_h < tsimp->avc.sps[idx].height)
							pck->stream->vid_h = tsimp->avc.sps[idx].height;
					}
				}
				if (import->flags & GF_IMPORT_FORCE_XPS_INBAND) {
					is_au_start = GF_TRUE;
					break;
				}
				return;
			case GF_HEVC_NALU_PIC_PARAM:
				idx = gf_media_hevc_read_pps(pck->data+4, pck->data_len-4, &tsimp->hevc);
				if ((idx>=0) && (tsimp->hevc.pps[idx].state==1)) {
					tsimp->hevc.pps[idx].state = 2;
					hevc_cfg_add_nalu(import, tsimp->hevccfg, nal_type, pck->data+4, pck->data_len-4);
				}
				if (import->flags & GF_IMPORT_FORCE_XPS_INBAND) {
					is_au_start = GF_TRUE;
					break;
				}
				return;
			case GF_HEVC_NALU_VID_PARAM:
				idx = gf_media_hevc_read_vps(pck->data+4, pck->data_len-4, &tsimp->hevc);
				if ((idx>=0) && (tsimp->hevc.vps[idx].state==1)) {
					tsimp->hevc.vps[idx].state = 2;
					tsimp->hevccfg->avgFrameRate = tsimp->hevc.vps[idx].rates[0].avg_pic_rate;
					tsimp->hevccfg->constantFrameRate = tsimp->hevc.vps[idx].rates[0].constand_pic_rate_idc;
					tsimp->hevccfg->numTemporalLayers = tsimp->hevc.vps[idx].max_sub_layers;
					hevc_cfg_add_nalu(import, tsimp->hevccfg, nal_type, pck->data+4, pck->data_len-4);
				}
				if (import->flags & GF_IMPORT_FORCE_XPS_INBAND) {
					is_au_start = GF_TRUE;
					break;
				}
				return;
			/*remove*/
			case GF_HEVC_NALU_ACCESS_UNIT:
				tsimp->force_next_au_start = GF_TRUE;
				return;
			case GF_HEVC_NALU_FILLER_DATA:
			case GF_HEVC_NALU_END_OF_SEQ:
			case GF_HEVC_NALU_END_OF_STREAM:
				return;
			case GF_HEVC_NALU_SEI_PREFIX:
				is_au_start = GF_TRUE;
				break;
			}

			if (tsimp->force_next_au_start) {
				is_au_start = GF_TRUE;
				tsimp->force_next_au_start = GF_FALSE;
			}
		}
#endif //GPAC_DISABLE_HEVC

		if (!is_au_start) {
			e = gf_isom_append_sample_data(import->dest, tsimp->track, (char*)pck->data, pck->data_len);
			if (e) {
				if (!gf_isom_get_sample_count(import->dest, tsimp->track)) {
					GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] missed beginning of sample data\n"));
					e = GF_OK;
				} else {
					GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] Error appending sample data\n"));
				}
			}
			if (pck->flags & GF_M2TS_PES_PCK_I_FRAME) tsimp->nb_i++;
			if (pck->flags & GF_M2TS_PES_PCK_P_FRAME) tsimp->nb_p++;
			if (pck->flags & GF_M2TS_PES_PCK_B_FRAME) tsimp->nb_b++;

			if (pck->flags & GF_M2TS_PES_PCK_RAP) {
				e = gf_isom_set_sample_rap(import->dest, tsimp->track);
			}
			return;
		}

		samp = gf_isom_sample_new();
		samp->DTS = pck->DTS;
		samp->CTS_Offset = (u32) (pck->PTS - samp->DTS);

		if (pck->stream->first_dts==samp->DTS) {
			switch (pck->stream->stream_type) {
			case GF_M2TS_VIDEO_MPEG1:
				gf_import_message(import, GF_OK, "MPEG-1 Video import (TS PID %d)", pck->stream->pid);
				break;
			case GF_M2TS_VIDEO_MPEG2:
				gf_import_message(import, GF_OK, "MPEG-2 Video import (TS PID %d)", pck->stream->pid);
				break;
			case GF_M2TS_VIDEO_MPEG4:
				gf_import_message(import, GF_OK, "MPEG-4 Video import (TS PID %d)", pck->stream->pid);
				break;
			case GF_M2TS_VIDEO_H264:
				gf_import_message(import, GF_OK, "MPEG-4 AVC/H264 Video import (TS PID %d)", pck->stream->pid);
				break;
			case GF_M2TS_VIDEO_HEVC:
				gf_import_message(import, GF_OK, "MPEG-H HEVC Video import (TS PID %d)", pck->stream->pid);
				break;
			case GF_M2TS_VIDEO_SVC:
				gf_import_message(import, GF_OK, "H264-SVC Video import (TS PID %d)", pck->stream->pid);
				break;
			case GF_M2TS_AUDIO_MPEG1:
				gf_import_message(import, GF_OK, "MPEG-1 Audio import - SampleRate %d Channels %d Language %s (TS PID %d)", pck->stream->aud_sr, pck->stream->aud_nb_ch, gf_4cc_to_str(pck->stream->lang), pck->stream->pid);
				break;
			case GF_M2TS_AUDIO_MPEG2:
				gf_import_message(import, GF_OK, "MPEG-2 Audio import - SampleRate %d Channels %d Language %s (TS PID %d)", pck->stream->aud_sr, pck->stream->aud_nb_ch, gf_4cc_to_str(pck->stream->lang), pck->stream->pid);
				break;
			case GF_M2TS_AUDIO_AAC:
				gf_import_message(import, GF_OK, "MPEG-4 AAC Audio import - SampleRate %d Channels %d Language %s (TS PID %d)", pck->stream->aud_sr, pck->stream->aud_nb_ch, gf_4cc_to_str(pck->stream->lang), pck->stream->pid);
				break;
			case GF_M2TS_AUDIO_AC3:
				gf_import_message(import, GF_OK, "Dolby AC3 Audio import - SampleRate %d Channels %d Language %s (TS PID %d)", pck->stream->aud_sr, pck->stream->aud_nb_ch, gf_4cc_to_str(pck->stream->lang), pck->stream->pid);
				break;
			case GF_M2TS_AUDIO_EC3:
				gf_import_message(import, GF_OK, "Dolby E-AC3 Audio import - SampleRate %d Channels %d Language %s (TS PID %d)", pck->stream->aud_sr, pck->stream->aud_nb_ch, gf_4cc_to_str(pck->stream->lang), pck->stream->pid);
				break;
			}
			if (pck->stream->lang)
				gf_isom_set_media_language(import->dest, tsimp->track, (char *) gf_4cc_to_str(pck->stream->lang)+1);
		}
		if (!tsimp->stream_setup) {
			if (pck->stream->aud_sr) {
				gf_isom_set_audio_info(import->dest, tsimp->track, 1, pck->stream->aud_sr, pck->stream->aud_nb_ch, 16);
				tsimp->stream_setup = GF_TRUE;
			}
			else if (pck->stream->vid_w) {
				u32 w = pck->stream->vid_w;
				if (pck->stream->vid_par) w = w * (pck->stream->vid_par>>16) / (pck->stream->vid_par&0xffff);
				gf_isom_set_visual_info(import->dest, tsimp->track, 1, pck->stream->vid_w, pck->stream->vid_h);
				gf_isom_set_track_layout_info(import->dest, tsimp->track, w<<16, pck->stream->vid_h<<16, 0, 0, 0);
				if (w != pck->stream->vid_w)
					e = gf_isom_set_pixel_aspect_ratio(import->dest, tsimp->track, 1, pck->stream->vid_par>>16, pck->stream->vid_par&0xff);

				tsimp->stream_setup = GF_TRUE;
			}
		}

		if (samp->DTS >= pck->stream->first_dts) {
			samp->DTS -= pck->stream->first_dts;
			samp->IsRAP = (pck->flags & GF_M2TS_PES_PCK_RAP) ? RAP : RAP_NO;
			samp->data = pck->data;
			samp->dataLength = pck->data_len;

			if (samp->DTS && (samp->DTS==tsimp->last_dts)) {
				e = gf_isom_append_sample_data(import->dest, tsimp->track, (char*)pck->data, pck->data_len);
			} else {

				if (tsimp->avccfg || tsimp->hevccfg) m2ts_rewrite_nalu_sample(import, tsimp);

				e = gf_isom_add_sample(import->dest, tsimp->track, 1, samp);
			}
			if (e) {
				GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] PID %d: Error adding sample: %s\n", pck->stream->pid, gf_error_to_string(e)));
				//import->flags |= GF_IMPORT_DO_ABORT;
				import->last_error = e;
			}
			if (import->duration && (import->duration<=(samp->DTS+samp->CTS_Offset)/90))
				//import->flags |= GF_IMPORT_DO_ABORT;

				if (pck->flags & GF_M2TS_PES_PCK_I_FRAME) tsimp->nb_i++;
			if (pck->flags & GF_M2TS_PES_PCK_P_FRAME) tsimp->nb_p++;
			if (pck->flags & GF_M2TS_PES_PCK_B_FRAME) tsimp->nb_b++;
			tsimp->last_dts = samp->DTS;
		} else {
			GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] negative time sample - skipping\n"));
		}
		samp->data = NULL;
		gf_isom_sample_del(&samp);
	}
	break;
	case GF_M2TS_EVT_SL_PCK:
	{
		GF_M2TS_SL_PCK *sl_pck = (GF_M2TS_SL_PCK *)par;

		/* if there is no IOD for this program we cannot handle SL packets */
		if (!sl_pck->stream->program->pmt_iod) return;

		if (sl_pck->stream->flags & GF_M2TS_ES_IS_SECTION) {
			//ses = (GF_M2TS_SECTION_ES *)sl_pck->stream;
		} else {
			pes = (GF_M2TS_PES *)sl_pck->stream;
		}

		if (sl_pck->stream->flags & GF_M2TS_ES_IS_MPEG4_OD) {
			/* We need to handle OD streams even if this is not the stream we are importing */
			GF_ESD *esd = gf_m2ts_get_esd(sl_pck->stream);
			if (esd) {
				GF_SLHeader hdr;
				u32 hdr_len;
				GF_ODCodec *od_codec = gf_odf_codec_new();
				GF_ODCom *com;
				GF_ODUpdate* odU;
				u32 com_count, com_index, od_count, od_index;

				gf_sl_depacketize(esd->slConfig, &hdr, sl_pck->data, sl_pck->data_len, &hdr_len);
				gf_odf_codec_set_au(od_codec, sl_pck->data+hdr_len, sl_pck->data_len - hdr_len);
				gf_odf_codec_decode(od_codec);
				com_count = gf_list_count(od_codec->CommandList);
				for (com_index = 0; com_index < com_count; com_index++) {
					com = (GF_ODCom *)gf_list_get(od_codec->CommandList, com_index);
					switch (com->tag) {
					case GF_ODF_OD_UPDATE_TAG:
						odU = (GF_ODUpdate*)com;
						od_count = gf_list_count(odU->objectDescriptors);
						for (od_index=0; od_index<od_count; od_index++) {
							GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, od_index);
							gf_list_add(sl_pck->stream->program->additional_ods, od);

							/* We need to set the remaining unset track info for the streams declared in this OD */
							m2ts_set_tracks_mpeg4_probe_info(import, sl_pck->stream->program, od->ESDescriptors);
						}
						gf_list_reset(odU->objectDescriptors);
					}
				}
				gf_odf_codec_del(od_codec);
			}

		}

		if (import->flags & GF_IMPORT_PROBE_ONLY) {
			if (pes) {
				for (i=0; i<import->nb_tracks; i++) {
					if (import->tk_info[i].track_num == sl_pck->stream->pid) {
						if (pes->aud_sr) {
							import->tk_info[i].audio_info.sample_rate = pes->aud_sr;
							import->tk_info[i].audio_info.nb_channels = pes->aud_nb_ch;
						} else {
							import->tk_info[i].video_info.width = pes->vid_w;
							import->tk_info[i].video_info.height = pes->vid_h;
						}
						break;
					}
				}
//					if (pes->vid_h || pes->aud_sr) import->flags |= GF_IMPORT_DO_ABORT;
			}
			return;
		}

		if (sl_pck->stream->pid != import->trackID) return;

		/* we create a track for the stream to import only if it was not created */
		if (!gf_isom_get_track_by_id(import->dest, (import->esd?import->esd->ESID:import->trackID))) {
			u32 mtype, stype, oti;
			mtype = stype = oti = 0;
			import->esd = gf_m2ts_get_esd(sl_pck->stream);
			m2ts_set_track_mpeg4_creation_info(import, &mtype, &stype, &oti);
			m2ts_create_track(tsimp, mtype, stype, oti, sl_pck->stream->mpeg4_es_id, GF_FALSE);
		}

		if (import->esd) {
			GF_SLHeader hdr;
			u32 hdr_len;
			gf_sl_depacketize(import->esd->slConfig, &hdr, sl_pck->data, sl_pck->data_len, &hdr_len);

			if (!hdr.accessUnitStartFlag) {
				e = gf_isom_append_sample_data(import->dest, tsimp->track, sl_pck->data + hdr_len, sl_pck->data_len - hdr_len);
				if (e) {
					GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] Error appending sample data\n"));
				}
			} else {
				if (!(sl_pck->stream->flags & GF_M2TS_ES_FIRST_DTS)) {
					sl_pck->stream->flags |= GF_M2TS_ES_FIRST_DTS;

					if (!hdr.compositionTimeStampFlag) {
						hdr.compositionTimeStamp = sl_pck->stream->program->first_dts;
						GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] PID %d First SL Access unit start flag set without any composition time stamp - defaulting to last CTS seen on program\n", sl_pck->stream->pid));
					}
					sl_pck->stream->first_dts = (hdr.decodingTimeStamp?hdr.decodingTimeStamp:hdr.compositionTimeStamp);
					if (!sl_pck->stream->program->first_dts ||
					        sl_pck->stream->program->first_dts > sl_pck->stream->first_dts) {
						sl_pck->stream->program->first_dts = sl_pck->stream->first_dts;
					}
				} else {
					if (!hdr.compositionTimeStampFlag) {
						hdr.compositionTimeStamp = sl_pck->stream->first_dts + tsimp->last_dts+1;
						GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] PID %d SL Access unit start flag set without any composition time stamp - defaulting to last CTS seen on stream + 1\n", sl_pck->stream->pid));
					}
				}

				samp = gf_isom_sample_new();
				samp->DTS = (hdr.decodingTimeStamp?hdr.decodingTimeStamp:hdr.compositionTimeStamp);
				samp->CTS_Offset = (u32) (hdr.compositionTimeStamp - samp->DTS);
				if (samp->DTS >= sl_pck->stream->first_dts) {
					samp->DTS -= sl_pck->stream->first_dts;
					samp->IsRAP = import->esd->slConfig->useRandomAccessPointFlag ? hdr.randomAccessPointFlag : RAP;

					/*fix for some DMB streams where TSs are not coded*/
					if ((tsimp->last_dts == samp->DTS) && gf_isom_get_sample_count(import->dest, tsimp->track))
						samp->DTS += gf_isom_get_media_timescale(import->dest, tsimp->track);

					samp->data = sl_pck->data + hdr_len;
					samp->dataLength = sl_pck->data_len - hdr_len;

					e = gf_isom_add_sample(import->dest, tsimp->track, 1, samp);
					/*if CTS was not specified, samples will simply be skipped*/
					if (e) {
						GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] PID %d Error adding sample\n", sl_pck->stream->pid));
					}
					if (import->duration && (import->duration<=(samp->DTS+samp->CTS_Offset)/90)) {
						//import->flags |= GF_IMPORT_DO_ABORT;
					}
					tsimp->last_dts = samp->DTS;

				} else {
					GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[MPEG-2 TS Import] negative time sample - skipping\n"));
					sl_pck->stream->first_dts = samp->DTS;
					if (!sl_pck->stream->program->first_dts ||
					        sl_pck->stream->program->first_dts > sl_pck->stream->first_dts) {
						sl_pck->stream->program->first_dts = sl_pck->stream->first_dts;
					}
				}
				samp->data = NULL;
				gf_isom_sample_del(&samp);
			}
		}
	}
	break;
	}
}