📄 nsv.c
字号:
/***************************************************************************** * nsv.c: NullSoft Video demuxer. ***************************************************************************** * Copyright (C) 2004 VideoLAN * $Id: nsv.c 10547 2005-04-04 23:50:07Z hartman $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h> /* malloc(), free() */#include <vlc/vlc.h>#include <vlc/input.h>/* TODO: * - implement NSVf parsing (to get meta data) * - implement missing Control (and in the right way) * - ... *//***************************************************************************** * Module descriptor *****************************************************************************/static int Open ( vlc_object_t * );static void Close ( vlc_object_t * );vlc_module_begin(); set_description( _("NullSoft demuxer" ) ); set_capability( "demux2", 10 ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_DEMUX ); set_callbacks( Open, Close ); add_shortcut( "nsv" );vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************/struct demux_sys_t{ es_format_t fmt_audio; es_out_id_t *p_audio; es_format_t fmt_video; es_out_id_t *p_video; es_format_t fmt_sub; es_out_id_t *p_sub; int64_t i_pcr; int64_t i_time; int64_t i_pcr_inc;};static int Demux ( demux_t *p_demux );static int Control( demux_t *p_demux, int i_query, va_list args );static int ReSynch( demux_t *p_demux );static int ReadNSVf( demux_t *p_demux );static int ReadNSVs( demux_t *p_demux );/***************************************************************************** * Open *****************************************************************************/static int Open( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys; uint8_t *p_peek; if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 ) return VLC_EGENERIC; if( strncmp( p_peek, "NSVf", 4 ) && strncmp( p_peek, "NSVs", 4 )) { /* In case we had force this demuxer we try to resynch */ if( strcmp( p_demux->psz_demux, "nsv" ) || ReSynch( p_demux ) ) { return VLC_EGENERIC; } } /* Fill p_demux field */ p_demux->pf_demux = Demux; p_demux->pf_control = Control; p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) ); es_format_Init( &p_sys->fmt_audio, AUDIO_ES, 0 ); p_sys->p_audio = NULL; es_format_Init( &p_sys->fmt_video, VIDEO_ES, 0 ); p_sys->p_video = NULL; es_format_Init( &p_sys->fmt_sub, SPU_ES, 0 ); p_sys->p_sub = NULL; p_sys->i_pcr = 1; p_sys->i_time = 0; p_sys->i_pcr_inc = 0; return VLC_SUCCESS;}/***************************************************************************** * Close *****************************************************************************/static void Close( vlc_object_t *p_this ){ demux_t *p_demux = (demux_t*)p_this; demux_sys_t *p_sys = p_demux->p_sys; free( p_sys );}/***************************************************************************** * Demux: *****************************************************************************/static int Demux( demux_t *p_demux ){ demux_sys_t *p_sys = p_demux->p_sys; uint8_t header[5]; uint8_t *p_peek; int i_size; block_t *p_frame; for( ;; ) { if( stream_Peek( p_demux->s, &p_peek, 8 ) < 8 ) { msg_Warn( p_demux, "cannot peek" ); return 0; } if( !strncmp( p_peek, "NSVf", 4 ) ) { if( ReadNSVf( p_demux ) ) { return -1; } } else if( !strncmp( p_peek, "NSVs", 4 ) ) { if( ReadNSVs( p_demux ) ) { return -1; } break; } else if( GetWLE( p_peek ) == 0xbeef ) { /* Next frame of the current NSVs chunk */ if( stream_Read( p_demux->s, NULL, 2 ) < 2 ) { msg_Warn( p_demux, "cannot read" ); return 0; } break; } else { msg_Err( p_demux, "invalid signature 0x%x (%4.4s)", *(uint32_t*)p_peek, (char*)p_peek ); if( ReSynch( p_demux ) ) { return -1; } } } if( stream_Read( p_demux->s, header, 5 ) < 5 ) { msg_Warn( p_demux, "cannot read" ); return 0; } /* Set PCR */ es_out_Control( p_demux->out, ES_OUT_SET_PCR, (int64_t)p_sys->i_pcr ); /* Read video */ i_size = ( header[0] >> 4 ) | ( header[1] << 4 ) | ( header[2] << 12 ); if( i_size > 0 ) { /* extra data ? */ if( (header[0]&0x0f) != 0x0 ) { uint8_t aux[6]; int i_aux; vlc_fourcc_t fcc; if( stream_Read( p_demux->s, aux, 6 ) < 6 ) { msg_Warn( p_demux, "cannot read" ); return 0; } i_aux = GetWLE( aux ); fcc = VLC_FOURCC( aux[2], aux[3], aux[4], aux[5] ); msg_Dbg( p_demux, "Belekas: %d - size=%d fcc=%4.4s", header[0]&0xf, i_aux, (char*)&fcc ); if( fcc == VLC_FOURCC( 'S', 'U', 'B', 'T' ) && i_aux > 2 ) { if( p_sys->p_sub == NULL ) { p_sys->fmt_sub.i_codec = VLC_FOURCC( 's', 'u', 'b', 't' ); p_sys->p_sub = es_out_Add( p_demux->out, &p_sys->fmt_sub ); es_out_Control( p_demux->out, ES_OUT_SET_ES, p_sys->p_sub ); } stream_Read( p_demux->s, NULL, 2 ); if( ( p_frame = stream_Block( p_demux->s, i_aux - 2 ) ) ) { uint8_t *p = p_frame->p_buffer; while( p < &p_frame->p_buffer[p_frame->i_buffer] && *p != 0 ) { p++; } if( *p == 0 && p + 1 < &p_frame->p_buffer[p_frame->i_buffer] ) { p_frame->i_buffer -= p + 1 - p_frame->p_buffer; p_frame->p_buffer = p + 1; } /* Skip the first part (it is the language name) */ p_frame->i_pts = p_sys->i_pcr; p_frame->i_dts = p_sys->i_pcr + 4000000; /* 4s */ es_out_Send( p_demux->out, p_sys->p_sub, p_frame ); } } else { /* We skip this extra data */ if( stream_Read( p_demux->s, NULL, i_aux ) < i_aux ) { msg_Warn( p_demux, "cannot read" ); return 0; } } i_size -= 6 + i_aux; } /* msg_Dbg( p_demux, "frame video size=%d", i_size ); */ if( i_size > 0 && ( p_frame = stream_Block( p_demux->s, i_size ) ) ) { p_frame->i_dts = p_sys->i_pcr; es_out_Send( p_demux->out, p_sys->p_video, p_frame ); } } /* Read audio */ i_size = header[3] | ( header[4] << 8 ); if( i_size > 0 ) { /* msg_Dbg( p_demux, "frame audio size=%d", i_size ); */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -