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

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

Issue 27498002: Add vaapi_h264_decoder_test. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix destruct order Created 7 years, 2 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
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
Pawel Osciak 2013/10/20 23:53:11 Why is this test not using gtest (even though you
chihchung 2013/10/21 09:33:05 It is supposed to be run as a standalone program,
Pawel Osciak 2013/11/21 06:31:41 But ultimately this is to be used for tests, frame
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stdio.h>
Pawel Osciak 2013/10/20 23:53:11 Headers should be in lexicographical order. But se
chihchung 2013/10/21 09:33:05 Yes, I did that originally, but then presubmit che
Pawel Osciak 2013/11/21 06:31:41 Perhaps if you used <cstdio> instead of <stdio.h>,
chihchung 2013/11/21 12:17:31 It's not needed anymore, so removed.
6 #include <iostream>
7
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/file_util.h"
11 #include "base/logging.h"
12 #include "base/synchronization/lock.h"
13 #include "content/common/gpu/media/vaapi_h264_decoder.h"
14 #include "media/base/video_decoder_config.h"
15
16 namespace content {
17
18 class VaapiH264DecoderLoop {
Pawel Osciak 2013/10/20 23:53:11 Please comment on what the class does.
chihchung 2013/10/21 09:33:05 Done.
19 public:
20 VaapiH264DecoderLoop();
21 ~VaapiH264DecoderLoop();
22
23 // Initialize the decoder. Return true if successful.
24 bool Initialize(base::FilePath input_path, base::FilePath output_path);
25
26 // Run the decode loop. The decoded YUV data is written to the file specified
27 // by output_path in Initialize(). Return true if all decoding is successful.
28 bool Run();
29
30 private:
31 scoped_ptr<VaapiH264Decoder> decoder_;
Pawel Osciak 2013/10/20 23:53:11 Methods should precede member variables.
chihchung 2013/10/21 09:33:05 Done.
32 scoped_ptr<VaapiWrapper> wrapper_;
33 std::string data_; // data read from input_path
34 base::Lock available_surfaces_lock_; // protects available_surfaces_
35 std::vector<VASurfaceID> available_surfaces_;
36
37 // Members need to be freed manually.
Pawel Osciak 2013/10/20 23:53:11 Which members?
chihchung 2013/10/21 09:33:05 Done.
38 Display *x_display_;
39 FILE* output_file_; // output data is written to this file
Pawel Osciak 2013/10/20 23:53:11 Please use file_util::AppendToFile() instead of st
chihchung 2013/10/21 09:33:05 Is there some advantage using that over fwrite? (
Pawel Osciak 2013/11/21 06:31:41 Yes, that was one of the reasons I pointed you to
chihchung 2013/11/21 12:17:31 Good idea. Done.
40 int picture_count_; // number of pictures already outputted
41
42 void ReportToUMA(VaapiH264Decoder::VAVDAH264DecoderFailure error) {}
43
44 // Callback from the decoder when a picture is decoded.
45 void OutputPicture(int32 input_id,
46 const scoped_refptr<VASurface>& va_surface);
47
48 // Free one surface and put it on available_surfaces_ list. This may be called
Pawel Osciak 2013/10/20 23:53:11 Does this really free? It looks like it just recyc
chihchung 2013/10/21 09:33:05 Yes, this just recycles it. Fixed.
49 // from another thread.
Pawel Osciak 2013/10/20 23:53:11 Which thread? What is the threading model of this
chihchung 2013/10/21 09:33:05 I misunderstood the threading model of VaapiH264De
50 void RecycleSurface(VASurfaceID va_surface_id);
Pawel Osciak 2013/10/20 23:53:11 You could use VASurface class and pass to it Recyc
chihchung 2013/10/21 09:33:05 I think I did that in RefillSurfaces(), or I shoul
Pawel Osciak 2013/11/21 06:31:41 Use VASurface class in c/c/gpu/media/va_surface.h,
chihchung 2013/11/21 12:17:31 Sorry I still don't understand. This is the code i
51
52 // Give all surfaces in available_surfaces_ to the decoder.
53 void RefillSurfaces();
54
55 // Free the current set of surfaces and allocate a new set of
56 // surfaces. Returns true when successful.
57 bool AllocateNewSurfaces();
58 };
59
60
61 VaapiH264DecoderLoop::VaapiH264DecoderLoop() : x_display_(NULL),
Pawel Osciak 2013/10/20 23:53:11 New line and 4-space indent on multiline initializ
chihchung 2013/10/21 09:33:05 Done.
62 output_file_(NULL),
63 picture_count_(0) {
64 }
65
66 VaapiH264DecoderLoop::~VaapiH264DecoderLoop() {
67 // We need to destruct decoder and wrapper first because:
68 // (1) The decoder may have references to some surfaces which will be
69 // recycled, and RecycleSurface() uses available_surfaces_lock_.
70 // (2) The wrapper have references to x_display_.
71 decoder_.reset();
72 wrapper_.reset();
73
74 if (x_display_) {
75 XCloseDisplay(x_display_);
76 }
77 if (output_file_) {
78 fclose(output_file_);
79 }
80 }
81
82 bool VaapiH264DecoderLoop::Initialize(base::FilePath input_path,
83 base::FilePath output_path) {
84 x_display_ = XOpenDisplay(NULL);
85 if (!x_display_) {
86 LOG(ERROR) << "Can't open X display";
87 return false;
88 }
89
90 media::VideoCodecProfile profile = media::H264PROFILE_HIGH;
Pawel Osciak 2013/10/20 23:53:11 Shouldn't profile be a parameter of the test, depe
chihchung 2013/10/21 09:33:05 Yes, I just picked a value which looks like a larg
Pawel Osciak 2013/11/21 06:31:41 Right, but did you test the other way around? In C
chihchung 2013/11/21 12:17:31 Grepping VAProfileH264 in libva-intel-driver, ther
91 base::Closure report_error_cb = base::Bind(&VaapiH264DecoderLoop::ReportToUMA,
92 base::Unretained(this),
Pawel Osciak 2013/10/20 23:53:11 Indent.
chihchung 2013/10/21 09:33:05 Done.
93 VaapiH264Decoder::VAAPI_ERROR);
94 wrapper_ = VaapiWrapper::Create(profile, x_display_, report_error_cb);
95 if (!wrapper_.get()) {
96 LOG(ERROR) << "Can't create vaapi wrapper";
97 return false;
98 }
99
100 decoder_.reset(new VaapiH264Decoder(
101 wrapper_.get(),
102 base::Bind(&VaapiH264DecoderLoop::OutputPicture, base::Unretained(this)),
103 base::Bind(&VaapiH264DecoderLoop::ReportToUMA, base::Unretained(this))));
104
105 if (!base::ReadFileToString(input_path, &data_)) {
106 LOG(ERROR)<< "failed to read input data from " << input_path.value() ;
107 return false;
108 }
109
110 decoder_->SetStream((uint8*)(data_.c_str()), data_.size(), 0 /* input_id */);
Pawel Osciak 2013/10/20 23:53:11 No c-style casts, here and everywhere.
chihchung 2013/10/21 09:33:05 Done.
111
112 output_file_ = fopen(output_path.value().c_str(), "w");
113 if (!output_file_) {
114 return false;
115 }
116
117 return true;
118 }
119
120 bool VaapiH264DecoderLoop::Run() {
121 while (1) {
122 switch (decoder_->Decode()) {
123 case VaapiH264Decoder::kDecodeError:
124 LOG(ERROR) << "Decode Error";
125 return false;
126 case VaapiH264Decoder::kAllocateNewSurfaces:
127 VLOG(1) << "Allocate new surfaces";
128 if (!AllocateNewSurfaces()) {
129 LOG(ERROR) << "Failed to allocate new surfaces";
130 return false;
131 }
132 break;
133 case VaapiH264Decoder::kRanOutOfStreamData:
Pawel Osciak 2013/10/20 23:53:11 Brace on this line.
chihchung 2013/10/21 09:33:05 Done.
134 {
135 bool rc = decoder_->Flush();
136 VLOG(1) << "Flush returns " << rc;
137 return rc;
138 }
139 case VaapiH264Decoder::kRanOutOfSurfaces:
140 VLOG(1) << "Ran out of surfaces";
141 RefillSurfaces();
142 break;
143 }
144 }
145 }
146
147 void VaapiH264DecoderLoop::OutputPicture(
148 int32 input_id,
149 const scoped_refptr<VASurface>& va_surface) {
150 VLOG(1) << "OutputPicture: picture " << picture_count_++;
151 void *buffer;
Pawel Osciak 2013/10/20 23:53:11 star goes next to void. Here and everywhere else.
chihchung 2013/10/21 09:33:05 Done.
152 size_t size;
153 if (wrapper_->GetI420FromSurface(va_surface->id(), &buffer, &size)) {
154 if (fwrite((const char *)buffer, size, 1, output_file_) != 1) {
155 LOG(ERROR) << "fwrite failed";
156 }
157 free(buffer);
158 } else {
159 LOG(ERROR) << "Cannot convert surface to I420.";
160 }
161 }
162
163 void VaapiH264DecoderLoop::RecycleSurface(VASurfaceID va_surface_id) {
Pawel Osciak 2013/10/20 23:53:11 As mentioned above, you can use VASurface and pass
chihchung 2013/10/21 09:33:05 I did, or I should do it some other way?
164 base::AutoLock auto_lock(available_surfaces_lock_);
165 available_surfaces_.push_back(va_surface_id);
166 }
167
168 void VaapiH264DecoderLoop::RefillSurfaces() {
169 base::AutoLock auto_lock(available_surfaces_lock_);
170 for (size_t i = 0; i < available_surfaces_.size(); i++) {
171 VASurface::ReleaseCB release_cb = base::Bind(
172 &VaapiH264DecoderLoop::RecycleSurface, base::Unretained(this));
173 scoped_refptr<VASurface> surface(
174 new VASurface(available_surfaces_[i], release_cb));
175 decoder_->ReuseSurface(surface);
176 }
177 available_surfaces_.clear();
178 }
179
180 bool VaapiH264DecoderLoop::AllocateNewSurfaces() {
181 {
182 // TODO: make sure all surfaces are returned
Pawel Osciak 2013/10/20 23:53:11 Todos have to be in this format: TODO(name):
chihchung 2013/10/21 09:33:05 Done.
183 base::AutoLock auto_lock(available_surfaces_lock_);
184 available_surfaces_.clear();
185 }
186
187 wrapper_->DestroySurfaces();
188
189 gfx::Size size = decoder_->GetPicSize();
190 size_t num_surfaces = decoder_->GetRequiredNumOfPictures();
191 return wrapper_->CreateSurfaces(size, num_surfaces, &available_surfaces_);
192 }
193
194 } // namespace content
195
196 int main(int argc, char** argv) {
Pawel Osciak 2013/10/20 23:53:11 Please use gtest.
chihchung 2013/10/21 09:33:05 As explained above, this is not a unit test (altho
197 CommandLine::Init(argc, argv);
198
199 // Needed to enable DVLOG through --vmodule.
200 logging::LoggingSettings settings;
201 settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
202 settings.dcheck_state =
203 logging::ENABLE_DCHECK_FOR_NON_OFFICIAL_RELEASE_BUILDS;
204 CHECK(logging::InitLogging(settings));
205
206 // Process command line.
207 CommandLine* cmd_line = CommandLine::ForCurrentProcess();
208 CHECK(cmd_line);
209 const CommandLine::StringVector& args = cmd_line->GetArgs();
210 if (args.size() != 2) {
211 std::cerr << "Usage: vaapi_h264_decoder_test input_file output_file\n";
212 return EXIT_FAILURE;
213 }
214
215 // We are not in a sandbox, but we still need to do the initialization.
216 content::VaapiWrapper::PreSandboxInitialization();
217
218 base::FilePath input_path(args[0]);
219 base::FilePath output_path(args[1]);
220
221 VLOG(1) << "Input File: " << input_path.value();
222 VLOG(1) << "Output File: " << output_path.value();
223
224 content::VaapiH264DecoderLoop loop;
225 if (!loop.Initialize(input_path, output_path)) {
226 std::cerr << "initialize decoder loop failed";
227 return EXIT_FAILURE;
228 }
229 if (!loop.Run()) {
230 std::cerr << "run decoder loop failed";
231 return EXIT_FAILURE;
232 }
233 return 0;
234 }
OLDNEW
« no previous file with comments | « no previous file | content/common/gpu/media/vaapi_wrapper.h » ('j') | content/common/gpu/media/vaapi_wrapper.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698