📄 read.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / IsoMedia reader module * * 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 "isom_in.h"#include <gpac/ismacryp.h>ISOMChannel *isor_get_channel(ISOMReader *reader, LPNETCHANNEL channel){ u32 i=0; ISOMChannel *ch; while ((ch = (ISOMChannel *)gf_list_enum(reader->channels, &i))) { if (ch->channel == channel) return ch; } return NULL;}static void isor_delete_channel(ISOMReader *reader, ISOMChannel *ch){ u32 i=0; ISOMChannel *ch2; while ((ch2 = (ISOMChannel *)gf_list_enum(reader->channels, &i))) { if (ch2 == ch) { isor_reset_reader(ch); free(ch); gf_list_rem(reader->channels, i-1); return; } }}static GFINLINE Bool isor_is_local(const char *url){ if (!strnicmp(url, "file://", 7)) return 1; if (strstr(url, "://")) return 0; /*the rest is local (mounted on FS)*/ return 1;}Bool ISOR_CanHandleURL(GF_InputService *plug, const char *url){ char *ext; if (!strnicmp(url, "rtsp://", 7)) return 0; ext = strrchr(url, '.'); if (!ext) return 0; if (gf_term_check_extension(plug, "video/mp4", "mp4 mpg4", "MPEG-4 Movies", ext)) return 1; if (gf_term_check_extension(plug, "audio/mp4", "m4a mp4 mpg4", "MPEG-4 Music", ext)) return 1; if (gf_term_check_extension(plug, "application/mp4", "mp4 mpg4", "MPEG-4 Applications", ext)) return 1; if (gf_term_check_extension(plug, "video/3gpp", "3gp 3gpp", "3GPP/MMS Movies", ext)) return 1; if (gf_term_check_extension(plug, "audio/3gpp", "3gp 3gpp", "3GPP/MMS Music",ext)) return 1; if (gf_term_check_extension(plug, "video/3gpp2", "3g2 3gp2", "3GPP2/MMS Movies",ext)) return 1; if (gf_term_check_extension(plug, "audio/3gpp2", "3g2 3gp2", "3GPP2/MMS Music",ext)) return 1; if (gf_isom_probe_file(url)) { gf_term_check_extension(plug, "application/x-isomedia", ext+1, "IsoMedia Files", ext); return 1; } return 0;}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, &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; } /*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);}void isor_setup_download(GF_InputService *plug, const char *url){ ISOMReader *read = (ISOMReader *) plug->priv; read->dnload = gf_term_download_new(read->service, url, 0, isor_net_io, read); if (!read->dnload) gf_term_on_connect(read->service, NULL, GF_NOT_SUPPORTED); /*service confirm is done once IOD can be fetched*/}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->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)) { if (!read->mov) read->mov = gf_isom_open(szURL, GF_ISOM_OPEN_READ, NULL); if (!read->mov) { gf_term_on_connect(serv, NULL, gf_isom_last_error(NULL)); return GF_OK; } 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;}GF_Err ISOR_CloseService(GF_InputService *plug){ GF_Err reply; ISOMReader *read; if (!plug || !plug->priv) return GF_SERVICE_ERROR; read = (ISOMReader *) plug->priv; reply = GF_OK; if (read->mov) gf_isom_close(read->mov); read->mov = NULL; while (gf_list_count(read->channels)) { ISOMChannel *ch = (ISOMChannel *)gf_list_get(read->channels, 0); gf_list_rem(read->channels, 0); isor_delete_channel(read, ch); } if (read->dnload) gf_term_download_del(read->dnload); read->dnload = NULL; gf_term_on_disconnect(read->service, NULL, reply); return GF_OK;}static Bool check_mpeg4_systems(GF_InputService *plug, GF_ISOFile *mov){ char *opt, *bname, *br, *next; u32 i, count, brand, has_mpeg4; GF_Err e; e = gf_isom_get_brand_info(mov, &brand, &i, &count); /*no brand == MP4 v1*/ if (e || !brand) return 1; has_mpeg4 = 0; if ((brand==GF_ISOM_BRAND_MP41) || (brand==GF_ISOM_BRAND_MP42)) has_mpeg4 = 1; opt = (char*) gf_modules_get_option((GF_BaseInterface *)plug, "ISOReader", "IgnoreMPEG-4ForBrands"); if (!opt) { gf_modules_set_option((GF_BaseInterface *)plug, "ISOReader", "IgnoreMPEG-4ForBrands", "nd*"); opt = (char*) gf_modules_get_option((GF_BaseInterface *)plug, "ISOReader", "IgnoreMPEG-4ForBrands"); } for (i=0; i<count; i++) { e = gf_isom_get_alternate_brand(mov, i+1, &brand); if (e) return 0; if ((brand==GF_ISOM_BRAND_MP41) || (brand==GF_ISOM_BRAND_MP42)) { has_mpeg4 = 1; continue; } bname = (char*)gf_4cc_to_str(brand); br = opt; while (br) { Bool ignore = 0; u32 orig_len, len; next = strchr(br, ' '); if (next) next[0] = 0; len = orig_len = strlen(br); while (len) { if (br[len-1]=='*') { br[len-1]=0; len--; } else { break; } } /*ignor all brands*/ if (!len) ignore = 1; else if (!strncmp(bname, br, len)) ignore = 1; while (len<orig_len) { br[len] = '*'; len++; } if (next) { next[0] = ' '; br = next + 1; } else { br = NULL; } if (ignore) return 0; } } return has_mpeg4;}static u32 get_track_id(GF_ISOFile *mov, u32 media_type, u32 idx){ u32 i, count, cur; cur=0; count = gf_isom_get_track_count(mov); for (i=0; i<count; i++) { if (gf_isom_get_media_type(mov, i+1) != media_type) continue; if (!idx) return gf_isom_get_track_id(mov, i+1); cur++; if (cur==idx) return gf_isom_get_track_id(mov, i+1); } return 0;}/*fixme, this doesn't work properly with respect to @expect_type*/static GF_Descriptor *ISOR_GetServiceDesc(GF_InputService *plug, u32 expect_type, const char *sub_url){ u32 count, nb_st, i, trackID; GF_ESD *esd; ISOMReader *read; GF_InitialObjectDescriptor *iod; if (!plug || !plug->priv) return NULL; read = (ISOMReader *) plug->priv; if (!read->mov) return NULL; /*no matter what always read text as TTUs*/ gf_isom_text_set_streaming_mode(read->mov, 1); trackID = 0; if (!sub_url) { trackID = read->base_track_id; read->base_track_id = 0; } else { char *ext = strrchr(sub_url, '#'); if (!ext) { trackID = 0; } else { if (!strnicmp(ext, "#trackID=", 9)) trackID = atoi(ext+9); else if (!stricmp(ext, "#video")) trackID = get_track_id(read->mov, GF_ISOM_MEDIA_VISUAL, 0); else if (!strnicmp(ext, "#video", 6)) { trackID = atoi(ext+6); trackID = get_track_id(read->mov, GF_ISOM_MEDIA_VISUAL, trackID); } else if (!stricmp(ext, "#audio")) trackID = get_track_id(read->mov, GF_ISOM_MEDIA_AUDIO, 0); else if (!strnicmp(ext, "#audio", 6)) { trackID = atoi(ext+6); trackID = get_track_id(read->mov, GF_ISOM_MEDIA_AUDIO, trackID); } else trackID = atoi(ext+1); if (!trackID) return NULL; } } if (!trackID && (expect_type!=GF_MEDIA_OBJECT_SCENE) && (expect_type!=GF_MEDIA_OBJECT_UNDEF)) { for (i=0; i<gf_isom_get_track_count(read->mov); i++) { u32 type = gf_isom_get_media_type(read->mov, i+1); if ( ((type==GF_ISOM_MEDIA_VISUAL) && (expect_type==GF_MEDIA_OBJECT_VIDEO)) || ((type==GF_ISOM_MEDIA_AUDIO) && (expect_type==GF_MEDIA_OBJECT_AUDIO)) ) { trackID = gf_isom_get_track_id(read->mov, i+1); break; } } } if (trackID && (expect_type!=GF_MEDIA_OBJECT_SCENE) ) { u32 track = gf_isom_get_track_by_id(read->mov, trackID); if (!track) return NULL; esd = gf_media_map_esd(read->mov, track); esd->OCRESID = 0; iod = (GF_InitialObjectDescriptor *) gf_isom_get_root_od(read->mov); if (!iod) { iod = (GF_InitialObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG); iod->OD_profileAndLevel = iod->audio_profileAndLevel = iod->graphics_profileAndLevel = iod->scene_profileAndLevel = iod->visual_profileAndLevel = 0xFE; } else { while (gf_list_count(iod->ESDescriptors)) { GF_ESD *old = (GF_ESD *)gf_list_get(iod->ESDescriptors, 0); gf_odf_desc_del((GF_Descriptor *) old); gf_list_rem(iod->ESDescriptors, 0); } } gf_list_add(iod->ESDescriptors, esd); isor_emulate_chapters(read->mov, iod); return (GF_Descriptor *) iod; } iod = NULL; if (check_mpeg4_systems(plug, read->mov)) { iod = (GF_InitialObjectDescriptor *) gf_isom_get_root_od(read->mov); if (!iod) {#ifndef GPAC_DISABLE_LOG GF_Err e = gf_isom_last_error(read->mov); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_SERVICE, ("[IsoMedia] Cannot fetch MPEG-4 IOD (error %s) - generating one\n", gf_error_to_string(e) )); } else { GF_LOG(GF_LOG_DEBUG, GF_LOG_SERVICE, ("[IsoMedia] No MPEG-4 IOD found in file - generating one\n")); }#endif } } if (!iod) return isor_emulate_iod(read); count = gf_list_count(iod->ESDescriptors); if (!count) { gf_odf_desc_del((GF_Descriptor*) iod); return isor_emulate_iod(read); } if (count==1) { esd = (GF_ESD *)gf_list_get(iod->ESDescriptors, 0); switch (esd->decoderConfig->streamType) { case GF_STREAM_SCENE: case GF_STREAM_PRIVATE_SCENE: break; case GF_STREAM_VISUAL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -