Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(289)

Side by Side Diff: content/common/gpu/media/vaapi_h264_decoder.cc

Issue 10843058: VAVDA: Destroy vaapi buffers after we're done drawing. (Closed) Base URL: https://git.chromium.org/git/chromium/src@master
Patch Set: Did the locking in a separate CL. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/common/gpu/media/vaapi_h264_decoder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <dlfcn.h> 5 #include <dlfcn.h>
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "content/common/gpu/gl_scoped_binders.h" 11 #include "content/common/gpu/gl_scoped_binders.h"
12 #include "content/common/gpu/media/vaapi_h264_decoder.h" 12 #include "content/common/gpu/media/vaapi_h264_decoder.h"
13 #include "third_party/libva/va/va.h" 13 #include "third_party/libva/va/va.h"
14 #include "third_party/libva/va/va_x11.h" 14 #include "third_party/libva/va/va_x11.h"
15 #include "ui/gl/gl_bindings.h" 15 #include "ui/gl/gl_bindings.h"
16 16
17 #define VA_LOG_ON_ERROR(va_res, err_msg) \ 17 #define VA_LOG_ON_ERROR(va_res, err_msg) \
18 do { \ 18 do { \
19 if ((va_res) != VA_STATUS_SUCCESS) { \ 19 if ((va_res) != VA_STATUS_SUCCESS) { \
20 DVLOG(1) << err_msg \ 20 DVLOG(1) << err_msg \
21 << " VA error: " << VAAPI_ErrorStr(va_res); \ 21 << " VA error: " << VAAPI_ErrorStr(va_res); \
22 } \ 22 } \
23 } while(0) 23 } while (0)
24 24
25 #define VA_SUCCESS_OR_RETURN(va_res, err_msg, ret) \ 25 #define VA_SUCCESS_OR_RETURN(va_res, err_msg, ret) \
26 do { \ 26 do { \
27 if ((va_res) != VA_STATUS_SUCCESS) { \ 27 if ((va_res) != VA_STATUS_SUCCESS) { \
28 DVLOG(1) << err_msg \ 28 DVLOG(1) << err_msg \
29 << " VA error: " << VAAPI_ErrorStr(va_res); \ 29 << " VA error: " << VAAPI_ErrorStr(va_res); \
30 return (ret); \ 30 return (ret); \
31 } \ 31 } \
32 } while (0) 32 } while (0)
33 33
34 #define VA_LOG_ERROR(va_res, err_msg) \
35 do { \
36 DVLOG(1) << err_msg \
37 << " VA error: " << VAAPI_ErrorStr(va_res); \
38 } while (0)
39
34 namespace content { 40 namespace content {
35 41
36 void *vaapi_handle = dlopen("libva.so", RTLD_NOW); 42 void *vaapi_handle = dlopen("libva.so", RTLD_NOW);
37 void *vaapi_x11_handle = dlopen("libva-x11.so", RTLD_NOW); 43 void *vaapi_x11_handle = dlopen("libva-x11.so", RTLD_NOW);
38 44
39 typedef VADisplay (*VaapiGetDisplay)(Display *dpy); 45 typedef VADisplay (*VaapiGetDisplay)(Display *dpy);
40 typedef int (*VaapiDisplayIsValid)(VADisplay dpy); 46 typedef int (*VaapiDisplayIsValid)(VADisplay dpy);
41 typedef VAStatus (*VaapiInitialize)(VADisplay dpy, 47 typedef VAStatus (*VaapiInitialize)(VADisplay dpy,
42 int *major_version, 48 int *major_version,
43 int *minor_version); 49 int *minor_version);
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 frame_num_ = 0; 370 frame_num_ = 0;
365 prev_frame_num_ = -1; 371 prev_frame_num_ = -1;
366 prev_frame_num_offset_ = -1; 372 prev_frame_num_offset_ = -1;
367 373
368 prev_ref_has_memmgmnt5_ = false; 374 prev_ref_has_memmgmnt5_ = false;
369 prev_ref_top_field_order_cnt_ = -1; 375 prev_ref_top_field_order_cnt_ = -1;
370 prev_ref_pic_order_cnt_msb_ = -1; 376 prev_ref_pic_order_cnt_msb_ = -1;
371 prev_ref_pic_order_cnt_lsb_ = -1; 377 prev_ref_pic_order_cnt_lsb_ = -1;
372 prev_ref_field_ = H264Picture::FIELD_NONE; 378 prev_ref_field_ = H264Picture::FIELD_NONE;
373 379
380 // When called from the constructor, although va_display_ is invalid,
381 // |pending_slice_bufs_| and |pending_va_bufs_| are empty.
382 DestroyPendingBuffers();
383
374 pending_slice_bufs_ = std::queue<VABufferID>(); 384 pending_slice_bufs_ = std::queue<VABufferID>();
375 pending_va_bufs_ = std::queue<VABufferID>(); 385 pending_va_bufs_ = std::queue<VABufferID>();
376 386
377 ref_pic_list0_.clear(); 387 ref_pic_list0_.clear();
378 ref_pic_list1_.clear(); 388 ref_pic_list1_.clear();
379 389
380 for (POCToDecodeSurfaces::iterator it = poc_to_decode_surfaces_.begin(); 390 for (POCToDecodeSurfaces::iterator it = poc_to_decode_surfaces_.begin();
381 it != poc_to_decode_surfaces_.end(); ) { 391 it != poc_to_decode_surfaces_.end(); ) {
382 int poc = it->second->poc(); 392 int poc = it->second->poc();
383 // Must be incremented before UnassignSurfaceFromPoC as this call 393 // Must be incremented before UnassignSurfaceFromPoC as this call
(...skipping 25 matching lines...) Expand all
409 case kDecoding: 419 case kDecoding:
410 case kAfterReset: 420 case kAfterReset:
411 case kError: 421 case kError:
412 destroy_surfaces = true; 422 destroy_surfaces = true;
413 // fallthrough 423 // fallthrough
414 case kInitialized: 424 case kInitialized:
415 if (!make_context_current_.Run()) 425 if (!make_context_current_.Run())
416 break; 426 break;
417 if (destroy_surfaces) 427 if (destroy_surfaces)
418 DestroyVASurfaces(); 428 DestroyVASurfaces();
429 DestroyPendingBuffers();
Pawel Osciak 2012/08/03 20:57:14 This should only be required in one of the three a
419 va_res = VAAPI_DestroyConfig(va_display_, va_config_id_); 430 va_res = VAAPI_DestroyConfig(va_display_, va_config_id_);
420 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); 431 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed");
421 va_res = VAAPI_Terminate(va_display_); 432 va_res = VAAPI_Terminate(va_display_);
422 VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); 433 VA_LOG_ON_ERROR(va_res, "vaTerminate failed");
423 // fallthrough 434 // fallthrough
424 case kUninitialized: 435 case kUninitialized:
425 break; 436 break;
426 } 437 }
427 438
428 state_ = kUninitialized; 439 state_ = kUninitialized;
429 } 440 }
430 441
431 // Maps Profile enum values to VaProfile values. 442 // Maps Profile enum values to VaProfile values.
432 bool VaapiH264Decoder::SetProfile(media::VideoCodecProfile profile) { 443 bool VaapiH264Decoder::SetProfile(media::VideoCodecProfile profile) {
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
593 GetRequiredNumOfPictures(), 604 GetRequiredNumOfPictures(),
594 va_surface_ids_); 605 va_surface_ids_);
595 VA_SUCCESS_OR_RETURN(va_res, "vaCreateSurfaces failed", false); 606 VA_SUCCESS_OR_RETURN(va_res, "vaCreateSurfaces failed", false);
596 607
597 DCHECK(decode_surfaces_.empty()); 608 DCHECK(decode_surfaces_.empty());
598 // And create a context associated with them. 609 // And create a context associated with them.
599 va_res = VAAPI_CreateContext(va_display_, va_config_id_, 610 va_res = VAAPI_CreateContext(va_display_, va_config_id_,
600 pic_width_, pic_height_, VA_PROGRESSIVE, 611 pic_width_, pic_height_, VA_PROGRESSIVE,
601 va_surface_ids_, GetRequiredNumOfPictures(), 612 va_surface_ids_, GetRequiredNumOfPictures(),
602 &va_context_id_); 613 &va_context_id_);
603 VA_SUCCESS_OR_RETURN(va_res, "vaCreateContext failed", false); 614
615 if (va_res != VA_STATUS_SUCCESS) {
616 VAAPI_DestroySurfaces(va_display_, va_surface_ids_,
617 GetRequiredNumOfPictures());
618 DVLOG(1) << "vaCreateContext failed"
619 << " VA error: " << VAAPI_ErrorStr(va_res);
620 return false;
621 }
604 622
605 return true; 623 return true;
606 } 624 }
607 625
608 void VaapiH264Decoder::DestroyVASurfaces() { 626 void VaapiH264Decoder::DestroyVASurfaces() {
609 DCHECK(state_ == kDecoding || state_ == kError || state_ == kAfterReset); 627 DCHECK(state_ == kDecoding || state_ == kError || state_ == kAfterReset);
610 decode_surfaces_.clear(); 628 decode_surfaces_.clear();
611 629
612 VAStatus va_res = VAAPI_DestroyContext(va_display_, va_context_id_); 630 VAStatus va_res = VAAPI_DestroyContext(va_display_, va_context_id_);
613 VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed"); 631 VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed");
614 632
615 va_res = VAAPI_DestroySurfaces(va_display_, va_surface_ids_, 633 va_res = VAAPI_DestroySurfaces(va_display_, va_surface_ids_,
616 GetRequiredNumOfPictures()); 634 GetRequiredNumOfPictures());
617 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed"); 635 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed");
618 } 636 }
619 637
638 void VaapiH264Decoder::DestroyPendingBuffers() {
639 while (!pending_slice_bufs_.empty()) {
640 VABufferID buffer = pending_slice_bufs_.front();
641 VAStatus va_res = VAAPI_DestroyBuffer(va_display_, buffer);
642 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
643 pending_slice_bufs_.pop();
644 }
645 while (!pending_va_bufs_.empty()) {
646 VABufferID buffer = pending_va_bufs_.front();
647 VAStatus va_res = VAAPI_DestroyBuffer(va_display_, buffer);
648 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
649 pending_va_bufs_.pop();
650 }
651 }
652
620 // Fill |va_pic| with default/neutral values. 653 // Fill |va_pic| with default/neutral values.
621 static void InitVAPicture(VAPictureH264* va_pic) { 654 static void InitVAPicture(VAPictureH264* va_pic) {
622 memset(va_pic, 0, sizeof(*va_pic)); 655 memset(va_pic, 0, sizeof(*va_pic));
623 va_pic->picture_id = VA_INVALID_ID; 656 va_pic->picture_id = VA_INVALID_ID;
624 va_pic->flags = VA_PICTURE_H264_INVALID; 657 va_pic->flags = VA_PICTURE_H264_INVALID;
625 } 658 }
626 659
627 void VaapiH264Decoder::FillVAPicture(VAPictureH264 *va_pic, H264Picture* pic) { 660 void VaapiH264Decoder::FillVAPicture(VAPictureH264 *va_pic, H264Picture* pic) {
628 POCToDecodeSurfaces::iterator iter = poc_to_decode_surfaces_.find( 661 POCToDecodeSurfaces::iterator iter = poc_to_decode_surfaces_.find(
629 pic->pic_order_cnt); 662 pic->pic_order_cnt);
(...skipping 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
988 1021
989 if (!SendVASliceParam(slice_hdr)) 1022 if (!SendVASliceParam(slice_hdr))
990 return false; 1023 return false;
991 1024
992 if (!SendSliceData(slice_hdr->nalu_data, slice_hdr->nalu_size)) 1025 if (!SendSliceData(slice_hdr->nalu_data, slice_hdr->nalu_size))
993 return false; 1026 return false;
994 1027
995 return true; 1028 return true;
996 } 1029 }
997 1030
1031 void VaapiH264Decoder::DestroyBuffers(VABufferID* va_buffers,
1032 size_t num_va_buffers) {
1033 for (size_t i = 0; i < num_va_buffers; ++i) {
1034 VAStatus va_res = VAAPI_DestroyBuffer(va_display_, va_buffers[i]);
1035 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
1036 }
1037 }
1038
998 // TODO(posciak) start using vaMapBuffer instead of vaCreateBuffer wherever 1039 // TODO(posciak) start using vaMapBuffer instead of vaCreateBuffer wherever
999 // possible. 1040 // possible.
1000 1041
1001 bool VaapiH264Decoder::DecodePicture() { 1042 bool VaapiH264Decoder::DecodePicture() {
1002 DCHECK(!frame_ready_at_hw_); 1043 DCHECK(!frame_ready_at_hw_);
1003 DCHECK(curr_pic_.get()); 1044 DCHECK(curr_pic_.get());
1004 1045
1005 static const size_t kMaxVABuffers = 32; 1046 static const size_t kMaxVABuffers = 32;
1006 DCHECK_LE(pending_va_bufs_.size(), kMaxVABuffers); 1047 DCHECK_LE(pending_va_bufs_.size(), kMaxVABuffers);
1007 DCHECK_LE(pending_slice_bufs_.size(), kMaxVABuffers); 1048 DCHECK_LE(pending_slice_bufs_.size(), kMaxVABuffers);
1008 1049
1009 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); 1050 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size();
1010 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); 1051 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size();
1011 1052
1012 // Find the surface associated with the picture to be decoded. 1053 // Find the surface associated with the picture to be decoded.
1013 DCHECK(pending_slice_bufs_.size()); 1054 DCHECK(pending_slice_bufs_.size());
1014 DecodeSurface* dec_surface = 1055 DecodeSurface* dec_surface =
1015 poc_to_decode_surfaces_[curr_pic_->pic_order_cnt]; 1056 poc_to_decode_surfaces_[curr_pic_->pic_order_cnt];
1016 DVLOG(4) << "Decoding POC " << curr_pic_->pic_order_cnt 1057 DVLOG(4) << "Decoding POC " << curr_pic_->pic_order_cnt
1017 << " into surface " << dec_surface->va_surface_id(); 1058 << " into surface " << dec_surface->va_surface_id();
1018 1059
1019 // Get ready to decode into surface. 1060 // Get ready to decode into surface.
1020 VAStatus va_res = VAAPI_BeginPicture(va_display_, va_context_id_, 1061 VAStatus va_res = VAAPI_BeginPicture(va_display_, va_context_id_,
1021 dec_surface->va_surface_id()); 1062 dec_surface->va_surface_id());
1022 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); 1063 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false);
1023 1064
1024 // Put buffer IDs for pending parameter buffers into buffers[]. 1065 // Put buffer IDs for pending parameter buffers into va_buffers[].
1025 VABufferID buffers[kMaxVABuffers]; 1066 VABufferID va_buffers[kMaxVABuffers];
1026 size_t num_buffers = pending_va_bufs_.size(); 1067 size_t num_va_buffers = pending_va_bufs_.size();
1027 for (size_t i = 0; i < num_buffers && i < kMaxVABuffers; ++i) { 1068 for (size_t i = 0; i < num_va_buffers && i < kMaxVABuffers; ++i) {
1028 buffers[i] = pending_va_bufs_.front(); 1069 va_buffers[i] = pending_va_bufs_.front();
1029 pending_va_bufs_.pop(); 1070 pending_va_bufs_.pop();
1030 } 1071 }
1031 1072
1032 // And send them to the HW decoder. 1073 // And send them to the HW decoder.
1033 va_res = VAAPI_RenderPicture(va_display_, va_context_id_, buffers, 1074 va_res = VAAPI_RenderPicture(va_display_, va_context_id_, va_buffers,
1034 num_buffers); 1075 num_va_buffers);
1035 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false); 1076 if (va_res != VA_STATUS_SUCCESS) {
1036 1077 DestroyBuffers(va_buffers, num_va_buffers);
1037 DVLOG(4) << "Committed " << num_buffers << "VA buffers"; 1078 VA_LOG_ERROR(va_res, "vaRenderPicture for va_bufs failed");
1038 1079 return false;
1039 for (size_t i = 0; i < num_buffers; ++i) {
1040 va_res = VAAPI_DestroyBuffer(va_display_, buffers[i]);
1041 VA_SUCCESS_OR_RETURN(va_res, "vaDestroyBuffer for va_bufs failed", false);
1042 } 1080 }
1043 1081
1044 // Put buffer IDs for pending slice data buffers into buffers[]. 1082 DVLOG(4) << "Committed " << num_va_buffers << "VA buffers";
1045 num_buffers = pending_slice_bufs_.size(); 1083
1046 for (size_t i = 0; i < num_buffers && i < kMaxVABuffers; ++i) { 1084 // Put buffer IDs for pending slice data buffers into slice_buffers[].
1047 buffers[i] = pending_slice_bufs_.front(); 1085 VABufferID slice_buffers[kMaxVABuffers];
1086 size_t num_slice_buffers = pending_slice_bufs_.size();
1087 for (size_t i = 0; i < num_slice_buffers && i < kMaxVABuffers; ++i) {
1088 slice_buffers[i] = pending_slice_bufs_.front();
1048 pending_slice_bufs_.pop(); 1089 pending_slice_bufs_.pop();
1049 } 1090 }
1050 1091
1051 // And send them to the Hw decoder. 1092 // And send them to the Hw decoder.
1052 va_res = VAAPI_RenderPicture(va_display_, va_context_id_, buffers, 1093 va_res = VAAPI_RenderPicture(va_display_, va_context_id_, slice_buffers,
1053 num_buffers); 1094 num_slice_buffers);
1054 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false); 1095 if (va_res != VA_STATUS_SUCCESS) {
1096 DestroyBuffers(va_buffers, num_va_buffers);
1097 DestroyBuffers(slice_buffers, num_slice_buffers);
1098 VA_LOG_ERROR(va_res, "vaRenderPicture for slices failed");
1099 return false;
1100 }
1055 1101
1056 DVLOG(4) << "Committed " << num_buffers << "slice buffers"; 1102 DVLOG(4) << "Committed " << num_slice_buffers << "slice buffers";
1057
1058 for (size_t i = 0; i < num_buffers; ++i) {
1059 va_res = VAAPI_DestroyBuffer(va_display_, buffers[i]);
1060 VA_SUCCESS_OR_RETURN(va_res, "vaDestroyBuffer for slices failed", false);
1061 }
1062 1103
1063 // Instruct HW decoder to start processing committed buffers (decode this 1104 // Instruct HW decoder to start processing committed buffers (decode this
1064 // picture). This does not block until the end of decode. 1105 // picture). This does not block until the end of decode.
1065 va_res = VAAPI_EndPicture(va_display_, va_context_id_); 1106 va_res = VAAPI_EndPicture(va_display_, va_context_id_);
1066 VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false); 1107 VA_LOG_ON_ERROR(va_res, "vaEndPicture failed");
1108
1109 // Now that EndPicture has passed we can destroy our buffers.
1110 DestroyBuffers(va_buffers, num_va_buffers);
1111 DestroyBuffers(slice_buffers, num_slice_buffers);
1067 1112
1068 // Used to notify clients that we had sufficient data to start decoding 1113 // Used to notify clients that we had sufficient data to start decoding
1069 // a new frame. 1114 // a new frame.
1070 frame_ready_at_hw_ = true; 1115 frame_ready_at_hw_ = true;
1071 return true; 1116 return true;
1072 } 1117 }
1073 1118
1074 1119
1075 bool VaapiH264Decoder::InitCurrPicture(H264SliceHeader* slice_hdr) { 1120 bool VaapiH264Decoder::InitCurrPicture(H264SliceHeader* slice_hdr) {
1076 DCHECK(curr_pic_.get()); 1121 DCHECK(curr_pic_.get());
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after
2092 } 2137 }
2093 } 2138 }
2094 } 2139 }
2095 2140
2096 // static 2141 // static
2097 size_t VaapiH264Decoder::GetRequiredNumOfPictures() { 2142 size_t VaapiH264Decoder::GetRequiredNumOfPictures() {
2098 return kNumReqPictures; 2143 return kNumReqPictures;
2099 } 2144 }
2100 2145
2101 } // namespace content 2146 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/vaapi_h264_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698