📄 fileimport.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / mp4box application * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/scene_manager.h>#include <gpac/bifs.h>#include <gpac/media_tools.h>#include <gpac/constants.h>#include <gpac/scenegraph.h>#ifndef GPAC_READ_ONLYextern u32 swf_flags;extern Float swf_flatten_angle;const char *GetLanguageCode(char *lang);void scene_coding_log(void *cbk, u32 log_level, u32 log_tool, const char *fmt, va_list vlist);void convert_file_info(char *inName, u32 trackID){ GF_Err e; u32 i; Bool found; GF_MediaImporter import; memset(&import, 0, sizeof(GF_MediaImporter)); import.in_name = inName; import.flags = GF_IMPORT_PROBE_ONLY; e = gf_media_import(&import); if (e) { fprintf(stdout, "Error probing file %s: %s\n", inName, gf_error_to_string(e)); return; } if (trackID) { fprintf(stdout, "Import probing results for track %s#%d:\n", inName, trackID); } else { fprintf(stdout, "Import probing results for %s:\n", inName); if (!import.nb_tracks) { fprintf(stdout, "File has no selectable tracks\n"); return; } fprintf(stdout, "File has %d tracks\n", import.nb_tracks); } found = 0; for (i=0; i<import.nb_tracks; i++) { if (trackID && (trackID != import.tk_info[i].track_num)) continue; if (!trackID) fprintf(stdout, "\tTrack %d type: ", import.tk_info[i].track_num); else fprintf(stdout, "Track type: "); switch (import.tk_info[i].type) { case GF_ISOM_MEDIA_VISUAL: fprintf(stdout, "Video (%s)", gf_4cc_to_str(import.tk_info[i].media_type)); break; case GF_ISOM_MEDIA_AUDIO: fprintf(stdout, "Audio (%s)", gf_4cc_to_str(import.tk_info[i].media_type)); break; case GF_ISOM_MEDIA_TEXT: fprintf(stdout, "Text (%s)", gf_4cc_to_str(import.tk_info[i].media_type)); break; case GF_ISOM_MEDIA_SCENE: fprintf(stdout, "Scene (%s)", gf_4cc_to_str(import.tk_info[i].media_type)); break; default: fprintf(stdout, "Other (4CC: %s)", gf_4cc_to_str(import.tk_info[i].type)); break; } if (import.tk_info[i].lang) fprintf(stdout, " - lang %s", gf_4cc_to_str(import.tk_info[i].lang)); if (import.tk_info[i].prog_num) { if (!import.nb_progs) { fprintf(stdout, " - Program %d", import.tk_info[i].prog_num); } else { u32 j; for (j=0; j<import.nb_progs; j++) { if (import.tk_info[i].prog_num != import.pg_info[j].number) continue; fprintf(stdout, " - Program %s", import.pg_info[j].name); break; } } } fprintf(stdout, "\n"); if (!trackID) continue; if ((import.tk_info[i].type==GF_ISOM_MEDIA_VISUAL) && import.tk_info[i].video_info.width && import.tk_info[i].video_info.height ) { fprintf(stdout, "Source: %s %dx%d", gf_4cc_to_str(import.tk_info[i].media_type), import.tk_info[i].video_info.width, import.tk_info[i].video_info.height); if (import.tk_info[i].video_info.FPS) fprintf(stdout, " @ %g FPS", import.tk_info[i].video_info.FPS); if (import.tk_info[i].video_info.par) fprintf(stdout, " PAR: %d:%d", import.tk_info[i].video_info.par >> 16, import.tk_info[i].video_info.par & 0xFFFF); fprintf(stdout, "\n"); } else if ((import.tk_info[i].type==GF_ISOM_MEDIA_AUDIO) && import.tk_info[i].audio_info.sample_rate) { fprintf(stdout, "Source: %s - SampleRate %d - %d channels\n", gf_4cc_to_str(import.tk_info[i].media_type), import.tk_info[i].audio_info.sample_rate, import.tk_info[i].audio_info.nb_channels); } else { fprintf(stdout, "Source: %s\n", gf_4cc_to_str(import.tk_info[i].media_type)); } fprintf(stdout, "\nImport Capabilities:\n"); if (import.tk_info[i].flags & GF_IMPORT_USE_DATAREF) fprintf(stdout, "\tCan use data referencing\n"); if (import.tk_info[i].flags & GF_IMPORT_NO_FRAME_DROP) fprintf(stdout, "\tCan use fixed FPS import\n"); if (import.tk_info[i].flags & GF_IMPORT_FORCE_PACKED) fprintf(stdout, "\tCan force packed bitstream import\n"); if (import.tk_info[i].flags & GF_IMPORT_OVERRIDE_FPS) fprintf(stdout, "\tCan override source frame rate\n"); if (import.tk_info[i].flags & (GF_IMPORT_SBR_IMPLICIT|GF_IMPORT_SBR_EXPLICIT)) fprintf(stdout, "\tCan use AAC-SBR signaling\n"); if (import.tk_info[i].flags & GF_IMPORT_FORCE_MPEG4) fprintf(stdout, "\tCan force MPEG-4 Systems stream description\n"); if (import.tk_info[i].flags & GF_IMPORT_3GPP_AGGREGATION) fprintf(stdout, "\tCan use 3GPP frame aggregation\n"); if (import.tk_info[i].flags & GF_IMPORT_NO_DURATION) fprintf(stdout, "\tCannot use duration-based import\n"); found = 1; break; } fprintf(stdout, "\n"); if (!found && trackID) fprintf(stdout, "Cannot find track %d in file\n", trackID);}GF_Err import_file(GF_ISOFile *dest, char *inName, u32 import_flags, Double force_fps, u32 frames_per_sample){ u32 track_id, i, timescale, track; s32 par_d, par_n, prog_id, delay; Bool do_audio, do_video, do_all; const char *szLan; GF_Err e; GF_MediaImporter import; char *ext, szName[1000], *handler_name; memset(&import, 0, sizeof(GF_MediaImporter)); strcpy(szName, inName); ext = strrchr(inName, '.'); if (!ext) { fprintf(stdout, "Unknown input file type\n"); return GF_BAD_PARAM; } szLan = NULL; delay = 0; par_d = par_n = -2; /*use ':' as separator, but beware DOS paths...*/ ext = strchr(szName, ':'); if (ext && ext[1]=='\\') ext = strchr(szName+2, ':'); handler_name = NULL; while (ext) { char *ext2 = strchr(ext+1, ':'); if (ext2 && !strncmp(ext2, "://", 3)) ext2 = strchr(ext2+1, ':'); if (ext2 && !strncmp(ext2, ":\\", 2)) ext2 = strchr(ext2+1, ':'); if (ext2) ext2[0] = 0; /*all extensions for track-based importing*/ if (!strnicmp(ext+1, "lang=", 5)) szLan = GetLanguageCode(ext+6); else if (!strnicmp(ext+1, "delay=", 6)) delay = atoi(ext+7); else if (!strnicmp(ext+1, "fps=", 4)) { if (!strcmp(ext+5, "auto")) force_fps = 10000.0; else force_fps = atof(ext+5); } else if (!stricmp(ext+1, "dref")) import_flags |= GF_IMPORT_USE_DATAREF; else if (!stricmp(ext+1, "nodrop")) import_flags |= GF_IMPORT_NO_FRAME_DROP; else if (!stricmp(ext+1, "packed")) import_flags |= GF_IMPORT_FORCE_PACKED; else if (!stricmp(ext+1, "sbr")) import_flags |= GF_IMPORT_SBR_IMPLICIT; else if (!stricmp(ext+1, "sbrx")) import_flags |= GF_IMPORT_SBR_EXPLICIT; else if (!stricmp(ext+1, "mpeg4")) import_flags |= GF_IMPORT_FORCE_MPEG4; else if (!strnicmp(ext+1, "agg=", 4)) frames_per_sample = atoi(ext+5); else if (!strnicmp(ext+1, "dur=", 4)) import.duration = (u32) (atof(ext+5) * 1000); else if (!strnicmp(ext+1, "par=", 4)) { if (!stricmp(ext+5, "none")) { par_n = par_d = -1; } else { if (ext2) ext2[0] = ':'; if (ext2) ext2 = strchr(ext2+1, ':'); if (ext2) ext2[0] = 0; sscanf(ext+5, "%d:%d", &par_n, &par_d); } } else if (!strnicmp(ext+1, "name=", 5)) handler_name = strdup(ext+6); else if (!strnicmp(ext+1, "font=", 5)) import.fontName = strdup(ext+6); else if (!strnicmp(ext+1, "size=", 5)) import.fontSize = atoi(ext+6); else if (!strnicmp(ext+1, "fmt=", 4)) import.streamFormat = strdup(ext+5); /*unrecognized, assume name has colon in it*/ else { ext = ext2; continue; } if (ext2) ext2[0] = ':'; ext2 = ext+1; ext[0] = 0; ext = strchr(ext+1, ':'); } /*check duration import (old syntax)*/ ext = strrchr(szName, '%'); if (ext) { import.duration = (u32) (atof(ext+1) * 1000); ext[0] = 0; } /*select switches for av containers import*/ do_audio = do_video = 0; track_id = prog_id = 0; do_all = 1; ext = strrchr(szName, '#'); if (ext) ext[0] = 0; import.in_name = szName; import.flags = GF_IMPORT_PROBE_ONLY; e = gf_media_import(&import); if (e) goto exit; if (ext) { ext++; if (!strnicmp(ext, "audio", 5)) do_audio = 1; else if (!strnicmp(ext, "video", 5)) do_video = 1; else if (!strnicmp(ext, "trackID=", 8)) track_id = atoi(&ext[8]); else if (!strnicmp(ext, "PID=", 4)) track_id = atoi(&ext[4]); else if (!strnicmp(ext, "program=", 8)) { for (i=0; i<import.nb_progs; i++) { if (!stricmp(import.pg_info[i].name, ext+8)) { prog_id = import.pg_info[i].number; do_all = 0; break; } } } else track_id = atoi(ext); } if (do_audio || do_video || track_id) do_all = 0; import.dest = dest; import.video_fps = force_fps; import.frames_per_sample = frames_per_sample; import.flags = import_flags; if (!import.nb_tracks) { u32 count, o_count; o_count = gf_isom_get_track_count(import.dest); e = gf_media_import(&import); if (e) return e; count = gf_isom_get_track_count(import.dest); timescale = gf_isom_get_timescale(dest); for (i=o_count; i<count; i++) { if (szLan) gf_isom_set_media_language(import.dest, i+1, (char *) szLan); if (delay) { u64 tk_dur; gf_isom_remove_edit_segments(import.dest, i+1); tk_dur = gf_isom_get_track_duration(import.dest, i+1); if (delay>0) { gf_isom_append_edit_segment(import.dest, i+1, (timescale*delay)/1000, 0, GF_ISOM_EDIT_EMPTY); gf_isom_append_edit_segment(import.dest, i+1, tk_dur, 0, GF_ISOM_EDIT_NORMAL); } else { u64 to_skip = (timescale*(-delay))/1000; if (to_skip<tk_dur) { //u64 seg_dur = (-delay)*gf_isom_get_media_timescale(import.dest, i+1) / 1000; gf_isom_append_edit_segment(import.dest, i+1, tk_dur-to_skip, to_skip, GF_ISOM_EDIT_NORMAL); } else { fprintf(stdout, "Warning: request negative delay longer than track duration - ignoring\n"); } } } if ((par_n>=0) && (par_d>=0)) { e = gf_media_change_par(import.dest, i+1, par_n, par_d); } if (handler_name) gf_isom_set_handler_name(import.dest, i+1, handler_name); } } else { for (i=0; i<import.nb_tracks; i++) { import.trackID = import.tk_info[i].track_num; if (prog_id) { if (import.tk_info[i].prog_num!=prog_id) continue; e = gf_media_import(&import); } else if (do_all) e = gf_media_import(&import); else if (track_id && (track_id==import.trackID)) { track_id = 0; e = gf_media_import(&import); } else if (do_audio && (import.tk_info[i].type==GF_ISOM_MEDIA_AUDIO)) { do_audio = 0; e = gf_media_import(&import); } else if (do_video && (import.tk_info[i].type==GF_ISOM_MEDIA_VISUAL)) { do_video = 0; e = gf_media_import(&import); } else continue; if (e) goto exit; timescale = gf_isom_get_timescale(dest); track = gf_isom_get_track_by_id(import.dest, import.final_trackID); if (szLan) gf_isom_set_media_language(import.dest, track, (char *) szLan); if (delay) { u64 tk_dur; gf_isom_remove_edit_segments(import.dest, track); tk_dur = gf_isom_get_track_duration(import.dest, track); if (delay>0) { gf_isom_append_edit_segment(import.dest, track, (timescale*delay)/1000, 0, GF_ISOM_EDIT_EMPTY); gf_isom_append_edit_segment(import.dest, track, tk_dur, 0, GF_ISOM_EDIT_NORMAL); } else { u64 to_skip = (timescale*(-delay))/1000; if (to_skip<tk_dur) { //u64 seg_dur = (-delay)*gf_isom_get_media_timescale(import.dest, i+1) / 1000; gf_isom_append_edit_segment(import.dest, i+1, tk_dur-to_skip, to_skip, GF_ISOM_EDIT_NORMAL); } else { fprintf(stdout, "Warning: request negative delay longer than track duration - ignoring\n"); } } } if ((import.tk_info[i].type==GF_ISOM_MEDIA_VISUAL) && (par_n>=-1) && (par_d>=-1)) { e = gf_media_change_par(import.dest, track, par_n, par_d); } if (handler_name) gf_isom_set_handler_name(import.dest, track, handler_name); } if (track_id) fprintf(stdout, "WARNING: Track ID %d not found in file\n", track_id); else if (do_video) fprintf(stdout, "WARNING: Video track not found\n"); else if (do_audio) fprintf(stdout, "WARNING: Audio track not found\n"); }exit: if (handler_name) free(handler_name); if (import.fontName) free(import.fontName); if (import.streamFormat) free(import.streamFormat); return e;}typedef struct{ u32 tk; Bool has_non_raps; u32 last_sample; u32 sample_count; u32 time_scale; u64 firstDTS, lastDTS; u32 dst_tk; /*set if media can be duplicated at split boundaries - only used for text tracks and provate tracks, this assumes all samples are RAP*/ Bool can_duplicate; /*controls import by time rather than by sample (otherwise we would have to remove much more samples video vs audio for example*/ Bool first_sample_done; u32 stop_state;} TKInfo;GF_Err split_isomedia_file(GF_ISOFile *mp4, Double split_dur, u32 split_size_kb, char *inName, Double InterleavingTime, Double chunk_start_time, const char *tmpdir, char *outfile){ u32 i, count, nb_tk, needs_rap_sync, cur_file, conv_type, nb_tk_done, nb_samp, nb_done, di; Double max_dur, cur_file_time; Bool do_add, all_duplicatable, size_exceeded, chunk_extraction; GF_ISOFile *dest; GF_ISOSample *samp; GF_Err e; TKInfo *tks, *tki; char *ext, szName[1000], szFile[1000]; Double chunk_start = (Double) chunk_start_time; chunk_extraction = (chunk_start>=0) ? 1 : 0; strcpy(szName, inName); ext = strrchr(szName, '.'); if (ext) ext[0] = 0; ext = strrchr(inName, '.'); dest = NULL; conv_type = 0; switch (gf_isom_guess_specification(mp4)) { case GF_4CC('I','S','M','A'): conv_type = 1; break; case GF_ISOM_BRAND_3GP4: case GF_ISOM_BRAND_3GP5: case GF_ISOM_BRAND_3GP6: case GF_ISOM_BRAND_3GG6: case GF_ISOM_BRAND_3G2A: conv_type = 2; break; } if (!stricmp(ext, ".3gp") || !stricmp(ext, ".3g2")) conv_type = 2; count = gf_isom_get_track_count(mp4); tks = (TKInfo *)malloc(sizeof(TKInfo)*count); memset(tks, 0, sizeof(TKInfo)*count); e = GF_OK; max_dur = 0; nb_tk = 0; all_duplicatable = 1; needs_rap_sync = 0; nb_samp = 0; for (i=0; i<count; i++) { u32 mtype; Double dur; tks[nb_tk].tk = i+1; tks[nb_tk].can_duplicate = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -