1

キャプチャした一連の画像をエンコードするためのテストドライバーを作成しました。私はlibx264を使用しており、この男の答えに基づいてドライバーを作成しています。

StackOverflowリンク

私の場合、JPG画像を読み込んで、YUVに変換し、同じフレームをループでx264エンコーダーに何度も渡すことから始めています。

私の期待は、フレームが同じであるため、エンコーダーからの出力が非常に小さく、一定になることでした。

代わりに、NALペイロードが数バイトから数KBまで変化し、エンコーダーパラメーターで指定したフレームレートによっても大きく変化することがわかりました。

明らかに、私はビデオエンコーディングを理解していません。なぜ出力サイズが大きく変わるのですか?

int main() 
{
  Image image(WIDTH, HEIGHT);
  image.FromJpeg("frame-1.jpg");

  unsigned char *data = image.GetRGB();

  x264_param_t param;

  x264_param_default_preset(&param, "fast", "zerolatency");
  param.i_threads = 1;
  param.i_width = WIDTH;
  param.i_height = HEIGHT;
  param.i_fps_num = FPS;
  param.i_fps_den = 1;

  // Intra refres:
  param.i_keyint_max = FPS;
  param.b_intra_refresh = 1;

  //Rate control:
  param.rc.i_rc_method = X264_RC_CRF;
  param.rc.f_rf_constant = FPS-5;
  param.rc.f_rf_constant_max = FPS+5;

  //For streaming:
  param.b_repeat_headers = 1;
  param.b_annexb = 1;

  x264_param_apply_profile(&param, "baseline");

  // initialize the encoder
  x264_t* encoder = x264_encoder_open(&param);
  x264_picture_t pic_in, pic_out;
  x264_picture_alloc(&pic_in, X264_CSP_I420, WIDTH, HEIGHT);
  // X264 expects YUV420P data use libswscale 
  // (from ffmpeg) to convert images to the right format
  struct SwsContext* convertCtx =
        sws_getContext(WIDTH, HEIGHT, PIX_FMT_RGB24, WIDTH, HEIGHT,
                       PIX_FMT_YUV420P, SWS_FAST_BILINEAR,
                       NULL, NULL, NULL);

  // encoding is as simple as this then, for each frame do:
  // data is a pointer to your RGB structure
  int srcstride = WIDTH*3; //RGB stride is just 3*width
  sws_scale(convertCtx, &data, &srcstride, 0, HEIGHT,
            pic_in.img.plane, pic_in.img.i_stride);
  x264_nal_t* nals;
  int i_nals;
  int frame_size =
        x264_encoder_encode(encoder, &nals, &i_nals, &pic_in, &pic_out);

  int max_loop=15;
  int this_loop=1;

  while (frame_size >= 0 && --max_loop)
  {
      cout << "------------" << this_loop++ << "-----------------\n";
      cout << "Frame size = " << frame_size << endl;
      cout << "output has " << pic_out.img.i_csp << " colorspace\n";
      cout << "output has " << pic_out.img.i_plane << " # img planes\n";

      cout << "i_nals = " << i_nals << endl;
      for (int n=0; n<i_nals; n++)
        cout << "nal[" << n << "] payload size = "
             << nals[n].i_payload << endl;



      // clean this input frame and grab another
      x264_picture_clean(&pic_in);
      x264_picture_alloc(&pic_in, X264_CSP_I420, WIDTH, HEIGHT);
      sws_scale(convertCtx, &data, &srcstride, 0, HEIGHT,
                pic_in.img.plane, pic_in.img.i_stride);


      frame_size=
        x264_encoder_encode(encoder, &nals, &i_nals, &pic_in, &pic_out);
  }

  delete [] data;
  return 0;
}

私が読んでいる元のJPG画像は320x240で、ディスク上で約9KBです。同じ画像をエンコーダーに通して実行した場合の出力は、次のようになります。

x264 [warning]: ref > 1 + intra-refresh is not supported
x264 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle SSE4.2 AVX
x264 [info]: profile Constrained Baseline, level 1.3 
------------1-----------------
Frame size = 17412
output has 3 colorspace
output has 2 # img planes
i_nals = 4 
nal[0] payload size = 26
nal[1] payload size = 8 
nal[2] payload size = 610 
nal[3] payload size = 16768
------------2-----------------
Frame size = 11
output has 3 colorspace
output has 2 # img planes
i_nals = 1 
nal[0] payload size = 11
------------3-----------------
Frame size = 11
output has 3 colorspace
output has 2 # img planes
i_nals = 1 
nal[0] payload size = 11
------------4-----------------
Frame size = 16
output has 3 colorspace
output has 2 # img planes
i_nals = 1 
nal[0] payload size = 16
------------5-----------------
Frame size = 104 
output has 3 colorspace
output has 2 # img planes
i_nals = 1 
nal[0] payload size = 104 
------------6-----------------
Frame size = 973 
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 973
------------7-----------------
Frame size = 4576
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 4576
------------8-----------------
Frame size = 4040
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 4040
------------9-----------------
Frame size = 3917
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 3917
------------10-----------------
Frame size = 3799
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 3799
------------11-----------------
Frame size = 2454
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 2454
------------12-----------------
Frame size = 1641
output has 3 colorspace
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 1641
------------13-----------------
Frame size = 1121
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 1121
------------14-----------------
Frame size = 247
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 247

FPSを30ではなく10に設定すると、出力サイズが大幅に変化します。

x264 [warning]: ref > 1 + intra-refresh is not supported
x264 [info]: using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle SSE4.2 AVX
x264 [info]: profile Constrained Baseline, level 1.1 
------------1-----------------
Frame size = 60120
output has 3 colorspace
output has 2 # img planes
i_nals = 4 
nal[0] payload size = 25
nal[1] payload size = 9 
nal[2] payload size = 609 
nal[3] payload size = 59477
------------2-----------------
Frame size = 10
output has 3 colorspace
output has 2 # img planes
i_nals = 1 
nal[0] payload size = 10
------------3-----------------
Frame size = 151 
output has 3 colorspace
output has 2 # img planes
i_nals = 1 
nal[0] payload size = 151 
------------4-----------------
Frame size = 2329
output has 3 colorspace
output has 2 # img planes
i_nals = 1 
nal[0] payload size = 2329
------------5-----------------
Frame size = 1466
output has 3 colorspace
output has 2 # img planes
i_nals = 1 
nal[0] payload size = 1466
------------6-----------------
Frame size = 539 
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 539
------------7-----------------
Frame size = 311
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 311
------------8-----------------
Frame size = 291
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 291
------------9-----------------
Frame size = 302
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 302
------------10-----------------
Frame size = 287
output has 3 colorspace
output has 2 # img planes
i_nals = 1
nal[0] payload size = 287
------------11-----------------
Frame size = 11937
output has 3 colorspace
output has 2 # img planes
i_nals = 4
nal[0] payload size = 25
nal[1] payload size = 9
nal[2] payload size = 9
nal[3] payload size = 11894

教えてくれませんか?

4

1 に答える 1

3

この問題は、主に「レート制御」パラメータが原因です。CRF レート制御を削除し、定数量子化器を使用します。定数量子化は推奨される操作モードではありませんが、あなたの場合(同じ画像の繰り返し)は同様のサイズのフレームを生成します。

削除する:

param.b_intra_refresh = 1;

//Rate control:
param.rc.i_rc_method = X264_RC_CRF;
param.rc.f_rf_constant = FPS-5;
param.rc.f_rf_constant_max = FPS+5;

それから加えて:

 param.rc.i_qp_constant = 18; 
 param.rc.i_qp_min = 18; 
 param.rc.i_qp_max = 18;
于 2013-01-03T04:09:55.700 に答える