📄 media_import.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / Media Tools sub-project * * 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/internal/media_dev.h>#include <gpac/internal/avilib.h>#include <gpac/internal/ogg.h>#include <gpac/internal/vobsub.h>#include <gpac/xml.h>#include <gpac/mpegts.h>#include <gpac/constants.h>/*since 0.2.2, we use zlib for xmt/x3d reading to handle gz files*/#include <zlib.h>#ifndef GPAC_READ_ONLY#define GF_IMPORT_DEFAULT_FPS 25.0GF_Err gf_import_message(GF_MediaImporter *import, GF_Err e, char *format, ...){#ifndef GPAC_DISABLE_LOG if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_AUTHOR)) { va_list args; char szMsg[1024]; va_start(args, format); vsprintf(szMsg, format, args); va_end(args); GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_INFO), GF_LOG_AUTHOR, ("%s\n", szMsg) ); }#endif return e;}static GF_Err gf_media_update_par(GF_ISOFile *file, u32 track){ u32 tk_w, tk_h, stype; GF_Err e; e = gf_isom_get_visual_info(file, track, 1, &tk_w, &tk_h); if (e) return e; stype = gf_isom_get_media_subtype(file, track, 1); if (stype==GF_ISOM_SUBTYPE_AVC_H264) { s32 par_n, par_d; GF_AVCConfig *avcc = gf_isom_avc_config_get(file, track, 1); GF_AVCConfigSlot *slc = (GF_AVCConfigSlot *)gf_list_get(avcc->sequenceParameterSets, 0); par_n = par_d = 1; if (slc) gf_avc_get_sps_info(slc->data, slc->size, NULL, NULL, &par_n, &par_d); gf_odf_avc_cfg_del(avcc); if ((par_n>1) && (par_d>1)) tk_w = tk_w * par_n / par_d; } else if ((stype==GF_ISOM_SUBTYPE_MPEG4) || (stype==GF_ISOM_SUBTYPE_MPEG4_CRYP) ) { GF_M4VDecSpecInfo dsi; GF_ESD *esd = gf_isom_get_esd(file, track, 1); if (!esd || !esd->decoderConfig || (esd->decoderConfig->streamType!=4) || (esd->decoderConfig->objectTypeIndication!=0x20)) { if (esd) gf_odf_desc_del((GF_Descriptor *) esd); return GF_NOT_SUPPORTED; } gf_m4v_get_config(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, &dsi); if (esd) gf_odf_desc_del((GF_Descriptor *) esd); if ((dsi.par_num>1) && (dsi.par_num>1)) tk_w = dsi.width * dsi.par_num / dsi.par_den; } else { return GF_OK; } return gf_isom_set_track_layout_info(file, track, tk_w<<16, tk_h<<16, 0, 0, 0);}static void MP4T_RecomputeBitRate(GF_ISOFile *file, u32 track){ u32 i, count, timescale; u64 time_wnd, rate, max_rate, avg_rate; Double br; GF_ESD *esd; esd = gf_isom_get_esd(file, track, 1); if (!esd) return; esd->decoderConfig->avgBitrate = 0; esd->decoderConfig->maxBitrate = 0; rate = max_rate = avg_rate = time_wnd = 0; timescale = gf_isom_get_media_timescale(file, track); count = gf_isom_get_sample_count(file, track); for (i=0; i<count; i++) { GF_ISOSample *samp = gf_isom_get_sample_info(file, track, i+1, NULL, NULL); if (samp->dataLength>esd->decoderConfig->bufferSizeDB) esd->decoderConfig->bufferSizeDB = samp->dataLength; if (esd->decoderConfig->bufferSizeDB < samp->dataLength) esd->decoderConfig->bufferSizeDB = samp->dataLength; avg_rate += samp->dataLength; rate += samp->dataLength; if (samp->DTS > time_wnd + timescale) { if (rate > max_rate) max_rate = rate; time_wnd = samp->DTS; rate = 0; } gf_isom_sample_del(&samp); } br = (Double) (s64) gf_isom_get_media_duration(file, track); br /= timescale; esd->decoderConfig->avgBitrate = (u32) ((Double) (s64)avg_rate / br); /*move to bps*/ esd->decoderConfig->avgBitrate *= 8; esd->decoderConfig->maxBitrate = (u32) (max_rate*8); gf_isom_change_mpeg4_description(file, track, 1, esd); gf_odf_desc_del((GF_Descriptor *)esd);}static void get_video_timing(Double fps, u32 *timescale, u32 *dts_inc){ u32 fps_1000 = (u32) (fps*1000 + 0.5); /*handle all drop-frame formats*/ if (fps_1000==29970) { *timescale = 30000; *dts_inc = 1001; } else if (fps_1000==23976) { *timescale = 24000; *dts_inc = 1001; } else if (fps_1000==59940) { *timescale = 60000; *dts_inc = 1001; } else { *timescale = fps_1000; *dts_inc = 1000; }}static GF_Err gf_import_still_image(GF_MediaImporter *import){ GF_BitStream *bs; GF_Err e; Bool destroy_esd; u32 size, track, di, w, h, dsi_len, mtype; GF_ISOSample *samp; u8 OTI; char *dsi, *data; FILE *src; src = fopen(import->in_name, "rb"); if (!src) return gf_import_message(import, GF_URL_ERROR, "Opening file %s failed", import->in_name); fseek(src, 0, SEEK_END); size = ftell(src); fseek(src, 0, SEEK_SET); data = (char*)malloc(sizeof(char)*size); fread(data, sizeof(char)*size, 1, src); fclose(src); /*get image size*/ bs = gf_bs_new(data, size, GF_BITSTREAM_READ); gf_img_parse(bs, &OTI, &mtype, &w, &h, &dsi, &dsi_len); gf_bs_del(bs); if (!OTI) { free(data); return gf_import_message(import, GF_NOT_SUPPORTED, "Unrecognized file %s", import->in_name); } if (!w || !h) { free(data); if (dsi) free(dsi); return gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Invalid %s file", (OTI==0x6C) ? "JPEG" : (OTI==0x6D) ? "PNG" : "JPEG2000"); } if (import->flags & GF_IMPORT_PROBE_ONLY) { import->tk_info[0].track_num = 1; import->tk_info[0].type = GF_ISOM_MEDIA_VISUAL; import->tk_info[0].media_type = mtype; import->tk_info[0].flags = GF_IMPORT_USE_DATAREF | GF_IMPORT_NO_DURATION; import->tk_info[0].video_info.width = w; import->tk_info[0].video_info.height = h; import->nb_tracks = 1; if (dsi) free(dsi); return GF_OK; } e = GF_OK; destroy_esd = 0; if (!import->esd) { import->esd = gf_odf_desc_esd_new(2); destroy_esd = 1; } /*update stream type/oti*/ if (!import->esd->decoderConfig) import->esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG); if (!import->esd->slConfig) import->esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); import->esd->decoderConfig->streamType = GF_STREAM_VISUAL; import->esd->decoderConfig->objectTypeIndication = OTI; import->esd->decoderConfig->bufferSizeDB = size; import->esd->decoderConfig->avgBitrate = 8*size; import->esd->decoderConfig->maxBitrate = 8*size; import->esd->slConfig->timestampResolution = 1000; if (dsi) { if (!import->esd->decoderConfig->decoderSpecificInfo) import->esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG); if (import->esd->decoderConfig->decoderSpecificInfo->data) free(import->esd->decoderConfig->decoderSpecificInfo->data); import->esd->decoderConfig->decoderSpecificInfo->data = dsi; import->esd->decoderConfig->decoderSpecificInfo->dataLength = dsi_len; } track = gf_isom_new_track(import->dest, import->esd->ESID, GF_ISOM_MEDIA_VISUAL, 1000); if (!track) { e = gf_isom_last_error(import->dest); goto exit; } gf_isom_set_track_enabled(import->dest, track, 1); if (!import->esd->ESID) import->esd->ESID = gf_isom_get_track_id(import->dest, track); import->final_trackID = import->esd->ESID; e = gf_isom_new_mpeg4_description(import->dest, track, import->esd, (import->flags & GF_IMPORT_USE_DATAREF) ? import->in_name : NULL, NULL, &di); if (e) goto exit; gf_isom_set_visual_info(import->dest, track, di, w, h); samp = gf_isom_sample_new(); samp->IsRAP = 1; samp->dataLength = size; gf_import_message(import, GF_OK, "%s import - size %d x %d", (OTI==0x6C) ? "JPEG" : (OTI==0x6C) ? "PNG" : "JPEG2000", w, h); gf_set_progress("Importing Image", 0, 1); if (import->flags & GF_IMPORT_USE_DATAREF) { e = gf_isom_add_sample_reference(import->dest, track, di, samp, (u64) 0); } else { samp->data = data; e = gf_isom_add_sample(import->dest, track, di, samp); samp->data = NULL; } gf_set_progress("Importing Image", 1, 1); gf_isom_sample_del(&samp);exit: free(data); if (import->esd && destroy_esd) { gf_odf_desc_del((GF_Descriptor *) import->esd); import->esd = NULL; } return e;}GF_Err gf_import_mp3(GF_MediaImporter *import){ u8 oti; Bool destroy_esd; GF_Err e; u16 sr; u32 nb_chan; FILE *in; u32 hdr, size, max_size, track, di, tot_size, done, offset, duration; GF_ISOSample *samp; in = gf_f64_open(import->in_name, "rb"); if (!in) return gf_import_message(import, GF_URL_ERROR, "Opening file %s failed", import->in_name); hdr = gf_mp3_get_next_header(in); if (!hdr) { fclose(in); return gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Audio isn't MPEG-1/2 audio"); } sr = gf_mp3_sampling_rate(hdr); oti = gf_mp3_object_type_indication(hdr); if (!oti) { fclose(in); return gf_import_message(import, GF_NON_COMPLIANT_BITSTREAM, "Audio isn't MPEG-1/2 audio"); } if (import->flags & GF_IMPORT_PROBE_ONLY) { fclose(in); import->tk_info[0].track_num = 1; import->tk_info[0].type = GF_ISOM_MEDIA_AUDIO; import->tk_info[0].flags = GF_IMPORT_USE_DATAREF; import->tk_info[0].audio_info.sample_rate = sr; import->tk_info[0].audio_info.nb_channels = gf_mp3_num_channels(hdr); import->nb_tracks = 1; return GF_OK; } e = GF_OK; destroy_esd = 0; if (!import->esd) { import->esd = gf_odf_desc_esd_new(2); destroy_esd = 1; } if (!import->esd->decoderConfig) import->esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG); if (!import->esd->slConfig) import->esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); /*update stream type/oti*/ import->esd->decoderConfig->streamType = GF_STREAM_AUDIO; import->esd->decoderConfig->objectTypeIndication = oti; import->esd->decoderConfig->bufferSizeDB = 20; import->esd->slConfig->timestampResolution = sr; samp = NULL; nb_chan = gf_mp3_num_channels(hdr); gf_import_message(import, GF_OK, "MP3 import - sample rate %d - %s audio - %d channel%s", sr, (oti==0x6B) ? "MPEG-1" : "MPEG-2", nb_chan, (nb_chan>1) ? "s" : ""); track = gf_isom_new_track(import->dest, import->esd->ESID, GF_ISOM_MEDIA_AUDIO, sr); if (!track) { e = gf_isom_last_error(import->dest); goto exit; } gf_isom_set_track_enabled(import->dest, track, 1); if (!import->esd->ESID) import->esd->ESID = gf_isom_get_track_id(import->dest, track); import->final_trackID = import->esd->ESID; if (import->esd->decoderConfig->decoderSpecificInfo) gf_odf_desc_del((GF_Descriptor *) import->esd->decoderConfig->decoderSpecificInfo); import->esd->decoderConfig->decoderSpecificInfo = NULL; gf_isom_new_mpeg4_description(import->dest, track, import->esd, (import->flags & GF_IMPORT_USE_DATAREF) ? import->in_name : NULL, NULL, &di); gf_isom_set_audio_info(import->dest, track, di, sr, nb_chan, 16); fseek(in, 0, SEEK_END); tot_size = ftell(in); fseek(in, 0, SEEK_SET); e = GF_OK; samp = gf_isom_sample_new(); samp->IsRAP = 1; duration = import->duration*sr; duration /= 1000; max_size = 0; done = 0; while (tot_size > done) { /* get the next MP3 frame header */ hdr = gf_mp3_get_next_header(in); /*MP3 stream truncated*/ if (!hdr) break; offset = ftell(in) - 4; size = gf_mp3_frame_size(hdr); assert(size); if (size>max_size) { samp->data = (char*)realloc(samp->data, sizeof(char) * size); max_size = size; } samp->data[0] = (hdr >> 24) & 0xFF; samp->data[1] = (hdr >> 16) & 0xFF; samp->data[2] = (hdr >> 8) & 0xFF; samp->data[3] = hdr & 0xFF; samp->dataLength = size; /* read the frame data into the buffer */ if (fread(&samp->data[4], 1, size - 4, in) != size - 4) break; if (import->flags & GF_IMPORT_USE_DATAREF) { gf_isom_add_sample_reference(import->dest, track, di, samp, offset); } else { gf_isom_add_sample(import->dest, track, di, samp); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -