transrate.c
来自「VLC媒体播放程序」· C语言 代码 · 共 2,148 行 · 第 1/5 页
C
2,148 行
//LOGF("\n\to: %i c: %i n: %i\n", quantizer_scale, last_coded_scale, new_quantizer_scale); NEXT_MACROBLOCK; mba_inc = 0; for( ;; ) { if (bs->i_bit_in_cache >= 0x10000000) { mba = MBA_5 + (UBITS (bs->i_bit_in_cache, 5) - 2); break; } else if (bs->i_bit_in_cache >= 0x03000000) { mba = MBA_11 + (UBITS (bs->i_bit_in_cache, 11) - 24); break; } else if( UBITS (bs->i_bit_in_cache, 11 ) == 8 ) { /* macroblock_escape */ mba_inc += 33; bs_copy( bs, 11); } else { /* EOS or error */ return; } } bs_copy( bs, mba->len); mba_inc += mba->mba; while( mba_inc-- ) { NEXT_MACROBLOCK; } }}/////---- end ext mpeg codestatic int do_next_start_code( transrate_t *tr ){ bs_transrate_t *bs = &tr->bs; uint8_t ID; // get start code ID = bs->p_c[0]; /* Copy one byte */ *bs->p_w++ = *bs->p_c++; if (ID == 0x00) // pic header { tr->picture_coding_type = (bs->p_c[1] >> 3) & 0x7; bs->p_c[1] |= 0x7; bs->p_c[2] = 0xFF; bs->p_c[3] |= 0xF8; // vbv_delay is now 0xFFFF memcpy(bs->p_w, bs->p_c, 4); bs->p_c += 4; bs->p_w += 4; } else if (ID == 0xB3) // seq header { tr->horizontal_size_value = (bs->p_c[0] << 4) | (bs->p_c[1] >> 4); tr->vertical_size_value = ((bs->p_c[1] & 0xF) << 8) | bs->p_c[2]; if(!tr->horizontal_size_value || !tr->vertical_size_value ) { return -1; } memcpy(bs->p_w, bs->p_c, 8 ); bs->p_c += 8; bs->p_w += 8; } else if (ID == 0xB5) // extension { if ((bs->p_c[0] >> 4) == 0x8) // pic coding ext { tr->f_code[0][0] = (bs->p_c[0] & 0xF) - 1; tr->f_code[0][1] = (bs->p_c[1] >> 4) - 1; tr->f_code[1][0] = (bs->p_c[1] & 0xF) - 1; tr->f_code[1][1] = (bs->p_c[2] >> 4) - 1; /* tr->intra_dc_precision = (bs->p_c[2] >> 2) & 0x3; */ tr->picture_structure = bs->p_c[2] & 0x3; tr->frame_pred_frame_dct = (bs->p_c[3] >> 6) & 0x1; tr->concealment_motion_vectors = (bs->p_c[3] >> 5) & 0x1; tr->q_scale_type = (bs->p_c[3] >> 4) & 0x1; tr->intra_vlc_format = (bs->p_c[3] >> 3) & 0x1; /* tr->alternate_scan = (bs->p_c[3] >> 2) & 0x1; */ memcpy(bs->p_w, bs->p_c, 5); bs->p_c += 5; bs->p_w += 5; } else { *bs->p_w++ = *bs->p_c++; } } else if (ID == 0xB8) // gop header { memcpy(bs->p_w, bs->p_c, 4); bs->p_c += 4; bs->p_w += 4; } else if ((ID >= 0x01) && (ID <= 0xAF)) // slice { uint8_t *outTemp = bs->p_w, *inTemp = bs->p_c;#if 0 if( ( tr->picture_coding_type == B_TYPE && tr->quant_corr < 2.5f ) || // don't recompress if we're in advance! ( tr->picture_coding_type == P_TYPE && tr->quant_corr < -2.5f ) || ( tr->picture_coding_type == I_TYPE && tr->quant_corr < -5.0f ) )#else if( ( tr->picture_coding_type == B_TYPE ) || ( tr->picture_coding_type == P_TYPE && tr->level_p ) || ( tr->picture_coding_type == I_TYPE && tr->level_i ) )#endif { if( !tr->horizontal_size_value || !tr->vertical_size_value ) { return -1; } // init bit buffer bs->i_bit_in_cache = 0; bs->i_bit_in = 0; bs->i_bit_out_cache = 0; bs->i_bit_out = BITS_IN_BUF; // get 32 bits bs_refill( bs ); bs_refill( bs ); bs_refill( bs ); bs_refill( bs ); // begin bit level recoding mpeg2_slice(tr, ID); bs_flush_read( bs ); bs_flush_write( bs ); // end bit level recoding /* Basic sanity checks --Meuuh */ if (bs->p_c > bs->p_r || bs->p_w > bs->p_rw) { return -1; } /*LOGF("type: %s code: %02i in : %6i out : %6i diff : %6i fact: %2.2f\n", (picture_coding_type == I_TYPE ? "I_TYPE" : (picture_coding_type == P_TYPE ? "P_TYPE" : "B_TYPE")), ID, bs->p_c - inTemp, bs->p_w - outTemp, (bs->p_w - outTemp) - (bs->p_c - inTemp), (float)(bs->p_c - inTemp) / (float)(bs->p_w - outTemp));*/ if (bs->p_w - outTemp > bs->p_c - inTemp) // yes that might happen, rarely { /*LOGF("*** slice bigger than before !! (type: %s code: %i in : %i out : %i diff : %i)\n", (picture_coding_type == I_TYPE ? "I_TYPE" : (picture_coding_type == P_TYPE ? "P_TYPE" : "B_TYPE")), ID, bs->p_c - inTemp, bs->p_w - outTemp, (bs->p_w - outTemp) - (bs->p_c - inTemp));*/ // in this case, we'll just use the original slice ! memcpy(outTemp, inTemp, bs->p_c - inTemp); bs->p_w = outTemp + (bs->p_c - inTemp); // adjust bs->i_byte_out bs->i_byte_out -= (bs->p_w - outTemp) - (bs->p_c - inTemp); } } } return 0;}static void process_frame( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *in, sout_buffer_t **out ){ transrate_t *tr = &id->tr; bs_transrate_t *bs = &tr->bs; sout_buffer_t *p_out; double next_fact_x = 1.0; /* The output buffer can't be bigger than the input buffer. */ p_out = sout_BufferNew( p_stream->p_sout, in->i_size ); p_out->i_length = in->i_length; p_out->i_dts = in->i_dts; p_out->i_pts = in->i_pts; sout_BufferChain( out, p_out ); bs->p_rw = bs->p_ow = bs->p_w = p_out->p_buffer; bs->p_c = bs->p_r = in->p_buffer; bs->p_r += in->i_size + 4; bs->p_rw += in->i_size; *(in->p_buffer + in->i_size) = 0; *(in->p_buffer + in->i_size + 1) = 0; *(in->p_buffer + in->i_size + 2) = 1; *(in->p_buffer + in->i_size + 3) = 0; /* Calculate how late we are */ tr->quant_corr = 0.0 + B_HANDICAP; tr->level_i = 0; tr->level_p = 0; bs->i_byte_in = in->i_size; bs->i_byte_out = 0; if (tr->i_current_gop_size - in->i_size > 100) { if (tr->i_wanted_gop_size == in->i_size) { next_fact_x = 1.0; } else if ( tr->i_wanted_gop_size < in->i_size ) { /* We're really late */ next_fact_x = 10.0; } else { next_fact_x = ((double)(tr->i_current_gop_size - in->i_size)) / (tr->i_wanted_gop_size - in->i_size); } if (next_fact_x > QUANT_I) { tr->level_i = 1; } if (next_fact_x > QUANT_P) { tr->level_p = 1 + (next_fact_x - QUANT_P) / (QUANT_P_INC); } } if ( tr->i_wanted_gop_size < 0 ) { /* We're really late */ tr->current_fact_x = 3.0; } else { tr->current_fact_x = ((double)(tr->i_current_gop_size) / (tr->i_wanted_gop_size)); } for ( ; ; ) { uint8_t *p_end = &in->p_buffer[in->i_size]; /* Search next start code */ for( ;; ) { if( bs->p_c < p_end - 3 && bs->p_c[0] == 0 && bs->p_c[1] == 0 && bs->p_c[2] == 1 ) { /* Next start code */ break; } else if( bs->p_c < p_end - 6 && bs->p_c[0] == 0 && bs->p_c[1] == 0 && bs->p_c[2] == 0 && bs->p_c[3] == 0 && bs->p_c[4] == 0 && bs->p_c[5] == 0 ) { /* remove stuffing (looking for 6 0x00 bytes) */ bs->p_c++; } else { /* Copy */ *bs->p_w++ = *bs->p_c++; } if( bs->p_c >= p_end) { break; } } if( bs->p_c >= p_end ) { break; } /* Copy the start code */ memcpy(bs->p_w, bs->p_c, 3 ); bs->p_c += 3; bs->p_w += 3; if (do_next_start_code( tr ) ) { /* Error */ break; } tr->quant_corr = (((bs->i_byte_in - (bs->p_r - 4 - bs->p_c)) / tr->fact_x) - (bs->i_byte_out + (bs->p_w - bs->p_ow))) / REACT_DELAY + B_HANDICAP; } bs->i_byte_out += bs->p_w - bs->p_ow; p_out->i_size = bs->p_w - bs->p_ow; tr->i_current_gop_size -= in->i_size; tr->i_wanted_gop_size -= p_out->i_size; tr->i_new_gop_size += bs->i_byte_out;#if 0 msg_Dbg( p_stream, "%d: %d -> %d (r: %f, n:%f, corr:%f)", tr->picture_coding_type, in->i_size, p_out->i_size, (float)in->i_size / p_out->i_size, next_fact_x, tr->quant_corr);#endif}static int transrate_video_process( sout_stream_t *p_stream, sout_stream_id_t *id, sout_buffer_t *in, sout_buffer_t **out ){ transrate_t *tr = &id->tr; bs_transrate_t *bs = &tr->bs; vlc_bool_t b_gop = VLC_FALSE; *out = NULL; if( GetDWBE( in->p_buffer ) != 0x100 ) { uint8_t *p = in->p_buffer; uint8_t *p_end = &in->p_buffer[in->i_size]; uint32_t code = GetDWBE( p ); /* We may have a GOP */ while( p < p_end - 4 ) { if( code == 0x1b8 ) { b_gop = VLC_TRUE; break; } else if( code == 0x100 ) { break; } code = ( code << 8 )|p[4]; p++; } } if( b_gop && id->i_next_gop_duration >= 300000 ) { while ( id->p_current_buffer != NULL ) { sout_buffer_t * p_next = id->p_current_buffer->p_next; if ( tr->fact_x == 1.0 ) { bs->i_byte_out += id->p_current_buffer->i_size; id->p_current_buffer->p_next = NULL; sout_BufferChain( out, id->p_current_buffer ); } else { process_frame( p_stream, id, id->p_current_buffer, out ); sout_BufferDelete(p_stream->p_sout, id->p_current_buffer); } id->p_current_buffer = p_next; } if ( id->i_next_gop_duration ) { mtime_t i_bitrate = (mtime_t)id->i_next_gop_size * 8000 / (id->i_next_gop_duration / 1000); static mtime_t i_old_bitrate = 0; static mtime_t i_old_duration = 0; if (i_old_bitrate && tr->fact_x != 1.0) { mtime_t i_new_bitrate = tr->i_new_gop_size * 8000 / (i_old_duration / 1000); if (i_new_bitrate > p_stream->p_sys->i_vbitrate + 300000) msg_Err(p_stream, "%lld -> %lld (%f, r:%f)", i_old_bitrate, i_new_bitrate, tr->fact_x, (float)i_old_bitrate / i_new_bitrate);#if 0 else msg_Dbg(p_stream, "%lld -> %lld (%f, r:%f)", i_old_bitrate, i_new_bitrate, tr->fact_x, (float)i_old_bitrate / i_new_bitrate);#endif } i_old_bitrate = i_bitrate; i_old_duration = id->i_next_gop_duration; if ( i_bitrate > p_stream->p_sys->i_vbitrate ) { tr->fact_x = (double)i_bitrate / p_stream->p_sys->i_vbitrate; } else { tr->fact_x = 1.0; } id->tr.i_current_gop_size = id->i_next_gop_size; id->tr.i_wanted_gop_size = (p_stream->p_sys->i_vbitrate) * (id->i_next_gop_duration / 1000) / 8000; id->tr.i_new_gop_size = 0; id->p_current_buffer = id->p_next_gop; id->p_next_gop = NULL; id->i_next_gop_duration = 0; id->i_next_gop_size = 0; } } /* Store the buffer for the next GOP. */ sout_BufferChain( &id->p_next_gop, in ); id->i_next_gop_duration += in->i_length; id->i_next_gop_size += in->i_size; if ( id->p_current_buffer != NULL ) { sout_buffer_t * p_next = id->p_current_buffer->p_next; if ( tr->fact_x == 1.0 ) { bs->i_byte_out += id->p_current_buffer->i_size; id->p_current_buffer->p_next = NULL; sout_BufferChain( out, id->p_current_buffer ); } else { process_frame( p_stream, id, id->p_current_buffer, out ); sout_BufferDelete(p_stream->p_sout, id->p_current_buffer); } id->p_current_buffer = p_next; } return VLC_SUCCESS;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?