📄 streamstate.cc
字号:
/* (C) 2005 Andrew Stevens
* This file 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-1307, USA.
*
*/
#include "streamstate.h"
#include <algorithm>
#include "mjpeg_types.h"
#include "mjpeg_logging.h"
#include "encoderparams.hh"
#include "mpeg2syntaxcodes.h"
#include "picturereader.hh"
// --------------------------------------------------------------------------------
// Stream state maintenance class
StreamState::StreamState( EncoderParams &_encparams, PictureReader &_reader ) :
encparams(_encparams),
reader(_reader)
{
}
void StreamState::Init( )
{
seq_split_length = ((int64_t)encparams.seq_length_limit)*(8*1024*1024);
next_split_point = BITCOUNT_OFFSET + seq_split_length;
mjpeg_debug( "Split len = %lld", seq_split_length );
frame_num = 0;
s_idx = 0;
g_idx = 0;
b_idx = 0;
gop_length = 0; // Forces new GOP start 1st sequence.
seq_start_frame = 0;
gop_start_frame = 0;
gop_end_seq = true; // At start we act as after sequence split...
GopStart( );
SetEndSeq();
}
/*
Update ss to the next sequence state.
*/
void StreamState::Next( int64_t bits_after_mux ) // Estimate of how much output would have been produced
{
++frame_num;
++s_idx;
++g_idx;
++b_idx;
new_seq = false;
/* Are we starting a new B group */
if( b_idx >= bigrp_length )
{
b_idx = 0;
/* Does this need to be a short B group to make the GOP length
come out right ? */
if( bs_short != 0 && g_idx > (int)next_b_drop )
{
bigrp_length = encparams.M - 1;
if( bs_short )
next_b_drop += ((double)gop_length) / (double)(bs_short+1) ;
}
else
bigrp_length = encparams.M;
// Are we starting a new GOP
if( g_idx == gop_length )
{
GopStart( );
// Sets frame_type == I_TYPE
}
else
{
frame_type = P_TYPE;
}
}
else
{
frame_type = B_TYPE;
}
// Figure out if a sequence split is due...
if( (next_split_point != 0ULL && bits_after_mux > next_split_point)
|| (FrameInSeq() != 0 && encparams.seq_end_every_gop)
)
{
mjpeg_info( "Splitting sequence next GOP start" );
next_split_point += seq_split_length;
gop_end_seq = true;
}
SetEndSeq();
}
void StreamState::SetEndSeq()
{
// Ensure we have read up to the frame we plan to processs / decide
// EOS at (need to know if this frame is at EOF - hence must be read).
// TODO Cropping of Temporal reference from Picture::Set_IP_Frame
// should really be handled here...
reader.FillBufferUpto( InputFrameNum() );
end_seq = frame_num == (reader.NumberOfFrames()-1) || ( g_idx == gop_length-1 && gop_end_seq);
}
void StreamState::GopStart( )
{
//int nb, np;
uint64_t bits_after_mux;
double frame_periods;
/* If we're starting a GOP and have gone past the current
sequence splitting point split the sequence and
set the next splitting point.
*/
g_idx = 0;
b_idx = 0;
frame_type = I_TYPE;
/* Sequence ended at end previous GOP so this one starts a new sequence */
if( gop_end_seq )
{
/* We split sequence last frame.This is the input stream display
* order sequence number of the frame that will become frame 0 in display
* order in the new sequence
*/
seq_start_frame += s_idx;
s_idx = 0;
gop_end_seq = false;
new_seq = true;
}
/* Normally set closed_GOP in first GOP only... */
closed_gop = s_idx == 0 || encparams.closed_GOPs;
gop_start_frame = seq_start_frame + s_idx;
//
// GOPs initially always start out maximum length - short GOPs occur when we notice
// a P frame occurring after the minimum GOP lengthhas been reached
//
gop_length = encparams.N_max;
mjpeg_info( "NEW GOP INIT length %d", gop_length );
/* First figure out how many B frames we're short from
being able to achieve an even M-1 B's per I/P frame.
To avoid peaks in necessary data-rate we try to
lose the B's in the middle of the GOP. We always
*start* with M-1 B's (makes choosing I-frame breaks simpler).
A complication is the extra I-frame in the initial
closed GOP of a sequence.
*/
if( encparams.M-1 > 0 )
{
int pics_in_bigrps =
closed_gop ? gop_length - 1 : gop_length;
bs_short = (encparams.M - pics_in_bigrps % encparams.M)%encparams.M;
next_b_drop = ((double)gop_length) / (double)(bs_short+1)-1.0 ;
}
else
{
bs_short = 0;
next_b_drop = 0.0;
}
/* We aim to spread the dropped B's evenly across the GOP */
bigrp_length = (encparams.M-1);
if (closed_gop )
{
bigrp_length = 1;
np = (gop_length + 2*(encparams.M-1))/encparams.M - 1; /* Closed GOP */
}
else
{
bigrp_length = encparams.M;
np = (gop_length + (encparams.M-1))/encparams.M - 1;
}
/* number of B frames */
nb = gop_length - np - 1;
//np = np;
//nb = nb;
if( np+nb+1 != gop_length )
{
mjpeg_error_exit1( "****INTERNAL: inconsistent GOP %d %d %d",
gop_length, np, nb);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -