📄 mp4.c
字号:
{ MP4_Box_t *p_rdrf = MP4_BoxGet( p_rmra, "rmda[%d]/rdrf", i ); char *psz_ref; uint32_t i_ref_type; if( !p_rdrf || !( psz_ref = strdup( p_rdrf->data.p_rdrf->psz_ref ) ) ) { continue; } i_ref_type = p_rdrf->data.p_rdrf->i_ref_type; msg_Dbg( p_demux, "new ref=`%s' type=%4.4s", psz_ref, (char*)&i_ref_type ); if( i_ref_type == VLC_FOURCC( 'u', 'r', 'l', ' ' ) ) { if( strstr( psz_ref, "qt5gateQT" ) ) { msg_Dbg( p_demux, "ignoring pseudo ref =`%s'", psz_ref ); continue; } if( !strncmp( psz_ref, "http://", 7 ) || !strncmp( psz_ref, "rtsp://", 7 ) ) { ; } else { char *psz_absolute; char *psz_path = strdup( p_demux->psz_path ); char *end = strrchr( psz_path, '/' ); if( end ) end[1] = '\0'; else *psz_path = '\0'; if( asprintf( &psz_absolute, "%s://%s%s", p_demux->psz_access, psz_path, psz_ref ) < 0 ) return VLC_ENOMEM; free( psz_ref ); psz_ref = psz_absolute; free( psz_path ); } input_item_t *p_input; msg_Dbg( p_demux, "adding ref = `%s'", psz_ref ); p_input = input_item_NewExt( p_demux, psz_ref, NULL, 0, NULL, -1 ); input_item_CopyOptions( p_current, p_input ); input_item_AddSubItem( p_current, p_input ); vlc_gc_decref( p_input ); } else { msg_Err( p_demux, "unknown ref type=%4.4s FIXME (send a bug report)", (char*)&p_rdrf->data.p_rdrf->i_ref_type ); } free( psz_ref ); } vlc_object_release( p_input ); } if( !(p_mvhd = MP4_BoxGet( p_sys->p_root, "/moov/mvhd" ) ) ) { if( !p_rmra ) { msg_Err( p_demux, "cannot find /moov/mvhd" ); goto error; } else { msg_Warn( p_demux, "cannot find /moov/mvhd (pure ref file)" ); p_demux->pf_demux = DemuxRef; return VLC_SUCCESS; } } else { p_sys->i_timescale = p_mvhd->data.p_mvhd->i_timescale; if( p_sys->i_timescale == 0 ) { msg_Err( p_this, "bad timescale" ); goto error; } p_sys->i_duration = p_mvhd->data.p_mvhd->i_duration; } if( !( p_sys->i_tracks = MP4_BoxCount( p_sys->p_root, "/moov/trak" ) ) ) { msg_Err( p_demux, "cannot find any /moov/trak" ); goto error; } msg_Dbg( p_demux, "found %d track%c", p_sys->i_tracks, p_sys->i_tracks ? 's':' ' ); /* allocate memory */ p_sys->track = calloc( p_sys->i_tracks, sizeof( mp4_track_t ) ); if( p_sys->track == NULL ) goto error; memset( p_sys->track, 0, p_sys->i_tracks * sizeof( mp4_track_t ) ); /* Search the first chap reference (like quicktime) and * check that at least 1 stream is enabled */ p_sys->p_tref_chap = NULL; b_enabled_es = false; for( i = 0; i < p_sys->i_tracks; i++ ) { MP4_Box_t *p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i ); MP4_Box_t *p_tkhd = MP4_BoxGet( p_trak, "tkhd" ); if( p_tkhd && (p_tkhd->data.p_tkhd->i_flags&MP4_TRACK_ENABLED) ) b_enabled_es = true; MP4_Box_t *p_chap = MP4_BoxGet( p_trak, "tref/chap", i ); if( p_chap && p_chap->data.p_tref_generic->i_entry_count > 0 && !p_sys->p_tref_chap ) p_sys->p_tref_chap = p_chap; } /* now process each track and extract all usefull information */ for( i = 0; i < p_sys->i_tracks; i++ ) { p_trak = MP4_BoxGet( p_sys->p_root, "/moov/trak[%d]", i ); MP4_TrackCreate( p_demux, &p_sys->track[i], p_trak, !b_enabled_es ); if( p_sys->track[i].b_ok && !p_sys->track[i].b_chapter ) { const char *psz_cat; switch( p_sys->track[i].fmt.i_cat ) { case( VIDEO_ES ): psz_cat = "video"; break; case( AUDIO_ES ): psz_cat = "audio"; break; case( SPU_ES ): psz_cat = "subtitle"; break; default: psz_cat = "unknown"; break; } msg_Dbg( p_demux, "adding track[Id 0x%x] %s (%s) language %s", p_sys->track[i].i_track_ID, psz_cat, p_sys->track[i].b_enable ? "enable":"disable", p_sys->track[i].fmt.psz_language ? p_sys->track[i].fmt.psz_language : "undef" ); } else if( p_sys->track[i].b_ok && p_sys->track[i].b_chapter ) { msg_Dbg( p_demux, "using track[Id 0x%x] for chapter language %s", p_sys->track[i].i_track_ID, p_sys->track[i].fmt.psz_language ? p_sys->track[i].fmt.psz_language : "undef" ); } else { msg_Dbg( p_demux, "ignoring track[Id 0x%x]", p_sys->track[i].i_track_ID ); } } /* */ LoadChapter( p_demux ); return VLC_SUCCESS;error: if( p_sys->p_root ) { MP4_BoxFree( p_demux->s, p_sys->p_root ); } free( p_sys ); return VLC_EGENERIC;}/***************************************************************************** * Demux: read packet and send them to decoders ***************************************************************************** * TODO check for newly selected track (ie audio upt to now ) *****************************************************************************/static int Demux( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; unsigned int i_track; unsigned int i_track_selected; /* check for newly selected/unselected track */ for( i_track = 0, i_track_selected = 0; i_track < p_sys->i_tracks; i_track++ ) { mp4_track_t *tk = &p_sys->track[i_track]; bool b; if( !tk->b_ok || tk->b_chapter || ( tk->b_selected && tk->i_sample >= tk->i_sample_count ) ) { continue; } es_out_Control( p_demux->out, ES_OUT_GET_ES_STATE, tk->p_es, &b ); if( tk->b_selected && !b ) { MP4_TrackUnselect( p_demux, tk ); } else if( !tk->b_selected && b) { MP4_TrackSelect( p_demux, tk, MP4_GetMoviePTS( p_sys ) ); } if( tk->b_selected ) { i_track_selected++; } } if( i_track_selected <= 0 ) { p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 ); if( p_sys->i_timescale > 0 ) { int64_t i_length = (mtime_t)1000000 * (mtime_t)p_sys->i_duration / (mtime_t)p_sys->i_timescale; if( MP4_GetMoviePTS( p_sys ) >= i_length ) return 0; return 1; } msg_Warn( p_demux, "no track selected, exiting..." ); return 0; } /* */ MP4_UpdateSeekpoint( p_demux ); /* first wait for the good time to read a packet */ es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_pcr + 1 ); p_sys->i_pcr = MP4_GetMoviePTS( p_sys ); /* we will read 100ms for each stream so ...*/ p_sys->i_time += __MAX( p_sys->i_timescale / 10 , 1 ); for( i_track = 0; i_track < p_sys->i_tracks; i_track++ ) { mp4_track_t *tk = &p_sys->track[i_track]; if( !tk->b_ok || tk->b_chapter || !tk->b_selected || tk->i_sample >= tk->i_sample_count ) continue; while( MP4_TrackGetDTS( p_demux, tk ) < MP4_GetMoviePTS( p_sys ) ) {#if 0 msg_Dbg( p_demux, "tk(%i)=%lld mv=%lld", i_track, MP4_TrackGetDTS( p_demux, tk ), MP4_GetMoviePTS( p_sys ) );#endif if( MP4_TrackSampleSize( tk ) > 0 ) { block_t *p_block; int64_t i_delta; /* go,go go ! */ if( stream_Seek( p_demux->s, MP4_TrackGetPos( tk ) ) ) { msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)", tk->i_track_ID ); MP4_TrackUnselect( p_demux, tk ); break; } /* now read pes */ if( !(p_block = stream_Block( p_demux->s, MP4_TrackSampleSize(tk) )) ) { msg_Warn( p_demux, "track[0x%x] will be disabled (eof?)", tk->i_track_ID ); MP4_TrackUnselect( p_demux, tk ); break; } if( tk->b_drms && tk->p_drms ) { drms_decrypt( tk->p_drms, (uint32_t*)p_block->p_buffer, p_block->i_buffer ); } else if( tk->fmt.i_cat == SPU_ES ) { if( tk->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) && p_block->i_buffer >= 2 ) { uint16_t i_size = GetWBE( p_block->p_buffer ); if( i_size + 2 <= p_block->i_buffer ) { char *p; /* remove the length field, and append a '\0' */ memmove( &p_block->p_buffer[0], &p_block->p_buffer[2], i_size ); p_block->p_buffer[i_size] = '\0'; p_block->i_buffer = i_size + 1; /* convert \r -> \n */ while( ( p = strchr((char *) p_block->p_buffer, '\r' ) ) ) { *p = '\n'; } } else { /* Invalid */ p_block->i_buffer = 0; } } } /* dts */ p_block->i_dts = MP4_TrackGetDTS( p_demux, tk ) + 1; /* pts */ i_delta = MP4_TrackGetPTSDelta( tk ); if( i_delta != -1 ) p_block->i_pts = p_block->i_dts + i_delta; else if( tk->fmt.i_cat != VIDEO_ES ) p_block->i_pts = p_block->i_dts; else p_block->i_pts = 0; if( !tk->b_drms || ( tk->b_drms && tk->p_drms ) ) es_out_Send( p_demux->out, tk->p_es, p_block ); } /* Next sample */ if( MP4_TrackNextSample( p_demux, tk ) ) break; } } return 1;}static void MP4_UpdateSeekpoint( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; int64_t i_time; int i; if( !p_sys->p_title ) return; i_time = MP4_GetMoviePTS( p_sys ); for( i = 0; i < p_sys->p_title->i_seekpoint; i++ ) { if( i_time < p_sys->p_title->seekpoint[i]->i_time_offset ) break; } i--; if( i != p_demux->info.i_seekpoint && i >= 0 ) { p_demux->info.i_seekpoint = i; p_demux->info.i_update |= INPUT_UPDATE_SEEKPOINT; }}/***************************************************************************** * Seek: Got to i_date******************************************************************************/static int Seek( demux_t *p_demux, mtime_t i_date ){ demux_sys_t *p_sys = p_demux->p_sys; unsigned int i_track;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -