📄 ogg.c
字号:
p_stream->fmt.i_bitrate = GetDWLE((oggpacket.packet+132)) * 8; p_stream->fmt.audio.i_blockalign = GetWLE((oggpacket.packet+136)); p_stream->fmt.audio.i_bitspersample = GetWLE((oggpacket.packet+138)); wf_tag_to_fourcc( i_format_tag, &p_stream->fmt.i_codec, 0 ); if( p_stream->fmt.i_codec == VLC_FOURCC('u','n','d','f') ) { p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's', ( i_format_tag >> 8 ) & 0xff, i_format_tag & 0xff ); } msg_Dbg( p_demux, "found audio header of type: %.4s", (char *)&p_stream->fmt.i_codec ); msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz " "%dbits/sample %dkb/s", i_format_tag, p_stream->fmt.audio.i_channels, p_stream->fmt.audio.i_rate, p_stream->fmt.audio.i_bitspersample, p_stream->fmt.i_bitrate / 1024 ); } else { msg_Dbg( p_demux, "stream %d has an old header " "but is of an unknown type", p_ogg->i_streams-1 ); free( p_stream ); p_ogg->i_streams--; } } else if( (*oggpacket.packet & PACKET_TYPE_BITS ) == PACKET_TYPE_HEADER && oggpacket.bytes >= (int)sizeof(stream_header)+1 ) { stream_header *st = (stream_header *)(oggpacket.packet+1); /* Check for video header (new format) */ if( !strncmp( st->streamtype, "video", 5 ) ) { p_stream->fmt.i_cat = VIDEO_ES; /* We need to get rid of the header packet */ ogg_stream_packetout( &p_stream->os, &oggpacket ); p_stream->fmt.i_codec = VLC_FOURCC( st->subtype[0], st->subtype[1], st->subtype[2], st->subtype[3] ); msg_Dbg( p_demux, "found video header of type: %.4s", (char *)&p_stream->fmt.i_codec ); p_stream->fmt.video.i_frame_rate = 10000000; p_stream->fmt.video.i_frame_rate_base = GetQWLE(&st->time_unit); p_stream->f_rate = 10000000.0 / GetQWLE(&st->time_unit); p_stream->fmt.video.i_bits_per_pixel = GetWLE(&st->bits_per_sample); p_stream->fmt.video.i_width = GetDWLE(&st->sh.video.width); p_stream->fmt.video.i_height = GetDWLE(&st->sh.video.height); msg_Dbg( p_demux, "fps: %f, width:%i; height:%i, bitcount:%i", p_stream->f_rate, p_stream->fmt.video.i_width, p_stream->fmt.video.i_height, p_stream->fmt.video.i_bits_per_pixel ); } /* Check for audio header (new format) */ else if( !strncmp( st->streamtype, "audio", 5 ) ) { char p_buffer[5]; int i_format_tag; p_stream->fmt.i_cat = AUDIO_ES; /* We need to get rid of the header packet */ ogg_stream_packetout( &p_stream->os, &oggpacket ); p_stream->fmt.i_extra = GetQWLE(&st->size) - sizeof(stream_header); if( p_stream->fmt.i_extra > 0 && p_stream->fmt.i_extra < oggpacket.bytes - 1 - sizeof(stream_header) ) { p_stream->fmt.p_extra = malloc( p_stream->fmt.i_extra ); if( p_stream->fmt.p_extra ) memcpy( p_stream->fmt.p_extra, st + 1, p_stream->fmt.i_extra ); else p_stream->fmt.i_extra = 0; } memcpy( p_buffer, st->subtype, 4 ); p_buffer[4] = '\0'; i_format_tag = strtol(p_buffer,NULL,16); p_stream->fmt.audio.i_channels = GetWLE(&st->sh.audio.channels); p_stream->f_rate = p_stream->fmt.audio.i_rate = GetQWLE(&st->samples_per_unit); p_stream->fmt.i_bitrate = GetDWLE(&st->sh.audio.avgbytespersec) * 8; p_stream->fmt.audio.i_blockalign = GetWLE(&st->sh.audio.blockalign); p_stream->fmt.audio.i_bitspersample = GetWLE(&st->bits_per_sample); wf_tag_to_fourcc( i_format_tag, &p_stream->fmt.i_codec, 0 ); if( p_stream->fmt.i_codec == VLC_FOURCC('u','n','d','f') ) { p_stream->fmt.i_codec = VLC_FOURCC( 'm', 's', ( i_format_tag >> 8 ) & 0xff, i_format_tag & 0xff ); } msg_Dbg( p_demux, "found audio header of type: %.4s", (char *)&p_stream->fmt.i_codec ); msg_Dbg( p_demux, "audio:0x%4.4x channels:%d %dHz " "%dbits/sample %dkb/s", i_format_tag, p_stream->fmt.audio.i_channels, p_stream->fmt.audio.i_rate, p_stream->fmt.audio.i_bitspersample, p_stream->fmt.i_bitrate / 1024 ); } /* Check for text (subtitles) header */ else if( !strncmp(st->streamtype, "text", 4) ) { /* We need to get rid of the header packet */ ogg_stream_packetout( &p_stream->os, &oggpacket ); msg_Dbg( p_demux, "found text subtitles header" ); p_stream->fmt.i_cat = SPU_ES; p_stream->fmt.i_codec = VLC_FOURCC('s','u','b','t'); p_stream->f_rate = 1000; /* granulepos is in milisec */ } else { msg_Dbg( p_demux, "stream %d has a header marker " "but is of an unknown type", p_ogg->i_streams-1 ); free( p_stream ); p_ogg->i_streams--; } } else if( oggpacket.bytes >= 7 && ! memcmp( oggpacket.packet, "fishead", 7 ) ) { /* Skeleton */ msg_Dbg( p_demux, "stream %d is a skeleton", p_ogg->i_streams-1 ); /* FIXME: https://trac.videolan.org/vlc/ticket/1412 */ } else { msg_Dbg( p_demux, "stream %d is of unknown type", p_ogg->i_streams-1 ); free( p_stream ); p_ogg->i_streams--; } if( Ogg_ReadPage( p_demux, &oggpage ) != VLC_SUCCESS ) return VLC_EGENERIC; } /* This is the first data page, which means we are now finished * with the initial pages. We just need to store it in the relevant * bitstream. */ for( i_stream = 0; i_stream < p_ogg->i_streams; i_stream++ ) { if( ogg_stream_pagein( &p_ogg->pp_stream[i_stream]->os, &oggpage ) == 0 ) { break; } } return VLC_SUCCESS; } }#undef p_stream return VLC_EGENERIC;}/**************************************************************************** * Ogg_BeginningOfStream: Look for Beginning of Stream ogg pages and add * Elementary streams. ****************************************************************************/static int Ogg_BeginningOfStream( demux_t *p_demux ){ demux_sys_t *p_ogg = p_demux->p_sys ; logical_stream_t *p_old_stream = p_ogg->p_old_stream; int i_stream; /* Find the logical streams embedded in the physical stream and * initialize our p_ogg structure. */ if( Ogg_FindLogicalStreams( p_demux ) != VLC_SUCCESS ) { msg_Warn( p_demux, "couldn't find any ogg logical stream" ); return VLC_EGENERIC; } p_ogg->i_bitrate = 0; for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ ) { logical_stream_t *p_stream = p_ogg->pp_stream[i_stream]; p_stream->p_es = NULL; /* Try first to reuse an old ES */ if( p_old_stream && p_old_stream->fmt.i_cat == p_stream->fmt.i_cat && p_old_stream->fmt.i_codec == p_stream->fmt.i_codec ) { msg_Dbg( p_demux, "will reuse old stream to avoid glitch" ); p_stream->p_es = p_old_stream->p_es; es_format_Copy( &p_stream->fmt_old, &p_old_stream->fmt ); p_old_stream->p_es = NULL; p_old_stream = NULL; } if( !p_stream->p_es ) p_stream->p_es = es_out_Add( p_demux->out, &p_stream->fmt ); // TODO: something to do here ? if( p_stream->fmt.i_codec == VLC_FOURCC('c','m','m','l') ) { /* Set the CMML stream active */ es_out_Control( p_demux->out, ES_OUT_SET_ES, p_stream->p_es ); } p_ogg->i_bitrate += p_stream->fmt.i_bitrate; p_stream->i_pcr = p_stream->i_previous_pcr = p_stream->i_interpolated_pcr = -1; p_stream->b_reinit = 0; } if( p_ogg->p_old_stream ) { if( p_ogg->p_old_stream->p_es ) msg_Dbg( p_demux, "old stream not reused" ); Ogg_LogicalStreamDelete( p_demux, p_ogg->p_old_stream ); p_ogg->p_old_stream = NULL; } return VLC_SUCCESS;}/**************************************************************************** * Ogg_EndOfStream: clean up the ES when an End of Stream is detected. ****************************************************************************/static void Ogg_EndOfStream( demux_t *p_demux ){ demux_sys_t *p_ogg = p_demux->p_sys ; int i_stream; for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ ) Ogg_LogicalStreamDelete( p_demux, p_ogg->pp_stream[i_stream] ); free( p_ogg->pp_stream ); /* Reinit p_ogg */ p_ogg->i_bitrate = 0; p_ogg->i_streams = 0; p_ogg->pp_stream = NULL;}/** * This function delete and release all data associated to a logical_stream_t */static void Ogg_LogicalStreamDelete( demux_t *p_demux, logical_stream_t *p_stream ){ if( p_stream->p_es ) es_out_Del( p_demux->out, p_stream->p_es ); ogg_stream_clear( &p_stream->os ); free( p_stream->p_headers ); es_format_Clean( &p_stream->fmt_old ); es_format_Clean( &p_stream->fmt ); free( p_stream );}/** * This function check if a we need to reset a decoder in case we are * reusing an old ES */static bool Ogg_IsVorbisFormatCompatible( const es_format_t *p_new, const es_format_t *p_old ){ int i_new = 0; int i_old = 0; int i; for( i = 0; i < 3; i++ ) { const uint8_t *p_new_extra = ( const uint8_t*)p_new->p_extra + i_new; const uint8_t *p_old_extra = ( const uint8_t*)p_old->p_extra + i_old; if( p_new->i_extra < i_new+2 || p_old->i_extra < i_old+2 ) return false; const int i_new_size = GetWBE( &p_new_extra[0] ); const int i_old_size = GetWBE( &p_old_extra[0] ); if( i != 1 ) /* Ignore vorbis comment */ { if( i_new_size != i_old_size ) return false; if( memcmp( &p_new_extra[2], &p_old_extra[2], i_new_size ) ) return false; } i_new += 2 + i_new_size; i_old += 2 + i_old_size; } return true;}static bool Ogg_LogicalStreamResetEsFormat( demux_t *p_demux, logical_stream_t *p_stream ){ bool b_compatible; if( !p_stream->fmt_old.i_cat || !p_stream->fmt_old.i_codec ) return true; /* Only vorbis is supported */ if( p_stream->fmt.i_codec == VLC_FOURCC( 'v','o','r','b' ) ) b_compatible = Ogg_IsVorbisFormatCompatible( &p_stream->fmt, &p_stream->fmt_old ); if( !b_compatible ) msg_Warn( p_demux, "cannot reuse old stream, resetting the decoder" ); return !b_compatible;}static void Ogg_ReadTheoraHeader( logical_stream_t *p_stream, ogg_packet *p_oggpacket ){ bs_t bitstream;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -