GF_Err ISOR_ConnectService(GF_InputService *plug, GF_ClientService *serv, const char *url) { char szURL[2048]; char *tmp; ISOMReader *read; if (!plug || !plug->priv || !serv) return GF_SERVICE_ERROR; read = (ISOMReader *) plug->priv; read->input = plug; read->service = serv; if (read->dnload) gf_term_download_del(read->dnload); read->dnload = NULL; read->base_track_id = 0; strcpy(szURL, url); tmp = strrchr(szURL, '.'); if (tmp) { tmp = strchr(tmp, '#'); if (tmp) { if (!strnicmp(tmp, "#trackID=", 9)) { read->base_track_id = atoi(tmp+9); } else { read->base_track_id = atoi(tmp+1); } tmp[0] = 0; } } if (isor_is_local(szURL)) { GF_Err e; u64 start_range, end_range; start_range = end_range = 0; if (plug->query_proxy) { GF_NetworkCommand param; param.command_type = GF_NET_SERVICE_QUERY_INIT_RANGE; if (read->input->query_proxy(read->input, ¶m)==GF_OK) { start_range = param.url_query.start_range; end_range = param.url_query.end_range; } } e = gf_isom_open_progressive(szURL, start_range, end_range, &read->mov, &read->missing_bytes); if (e != GF_OK) { GF_LOG(GF_LOG_ERROR, GF_LOG_NETWORK, ("[IsoMedia] : error while opening %s, error=%s\n", szURL, gf_error_to_string(e))); gf_term_on_connect(serv, NULL, e); return GF_OK; } read->frag_type = gf_isom_is_fragmented(read->mov) ? 1 : 0; read->time_scale = gf_isom_get_timescale(read->mov); /*reply to user*/ gf_term_on_connect(serv, NULL, GF_OK); if (read->no_service_desc) isor_declare_objects(read); } else { /*setup downloader*/ isor_setup_download(plug, szURL); } return GF_OK; }
GPACDemuxMP4Simple::GPACDemuxMP4Simple(std::string const& path) : reader(new ISOFileReader) { GF_ISOFile *movie; u64 missingBytes; GF_Err e = gf_isom_open_progressive(path.c_str(), 0, 0, &movie, &missingBytes); if ((e != GF_OK && e != GF_ISOM_INCOMPLETE_FILE) || movie == nullptr) { throw error(format("Could not open file %s for reading (%s).", path, gf_error_to_string(e))); } reader->init(movie); output = addOutput(new OutputDefault); }
void isor_net_io(void *cbk, GF_NETIO_Parameter *param) { GF_Err e; u32 size = 0; char *local_name; ISOMReader *read = (ISOMReader *) cbk; /*handle service message*/ gf_term_download_update_stats(read->dnload); if (param->msg_type==GF_NETIO_DATA_TRANSFERED) { e = GF_EOS; } else if (param->msg_type==GF_NETIO_DATA_EXCHANGE) { e = GF_OK; size = param->size; } else { e = param->error; } if (e<GF_OK) { /*error opening service*/ if (!read->mov) gf_term_on_connect(read->service, NULL, e); return; } /*open file if not done yet (bad interleaving)*/ if (e==GF_EOS) { const char *local_name; if (read->mov) return; local_name = gf_dm_sess_get_cache_name(read->dnload); if (!local_name) { gf_term_on_connect(read->service, NULL, GF_SERVICE_ERROR); return; } e = GF_OK; read->mov = gf_isom_open(local_name, GF_ISOM_OPEN_READ, NULL); if (!read->mov) e = gf_isom_last_error(NULL); else read->time_scale = gf_isom_get_timescale(read->mov); gf_term_on_connect(read->service, NULL, GF_OK); if (read->no_service_desc) isor_declare_objects(read); } if (!size) return; /*service is opened, nothing to do*/ if (read->mov) return; /*try to open the service*/ local_name = (char *)gf_dm_sess_get_cache_name(read->dnload); if (!local_name) { gf_term_on_connect(read->service, NULL, GF_SERVICE_ERROR); return; } /*not enogh data yet*/ if (read->missing_bytes && (read->missing_bytes > size) ) { read->missing_bytes -= size; return; } e = gf_isom_open_progressive(local_name, 0, 0, &read->mov, &read->missing_bytes); switch (e) { case GF_ISOM_INCOMPLETE_FILE: return; case GF_OK: break; default: gf_term_on_connect(read->service, NULL, e); return; } read->frag_type = gf_isom_is_fragmented(read->mov) ? 1 : 0; /*ok let's go*/ read->time_scale = gf_isom_get_timescale(read->mov); gf_term_on_connect(read->service, NULL, GF_OK); if (read->no_service_desc) isor_declare_objects(read); }
int main(int argc, char **argv) { /* The ISO progressive reader */ GF_ISOFile *movie; /* Error indicator */ GF_Err e; /* Number of bytes required to finish the current ISO Box reading */ u64 missing_bytes; /* Return value for the program */ int ret = 0; /* Maximum index of the segments*/ u32 seg_max = argc-2; /* Number of the segment being processed*/ u32 seg_curr = 0; u32 track_id = 1; u32 sample_index = 1; /* Usage */ if (argc < 2) { fprintf(stdout, "Usage: %s filename0 [filename1 filename2 ...]\n", argv[0]); return 1; } #if defined(DEBUG) || defined(_DEBUG) /* Enables GPAC memory tracking in debug mode only */ gf_sys_init(GF_TRUE); gf_log_set_tool_level(GF_LOG_CONTAINER, GF_LOG_INFO); gf_log_set_tool_level(GF_LOG_MEMORY, GF_LOG_INFO); #endif /* First or init segment */ fprintf(stdout, "Process segment %5d/%5d: %s\n", seg_curr, seg_max, argv[seg_curr+1]); e = gf_isom_open_progressive(argv[seg_curr+1], 0, 0, &movie, &missing_bytes); if ((e != GF_OK && e != GF_ISOM_INCOMPLETE_FILE) || movie == NULL) { fprintf(stdout, "Could not open file %s for reading (%s).\n", argv[seg_curr+1], gf_error_to_string(e)); return 1; } process_samples_from_track(movie, track_id, &sample_index); seg_curr++; /* Process segments */ while (seg_curr <= seg_max) { fprintf(stdout, "Process segment %5d/%5d: %s\n", seg_curr, seg_max, argv[seg_curr+1]); /* Open the segment */ e = gf_isom_open_segment(movie, argv[seg_curr+1], 0, 0, GF_FALSE); if (e != GF_OK) { fprintf(stdout, "Could not open segment %s for reading (%s).\n", argv[seg_curr+1], gf_error_to_string(e)); ret = 1; goto exit; } /* Process the segment */ process_samples_from_track(movie, track_id, &sample_index); /* Release the segment */ gf_isom_release_segment(movie, 1); seg_curr++; } exit: fprintf(stdout, "Total nb Samples: %d\n", gf_isom_get_sample_count(movie, gf_isom_get_track_by_id(movie, track_id) ) ); gf_isom_release_segment(movie, 1); gf_isom_close(movie); #if defined(DEBUG) || defined(_DEBUG) /* Closes GPAC memory tracking in debug mode only */ gf_sys_close(); #endif return ret; }
void isor_net_io(void *cbk, GF_NETIO_Parameter *param) { GF_Err e; u32 size = 0; char *local_name; ISOMReader *read = (ISOMReader *) cbk; /*handle service message*/ if (!read->buffering) gf_service_download_update_stats(read->dnload); if (param->msg_type==GF_NETIO_DATA_TRANSFERED) { e = GF_EOS; } else if (param->msg_type==GF_NETIO_DATA_EXCHANGE) { e = GF_OK; size = param->size; } else { e = param->error; } if (e<GF_OK) { /*error opening service*/ if (!read->mov) { /* if there is an intermediate between this module and the terminal, report to it */ if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) { send_proxy_command(read, GF_FALSE, GF_FALSE, e, NULL, NULL); } else { gf_service_connect_ack(read->service, NULL, e); } } return; } /*open file if not done yet (bad interleaving)*/ if (e==GF_EOS) { const char *local_name; if (read->mov) return; local_name = gf_dm_sess_get_cache_name(read->dnload); if (!local_name) { if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) { send_proxy_command(read, GF_FALSE, GF_FALSE, GF_SERVICE_ERROR, NULL, NULL); } else { gf_service_connect_ack(read->service, NULL, GF_SERVICE_ERROR); } return; } e = GF_OK; read->mov = gf_isom_open(local_name, GF_ISOM_OPEN_READ, NULL); if (!read->mov) e = gf_isom_last_error(NULL); else read->time_scale = gf_isom_get_timescale(read->mov); read->frag_type = gf_isom_is_fragmented(read->mov) ? 1 : 0; if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) { send_proxy_command(read, GF_FALSE, GF_FALSE, GF_OK, NULL, NULL); } else { gf_service_connect_ack(read->service, NULL, GF_OK); } if (read->no_service_desc) isor_declare_objects(read); } if (!size) return; /*service is opened, nothing to do*/ if (read->mov) { isor_check_buffer_level(read); /*end of chunk*/ if (read->frag_type && (param->reply==1) ) { u64 bytesMissing = 0; gf_mx_p(read->segment_mutex); e = gf_isom_refresh_fragmented(read->mov, &bytesMissing, NULL); gf_mx_v(read->segment_mutex); } return; } /*try to open the service*/ local_name = (char *)gf_dm_sess_get_cache_name(read->dnload); if (!local_name) { if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) { send_proxy_command(read, GF_FALSE, GF_FALSE, GF_SERVICE_ERROR, NULL, NULL); } else { gf_service_connect_ack(read->service, NULL, GF_SERVICE_ERROR); } return; } /*not enogh data yet*/ if (read->missing_bytes && (read->missing_bytes > size) ) { read->missing_bytes -= size; return; } e = gf_isom_open_progressive(local_name, 0, 0, &read->mov, &read->missing_bytes); switch (e) { case GF_ISOM_INCOMPLETE_FILE: return; case GF_OK: break; default: if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) { send_proxy_command(read, GF_FALSE, GF_FALSE, e, NULL, NULL); } else { gf_service_connect_ack(read->service, NULL, e); } return; } read->frag_type = gf_isom_is_fragmented(read->mov) ? 1 : 0; /*ok let's go, we can setup the decoders */ read->time_scale = gf_isom_get_timescale(read->mov); if (read->input->query_proxy && read->input->proxy_udta && read->input->proxy_type) { send_proxy_command(read, GF_FALSE, GF_FALSE, GF_OK, NULL, NULL); } else { gf_service_connect_ack(read->service, NULL, GF_OK); } if (read->no_service_desc) isor_declare_objects(read); }
int main(int argc, char **argv) { /* The ISO progressive reader */ ISOProgressiveReader reader; /* Error indicator */ GF_Err e; /* input file to be read in the data buffer */ FILE *input; /* number of bytes read from the file at each read operation */ u32 read_bytes; /* number of bytes read from the file (total) */ u64 total_read_bytes; /* size of the input file */ u64 file_size; /* number of bytes required to finish the current ISO Box reading (not used here)*/ u64 missing_bytes; /* Thread used to run the ISO parsing in */ GF_Thread *reading_thread; /* Return value for the program */ int ret = 0; /* Usage */ if (argc != 2) { fprintf(stdout, "Usage: %s filename\n", argv[0]); return 1; } /* Initializing GPAC framework */ /* Enables GPAC memory tracking in debug mode only */ #if defined(DEBUG) || defined(_DEBUG) gf_sys_init(GF_MemTrackerSimple); gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING); gf_log_set_tool_level(GF_LOG_MEMORY, GF_LOG_INFO); #else gf_sys_init(GF_MemTrackerNone); gf_log_set_tool_level(GF_LOG_ALL, GF_LOG_WARNING); #endif /* This is an input file to read data from. Could be replaced by any other method to retrieve the data (e.g. JavaScript, socket, ...)*/ input = gf_fopen(argv[1], "rb"); if (!input) { fprintf(stdout, "Could not open file %s for reading.\n", argv[1]); gf_sys_close(); return 1; } gf_fseek(input, 0, SEEK_END); file_size = gf_ftell(input); gf_fseek(input, 0, SEEK_SET); /* Initializing the progressive reader */ memset(&reader, 0, sizeof(ISOProgressiveReader)); reading_thread = gf_th_new("ISO reading thread"); reader.mutex = gf_mx_new("ISO Segment"); reader.do_run = GF_TRUE; /* we want to parse the first track */ reader.track_id = 1; /* start the async parsing */ gf_th_run(reading_thread, iso_progressive_read_thread, &reader); /* start the data reading */ reader.data_size = BUFFER_BLOCK_SIZE; reader.data = (u8 *)gf_malloc(reader.data_size); reader.valid_data_size = 0; total_read_bytes = 0; while (1) { /* block the parser until we are done manipulating the data buffer */ gf_mx_p(reader.mutex); if (reader.valid_data_size + BUFFER_BLOCK_SIZE > MAX_BUFFER_SIZE) { /* regulate the reader to limit the max buffer size and let some time to the parser to release buffer data */ fprintf(stdout, "Buffer full (%d/%d)- waiting to read next data \r", reader.valid_data_size, reader.data_size); gf_mx_v(reader.mutex); //gf_sleep(10); } else { /* make sure we have enough space in the buffer to read the next bloc of data */ if (reader.valid_data_size + BUFFER_BLOCK_SIZE > reader.data_size) { reader.data = (u8 *)gf_realloc(reader.data, reader.data_size + BUFFER_BLOCK_SIZE); reader.data_size += BUFFER_BLOCK_SIZE; } /* read the next bloc of data and update the data buffer url */ read_bytes = fread(reader.data+reader.valid_data_size, 1, BUFFER_BLOCK_SIZE, input); total_read_bytes += read_bytes; fprintf(stdout, "Read "LLD" bytes of "LLD" bytes from input file %s (buffer status: %5d/%5d)\r", total_read_bytes, file_size, argv[1], reader.valid_data_size, reader.data_size); if (read_bytes) { reader.valid_data_size += read_bytes; sprintf(reader.data_url, "gmem://%d@%p", reader.valid_data_size, reader.data); } else { /* end of file we can quit */ gf_mx_v(reader.mutex); break; } /* if the file is not yet opened (no movie), open it in progressive mode (to update its data later on) */ if (!reader.movie) { /* let's initialize the parser */ e = gf_isom_open_progressive(reader.data_url, 0, 0, &reader.movie, &missing_bytes); if (reader.movie) { gf_isom_set_single_moof_mode(reader.movie, GF_TRUE); } /* we can let parser try to work now */ gf_mx_v(reader.mutex); if ((e == GF_OK || e == GF_ISOM_INCOMPLETE_FILE) && reader.movie) { /* nothing to do, this is normal */ } else { fprintf(stdout, "Error opening fragmented mp4 in progressive mode: %s (missing "LLD" bytes)\n", gf_error_to_string(e), missing_bytes); ret = 1; goto exit; } } else { /* let inform the parser that the buffer has been updated with new data */ e = gf_isom_refresh_fragmented(reader.movie, &missing_bytes, reader.data_url); /* we can let parser try to work now */ gf_mx_v(reader.mutex); if (e != GF_OK && e != GF_ISOM_INCOMPLETE_FILE) { fprintf(stdout, "Error refreshing fragmented mp4: %s (missing "LLD" bytes)\n", gf_error_to_string(e), missing_bytes); ret = 1; goto exit; } } //gf_sleep(1); } } exit: /* stop the parser */ reader.do_run = GF_FALSE; gf_th_stop(reading_thread); /* clean structures */ gf_th_del(reading_thread); gf_mx_del(reader.mutex); gf_free(reader.data); gf_isom_close(reader.movie); gf_fclose(input); gf_sys_close(); return ret; }