📄 ogg.c
字号:
***************************************************************************** * The initial page of a logical stream is marked as a 'bos' page. * Furthermore, the Ogg specification mandates that grouped bitstreams begin * together and all of the initial pages must appear before any data pages. * * On success this function returns VLC_SUCCESS. ****************************************************************************/static int Ogg_FindLogicalStreams( demux_t *p_demux ){ demux_sys_t *p_ogg = p_demux->p_sys ; ogg_packet oggpacket; ogg_page oggpage; int i_stream;#define p_stream p_ogg->pp_stream[p_ogg->i_streams - 1] while( Ogg_ReadPage( p_demux, &oggpage ) == VLC_SUCCESS ) { if( ogg_page_bos( &oggpage ) ) { /* All is wonderful in our fine fine little world. * We found the beginning of our first logical stream. */ while( ogg_page_bos( &oggpage ) ) { p_ogg->i_streams++; p_ogg->pp_stream = realloc( p_ogg->pp_stream, p_ogg->i_streams * sizeof(logical_stream_t *) ); p_stream = malloc( sizeof(logical_stream_t) ); memset( p_stream, 0, sizeof(logical_stream_t) ); p_stream->p_headers = 0; p_stream->secondary_header_packets = 0; es_format_Init( &p_stream->fmt, 0, 0 ); /* Setup the logical stream */ p_stream->i_serial_no = ogg_page_serialno( &oggpage ); ogg_stream_init( &p_stream->os, p_stream->i_serial_no ); /* Extract the initial header from the first page and verify * the codec type of tis Ogg bitstream */ if( ogg_stream_pagein( &p_stream->os, &oggpage ) < 0 ) { /* error. stream version mismatch perhaps */ msg_Err( p_demux, "error reading first page of " "Ogg bitstream data" ); return VLC_EGENERIC; } /* FIXME: check return value */ ogg_stream_packetpeek( &p_stream->os, &oggpacket ); /* Check for Vorbis header */ if( oggpacket.bytes >= 7 && ! memcmp( &oggpacket.packet[1], "vorbis", 6 ) ) { Ogg_ReadVorbisHeader( p_stream, &oggpacket ); msg_Dbg( p_demux, "found vorbis header" ); } /* Check for Speex header */ else if( oggpacket.bytes >= 7 && ! memcmp( &oggpacket.packet[0], "Speex", 5 ) ) { Ogg_ReadSpeexHeader( p_stream, &oggpacket ); msg_Dbg( p_demux, "found speex header, channels: %i, " "rate: %i, bitrate: %i", p_stream->fmt.audio.i_channels, (int)p_stream->f_rate, p_stream->fmt.i_bitrate ); } /* Check for Flac header (< version 1.1.1) */ else if( oggpacket.bytes >= 4 && ! memcmp( &oggpacket.packet[0], "fLaC", 4 ) ) { msg_Dbg( p_demux, "found FLAC header" ); /* Grrrr!!!! Did they really have to put all the * important info in the second header packet!!! * (STREAMINFO metadata is in the following packet) */ p_stream->b_force_backup = 1; p_stream->fmt.i_cat = AUDIO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'f','l','a','c' ); } /* Check for Flac header (>= version 1.1.1) */ else if( oggpacket.bytes >= 13 && oggpacket.packet[0] ==0x7F && ! memcmp( &oggpacket.packet[1], "FLAC", 4 ) && ! memcmp( &oggpacket.packet[9], "fLaC", 4 ) ) { int i_packets = ((int)oggpacket.packet[7]) << 8 | oggpacket.packet[8]; msg_Dbg( p_demux, "found FLAC header version %i.%i " "(%i header packets)", oggpacket.packet[5], oggpacket.packet[6], i_packets ); p_stream->b_force_backup = 1; p_stream->fmt.i_cat = AUDIO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'f','l','a','c' ); oggpacket.packet += 13; oggpacket.bytes -= 13; Ogg_ReadFlacHeader( p_demux, p_stream, &oggpacket ); } /* Check for Theora header */ else if( oggpacket.bytes >= 7 && ! memcmp( &oggpacket.packet[1], "theora", 6 ) ) { Ogg_ReadTheoraHeader( p_stream, &oggpacket ); msg_Dbg( p_demux, "found theora header, bitrate: %i, rate: %f", p_stream->fmt.i_bitrate, p_stream->f_rate ); } /* Check for Tarkin header */ else if( oggpacket.bytes >= 7 && ! memcmp( &oggpacket.packet[1], "tarkin", 6 ) ) { oggpack_buffer opb; msg_Dbg( p_demux, "found tarkin header" ); p_stream->fmt.i_cat = VIDEO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 't','a','r','k' ); /* Cheat and get additionnal info ;) */ oggpack_readinit( &opb, oggpacket.packet, oggpacket.bytes); oggpack_adv( &opb, 88 ); oggpack_adv( &opb, 104 ); p_stream->fmt.i_bitrate = oggpack_read( &opb, 32 ); p_stream->f_rate = 2; /* FIXME */ msg_Dbg( p_demux, "found tarkin header, bitrate: %i, rate: %f", p_stream->fmt.i_bitrate, p_stream->f_rate ); } /* Check for Annodex header */ else if( oggpacket.bytes >= 7 && ! memcmp( &oggpacket.packet[0], "Annodex", 7 ) ) { Ogg_ReadAnnodexHeader( VLC_OBJECT(p_demux), p_stream, &oggpacket ); /* kill annodex track */ free( p_stream ); p_ogg->i_streams--; } /* Check for Annodex header */ else if( oggpacket.bytes >= 7 && ! memcmp( &oggpacket.packet[0], "AnxData", 7 ) ) { Ogg_ReadAnnodexHeader( VLC_OBJECT(p_demux), p_stream, &oggpacket ); } else if( oggpacket.bytes >= 142 && !memcmp( &oggpacket.packet[1], "Direct Show Samples embedded in Ogg", 35 )) { /* Old header type */ /* Check for video header (old format) */ if( GetDWLE((oggpacket.packet+96)) == 0x05589f80 && oggpacket.bytes >= 184 ) { p_stream->fmt.i_cat = VIDEO_ES; p_stream->fmt.i_codec = VLC_FOURCC( oggpacket.packet[68], oggpacket.packet[69], oggpacket.packet[70], oggpacket.packet[71] ); 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((oggpacket.packet+164)); p_stream->f_rate = 10000000.0 / GetQWLE((oggpacket.packet+164)); p_stream->fmt.video.i_bits_per_pixel = GetWLE((oggpacket.packet+182)); if( !p_stream->fmt.video.i_bits_per_pixel ) /* hack, FIXME */ p_stream->fmt.video.i_bits_per_pixel = 24; p_stream->fmt.video.i_width = GetDWLE((oggpacket.packet+176)); p_stream->fmt.video.i_height = GetDWLE((oggpacket.packet+180)); 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 (old format) */ else if( GetDWLE((oggpacket.packet+96)) == 0x05589F81 ) { unsigned int i_extra_size; unsigned int i_format_tag; p_stream->fmt.i_cat = AUDIO_ES; i_extra_size = GetWLE((oggpacket.packet+140)); if( i_extra_size ) { p_stream->fmt.i_extra = i_extra_size; p_stream->fmt.p_extra = malloc( i_extra_size ); memcpy( p_stream->fmt.p_extra, oggpacket.packet + 142, i_extra_size ); } i_format_tag = GetWLE((oggpacket.packet+124)); p_stream->fmt.audio.i_channels = GetWLE((oggpacket.packet+126)); p_stream->f_rate = p_stream->fmt.audio.i_rate = GetDWLE((oggpacket.packet+128)); 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 ) { p_stream->fmt.p_extra = malloc( p_stream->fmt.i_extra ); memcpy( p_stream->fmt.p_extra, st + 1, p_stream->fmt.i_extra ); } 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 */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -