OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/common/gpu/media/vaapi_video_encode_accelerator.h" | 5 #include "content/common/gpu/media/vaapi_video_encode_accelerator.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/message_loop/message_loop_proxy.h" | 9 #include "base/message_loop/message_loop_proxy.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
254 void VaapiVideoEncodeAccelerator::RecycleVASurfaceID( | 254 void VaapiVideoEncodeAccelerator::RecycleVASurfaceID( |
255 VASurfaceID va_surface_id) { | 255 VASurfaceID va_surface_id) { |
256 DVLOGF(4) << "va_surface_id: " << va_surface_id; | 256 DVLOGF(4) << "va_surface_id: " << va_surface_id; |
257 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); | 257 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
258 | 258 |
259 available_va_surface_ids_.push_back(va_surface_id); | 259 available_va_surface_ids_.push_back(va_surface_id); |
260 EncodeFrameTask(); | 260 EncodeFrameTask(); |
261 } | 261 } |
262 | 262 |
263 void VaapiVideoEncodeAccelerator::BeginFrame(bool force_keyframe) { | 263 void VaapiVideoEncodeAccelerator::BeginFrame(bool force_keyframe) { |
264 memset(¤t_pic_, 0, sizeof(current_pic_)); | 264 current_pic_ = new H264Picture(); |
kcwu
2015/03/31 15:20:09
Is EndFrame() always paired with BeginFrame() ?
If
Pawel Osciak
2015/04/03 07:06:00
Yes, I considered that, but I thought it would be
| |
265 | 265 |
266 // If the current picture is an IDR picture, frame_num shall be equal to 0. | 266 // If the current picture is an IDR picture, frame_num shall be equal to 0. |
267 if (force_keyframe) | 267 if (force_keyframe) |
268 frame_num_ = 0; | 268 frame_num_ = 0; |
269 | 269 |
270 current_pic_.frame_num = frame_num_++; | 270 current_pic_->frame_num = frame_num_++; |
271 frame_num_ %= idr_period_; | 271 frame_num_ %= idr_period_; |
272 | 272 |
273 if (current_pic_.frame_num == 0) { | 273 if (current_pic_->frame_num == 0) { |
274 current_pic_.idr = true; | 274 current_pic_->idr = true; |
275 // H264 spec mandates idr_pic_id to differ between two consecutive IDRs. | 275 // H264 spec mandates idr_pic_id to differ between two consecutive IDRs. |
276 idr_pic_id_ ^= 1; | 276 idr_pic_id_ ^= 1; |
277 ref_pic_list0_.clear(); | 277 ref_pic_list0_.clear(); |
278 } | 278 } |
279 | 279 |
280 if (current_pic_.frame_num % i_period_ == 0) | 280 if (current_pic_->frame_num % i_period_ == 0) |
281 current_pic_.type = media::H264SliceHeader::kISlice; | 281 current_pic_->type = media::H264SliceHeader::kISlice; |
282 else | 282 else |
283 current_pic_.type = media::H264SliceHeader::kPSlice; | 283 current_pic_->type = media::H264SliceHeader::kPSlice; |
284 | 284 |
285 if (current_pic_.type != media::H264SliceHeader::kBSlice) | 285 if (current_pic_->type != media::H264SliceHeader::kBSlice) |
286 current_pic_.ref = true; | 286 current_pic_->ref = true; |
287 | 287 |
288 current_pic_.pic_order_cnt = current_pic_.frame_num * 2; | 288 current_pic_->pic_order_cnt = current_pic_->frame_num * 2; |
289 current_pic_.top_field_order_cnt = current_pic_.pic_order_cnt; | 289 current_pic_->top_field_order_cnt = current_pic_->pic_order_cnt; |
290 current_pic_.pic_order_cnt_lsb = current_pic_.pic_order_cnt; | 290 current_pic_->pic_order_cnt_lsb = current_pic_->pic_order_cnt; |
291 | 291 |
292 current_encode_job_->keyframe = current_pic_.idr; | 292 current_encode_job_->keyframe = current_pic_->idr; |
293 | 293 |
294 DVLOGF(4) << "Starting a new frame, type: " << current_pic_.type | 294 DVLOGF(4) << "Starting a new frame, type: " << current_pic_->type |
295 << (force_keyframe ? " (forced keyframe)" : "") | 295 << (force_keyframe ? " (forced keyframe)" : "") |
296 << " frame_num: " << current_pic_.frame_num | 296 << " frame_num: " << current_pic_->frame_num |
297 << " POC: " << current_pic_.pic_order_cnt; | 297 << " POC: " << current_pic_->pic_order_cnt; |
298 } | 298 } |
299 | 299 |
300 void VaapiVideoEncodeAccelerator::EndFrame() { | 300 void VaapiVideoEncodeAccelerator::EndFrame() { |
301 DCHECK(current_pic_); | |
301 // Store the picture on the list of reference pictures and keep the list | 302 // Store the picture on the list of reference pictures and keep the list |
302 // below maximum size, dropping oldest references. | 303 // below maximum size, dropping oldest references. |
303 if (current_pic_.ref) | 304 if (current_pic_->ref) |
304 ref_pic_list0_.push_front(current_encode_job_->recon_surface); | 305 ref_pic_list0_.push_front(current_encode_job_->recon_surface); |
305 size_t max_num_ref_frames = | 306 size_t max_num_ref_frames = |
306 base::checked_cast<size_t>(current_sps_.max_num_ref_frames); | 307 base::checked_cast<size_t>(current_sps_.max_num_ref_frames); |
307 while (ref_pic_list0_.size() > max_num_ref_frames) | 308 while (ref_pic_list0_.size() > max_num_ref_frames) |
308 ref_pic_list0_.pop_back(); | 309 ref_pic_list0_.pop_back(); |
309 | 310 |
310 submitted_encode_jobs_.push(make_linked_ptr(current_encode_job_.release())); | 311 submitted_encode_jobs_.push(make_linked_ptr(current_encode_job_.release())); |
311 } | 312 } |
312 | 313 |
313 static void InitVAPicture(VAPictureH264* va_pic) { | 314 static void InitVAPicture(VAPictureH264* va_pic) { |
314 memset(va_pic, 0, sizeof(*va_pic)); | 315 memset(va_pic, 0, sizeof(*va_pic)); |
315 va_pic->picture_id = VA_INVALID_ID; | 316 va_pic->picture_id = VA_INVALID_ID; |
316 va_pic->flags = VA_PICTURE_H264_INVALID; | 317 va_pic->flags = VA_PICTURE_H264_INVALID; |
317 } | 318 } |
318 | 319 |
319 bool VaapiVideoEncodeAccelerator::SubmitFrameParameters() { | 320 bool VaapiVideoEncodeAccelerator::SubmitFrameParameters() { |
321 DCHECK(current_pic_); | |
320 VAEncSequenceParameterBufferH264 seq_param; | 322 VAEncSequenceParameterBufferH264 seq_param; |
321 memset(&seq_param, 0, sizeof(seq_param)); | 323 memset(&seq_param, 0, sizeof(seq_param)); |
322 | 324 |
323 #define SPS_TO_SP(a) seq_param.a = current_sps_.a; | 325 #define SPS_TO_SP(a) seq_param.a = current_sps_.a; |
324 SPS_TO_SP(seq_parameter_set_id); | 326 SPS_TO_SP(seq_parameter_set_id); |
325 SPS_TO_SP(level_idc); | 327 SPS_TO_SP(level_idc); |
326 | 328 |
327 seq_param.intra_period = i_period_; | 329 seq_param.intra_period = i_period_; |
328 seq_param.intra_idr_period = idr_period_; | 330 seq_param.intra_idr_period = idr_period_; |
329 seq_param.ip_period = ip_period_; | 331 seq_param.ip_period = ip_period_; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
362 | 364 |
363 if (!vaapi_wrapper_->SubmitBuffer(VAEncSequenceParameterBufferType, | 365 if (!vaapi_wrapper_->SubmitBuffer(VAEncSequenceParameterBufferType, |
364 sizeof(seq_param), | 366 sizeof(seq_param), |
365 &seq_param)) | 367 &seq_param)) |
366 return false; | 368 return false; |
367 | 369 |
368 VAEncPictureParameterBufferH264 pic_param; | 370 VAEncPictureParameterBufferH264 pic_param; |
369 memset(&pic_param, 0, sizeof(pic_param)); | 371 memset(&pic_param, 0, sizeof(pic_param)); |
370 | 372 |
371 pic_param.CurrPic.picture_id = current_encode_job_->recon_surface->id(); | 373 pic_param.CurrPic.picture_id = current_encode_job_->recon_surface->id(); |
372 pic_param.CurrPic.TopFieldOrderCnt = current_pic_.top_field_order_cnt; | 374 pic_param.CurrPic.TopFieldOrderCnt = current_pic_->top_field_order_cnt; |
373 pic_param.CurrPic.BottomFieldOrderCnt = current_pic_.bottom_field_order_cnt; | 375 pic_param.CurrPic.BottomFieldOrderCnt = current_pic_->bottom_field_order_cnt; |
374 pic_param.CurrPic.flags = 0; | 376 pic_param.CurrPic.flags = 0; |
375 | 377 |
376 for (size_t i = 0; i < arraysize(pic_param.ReferenceFrames); ++i) | 378 for (size_t i = 0; i < arraysize(pic_param.ReferenceFrames); ++i) |
377 InitVAPicture(&pic_param.ReferenceFrames[i]); | 379 InitVAPicture(&pic_param.ReferenceFrames[i]); |
378 | 380 |
379 DCHECK_LE(ref_pic_list0_.size(), arraysize(pic_param.ReferenceFrames)); | 381 DCHECK_LE(ref_pic_list0_.size(), arraysize(pic_param.ReferenceFrames)); |
380 RefPicList::const_iterator iter = ref_pic_list0_.begin(); | 382 RefPicList::const_iterator iter = ref_pic_list0_.begin(); |
381 for (size_t i = 0; | 383 for (size_t i = 0; |
382 i < arraysize(pic_param.ReferenceFrames) && iter != ref_pic_list0_.end(); | 384 i < arraysize(pic_param.ReferenceFrames) && iter != ref_pic_list0_.end(); |
383 ++iter, ++i) { | 385 ++iter, ++i) { |
384 pic_param.ReferenceFrames[i].picture_id = (*iter)->id(); | 386 pic_param.ReferenceFrames[i].picture_id = (*iter)->id(); |
385 pic_param.ReferenceFrames[i].flags = 0; | 387 pic_param.ReferenceFrames[i].flags = 0; |
386 } | 388 } |
387 | 389 |
388 pic_param.coded_buf = current_encode_job_->coded_buffer; | 390 pic_param.coded_buf = current_encode_job_->coded_buffer; |
389 pic_param.pic_parameter_set_id = current_pps_.pic_parameter_set_id; | 391 pic_param.pic_parameter_set_id = current_pps_.pic_parameter_set_id; |
390 pic_param.seq_parameter_set_id = current_pps_.seq_parameter_set_id; | 392 pic_param.seq_parameter_set_id = current_pps_.seq_parameter_set_id; |
391 pic_param.frame_num = current_pic_.frame_num; | 393 pic_param.frame_num = current_pic_->frame_num; |
392 pic_param.pic_init_qp = qp_; | 394 pic_param.pic_init_qp = qp_; |
393 pic_param.num_ref_idx_l0_active_minus1 = max_ref_idx_l0_size_ - 1; | 395 pic_param.num_ref_idx_l0_active_minus1 = max_ref_idx_l0_size_ - 1; |
394 pic_param.pic_fields.bits.idr_pic_flag = current_pic_.idr; | 396 pic_param.pic_fields.bits.idr_pic_flag = current_pic_->idr; |
395 pic_param.pic_fields.bits.reference_pic_flag = current_pic_.ref; | 397 pic_param.pic_fields.bits.reference_pic_flag = current_pic_->ref; |
396 #define PPS_TO_PP_PF(a) pic_param.pic_fields.bits.a = current_pps_.a; | 398 #define PPS_TO_PP_PF(a) pic_param.pic_fields.bits.a = current_pps_.a; |
397 PPS_TO_PP_PF(entropy_coding_mode_flag); | 399 PPS_TO_PP_PF(entropy_coding_mode_flag); |
398 PPS_TO_PP_PF(transform_8x8_mode_flag); | 400 PPS_TO_PP_PF(transform_8x8_mode_flag); |
399 PPS_TO_PP_PF(deblocking_filter_control_present_flag); | 401 PPS_TO_PP_PF(deblocking_filter_control_present_flag); |
400 #undef PPS_TO_PP_PF | 402 #undef PPS_TO_PP_PF |
401 | 403 |
402 if (!vaapi_wrapper_->SubmitBuffer(VAEncPictureParameterBufferType, | 404 if (!vaapi_wrapper_->SubmitBuffer(VAEncPictureParameterBufferType, |
403 sizeof(pic_param), | 405 sizeof(pic_param), |
404 &pic_param)) | 406 &pic_param)) |
405 return false; | 407 return false; |
406 | 408 |
407 VAEncSliceParameterBufferH264 slice_param; | 409 VAEncSliceParameterBufferH264 slice_param; |
408 memset(&slice_param, 0, sizeof(slice_param)); | 410 memset(&slice_param, 0, sizeof(slice_param)); |
409 | 411 |
410 slice_param.num_macroblocks = mb_width_ * mb_height_; | 412 slice_param.num_macroblocks = mb_width_ * mb_height_; |
411 slice_param.macroblock_info = VA_INVALID_ID; | 413 slice_param.macroblock_info = VA_INVALID_ID; |
412 slice_param.slice_type = current_pic_.type; | 414 slice_param.slice_type = current_pic_->type; |
413 slice_param.pic_parameter_set_id = current_pps_.pic_parameter_set_id; | 415 slice_param.pic_parameter_set_id = current_pps_.pic_parameter_set_id; |
414 slice_param.idr_pic_id = idr_pic_id_; | 416 slice_param.idr_pic_id = idr_pic_id_; |
415 slice_param.pic_order_cnt_lsb = current_pic_.pic_order_cnt_lsb; | 417 slice_param.pic_order_cnt_lsb = current_pic_->pic_order_cnt_lsb; |
416 slice_param.num_ref_idx_active_override_flag = true; | 418 slice_param.num_ref_idx_active_override_flag = true; |
417 | 419 |
418 for (size_t i = 0; i < arraysize(slice_param.RefPicList0); ++i) | 420 for (size_t i = 0; i < arraysize(slice_param.RefPicList0); ++i) |
419 InitVAPicture(&slice_param.RefPicList0[i]); | 421 InitVAPicture(&slice_param.RefPicList0[i]); |
420 | 422 |
421 for (size_t i = 0; i < arraysize(slice_param.RefPicList1); ++i) | 423 for (size_t i = 0; i < arraysize(slice_param.RefPicList1); ++i) |
422 InitVAPicture(&slice_param.RefPicList1[i]); | 424 InitVAPicture(&slice_param.RefPicList1[i]); |
423 | 425 |
424 DCHECK_LE(ref_pic_list0_.size(), arraysize(slice_param.RefPicList0)); | 426 DCHECK_LE(ref_pic_list0_.size(), arraysize(slice_param.RefPicList0)); |
425 iter = ref_pic_list0_.begin(); | 427 iter = ref_pic_list0_.begin(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
465 hrd_param.initial_buffer_fullness = cpb_size_ / 2; | 467 hrd_param.initial_buffer_fullness = cpb_size_ / 2; |
466 if (!vaapi_wrapper_->SubmitVAEncMiscParamBuffer(VAEncMiscParameterTypeHRD, | 468 if (!vaapi_wrapper_->SubmitVAEncMiscParamBuffer(VAEncMiscParameterTypeHRD, |
467 sizeof(hrd_param), | 469 sizeof(hrd_param), |
468 &hrd_param)) | 470 &hrd_param)) |
469 return false; | 471 return false; |
470 | 472 |
471 return true; | 473 return true; |
472 } | 474 } |
473 | 475 |
474 bool VaapiVideoEncodeAccelerator::SubmitHeadersIfNeeded() { | 476 bool VaapiVideoEncodeAccelerator::SubmitHeadersIfNeeded() { |
475 if (current_pic_.type != media::H264SliceHeader::kISlice) | 477 DCHECK(current_pic_); |
478 if (current_pic_->type != media::H264SliceHeader::kISlice) | |
476 return true; | 479 return true; |
477 | 480 |
478 // Submit PPS. | 481 // Submit PPS. |
479 VAEncPackedHeaderParameterBuffer par_buffer; | 482 VAEncPackedHeaderParameterBuffer par_buffer; |
480 memset(&par_buffer, 0, sizeof(par_buffer)); | 483 memset(&par_buffer, 0, sizeof(par_buffer)); |
481 par_buffer.type = VAEncPackedHeaderSequence; | 484 par_buffer.type = VAEncPackedHeaderSequence; |
482 par_buffer.bit_length = packed_sps_.BytesInBuffer() * 8; | 485 par_buffer.bit_length = packed_sps_.BytesInBuffer() * 8; |
483 | 486 |
484 if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderParameterBufferType, | 487 if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderParameterBufferType, |
485 sizeof(par_buffer), | 488 sizeof(par_buffer), |
(...skipping 17 matching lines...) Expand all Loading... | |
503 | 506 |
504 if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderDataBufferType, | 507 if (!vaapi_wrapper_->SubmitBuffer(VAEncPackedHeaderDataBufferType, |
505 packed_pps_.BytesInBuffer(), | 508 packed_pps_.BytesInBuffer(), |
506 packed_pps_.data())) | 509 packed_pps_.data())) |
507 return false; | 510 return false; |
508 | 511 |
509 return true; | 512 return true; |
510 } | 513 } |
511 | 514 |
512 bool VaapiVideoEncodeAccelerator::ExecuteEncode() { | 515 bool VaapiVideoEncodeAccelerator::ExecuteEncode() { |
513 DVLOGF(3) << "Encoding frame_num: " << current_pic_.frame_num; | 516 DCHECK(current_pic_); |
517 DVLOGF(3) << "Encoding frame_num: " << current_pic_->frame_num; | |
514 return vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( | 518 return vaapi_wrapper_->ExecuteAndDestroyPendingBuffers( |
515 current_encode_job_->input_surface->id()); | 519 current_encode_job_->input_surface->id()); |
516 } | 520 } |
517 | 521 |
518 bool VaapiVideoEncodeAccelerator::UploadFrame( | 522 bool VaapiVideoEncodeAccelerator::UploadFrame( |
519 const scoped_refptr<media::VideoFrame>& frame) { | 523 const scoped_refptr<media::VideoFrame>& frame) { |
520 return vaapi_wrapper_->UploadVideoFrameToSurface( | 524 return vaapi_wrapper_->UploadVideoFrameToSurface( |
521 frame, current_encode_job_->input_surface->id()); | 525 frame, current_encode_job_->input_surface->id()); |
522 } | 526 } |
523 | 527 |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1062 } | 1066 } |
1063 | 1067 |
1064 VaapiVideoEncodeAccelerator::EncodeJob::EncodeJob() | 1068 VaapiVideoEncodeAccelerator::EncodeJob::EncodeJob() |
1065 : coded_buffer(VA_INVALID_ID), keyframe(false) { | 1069 : coded_buffer(VA_INVALID_ID), keyframe(false) { |
1066 } | 1070 } |
1067 | 1071 |
1068 VaapiVideoEncodeAccelerator::EncodeJob::~EncodeJob() { | 1072 VaapiVideoEncodeAccelerator::EncodeJob::~EncodeJob() { |
1069 } | 1073 } |
1070 | 1074 |
1071 } // namespace content | 1075 } // namespace content |
OLD | NEW |