📄 livedotcom.cpp
字号:
p_sys->i_start ) ) / 1000000.00; b_bool = (vlc_bool_t)va_arg( args, vlc_bool_t ); if( p_sys->rtsp == NULL ) return VLC_EGENERIC; iter = new MediaSubsessionIterator( *p_sys->ms ); while( ( sub = iter->next() ) != NULL ) { if( ( b_bool && !p_sys->rtsp->pauseMediaSubsession( *sub ) ) || ( !b_bool && !p_sys->rtsp->playMediaSubsession( *sub, d_npt > 0 ? d_npt : -1 ) ) ) { delete iter; return VLC_EGENERIC; } } delete iter;#if 0 /* reset PCR and PCR start, mmh won't work well for multi-stream I fear */ for( i = 0; i < p_sys->i_track; i++ ) { p_sys->track[i]->i_pts = 0; } p_sys->i_pcr_start = 0; /* FIXME Wrong */ p_sys->i_pcr = 0;#endif return VLC_SUCCESS; case DEMUX_GET_TITLE_INFO: case DEMUX_SET_TITLE: case DEMUX_SET_SEEKPOINT: return VLC_EGENERIC; case DEMUX_GET_PTS_DELAY: pi64 = (int64_t*)va_arg( args, int64_t * ); *pi64 = (int64_t)var_GetInteger( p_demux, "rtsp-caching" ) * 1000; return VLC_SUCCESS; default: return VLC_EGENERIC; }}/***************************************************************************** * RollOverTcp: reopen the rtsp into TCP mode * XXX: ugly, a lot of code are duplicated from Open() *****************************************************************************/static int RollOverTcp( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; MediaSubsessionIterator *iter; MediaSubsession *sub; char *psz_url; char *psz_options; uint8_t *p_sdp; int i_tk; /* We close the old RTSP session */ p_sys->rtsp->teardownMediaSession( *p_sys->ms ); Medium::close( p_sys->ms ); Medium::close( p_sys->rtsp ); p_sys->ms = NULL; p_sys->rtsp = NULL; /* Reopen rtsp client */ if( ( p_sys->rtsp = RTSPClient::createNew(*p_sys->env, 1/*verbose*/, "VLC Media Player" ) ) == NULL ) { msg_Err( p_demux, "RTSPClient::createNew failed (%s)", p_sys->env->getResultMsg() ); return VLC_EGENERIC; } asprintf( &psz_url, "rtsp://%s", p_sys->psz_path ); if( ( psz_options = p_sys->rtsp->sendOptionsCmd( psz_url ) ) ) delete [] psz_options; p_sdp = (uint8_t*)p_sys->rtsp->describeURL( psz_url, NULL, var_CreateGetBool( p_demux, "rtsp-kasenna" ) ); free( psz_url ); if( p_sdp == NULL ) { msg_Err( p_demux, "describeURL failed (%s)", p_sys->env->getResultMsg() ); return VLC_EGENERIC; } /* malloc-ated copy */ p_sys->p_sdp = strdup( (char*)p_sdp ); delete[] p_sdp; if( !( p_sys->ms = MediaSession::createNew( *p_sys->env, p_sys->p_sdp ) ) ) { msg_Err( p_demux, "MediaSession::createNew failed" ); return VLC_EGENERIC; } /* Initialise each media subsession */ iter = new MediaSubsessionIterator( *p_sys->ms ); while( ( sub = iter->next() ) != NULL ) { Boolean bInit; if( !strcmp( sub->codecName(), "X-ASF-PF" ) ) bInit = sub->initiate( 4 ); /* Constant ? */ else bInit = sub->initiate(); if( !bInit ) { msg_Warn( p_demux, "RTP subsession '%s/%s' failed (%s)", sub->mediumName(), sub->codecName(), p_sys->env->getResultMsg() ); continue; } msg_Dbg( p_demux, "RTP subsession '%s/%s'", sub->mediumName(), sub->codecName() ); /* Issue the SETUP */ p_sys->rtsp->setupMediaSubsession( *sub, False, True /* tcp */ ); } /* The PLAY */ if( !p_sys->rtsp->playMediaSession( *p_sys->ms ) ) { msg_Err( p_demux, "PLAY failed %s", p_sys->env->getResultMsg() ); return VLC_EGENERIC; } /* Update all tracks */ iter->reset(); i_tk = 0; while( ( sub = iter->next() ) != NULL ) { live_track_t *tk; if( sub->readSource() == NULL ) continue; if( i_tk >= p_sys->i_track ) { msg_Err( p_demux, "WTF !" ); break; } tk = p_sys->track[i_tk]; /* Reset state */ tk->waiting = 0; tk->i_pts = 0; tk->b_rtcp_sync = VLC_FALSE; if( sub->rtcpInstance() != NULL ) sub->rtcpInstance()->setByeHandler( StreamClose, tk ); tk->readSource = sub->readSource(); tk->rtpSource = sub->rtpSource(); i_tk++; } delete iter; return VLC_SUCCESS;}/***************************************************************************** * *****************************************************************************/static void StreamRead( void *p_private, unsigned int i_size, unsigned int i_truncated_bytes, struct timeval pts, unsigned int duration ){ live_track_t *tk = (live_track_t*)p_private; demux_t *p_demux = tk->p_demux; demux_sys_t *p_sys = p_demux->p_sys; block_t *p_block; mtime_t i_pts = (uint64_t)pts.tv_sec * UI64C(1000000) + (uint64_t)pts.tv_usec; /* XXX Beurk beurk beurk Avoid having negative value XXX */ i_pts &= UI64C(0x00ffffffffffffff); if( tk->b_quicktime && tk->p_es == NULL ) { QuickTimeGenericRTPSource *qtRTPSource = (QuickTimeGenericRTPSource*)tk->rtpSource; QuickTimeGenericRTPSource::QTState &qtState = qtRTPSource->qtState; uint8_t *sdAtom = (uint8_t*)&qtState.sdAtom[4]; if( qtState.sdAtomSize < 16 + 32 ) { /* invalid */ p_sys->event = 0xff; tk->waiting = 0; return; } tk->fmt.i_codec = VLC_FOURCC(sdAtom[0],sdAtom[1],sdAtom[2],sdAtom[3]); tk->fmt.video.i_width = (sdAtom[28] << 8) | sdAtom[29]; tk->fmt.video.i_height = (sdAtom[30] << 8) | sdAtom[31]; tk->fmt.i_extra = qtState.sdAtomSize - 16; tk->fmt.p_extra = malloc( tk->fmt.i_extra ); memcpy( tk->fmt.p_extra, &sdAtom[12], tk->fmt.i_extra ); tk->p_es = es_out_Add( p_demux->out, &tk->fmt ); }#if 0 fprintf( stderr, "StreamRead size=%d pts=%lld\n", i_size, pts.tv_sec * 1000000LL + pts.tv_usec );#endif /* grow buffer if it looks like buffer is too small, but don't eat * up all the memory on strange streams */ if( i_truncated_bytes > 0 && tk->i_buffer < 2000000 ) { void *p_tmp; msg_Dbg( p_demux, "lost %d bytes", i_truncated_bytes ); msg_Dbg( p_demux, "increasing buffer size to %d", tk->i_buffer * 2 ); tk->i_buffer *= 2; p_tmp = realloc( tk->p_buffer, tk->i_buffer ); if (p_tmp == NULL) { msg_Warn( p_demux, "realloc failed" ); } else { tk->p_buffer = (uint8_t*)p_tmp; } } if( i_size > tk->i_buffer ) { msg_Warn( p_demux, "buffer overflow" ); } /* FIXME could i_size be > buffer size ? */ if( tk->fmt.i_codec == VLC_FOURCC('h','2','6','1') ) {#if LIVEMEDIA_LIBRARY_VERSION_INT >= 1081468800 H261VideoRTPSource *h261Source = (H261VideoRTPSource*)tk->rtpSource; uint32_t header = h261Source->lastSpecialHeader();#else uint32_t header = 0; msg_Warn( p_demux, "need livemedia library >= \"2004.04.09\"" );#endif p_block = block_New( p_demux, i_size + 4 ); memcpy( p_block->p_buffer, &header, 4 ); memcpy( p_block->p_buffer + 4, tk->p_buffer, i_size ); } else if( tk->b_asf ) { int i_copy = __MIN( p_sys->asfh.i_min_data_packet_size, (int)i_size ); p_block = block_New( p_demux, p_sys->asfh.i_min_data_packet_size ); memcpy( p_block->p_buffer, tk->p_buffer, i_copy ); } else { p_block = block_New( p_demux, i_size ); memcpy( p_block->p_buffer, tk->p_buffer, i_size ); } if( tk->fmt.i_codec == VLC_FOURCC('h','2','6','1') && tk->rtpSource->curPacketMarkerBit() ) { p_block->i_flags |= BLOCK_FLAG_END_OF_FRAME; } //p_block->i_rate = p_input->stream.control.i_rate; if( i_pts != tk->i_pts && !tk->b_muxed ) { p_block->i_dts = ( tk->fmt.i_cat == VIDEO_ES ) ? 0 : i_pts; p_block->i_pts = i_pts; } //fprintf( stderr, "tk -> dpts=%lld\n", i_pts - tk->i_pts ); if( tk->b_muxed ) { stream_DemuxSend( tk->p_out_muxed, p_block ); } else if( tk->b_asf ) { stream_DemuxSend( p_sys->p_out_asf, p_block ); } else { es_out_Send( p_demux->out, tk->p_es, p_block ); } /* warm that's ok */ p_sys->event = 0xff; /* we have read data */ tk->waiting = 0; p_demux->p_sys->b_no_data = VLC_FALSE; p_demux->p_sys->i_no_data_ti = 0; if( i_pts > 0 && !tk->b_muxed ) { tk->i_pts = i_pts; }}/***************************************************************************** * *****************************************************************************/static void StreamClose( void *p_private ){ live_track_t *tk = (live_track_t*)p_private; demux_t *p_demux = tk->p_demux; demux_sys_t *p_sys = p_demux->p_sys; fprintf( stderr, "StreamClose\n" ); p_sys->event = 0xff; p_demux->b_error = VLC_TRUE;}/***************************************************************************** * *****************************************************************************/static void TaskInterrupt( void *p_private ){ demux_t *p_demux = (demux_t*)p_private; fprintf( stderr, "TaskInterrupt\n" ); p_demux->p_sys->i_no_data_ti++; /* Avoid lock */ p_demux->p_sys->event = 0xff;}/***************************************************************************** * *****************************************************************************/static int b64_decode( char *dest, char *src );static int ParseASF( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; const char *psz_marker = "a=pgmpu:data:application/vnd.ms.wms-hdr.asfv1;base64,"; char *psz_asf = strcasestr( p_sys->p_sdp, psz_marker ); char *psz_end; block_t *p_header; /* Parse the asf header */ if( psz_asf == NULL ) return VLC_EGENERIC; psz_asf += strlen( psz_marker ); psz_asf = strdup( psz_asf ); /* Duplicate it */ psz_end = strchr( psz_asf, '\n' ); while( psz_end > psz_asf && ( *psz_end == '\n' || *psz_end == '\r' ) ) *psz_end-- = '\0'; if( psz_asf >= psz_end ) { free( psz_asf ); return VLC_EGENERIC; } /* Always smaller */ p_header = block_New( p_demux, psz_end - psz_asf ); p_header->i_buffer = b64_decode( (char*)p_header->p_buffer, psz_asf ); fprintf( stderr, "Size=%d Hdrb64=%s\n", p_header->i_buffer, psz_asf ); if( p_header->i_buffer <= 0 ) { free( psz_asf ); return VLC_EGENERIC; } /* Parse it to get packet size */ E_(asf_HeaderParse)( &p_sys->asfh, p_header->p_buffer, p_header->i_buffer ); /* Send it to demuxer */ stream_DemuxSend( p_sys->p_out_asf, p_header ); free( psz_asf ); return VLC_SUCCESS;}/*char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";*/static int b64_decode( char *dest, char *src ){ const char *dest_start = dest; int i_level; int last = 0; int b64[256] = { -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 00-0F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 10-1F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63, /* 20-2F */ 52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1, /* 30-3F */ -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14, /* 40-4F */ 15,16,17,18,19,20,21,22,23,24,25,-1,-1,-1,-1,-1, /* 50-5F */ -1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, /* 60-6F */ 41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1, /* 70-7F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 80-8F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* 90-9F */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* A0-AF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* B0-BF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* C0-CF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* D0-DF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, /* E0-EF */ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 /* F0-FF */ }; for( i_level = 0; *src != '\0'; src++ ) { int c; c = b64[(unsigned int)*src]; if( c == -1 ) { continue; } switch( i_level ) { case 0: i_level++; break; case 1: *dest++ = ( last << 2 ) | ( ( c >> 4)&0x03 ); i_level++; break; case 2: *dest++ = ( ( last << 4 )&0xf0 ) | ( ( c >> 2 )&0x0f ); i_level++; break; case 3: *dest++ = ( ( last &0x03 ) << 6 ) | c; i_level = 0; } last = c; } *dest = '\0'; return dest - dest_start;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -