1 /*
2  *			GPAC - Multimedia Framework C SDK
3  *
4  *			Authors: Jean Le Feuvre
5  *			Copyright (c) Telecom ParisTech 2000-2019
6  *					All rights reserved
7  *
8  *  This file is part of GPAC / ISO Media File Format sub-project
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/internal/isomedia_dev.h>
27 #include <gpac/network.h>
28 
29 #ifndef GPAC_DISABLE_ISOM
30 
31 
gf_isom_datamap_del(GF_DataMap * ptr)32 void gf_isom_datamap_del(GF_DataMap *ptr)
33 {
34 	if (!ptr) return;
35 
36 	if (ptr->szName) gf_free(ptr->szName);
37 
38 	//then delete the structure itself....
39 	switch (ptr->type) {
40 	//file-based
41 	case GF_ISOM_DATA_FILE:
42 	case GF_ISOM_DATA_MEM:
43 		gf_isom_fdm_del((GF_FileDataMap *)ptr);
44 		break;
45 	case GF_ISOM_DATA_FILE_MAPPING:
46 		gf_isom_fmo_del((GF_FileMappingDataMap *)ptr);
47 		break;
48 	default:
49 		if (ptr->bs) gf_bs_del(ptr->bs);
50 		gf_free(ptr);
51 		break;
52 	}
53 }
54 
55 //Close a data entry
gf_isom_datamap_close(GF_MediaInformationBox * minf)56 void gf_isom_datamap_close(GF_MediaInformationBox *minf)
57 {
58 	GF_DataEntryBox *ent = NULL;
59 	if (!minf || !minf->dataHandler) return;
60 
61 	if (minf->dataInformation && minf->dataInformation->dref) {
62 		ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->child_boxes, minf->dataEntryIndex - 1);
63 	}
64 
65 	//if ent NULL, the data entry was not used (smooth)
66 	if (ent == NULL) return;
67 
68 	//self contained, do nothing
69 	switch (ent->type) {
70 	case GF_ISOM_BOX_TYPE_URL:
71 	case GF_ISOM_BOX_TYPE_URN:
72 		if (ent->flags == 1) return;
73 		break;
74 	default:
75 		return;
76 	}
77 
78 	//finally close it
79 	gf_isom_datamap_del(minf->dataHandler);
80 	minf->dataHandler = NULL;
81 }
82 
83 /*cf below, we disable filedatamap since it tricks mem usage on w32*/
84 #if 0
85 static Bool IsLargeFile(char *path)
86 {
87 #ifndef _WIN32_WCE
88 	FILE *stream;
89 	s64 size;
90 	stream = gf_fopen(path, "rb");
91 	if (!stream) return 0;
92 	size = gf_fsize(stream);
93 	gf_fclose(stream);
94 	if (size == -1L) return 0;
95 	if (size > 0xFFFFFFFF) return 1;
96 #endif
97 	return 0;
98 }
99 #endif
100 
101 
102 //Special constructor, we need some error feedback...
103 
gf_isom_datamap_new(const char * location,const char * parentPath,u8 mode,GF_DataMap ** outDataMap)104 GF_Err gf_isom_datamap_new(const char *location, const char *parentPath, u8 mode, GF_DataMap **outDataMap)
105 {
106 	Bool extern_file;
107 	char *sPath;
108 	*outDataMap = NULL;
109 
110 	//if nothing specified, this is a MEMORY data map
111 	if (!location) {
112 		*outDataMap = gf_isom_fdm_new(location, GF_ISOM_DATA_MAP_WRITE);
113 		if (!(*outDataMap)) {
114 			return GF_IO_ERR;
115 		}
116 		return GF_OK;
117 	}
118 	//we need a temp file ...
119 	if (!strcmp(location, "mp4_tmp_edit")) {
120 #ifndef GPAC_DISABLE_ISOM_WRITE
121 		*outDataMap = gf_isom_fdm_new_temp(parentPath);
122 		if (! (*outDataMap)) {
123 			return GF_IO_ERR;
124 		}
125 		return GF_OK;
126 #else
127 		return GF_NOT_SUPPORTED;
128 #endif
129 	} else if (!strncmp(location, "gmem://", 7) || !strncmp(location, "gfio://", 7)) {
130 		*outDataMap = gf_isom_fdm_new(location, GF_ISOM_DATA_MAP_READ);
131 		if (! (*outDataMap)) {
132 			return GF_IO_ERR;
133 		}
134 		return GF_OK;
135 	} else if (!strcmp(location, "_gpac_isobmff_redirect")) {
136 		*outDataMap = gf_isom_fdm_new(location, mode);
137 		if (! (*outDataMap)) {
138 			return GF_IO_ERR;
139 		}
140 		return GF_OK;
141 	}
142 
143 	extern_file = !gf_url_is_local(location);
144 
145 	if (mode == GF_ISOM_DATA_MAP_EDIT) {
146 		//we need a local file for edition!!!
147 		if (extern_file) return GF_ISOM_INVALID_MODE;
148 		//OK, switch back to READ mode
149 		mode = GF_ISOM_DATA_MAP_READ;
150 	}
151 
152 	//TEMP: however, only support for file right now (we'd have to add some callback functions at some point)
153 	if (extern_file) {
154 		return GF_NOT_SUPPORTED;
155 	}
156 
157 	sPath = gf_url_concatenate(parentPath, location);
158 	if (sPath == NULL) {
159 		return GF_URL_ERROR;
160 	}
161 
162 	if (mode == GF_ISOM_DATA_MAP_READ_ONLY) {
163 		mode = GF_ISOM_DATA_MAP_READ;
164 		/*It seems win32 file mapping is reported in prog mem usage -> large increases of occupancy. Should not be a pb
165 		but unless you want mapping, only regular IO will be used...*/
166 #if 0
167 		if (IsLargeFile(sPath)) {
168 			*outDataMap = gf_isom_fdm_new(sPath, mode);
169 		} else {
170 			*outDataMap = gf_isom_fmo_new(sPath, mode);
171 		}
172 #else
173 		*outDataMap = gf_isom_fdm_new(sPath, mode);
174 #endif
175 	} else {
176 		*outDataMap = gf_isom_fdm_new(sPath, mode);
177 		if (*outDataMap) {
178 			(*outDataMap)->szName = sPath;
179 			sPath = NULL;
180 		}
181 	}
182 
183 	if (sPath) {
184 		gf_free(sPath);
185 	}
186 	if (! (*outDataMap)) {
187 		return GF_URL_ERROR;
188 	}
189 
190 	return GF_OK;
191 }
192 
193 //Open a data entry of a track
194 //Edit is used to switch between original and edition file
gf_isom_datamap_open(GF_MediaBox * mdia,u32 dataRefIndex,u8 Edit)195 GF_Err gf_isom_datamap_open(GF_MediaBox *mdia, u32 dataRefIndex, u8 Edit)
196 {
197 	GF_DataEntryBox *ent;
198 	GF_MediaInformationBox *minf;
199 	u32 SelfCont, count;
200 	GF_Err e = GF_OK;
201 	if ((mdia == NULL) || (! mdia->information) || !dataRefIndex)
202 		return GF_ISOM_INVALID_MEDIA;
203 
204 	minf = mdia->information;
205 	if (!minf->dataInformation || !minf->dataInformation->dref)
206 		return GF_ISOM_INVALID_MEDIA;
207 
208 	count = gf_list_count(minf->dataInformation->dref->child_boxes);
209 	if (!count) {
210 		SelfCont = 1;
211 		ent = NULL;
212 	} else {
213 		if (dataRefIndex > gf_list_count(minf->dataInformation->dref->child_boxes))
214 			return GF_BAD_PARAM;
215 
216 		ent = (GF_DataEntryBox*)gf_list_get(minf->dataInformation->dref->child_boxes, dataRefIndex - 1);
217 		if (ent == NULL) return GF_ISOM_INVALID_MEDIA;
218 
219 		//if the current dataEntry is the desired one, and not self contained, return
220 		if ((minf->dataEntryIndex == dataRefIndex) && (ent->flags != 1)) {
221 			return GF_OK;
222 		}
223 
224 		SelfCont = 0;
225 		switch (ent->type) {
226 		case GF_ISOM_BOX_TYPE_URL:
227 		case GF_ISOM_BOX_TYPE_URN:
228 			if (ent->flags == 1) SelfCont = 1;
229 			break;
230 		default:
231 			SelfCont = 1;
232 			break;
233 		}
234 	}
235 
236 	//we need to open a new one
237 	//first close the existing one
238 	if (minf->dataHandler) gf_isom_datamap_close(minf);
239 
240 	//if self-contained, assign the input file
241 	if (SelfCont) {
242 		//if no edit, open the input file
243 		if (!Edit) {
244 			if (mdia->mediaTrack->moov->mov->movieFileMap == NULL) return GF_ISOM_INVALID_FILE;
245 			minf->dataHandler = mdia->mediaTrack->moov->mov->movieFileMap;
246 		} else {
247 #ifndef GPAC_DISABLE_ISOM_WRITE
248 			if (mdia->mediaTrack->moov->mov->editFileMap == NULL) return GF_ISOM_INVALID_FILE;
249 			minf->dataHandler = mdia->mediaTrack->moov->mov->editFileMap;
250 #else
251 			//this should never be the case in an read-only MP4 file
252 			return GF_BAD_PARAM;
253 #endif
254 		}
255 		//else this is a URL (read mode only)
256 	} else {
257 		e = gf_isom_datamap_new(ent->location, mdia->mediaTrack->moov->mov->fileName ? mdia->mediaTrack->moov->mov->fileName : mdia->mediaTrack->moov->mov->finalName, GF_ISOM_DATA_MAP_READ, & mdia->information->dataHandler);
258 		if (e) return (e==GF_URL_ERROR) ? GF_ISOM_UNKNOWN_DATA_REF : e;
259 	}
260 	//OK, set the data entry index
261 	minf->dataEntryIndex = dataRefIndex;
262 	return GF_OK;
263 }
264 
265 //return the NB of bytes actually read (used for HTTP, ...) in case file is uncomplete
gf_isom_datamap_get_data(GF_DataMap * map,u8 * buffer,u32 bufferLength,u64 Offset)266 u32 gf_isom_datamap_get_data(GF_DataMap *map, u8 *buffer, u32 bufferLength, u64 Offset)
267 {
268 	if (!map || !buffer) return 0;
269 
270 	switch (map->type) {
271 	case GF_ISOM_DATA_FILE:
272 	case GF_ISOM_DATA_MEM:
273 		return gf_isom_fdm_get_data((GF_FileDataMap *)map, buffer, bufferLength, Offset);
274 
275 	case GF_ISOM_DATA_FILE_MAPPING:
276 		return gf_isom_fmo_get_data((GF_FileMappingDataMap *)map, buffer, bufferLength, Offset);
277 
278 	default:
279 		return 0;
280 	}
281 }
282 
gf_isom_datamap_flush(GF_DataMap * map)283 void gf_isom_datamap_flush(GF_DataMap *map)
284 {
285 	if (!map) return;
286 
287 	if (map->type == GF_ISOM_DATA_FILE || map->type == GF_ISOM_DATA_MEM) {
288 		GF_FileDataMap *fdm = (GF_FileDataMap *)map;
289 		gf_bs_flush(fdm->bs);
290 	}
291 }
292 
293 #ifndef GPAC_DISABLE_ISOM_WRITE
294 
295 u64 FDM_GetTotalOffset(GF_FileDataMap *ptr);
296 GF_Err FDM_AddData(GF_FileDataMap *ptr, char *data, u32 dataSize);
297 
gf_isom_datamap_get_offset(GF_DataMap * map)298 u64 gf_isom_datamap_get_offset(GF_DataMap *map)
299 {
300 	if (!map) return 0;
301 
302 	switch (map->type) {
303 	case GF_ISOM_DATA_FILE:
304 		return FDM_GetTotalOffset((GF_FileDataMap *)map);
305 	case GF_ISOM_DATA_MEM:
306 		return gf_bs_get_position(map->bs);
307 	default:
308 		return 0;
309 	}
310 }
311 
312 
gf_isom_datamap_add_data(GF_DataMap * ptr,u8 * data,u32 dataSize)313 GF_Err gf_isom_datamap_add_data(GF_DataMap *ptr, u8 *data, u32 dataSize)
314 {
315 	if (!ptr || !data|| !dataSize) return GF_BAD_PARAM;
316 
317 	switch (ptr->type) {
318 	case GF_ISOM_DATA_FILE:
319 	case GF_ISOM_DATA_MEM:
320 		return FDM_AddData((GF_FileDataMap *)ptr, data, dataSize);
321 	default:
322 		return GF_NOT_SUPPORTED;
323 	}
324 }
325 
gf_isom_fdm_new_temp(const char * sPath)326 GF_DataMap *gf_isom_fdm_new_temp(const char *sPath)
327 {
328 	GF_FileDataMap *tmp;
329 	GF_SAFEALLOC(tmp, GF_FileDataMap);
330 	if (!tmp) return NULL;
331 
332 	tmp->type = GF_ISOM_DATA_FILE;
333 	tmp->mode = GF_ISOM_DATA_MAP_WRITE;
334 
335 	if (!sPath) {
336 		tmp->stream = gf_file_temp(&tmp->temp_file);
337 	} else {
338 		char szPath[GF_MAX_PATH];
339 		if ((sPath[strlen(sPath)-1] != '\\') && (sPath[strlen(sPath)-1] != '/')) {
340 			sprintf(szPath, "%s%c%p_isotmp", sPath, GF_PATH_SEPARATOR, (void*) tmp);
341 		} else {
342 			sprintf(szPath, "%s%p_isotmp", sPath, (void*) tmp);
343 		}
344 		tmp->stream = gf_fopen(szPath, "w+b");
345 		tmp->temp_file = gf_strdup(szPath);
346 	}
347 	if (!tmp->stream) {
348 		if (tmp->temp_file) gf_free(tmp->temp_file);
349 		gf_free(tmp);
350 		return NULL;
351 	}
352 	tmp->bs = gf_bs_from_file(tmp->stream, GF_BITSTREAM_WRITE);
353 	if (!tmp->bs) {
354 		gf_fclose(tmp->stream);
355 		gf_free(tmp);
356 		return NULL;
357 	}
358 	return (GF_DataMap *)tmp;
359 }
360 
361 #endif /*GPAC_DISABLE_ISOM_WRITE*/
362 
363 #include <errno.h>
364 #include <string.h>
gf_isom_fdm_new(const char * sPath,u8 mode)365 GF_DataMap *gf_isom_fdm_new(const char *sPath, u8 mode)
366 {
367 	u8 bs_mode;
368 	GF_FileDataMap *tmp;
369 	GF_SAFEALLOC(tmp, GF_FileDataMap);
370 	if (!tmp) return NULL;
371 
372 	tmp->mode = mode;
373 
374 	if (sPath == NULL) {
375 		tmp->type = GF_ISOM_DATA_MEM;
376 		tmp->bs = gf_bs_new (NULL, 0, GF_BITSTREAM_WRITE);
377 		if (!tmp->bs) {
378 			gf_free(tmp);
379 			return NULL;
380 		}
381 		return (GF_DataMap *)tmp;
382 	}
383 
384 	tmp->type = GF_ISOM_DATA_FILE;
385 #ifndef GPAC_DISABLE_ISOM_WRITE
386 	//open a temp file
387 	if (!strcmp(sPath, "mp4_tmp_edit")) {
388 		//create a temp file (that only occurs in EDIT/WRITE mode)
389 		tmp->stream = gf_file_temp(&tmp->temp_file);
390 //		bs_mode = GF_BITSTREAM_READ;
391 	}
392 #endif
393 	if (!strncmp(sPath, "gmem://", 7)) {
394 		u32 size;
395 		u8 *mem_address;
396 		if (gf_blob_get_data(sPath, &mem_address, &size) != GF_OK)
397 			return NULL;
398 		tmp->bs = gf_bs_new((const char *)mem_address, size, GF_BITSTREAM_READ);
399 		if (!tmp->bs) {
400 			gf_free(tmp);
401 			return NULL;
402 		}
403 		return (GF_DataMap *)tmp;
404 	}
405 
406 	switch (mode) {
407 	case GF_ISOM_DATA_MAP_READ:
408 		if (!tmp->stream) tmp->stream = gf_fopen(sPath, "rb");
409 		bs_mode = GF_BITSTREAM_READ;
410 		break;
411 	///we open the file in READ/WRITE mode, in case
412 	case GF_ISOM_DATA_MAP_WRITE:
413 		if (!strcmp(sPath, "_gpac_isobmff_redirect")) {
414 			tmp->stream = NULL;
415 			tmp->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
416 		} else {
417 			if (!strcmp(sPath, "std")) {
418 				tmp->stream = stdout;
419 				tmp->is_stdout = 1;
420 			}
421 
422 			if (!tmp->stream) tmp->stream = gf_fopen(sPath, "w+b");
423 			if (!tmp->stream) tmp->stream = gf_fopen(sPath, "wb");
424 		}
425 		bs_mode = GF_BITSTREAM_WRITE;
426 		break;
427 	///we open the file in CAT mode, in case
428 	case GF_ISOM_DATA_MAP_CAT:
429 		if (!strcmp(sPath, "_gpac_isobmff_redirect")) {
430 			tmp->stream = NULL;
431 			tmp->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
432 		} else {
433 			if (!strcmp(sPath, "std")) {
434 				tmp->stream = stdout;
435 				tmp->is_stdout = 1;
436 			}
437 
438 			if (!tmp->stream) tmp->stream = gf_fopen(sPath, "a+b");
439 			if (tmp->stream) gf_fseek(tmp->stream, 0, SEEK_END);
440 		}
441 		bs_mode = GF_BITSTREAM_WRITE;
442 		break;
443 	default:
444 		gf_free(tmp);
445 		return NULL;
446 	}
447 	if (!tmp->stream && !tmp->bs) {
448 		gf_free(tmp);
449 		return NULL;
450 	}
451 	if (!tmp->bs)
452 		tmp->bs = gf_bs_from_file(tmp->stream, bs_mode);
453 
454 	if (!tmp->bs) {
455 		gf_fclose(tmp->stream);
456 		gf_free(tmp);
457 		return NULL;
458 	}
459 	return (GF_DataMap *)tmp;
460 }
461 
gf_isom_fdm_del(GF_FileDataMap * ptr)462 void gf_isom_fdm_del(GF_FileDataMap *ptr)
463 {
464 	if (!ptr || (ptr->type != GF_ISOM_DATA_FILE && ptr->type != GF_ISOM_DATA_MEM)) return;
465 	if (ptr->bs) gf_bs_del(ptr->bs);
466 	if (ptr->stream && !ptr->is_stdout)
467 		gf_fclose(ptr->stream);
468 
469 #ifndef GPAC_DISABLE_ISOM_WRITE
470 	if (ptr->temp_file) {
471 		gf_file_delete(ptr->temp_file);
472 		gf_free(ptr->temp_file);
473 	}
474 #endif
475 	gf_free(ptr);
476 }
477 
gf_isom_fdm_get_data(GF_FileDataMap * ptr,u8 * buffer,u32 bufferLength,u64 fileOffset)478 u32 gf_isom_fdm_get_data(GF_FileDataMap *ptr, u8 *buffer, u32 bufferLength, u64 fileOffset)
479 {
480 	u32 bytesRead;
481 
482 	//can we seek till that point ???
483 	if (fileOffset > gf_bs_get_size(ptr->bs))
484 		return 0;
485 
486 	if (gf_bs_get_position(ptr->bs) != fileOffset) {
487 		//we are not at the previous location, do a seek
488 		if (gf_bs_seek(ptr->bs, fileOffset) != GF_OK) return 0;
489 	}
490 	ptr->curPos = fileOffset;
491 
492 	//read our data.
493 	bytesRead = gf_bs_read_data(ptr->bs, buffer, bufferLength);
494 	//update our cache
495 	if (bytesRead == bufferLength) {
496 		ptr->curPos += bytesRead;
497 	} else {
498 		gf_bs_get_refreshed_size(ptr->bs);
499 		gf_bs_seek(ptr->bs, fileOffset);
500 		bytesRead = gf_bs_read_data(ptr->bs, buffer, bufferLength);
501 		//update our cache
502 		if (bytesRead == bufferLength) {
503 			ptr->curPos += bytesRead;
504 		} else {
505 			gf_bs_seek(ptr->bs, ptr->curPos);
506 			bytesRead = 0;
507 		}
508 	}
509 	ptr->last_acces_was_read = 1;
510 	return bytesRead;
511 }
512 
513 
514 #ifndef GPAC_DISABLE_ISOM_WRITE
515 
516 
FDM_GetTotalOffset(GF_FileDataMap * ptr)517 u64 FDM_GetTotalOffset(GF_FileDataMap *ptr)
518 {
519 	if (!ptr) return 0;
520 	//the pos is not always at the end
521 	//this function is called to set up the chunks
522 	//so we need the next WRITE offset
523 	return gf_bs_get_size(ptr->bs);
524 }
525 
FDM_AddData(GF_FileDataMap * ptr,char * data,u32 dataSize)526 GF_Err FDM_AddData(GF_FileDataMap *ptr, char *data, u32 dataSize)
527 {
528 	u32 ret;
529 	u64 orig;
530 	if (ptr->mode == GF_ISOM_DATA_MAP_READ) return GF_BAD_PARAM;
531 
532 	orig = gf_bs_get_size(ptr->bs);
533 
534 	/*last access was read, seek to end of file*/
535 	if (ptr->last_acces_was_read) {
536 		gf_bs_seek(ptr->bs, orig);
537 		ptr->last_acces_was_read = 0;
538 	}
539 	//OK, write our stuff to the datamap...
540 	//we don't use bs here cause we want to know more about what has been written
541 	ret = gf_bs_write_data(ptr->bs, data, dataSize);
542 	if (ret != dataSize) {
543 		ptr->curPos = orig;
544 		gf_bs_seek(ptr->bs, orig);
545 		return GF_IO_ERR;
546 	}
547 	ptr->curPos = gf_bs_get_position(ptr->bs);
548 #if 0
549 	//flush the stream !!
550 	if (ptr->stream) gf_bs_flush(ptr->bs);
551 #endif
552 	return GF_OK;
553 }
554 
555 #endif	/*GPAC_DISABLE_ISOM_WRITE*/
556 
557 
558 #ifdef WIN32
559 
560 #include <windows.h>
561 #include <winerror.h>
562 
gf_isom_fmo_new(const char * sPath,u8 mode)563 GF_DataMap *gf_isom_fmo_new(const char *sPath, u8 mode)
564 {
565 	GF_FileMappingDataMap *tmp;
566 	HANDLE fileH, fileMapH;
567 #ifdef _WIN32_WCE
568 	unsigned short sWPath[MAX_PATH];
569 #endif
570 
571 	//only in read only
572 	if (mode != GF_ISOM_DATA_MAP_READ) return NULL;
573 
574 	GF_SAFEALLOC(tmp, GF_FileMappingDataMap);
575 	if (!tmp) return NULL;
576 
577 	tmp->type = GF_ISOM_DATA_FILE_MAPPING;
578 	tmp->mode = mode;
579 	tmp->name = gf_strdup(sPath);
580 
581 	//
582 	//	Open the file
583 	//
584 #ifdef _WIN32_WCE
585 	//convert to WIDE
586 	CE_CharToWide((char *)sPath, sWPath);
587 
588 	fileH = CreateFileForMapping(sWPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
589 	                             (FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS), NULL );
590 #else
591 	fileH = CreateFile(sPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
592 	                   (FILE_ATTRIBUTE_READONLY | FILE_FLAG_RANDOM_ACCESS), NULL );
593 #endif
594 
595 
596 	if (fileH == INVALID_HANDLE_VALUE) {
597 		gf_free(tmp->name);
598 		gf_free(tmp);
599 		return NULL;
600 	}
601 
602 	tmp->file_size = GetFileSize(fileH, NULL);
603 	if (tmp->file_size == 0xFFFFFFFF) {
604 		CloseHandle(fileH);
605 		gf_free(tmp->name);
606 		gf_free(tmp);
607 		return NULL;
608 	}
609 
610 	//
611 	//	Create the mapping
612 	//
613 	fileMapH = CreateFileMapping(fileH, NULL, PAGE_READONLY, 0, 0, NULL);
614 	if (fileMapH == NULL) {
615 		CloseHandle(fileH);
616 		gf_free(tmp->name);
617 		gf_free(tmp);
618 		return NULL;
619 	}
620 
621 	tmp->byte_map = MapViewOfFile(fileMapH, FILE_MAP_READ, 0, 0, 0);
622 	if (tmp->byte_map == NULL) {
623 		CloseHandle(fileMapH);
624 		CloseHandle(fileH);
625 		gf_free(tmp->name);
626 		gf_free(tmp);
627 		return NULL;
628 	}
629 
630 	CloseHandle(fileH);
631 	CloseHandle(fileMapH);
632 
633 	//finaly open our bitstream (from buffer)
634 	tmp->bs = gf_bs_new(tmp->byte_map, tmp->file_size, GF_BITSTREAM_READ);
635 	return (GF_DataMap *)tmp;
636 }
637 
gf_isom_fmo_del(GF_FileMappingDataMap * ptr)638 void gf_isom_fmo_del(GF_FileMappingDataMap *ptr)
639 {
640 	if (!ptr || (ptr->type != GF_ISOM_DATA_FILE_MAPPING)) return;
641 
642 	if (ptr->bs) gf_bs_del(ptr->bs);
643 	if (ptr->byte_map) UnmapViewOfFile(ptr->byte_map);
644 	gf_free(ptr->name);
645 	gf_free(ptr);
646 }
647 
648 
gf_isom_fmo_get_data(GF_FileMappingDataMap * ptr,u8 * buffer,u32 bufferLength,u64 fileOffset)649 u32 gf_isom_fmo_get_data(GF_FileMappingDataMap *ptr, u8 *buffer, u32 bufferLength, u64 fileOffset)
650 {
651 	//can we seek till that point ???
652 	if (fileOffset > ptr->file_size) return 0;
653 
654 	//we do only read operations, so trivial
655 	memcpy(buffer, ptr->byte_map + fileOffset, bufferLength);
656 	return bufferLength;
657 }
658 
659 #else
660 
gf_isom_fmo_new(const char * sPath,u8 mode)661 GF_DataMap *gf_isom_fmo_new(const char *sPath, u8 mode)
662 {
663 	return gf_isom_fdm_new(sPath, mode);
664 }
665 
gf_isom_fmo_del(GF_FileMappingDataMap * ptr)666 void gf_isom_fmo_del(GF_FileMappingDataMap *ptr)
667 {
668 	gf_isom_fdm_del((GF_FileDataMap *)ptr);
669 }
670 
gf_isom_fmo_get_data(GF_FileMappingDataMap * ptr,u8 * buffer,u32 bufferLength,u64 fileOffset)671 u32 gf_isom_fmo_get_data(GF_FileMappingDataMap *ptr, u8 *buffer, u32 bufferLength, u64 fileOffset)
672 {
673 	return gf_isom_fdm_get_data((GF_FileDataMap *)ptr, buffer, bufferLength, fileOffset);
674 }
675 
676 #endif
677 
678 #endif /*GPAC_DISABLE_ISOM*/
679