📄 mpegvideo.c
字号:
/***************************************************************************** * mpegvideo.c: parse and packetize an MPEG1/2 video stream ***************************************************************************** * Copyright (C) 2001, 2002 VideoLAN * $Id: mpegvideo.c 10101 2005-03-02 16:47:31Z robux4 $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * Eric Petit <titer@videolan.org> * Gildas Bazin <gbazin@videolan.org> * * 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. *****************************************************************************//***************************************************************************** * Problem with this implementation: * * Although we should time-stamp each picture with a PTS, this isn't possible * with the current implementation. * The problem comes from the fact that for non-low-delay streams we can't * calculate the PTS of pictures used as backward reference. Even the temporal * reference number doesn't help here because all the pictures don't * necessarily have the same duration (eg. 3:2 pulldown). * * However this doesn't really matter as far as the MPEG muxers are concerned * because they allow having empty PTS fields. --gibalou *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#include <stdlib.h> /* malloc(), free() */#include <vlc/vlc.h>#include <vlc/decoder.h>#include <vlc/input.h>#include "vlc_block_helper.h"/***************************************************************************** * Module descriptor *****************************************************************************/static int Open ( vlc_object_t * );static void Close( vlc_object_t * );vlc_module_begin(); set_category( CAT_SOUT ); set_subcategory( SUBCAT_SOUT_PACKETIZER ); set_description( _("MPEG-I/II video packetizer") ); set_capability( "packetizer", 50 ); set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************/static block_t *Packetize( decoder_t *, block_t ** );static block_t *ParseMPEGBlock( decoder_t *, block_t * );struct decoder_sys_t{ /* * Input properties */ block_bytestream_t bytestream; int i_state; int i_offset; uint8_t p_startcode[3]; /* Sequence header and extension */ block_t *p_seq; block_t *p_ext; /* Current frame being built */ block_t *p_frame; block_t **pp_last; vlc_bool_t b_frame_slice; mtime_t i_pts; mtime_t i_dts; /* Sequence properties */ int i_frame_rate; int i_frame_rate_base; vlc_bool_t b_seq_progressive; vlc_bool_t b_low_delay; int i_aspect_ratio_info; vlc_bool_t b_inited; /* Picture properties */ int i_temporal_ref; int i_picture_type; int i_picture_structure; int i_top_field_first; int i_repeat_first_field; int i_progressive_frame; mtime_t i_interpolated_dts; mtime_t i_old_duration; mtime_t i_last_ref_pts; /* Number of pictures since last sequence header */ int i_seq_old;};enum { STATE_NOSYNC, STATE_NEXT_SYNC};/***************************************************************************** * Open: *****************************************************************************/static int Open( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', '1' ) && p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', '2' ) && p_dec->fmt_in.i_codec != VLC_FOURCC( 'm', 'p', 'g', 'v' ) ) { return VLC_EGENERIC; } es_format_Init( &p_dec->fmt_out, VIDEO_ES, VLC_FOURCC('m','p','g','v') ); p_dec->pf_packetize = Packetize; p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) ); /* Misc init */ p_sys->i_state = STATE_NOSYNC; p_sys->bytestream = block_BytestreamInit( p_dec ); p_sys->p_startcode[0] = 0; p_sys->p_startcode[1] = 0; p_sys->p_startcode[2] = 1; p_sys->i_offset = 0; p_sys->p_seq = NULL; p_sys->p_ext = NULL; p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; p_sys->b_frame_slice = VLC_FALSE; p_sys->i_dts = p_sys->i_pts = 0; p_sys->i_frame_rate = 1; p_sys->i_frame_rate_base = 1; p_sys->b_seq_progressive = VLC_TRUE; p_sys->b_low_delay = VLC_TRUE; p_sys->i_seq_old = 0; p_sys->i_temporal_ref = 0; p_sys->i_picture_type = 0; p_sys->i_picture_structure = 0x03; /* frame */ p_sys->i_top_field_first = 0; p_sys->i_repeat_first_field = 0; p_sys->i_progressive_frame = 0; p_sys->b_inited = 0; p_sys->i_interpolated_dts = 0; p_sys->i_old_duration = 0; p_sys->i_last_ref_pts = 0; return VLC_SUCCESS;}/***************************************************************************** * Close: *****************************************************************************/static void Close( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys = p_dec->p_sys; block_BytestreamRelease( &p_sys->bytestream ); if( p_sys->p_seq ) { block_Release( p_sys->p_seq ); } if( p_sys->p_ext ) { block_Release( p_sys->p_ext ); } if( p_sys->p_frame ) { block_ChainRelease( p_sys->p_frame ); } free( p_sys );}/***************************************************************************** * Packetize: *****************************************************************************/static block_t *Packetize( decoder_t *p_dec, block_t **pp_block ){ decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_pic; if( pp_block == NULL || *pp_block == NULL ) { return NULL; } if( (*pp_block)->i_flags & BLOCK_FLAG_DISCONTINUITY ) { p_sys->i_state = STATE_NOSYNC; if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame ); p_sys->p_frame = NULL; p_sys->pp_last = &p_sys->p_frame; p_sys->b_frame_slice = VLC_FALSE; block_Release( *pp_block ); return NULL; } block_BytestreamPush( &p_sys->bytestream, *pp_block ); while( 1 ) { switch( p_sys->i_state ) { case STATE_NOSYNC: if( block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_sys->p_startcode, 3 ) == VLC_SUCCESS ) { p_sys->i_state = STATE_NEXT_SYNC; } if( p_sys->i_offset ) { block_SkipBytes( &p_sys->bytestream, p_sys->i_offset ); p_sys->i_offset = 0; block_BytestreamFlush( &p_sys->bytestream ); } if( p_sys->i_state != STATE_NEXT_SYNC ) { /* Need more data */ return NULL; } p_sys->i_offset = 1; /* To find next startcode */ case STATE_NEXT_SYNC: /* TODO: If p_block == NULL, flush the buffer without checking the * next sync word */ /* Find the next startcode */ if( block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_sys->p_startcode, 3 ) != VLC_SUCCESS ) { /* Need more data */ return NULL; } /* Get the new fragment and set the pts/dts */ p_pic = block_New( p_dec, p_sys->i_offset ); block_BytestreamFlush( &p_sys->bytestream ); p_pic->i_pts = p_sys->bytestream.p_block->i_pts; p_pic->i_dts = p_sys->bytestream.p_block->i_dts; block_GetBytes( &p_sys->bytestream, p_pic->p_buffer, p_pic->i_buffer ); /* don't reuse the same timestamps several times */ if( p_pic->i_buffer >= 4 && p_pic->p_buffer[3] == 0x00 ) { /* We have a picture start code */ p_sys->bytestream.p_block->i_pts = 0; p_sys->bytestream.p_block->i_dts = 0; } p_sys->i_offset = 0; /* Get picture if any */ if( !( p_pic = ParseMPEGBlock( p_dec, p_pic ) ) ) { p_sys->i_state = STATE_NOSYNC; break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -