关于参考帧中的x264_reference_update函数的补充及h->frames.unused[]的理解 .

本文深入探讨了x264编码器中参考帧管理与FEC编码流程,详细解释了如何通过更新参考帧和FEC编码提高视频编码效率与质量。通过解析关键函数,展示了如何在多线程环境下动态调整参考帧使用策略,以及FEC编码在提升视频鲁棒性方面的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

encoder.c


 1.   x264_encoder_encode(  )函数里面:
if( x264_reference_update( h ) )
return -1;



其中:
static inline int x264_reference_update( x264_t *h )
{   //在b_kept_as_ref=0的时候,也就是B帧不作为参考帧的时候,
//h->fenc->b_kept_as_ref =
//   h->fdec->b_kept_as_ref = i_nal_ref_idc != NAL_PRIORITY_DISPOSABLE && h->param.i_keyint_max > 1;


if( !h->fdec->b_kept_as_ref )
{
if( h->param.i_threads > 1 )//多线程的情况
{                  
/
/这里面的语句就是取出h->fdec并不断的更新h->fdec
,关于POP和PUSH函数的详解在下面
x264_frame_push_unused( h, h->fdec );//这个函数的就是当h->fdec中的参考帧数目为1的时候将h->fdec压进h的 unused[frame->b_fdec]数组里面        见函数解析1

h->fdec = x264_frame_pop_unused( h, 1 );//这个函数是在这里相当于在fdec顶上中取一个farme出来给h->fdec             “见函数解析2”
if( !h->fdec )
return -1;
}
return 0;
}

/* move frame in the buffer */
//将 h->fdec压进h->frames.reference中作为参考
x264_frame_push( h->frames.reference, h->fdec );
//当还有参考帧存在时,x264_frame_shift( h->frames.reference )就是取出第一个参考帧h的 unused[frame->b_fdec]数组里面
if( h->frames.reference[h->frames.i_max_dpb] )
x264_frame_push_unused( h, x264_frame_shift( h->frames.reference ) );
//......
h->fdec = x264_frame_pop_unused( h, 1 );
if( !h->fdec )
return -1;
//当参考没有参考完就一直得到return 0
return 0;
}



函数解析1
//这个函数的就是参考帧数目为1的时候将frame压进unused数组里面
void x264_frame_push_unused( x264_t *h, x264_frame_t *frame )
{
assert( frame->i_reference_count > 0 );//参考帧的数目要大于0
frame->i_reference_count--;
if( frame->i_reference_count == 0 )//成立的条件是参看帧的数目只有一个
x264_frame_push( h->frames.unused[frame->b_fdec], frame );//从下面的分析x264_frame_push就是将
frame压进h->frames.unused[frame->b_fdec]数组里面
}

void x264_frame_push( x264_frame_t **list, x264_frame_t *frame )
{
int i = 0;
while( list[i] ) i++;
list[i] = frame;
}


函数解析2
x264_frame_t *x264_frame_pop_unused( x264_t *h, int b_fdec )//b_fdec=1
{
x264_frame_t *frame;
if( h->frames.unused[b_fdec][0] )
frame = x264_frame_pop( h->frames.unused[b_fdec] );//这里相当于再fdec顶上中取一个farme出来
else
frame = x264_frame_new( h, b_fdec );
if( !frame )
return NULL;
frame->b_last_minigop_bframe = 0;
frame->i_reference_count = 1;//初始化
frame->b_intra_calculated = 0;
return frame;
}

x264_frame_t *x264_frame_pop( x264_frame_t **list )
{
x264_frame_t *frame;
int i = 0;
assert( list[0] );
while( list[i+1] ) i++;
frame = list[i];
list[i] = NULL;
return frame;
}


2.关于unuesed的问题
struct
{
/* Frames to be encoded (whose types have been decided) */
x264_frame_t **current;
/* Unused frames: 0 = fenc, 1 = fdec */
x264_frame_t **unused[2];

/* frames used for reference + sentinels */
x264_frame_t *reference[16+2];

int i_last_idr; /* Frame number of the last IDR */

int i_input;    /* Number of input frames already accepted */

int i_max_dpb;  /* Number of frames allocated in the decoded picture buffer */
int i_max_ref0;
int i_max_ref1;
int i_delay;    /* Number of frames buffered for B reordering */
int b_have_lowres;  /* Whether 1/2 resolution luma planes are being used */
int b_have_sub8x8_esa;
} frames;


//截取的关于**unused[]的空间分配定义
CHECKED_MALLOCZERO( h->frames.unused[0], (h->frames.i_delay + 3) * sizeof(x264_frame_t *) );
/* Allocate room for max refs plus a few extra just in case. */
CHECKED_MALLOCZERO( h->frames.unused[1], (h->param.i_threads + 20) * sizeof(x264_frame_t *) );


从上面的/* Unused frames: 0 = fenc, 1 = fdec */
x264_frame_t **unused[2];
中可以看出二维指针**unused[0]代表的fenc的缓存,**unused[1]代表的fdec的缓存,至于这两个缓存的作用进我的博客
《参考帧管理》,至于为什么取名为unused,我觉得应该可以这么理解:从上面得update函数中可以看出来,pop,push中都是将
参考帧不停在**unused[0/1]中更新,也就是这里面的都是没有用到得帧。可以由定义x264_frame_t **unused[2];中的参数类型来
得出结论。
static inline const struct legacy_audio_device * to_cladev(const struct audio_hw_device *dev) 416 { 417 return reinterpret_cast<const struct legacy_audio_device *>(dev); 418 } 419 420 static int adev_init_check(const struct audio_hw_device *dev) 421 { 422 const struct legacy_audio_device *ladev = to_cladev(dev); 423 424 return ladev->hwif->initCheck(); 425 } 426 427 static int adev_set_voice_volume(struct audio_hw_device *dev, float volume) 428 { 429 struct legacy_audio_device *ladev = to_ladev(dev); 430 return ladev->hwif->setVoiceVolume(volume); 431 } 432 433 static int adev_set_master_volume(struct audio_hw_device *dev, float volume) 434 { 435 struct legacy_audio_device *ladev = to_ladev(dev); 436 return ladev->hwif->setMasterVolume(volume); 437 } 438 439 static int adev_get_master_volume(struct audio_hw_device *dev, float* volume) 440 { 441 struct legacy_audio_device *ladev = to_ladev(dev); 442 return ladev->hwif->getMasterVolume(volume); 443 } 444 445 static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode) 446 { 447 struct legacy_audio_device *ladev = to_ladev(dev); 448 // as this is the legacy API, don't change it to use audio_mode_t instead of int 449 return ladev->hwif->setMode((int) mode); 450 } 451 452 static int adev_set_mic_mute(struct audio_hw_device *dev, bool state) 453 { 454 struct legacy_audio_device *ladev = to_ladev(dev); 455 return ladev->hwif->setMicMute(state); 456 } 457 458 static int adev_get_mic_mute(const struct audio_hw_device *dev, bool *state) 459 { 460 const struct legacy_audio_device *ladev = to_cladev(dev); 461 return ladev->hwif->getMicMute(state); 462 } 463 464 static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs) 465 { 466 struct legacy_audio_device *ladev = to_ladev(dev); 467 return ladev->hwif->setParameters(String8(kvpairs)); 468 } 469 470 static char * adev_get_parameters(const struct audio_hw_device *dev, 471 const char *keys) 472 { 473 const struct legacy_audio_device *ladev = to_cladev(dev); 474 String8 s8; 475 476 s8 = ladev->hwif->getParameters(String8(keys)); 477 return strdup(s8.string()); 478 } 479 480 static size_t adev_get_input_buffer_size(const struct audio_hw_device *dev, 481 const struct audio_config *config) 482 { 483 const struct legacy_audio_device *ladev = to_cladev(dev); 484 return ladev->hwif->getInputBufferSize(config->sample_rate, (int) config->format, 485 audio_channel_count_from_in_mask(config->channel_mask)); 486 } 487 488 static int adev_open_output_stream(struct audio_hw_device *dev, 489 audio_io_handle_t handle, 490 audio_devices_t devices, 491 audio_output_flags_t flags, 492 struct audio_config *config, 493 struct audio_stream_out **stream_out, 494 const char *address __unused) 495 { 496 struct legacy_audio_device *ladev = to_ladev(dev); 497 status_t status; 498 struct legacy_stream_out *out; 499 int ret; 500 501 out = (struct legacy_stream_out *)calloc(1, sizeof(*out)); 502 if (!out) 503 return -ENOMEM; 504 505 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0); 506 507 out->legacy_out = ladev->hwif->openOutputStreamWithFlags(devices, flags, 508 (int *) &config->format, 509 &config->channel_mask, 510 &config->sample_rate, &status); 511 if (!out->legacy_out) { 512 ret = status; 513 goto err_open; 514 } 515 516 out->stream.common.get_sample_rate = out_get_sample_rate; 517 out->stream.common.set_sample_rate = out_set_sample_rate; 518 out->stream.common.get_buffer_size = out_get_buffer_size; 519 out->stream.common.get_channels = out_get_channels; 520 out->stream.common.get_format = out_get_format; 521 out->stream.common.set_format = out_set_format; 522 out->stream.common.standby = out_standby; 523 out->stream.common.dump = out_dump; 524 out->stream.common.set_parameters = out_set_parameters; 525 out->stream.common.get_parameters = out_get_parameters; 526 out->stream.common.add_audio_effect = out_add_audio_effect; 527 out->stream.common.remove_audio_effect = out_remove_audio_effect; 528 out->stream.get_latency = out_get_latency; 529 out->stream.set_volume = out_set_volume; 530 out->stream.write = out_write; 531 out->stream.get_render_position = out_get_render_position; 532 out->stream.get_next_write_timestamp = out_get_next_write_timestamp; 533 534 *stream_out = &out->stream; 535 return 0; 536 537 err_open: 538 free(out); 539 *stream_out = NULL; 540 return ret; 541 } 542 543 static void adev_close_output_stream(struct audio_hw_device *dev, 544 struct audio_stream_out* stream) 545 { 546 struct legacy_audio_device *ladev = to_ladev(dev); 547 struct legacy_stream_out *out = reinterpret_cast<struct legacy_stream_out *>(stream); 548 549 ladev->hwif->closeOutputStream(out->legacy_out); 550 free(out); 551 } 552 553 /** This method creates and opens the audio hardware input stream */ 554 static int adev_open_input_stream(struct audio_hw_device *dev, 555 audio_io_handle_t handle, 556 audio_devices_t devices, 557 struct audio_config *config, 558 struct audio_stream_in **stream_in, 559 audio_input_flags_t flags __unused, 560 const char *address __unused, 561 audio_source_t source __unused) 562 { 563 struct legacy_audio_device *ladev = to_ladev(dev); 564 status_t status; 565 struct legacy_stream_in *in; 566 int ret; 567 568 in = (struct legacy_stream_in *)calloc(1, sizeof(*in)); 569 if (!in) 570 return -ENOMEM; 571 572 devices = convert_audio_device(devices, HAL_API_REV_2_0, HAL_API_REV_1_0); 573 574 in->legacy_in = ladev->hwif->openInputStream(devices, (int *) &config->format, 575 &config->channel_mask, &config->sample_rate, 576 &status, (AudioSystem::audio_in_acoustics)0); 577 if (!in->legacy_in) { 578 ret = status; 579 goto err_open; 580 } 581 582 in->stream.common.get_sample_rate = in_get_sample_rate; 583 in->stream.common.set_sample_rate = in_set_sample_rate; 584 in->stream.common.get_buffer_size = in_get_buffer_size; 585 in->stream.common.get_channels = in_get_channels; 586 in->stream.common.get_format = in_get_format; 587 in->stream.common.set_format = in_set_format; 588 in->stream.common.standby = in_standby; 589 in->stream.common.dump = in_dump; 590 in->stream.common.set_parameters = in_set_parameters; 591 in->stream.common.get_parameters = in_get_parameters; 592 in->stream.common.add_audio_effect = in_add_audio_effect; 593 in->stream.common.remove_audio_effect = in_remove_audio_effect; 594 in->stream.set_gain = in_set_gain; 595 in->stream.read = in_read; 596 in->stream.get_input_frames_lost = in_get_input_frames_lost; 597 598 *stream_in = &in->stream; 599 return 0; 600 601 err_open: 602 free(in); 603 *stream_in = NULL; 604 return ret; 605 }
最新发布
07-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值