📄 ogg.c
字号:
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 { 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 ; 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++ ) {#define p_stream p_ogg->pp_stream[i_stream] p_stream->p_es = es_out_Add( p_demux->out, &p_stream->fmt ); 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;#undef p_stream } 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;#define p_stream p_ogg->pp_stream[i_stream] for( i_stream = 0 ; i_stream < p_ogg->i_streams; i_stream++ ) { if( p_stream->p_es ) es_out_Del( p_demux->out, p_stream->p_es ); p_ogg->i_bitrate -= p_stream->fmt.i_bitrate; ogg_stream_clear( &p_ogg->pp_stream[i_stream]->os ); if( p_ogg->pp_stream[i_stream]->p_headers) free( p_ogg->pp_stream[i_stream]->p_headers ); es_format_Clean( &p_stream->fmt ); free( p_ogg->pp_stream[i_stream] ); }#undef p_stream /* Reinit p_ogg */ if( p_ogg->pp_stream ) free( p_ogg->pp_stream ); p_ogg->pp_stream = NULL; p_ogg->i_streams = 0;}static void Ogg_ReadTheoraHeader( logical_stream_t *p_stream, ogg_packet *p_oggpacket ){ bs_t bitstream; int i_fps_numerator; int i_fps_denominator; int i_keyframe_frequency_force; p_stream->fmt.i_cat = VIDEO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 't','h','e','o' ); /* Signal that we want to keep a backup of the theora * stream headers. They will be used when switching between * audio streams. */ p_stream->b_force_backup = 1; /* Cheat and get additionnal info ;) */ bs_init( &bitstream, p_oggpacket->packet, p_oggpacket->bytes ); bs_skip( &bitstream, 56 ); bs_read( &bitstream, 8 ); /* major version num */ bs_read( &bitstream, 8 ); /* minor version num */ bs_read( &bitstream, 8 ); /* subminor version num */ bs_read( &bitstream, 16 ) /*<< 4*/; /* width */ bs_read( &bitstream, 16 ) /*<< 4*/; /* height */ bs_read( &bitstream, 24 ); /* frame width */ bs_read( &bitstream, 24 ); /* frame height */ bs_read( &bitstream, 8 ); /* x offset */ bs_read( &bitstream, 8 ); /* y offset */ i_fps_numerator = bs_read( &bitstream, 32 ); i_fps_denominator = bs_read( &bitstream, 32 ); bs_read( &bitstream, 24 ); /* aspect_numerator */ bs_read( &bitstream, 24 ); /* aspect_denominator */ p_stream->fmt.video.i_frame_rate = i_fps_numerator; p_stream->fmt.video.i_frame_rate_base = i_fps_denominator; bs_read( &bitstream, 8 ); /* colorspace */ p_stream->fmt.i_bitrate = bs_read( &bitstream, 24 ); bs_read( &bitstream, 6 ); /* quality */ i_keyframe_frequency_force = 1 << bs_read( &bitstream, 5 ); /* granule_shift = i_log( frequency_force -1 ) */ p_stream->i_theora_keyframe_granule_shift = 0; i_keyframe_frequency_force--; while( i_keyframe_frequency_force ) { p_stream->i_theora_keyframe_granule_shift++; i_keyframe_frequency_force >>= 1; } p_stream->f_rate = ((float)i_fps_numerator) / i_fps_denominator;}static void Ogg_ReadVorbisHeader( logical_stream_t *p_stream, ogg_packet *p_oggpacket ){ oggpack_buffer opb; p_stream->fmt.i_cat = AUDIO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'v','o','r','b' ); /* Signal that we want to keep a backup of the vorbis * stream headers. They will be used when switching between * audio streams. */ p_stream->b_force_backup = 1; /* Cheat and get additionnal info ;) */ oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes); oggpack_adv( &opb, 88 ); p_stream->fmt.audio.i_channels = oggpack_read( &opb, 8 ); p_stream->f_rate = p_stream->fmt.audio.i_rate = oggpack_read( &opb, 32 ); oggpack_adv( &opb, 32 ); p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );}static void Ogg_ReadSpeexHeader( logical_stream_t *p_stream, ogg_packet *p_oggpacket ){ oggpack_buffer opb; p_stream->fmt.i_cat = AUDIO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 's','p','x',' ' ); /* Signal that we want to keep a backup of the speex * stream headers. They will be used when switching between * audio streams. */ p_stream->b_force_backup = 1; /* Cheat and get additionnal info ;) */ oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes); oggpack_adv( &opb, 224 ); oggpack_adv( &opb, 32 ); /* speex_version_id */ oggpack_adv( &opb, 32 ); /* header_size */ p_stream->f_rate = p_stream->fmt.audio.i_rate = oggpack_read( &opb, 32 ); oggpack_adv( &opb, 32 ); /* mode */ oggpack_adv( &opb, 32 ); /* mode_bitstream_version */ p_stream->fmt.audio.i_channels = oggpack_read( &opb, 32 ); p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 );}static void Ogg_ReadFlacHeader( demux_t *p_demux, logical_stream_t *p_stream, ogg_packet *p_oggpacket ){ /* Parse the STREAMINFO metadata */ bs_t s; bs_init( &s, p_oggpacket->packet, p_oggpacket->bytes ); bs_read( &s, 1 ); if( bs_read( &s, 7 ) == 0 ) { if( bs_read( &s, 24 ) >= 34 /*size STREAMINFO*/ ) { bs_skip( &s, 80 ); p_stream->f_rate = p_stream->fmt.audio.i_rate = bs_read( &s, 20 ); p_stream->fmt.audio.i_channels = bs_read( &s, 3 ) + 1; msg_Dbg( p_demux, "FLAC header, channels: %i, rate: %i", p_stream->fmt.audio.i_channels, (int)p_stream->f_rate ); } else msg_Dbg( p_demux, "FLAC STREAMINFO metadata too short" ); /* Fake this as the last metadata block */ *((uint8_t*)p_oggpacket->packet) |= 0x80; } else { /* This ain't a STREAMINFO metadata */ msg_Dbg( p_demux, "Invalid FLAC STREAMINFO metadata" ); }}static void Ogg_ReadAnnodexHeader( vlc_object_t *p_this, logical_stream_t *p_stream, ogg_packet *p_oggpacket ){ if( p_oggpacket->bytes >= 28 && !memcmp( &p_oggpacket->packet[0], "Annodex", 7 ) ) { oggpack_buffer opb; uint16_t major_version; uint16_t minor_version; uint64_t timebase_numerator; uint64_t timebase_denominator; Ogg_ReadTheoraHeader( p_stream, p_oggpacket ); oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes); oggpack_adv( &opb, 8*8 ); /* "Annodex\0" header */ major_version = oggpack_read( &opb, 2*8 ); /* major version */ minor_version = oggpack_read( &opb, 2*8 ); /* minor version */ timebase_numerator = GetQWLE( &p_oggpacket->packet[16] ); timebase_denominator = GetQWLE( &p_oggpacket->packet[24] ); } else if( p_oggpacket->bytes >= 42 && !memcmp( &p_oggpacket->packet[0], "AnxData", 7 ) ) { uint64_t granule_rate_numerator; uint64_t granule_rate_denominator; char content_type_string[1024]; /* Read in Annodex header fields */ granule_rate_numerator = GetQWLE( &p_oggpacket->packet[8] ); granule_rate_denominator = GetQWLE( &p_oggpacket->packet[16] ); p_stream->secondary_header_packets = GetDWLE( &p_oggpacket->packet[24] ); /* we are guaranteed that the first header field will be * the content-type (by the Annodex standard) */ content_type_string[0] = '\0'; if( !strncasecmp( (char*)(&p_oggpacket->packet[28]), "Content-Type: ", 14 ) ) { uint8_t *p = memchr( &p_oggpacket->packet[42], '\r', p_oggpacket->bytes - 1 ); if( p && p[0] == '\r' && p[1] == '\n' ) sscanf( (char*)(&p_oggpacket->packet[42]), "%1024s\r\n", content_type_string ); } msg_Dbg( p_this, "AnxData packet info: "I64Fd" / "I64Fd", %d, ``%s''", granule_rate_numerator, granule_rate_denominator, p_stream->secondary_header_packets, content_type_string ); p_stream->f_rate = (float) granule_rate_numerator / (float) granule_rate_denominator; /* What type of file do we have? * strcmp is safe to use here because we've extracted * content_type_string from the stream manually */ if( !strncmp(content_type_string, "audio/x-wav", 11) ) { /* n.b. WAVs are unsupported right now */ p_stream->fmt.i_cat = UNKNOWN_ES; } else if( !strncmp(content_type_string, "audio/x-vorbis", 14) ) { p_stream->fmt.i_cat = AUDIO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'v','o','r','b' ); p_stream->b_force_backup = 1; } else if( !strncmp(content_type_string, "audio/x-speex", 14) ) { p_stream->fmt.i_cat = AUDIO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 's','p','x',' ' ); p_stream->b_force_backup = 1; } else if( !strncmp(content_type_string, "video/x-theora", 14) ) { p_stream->fmt.i_cat = VIDEO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 't','h','e','o' ); p_stream->b_force_backup = 1; } else if( !strncmp(content_type_string, "video/x-xvid", 14) ) { p_stream->fmt.i_cat = VIDEO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'x','v','i','d' ); p_stream->b_force_backup = 1; } else if( !strncmp(content_type_string, "video/mpeg", 14) ) { /* n.b. MPEG streams are unsupported right now */ p_stream->fmt.i_cat = VIDEO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'm','p','g','v' ); } else if( !strncmp(content_type_string, "text/x-cmml", 11) ) { ogg_stream_packetout( &p_stream->os, p_oggpacket ); p_stream->fmt.i_cat = SPU_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'c','m','m','l' ); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -