📄 ogg.c
字号:
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_granule_shift = 0; i_keyframe_frequency_force--; while( i_keyframe_frequency_force ) { p_stream->i_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_ReadKateHeader( logical_stream_t *p_stream, ogg_packet *p_oggpacket ){ oggpack_buffer opb; int32_t gnum; int32_t gden; int n; p_stream->fmt.i_cat = SPU_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'k','a','t','e' ); /* Signal that we want to keep a backup of the kate * stream headers. They will be used when switching between * kate streams. */ p_stream->b_force_backup = 1; /* Cheat and get additionnal info ;) */ oggpack_readinit( &opb, p_oggpacket->packet, p_oggpacket->bytes); oggpack_adv( &opb, 11*8 ); /* packet type, kate magic, version */ p_stream->i_kate_num_headers = oggpack_read( &opb, 8 ); oggpack_adv( &opb, 3*8 ); p_stream->i_granule_shift = oggpack_read( &opb, 8 ); oggpack_adv( &opb, 8*8 ); /* reserved */ gnum = oggpack_read( &opb, 32 ); gden = oggpack_read( &opb, 32 ); p_stream->f_rate = (double)gnum/gden; p_stream->fmt.psz_language = malloc(16); if (p_stream->fmt.psz_language) { for (n=0;n<16;++n) p_stream->fmt.psz_language[n] = oggpack_read(&opb,8); p_stream->fmt.psz_language[15] = 0; /* just in case */ } else { for (n=0;n<16;++n) oggpack_read(&opb,8); } p_stream->fmt.psz_description = malloc(16); if (p_stream->fmt.psz_description) { for (n=0;n<16;++n) p_stream->fmt.psz_description[n] = oggpack_read(&opb,8); p_stream->fmt.psz_description[15] = 0; /* just in case */ } else { for (n=0;n<16;++n) oggpack_read(&opb,8); }}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, "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, "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: %"PRId64" / %"PRId64", %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' ); } }}static uint32_t dirac_uint( bs_t *p_bs ){ uint32_t count = 0, value = 0; while( !bs_read ( p_bs, 1 ) ) { count++; value <<= 1; value |= bs_read ( p_bs, 1 ); } return (1<<count) - 1 + value;}static int dirac_bool( bs_t *p_bs ){ return bs_read ( p_bs, 1 );}static void Ogg_ReadDiracHeader( logical_stream_t *p_stream, ogg_packet *p_oggpacket ){ bs_t bs; p_stream->fmt.i_cat = VIDEO_ES; p_stream->fmt.i_codec = VLC_FOURCC( 'd','r','a','c' ); p_stream->i_granule_shift = 32; /* Backing up stream headers is not required -- seqhdrs are repeated * thoughout the stream at suitable decoding start points */ p_stream->b_force_backup = 0; /* read in useful bits from sequence header */ bs_init( &bs, p_oggpacket->packet, p_oggpacket->bytes ); bs_skip( &bs, 13*8); /* parse_info_header */ dirac_uint( &bs ); /* major_version */ dirac_uint( &bs ); /* minor_version */ dirac_uint( &bs ); /* profile */ dirac_uint( &bs ); /* level */ uint32_t u_video_format = dirac_uint( &bs ); /* index */ if (dirac_bool( &bs )) { dirac_uint( &bs ); /* frame_width */ dirac_uint( &bs ); /* frame_height */ } if (dirac_bool( &bs )) { dirac_uint( &bs ); /* chroma_format */ } if (dirac_bool( &bs )) { if (dirac_bool( &bs )) { /* interlaced */ dirac_bool( &bs ); /* top_field_first */ } } static const struct { uint32_t u_n /* numerator */, u_d /* denominator */; } dirac_frate
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -