📄 ogg.c
字号:
if( !b_selected ) { /* This stream isn't currently selected so we don't need to decode it, * but we did need to store its pcr as it might be selected later on */ return; } if( p_oggpacket->bytes <= 0 ) return; if( !( p_block = block_New( p_demux, p_oggpacket->bytes ) ) ) return; /* Normalize PTS */ if( i_pts == 0 ) i_pts = 1; else if( i_pts == -1 && i_interpolated_pts == 0 ) i_pts = 1; else if( i_pts == -1 ) i_pts = 0; if( p_stream->fmt.i_cat == AUDIO_ES ) p_block->i_dts = p_block->i_pts = i_pts; else if( p_stream->fmt.i_cat == SPU_ES ) { p_block->i_dts = p_block->i_pts = i_pts; p_block->i_length = 0; } else if( p_stream->fmt.i_codec == VLC_FOURCC( 't','h','e','o' ) ) p_block->i_dts = p_block->i_pts = i_pts; else if( p_stream->fmt.i_codec == VLC_FOURCC( 'd','r','a','c' ) ) { ogg_int64_t dts = p_oggpacket->granulepos >> 31; ogg_int64_t delay = (p_oggpacket->granulepos >> 9) & 0x1fff; uint64_t u_pnum = dts + delay; p_block->i_dts = p_stream->i_pcr; p_block->i_pts = 0; /* NB, OggDirac granulepos values are in units of 2*picturerate */ if( -1 != p_oggpacket->granulepos ) p_block->i_pts = u_pnum * INT64_C(1000000) / p_stream->f_rate / 2; } else { p_block->i_dts = i_pts; p_block->i_pts = 0; } if( p_stream->fmt.i_codec != VLC_FOURCC( 'v','o','r','b' ) && p_stream->fmt.i_codec != VLC_FOURCC( 's','p','x',' ' ) && p_stream->fmt.i_codec != VLC_FOURCC( 'f','l','a','c' ) && p_stream->fmt.i_codec != VLC_FOURCC( 't','a','r','k' ) && p_stream->fmt.i_codec != VLC_FOURCC( 't','h','e','o' ) && p_stream->fmt.i_codec != VLC_FOURCC( 'c','m','m','l' ) && p_stream->fmt.i_codec != VLC_FOURCC( 'd','r','a','c' ) && p_stream->fmt.i_codec != VLC_FOURCC( 'k','a','t','e' ) ) { /* We remove the header from the packet */ i_header_len = (*p_oggpacket->packet & PACKET_LEN_BITS01) >> 6; i_header_len |= (*p_oggpacket->packet & PACKET_LEN_BITS2) << 1; if( p_stream->fmt.i_codec == VLC_FOURCC( 's','u','b','t' )) { /* But with subtitles we need to retrieve the duration first */ int i, lenbytes = 0; if( i_header_len > 0 && p_oggpacket->bytes >= i_header_len + 1 ) { for( i = 0, lenbytes = 0; i < i_header_len; i++ ) { lenbytes = lenbytes << 8; lenbytes += *(p_oggpacket->packet + i_header_len - i); } } if( p_oggpacket->bytes - 1 - i_header_len > 2 || ( p_oggpacket->packet[i_header_len + 1] != ' ' && p_oggpacket->packet[i_header_len + 1] != 0 && p_oggpacket->packet[i_header_len + 1] != '\n' && p_oggpacket->packet[i_header_len + 1] != '\r' ) ) { p_block->i_length = (mtime_t)lenbytes * 1000; } } i_header_len++; if( p_block->i_buffer >= (unsigned int)i_header_len ) p_block->i_buffer -= i_header_len; else p_block->i_buffer = 0; } if( p_stream->fmt.i_codec == VLC_FOURCC( 't','a','r','k' ) ) { /* FIXME: the biggest hack I've ever done */ msg_Warn( p_demux, "tarkin pts: %"PRId64", granule: %"PRId64, p_block->i_pts, p_block->i_dts ); msleep(10000); } memcpy( p_block->p_buffer, p_oggpacket->packet + i_header_len, p_oggpacket->bytes - i_header_len ); es_out_Send( p_demux->out, p_stream->p_es, p_block );}/**************************************************************************** * Ogg_FindLogicalStreams: Find the logical streams embedded in the physical * stream and fill p_ogg. ***************************************************************************** * 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 ) ) { logical_stream_t **pp_sav = p_ogg->pp_stream; p_ogg->i_streams++; p_ogg->pp_stream = realloc( p_ogg->pp_stream, p_ogg->i_streams * sizeof(logical_stream_t *) ); if( !p_ogg->pp_stream ) { p_ogg->pp_stream = pp_sav; p_ogg->i_streams--; return VLC_ENOMEM; } p_stream = malloc( sizeof(logical_stream_t) ); if( !p_stream ) return VLC_ENOMEM; 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 ); es_format_Init( &p_stream->fmt_old, 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, "\x01vorbis", 7 ) ) { Ogg_ReadVorbisHeader( p_stream, &oggpacket ); msg_Dbg( p_demux, "found vorbis header" ); } /* Check for Speex header */ else if( oggpacket.bytes >= 5 && ! memcmp( oggpacket.packet, "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, "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, "\x80theora", 7 ) ) { 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 Dirac header */ else if( oggpacket.bytes >= 5 && ! memcmp( oggpacket.packet, "BBCD\x00", 5 ) ) { Ogg_ReadDiracHeader( p_stream, &oggpacket ); msg_Dbg( p_demux, "found dirac header" ); } /* 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, "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, "AnxData", 7 ) ) { Ogg_ReadAnnodexHeader( VLC_OBJECT(p_demux), p_stream, &oggpacket ); } /* Check for Kate header */ else if( oggpacket.bytes >= 8 && ! memcmp( &oggpacket.packet[1], "kate\0\0\0", 7 ) ) { Ogg_ReadKateHeader( p_stream, &oggpacket ); msg_Dbg( p_demux, "found kate header" ); } 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 > 0 && i_extra_size < oggpacket.bytes - 142 ) { p_stream->fmt.i_extra = i_extra_size; p_stream->fmt.p_extra = malloc( i_extra_size ); if( p_stream->fmt.p_extra ) memcpy( p_stream->fmt.p_extra, oggpacket.packet + 142, i_extra_size ); else p_stream->fmt.i_extra = 0; } 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -