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