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

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

Issue 1318863003: Add accelerated VP9 decode infrastructure and an implementation for VA-API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 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 2015 The Chromium Authors. All rights reserved.
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 "base/logging.h"
6 #include "content/common/gpu/media/vp9_decoder.h"
7 #include "media/base/limits.h"
8
9 namespace content {
10
11 VP9Decoder::VP9Accelerator::VP9Accelerator() {}
12
13 VP9Decoder::VP9Accelerator::~VP9Accelerator() {}
14
15 VP9Decoder::VP9Decoder(VP9Accelerator* accelerator)
16 : state_(kNeedStreamMetadata), accelerator_(accelerator) {
17 DCHECK(accelerator_);
18 ref_frames_.resize(media::kVp9NumRefFrames);
19 }
20
21 VP9Decoder::~VP9Decoder() {}
22
23 void VP9Decoder::SetStream(const uint8_t* ptr, size_t size) {
24 DCHECK(ptr);
25 DCHECK(size);
26
27 DVLOG(4) << "New input stream at: " << (void*)ptr << " size: " << size;
28 parser_.SetStream(ptr, size);
29 }
30
31 bool VP9Decoder::Flush() {
32 DVLOG(2) << "Decoder flush";
33 Reset();
34 return true;
35 }
36
37 void VP9Decoder::Reset() {
38 curr_frame_hdr_ = nullptr;
39 for (auto& ref_frame : ref_frames_)
40 ref_frame = nullptr;
41
42 if (state_ == kDecoding)
43 state_ = kAfterReset;
44 }
45
46 VP9Decoder::DecodeResult VP9Decoder::Decode() {
47 while (1) {
48 // Read a new frame header if one is not awaiting decoding already.
49 if (!curr_frame_hdr_) {
50 scoped_ptr<media::Vp9FrameHeader> hdr(new media::Vp9FrameHeader());
51 media::Vp9Parser::Result res = parser_.ParseNextFrame(hdr.get());
52 switch (res) {
53 case media::Vp9Parser::kOk:
54 curr_frame_hdr_.reset(hdr.release());
55 break;
56
57 case media::Vp9Parser::kEOStream:
58 return kRanOutOfStreamData;
59
60 case media::Vp9Parser::kInvalidStream:
61 DVLOG(1) << "Error parsing stream";
62 return kDecodeError;
kcwu 2015/09/02 10:09:45 Should we update |state_| as well for all errors?
Pawel Osciak 2015/09/08 06:43:48 Yes, was missing some cleanup.
63 }
64 }
65
66 // If the frame header instructs us to additionally display any of the
67 // previously-decoded frames, do so now.
68 if (curr_frame_hdr_->show_existing_frame) {
69 size_t frame_to_show = curr_frame_hdr_->frame_to_show;
70 if (frame_to_show >= ref_frames_.size() || !ref_frames_[frame_to_show]) {
71 DVLOG(1) << "Request to show an invalid frame";
72 return kDecodeError;
73 }
74
75 if (!accelerator_->OutputPicture(ref_frames_[frame_to_show]))
76 return kDecodeError;
77 }
kcwu 2015/09/02 10:09:45 continue; here?
Pawel Osciak 2015/09/08 06:43:48 I treat this as a critical error.
78
79 if (curr_frame_hdr_->IsKeyframe()) {
80 gfx::Size new_pic_size(curr_frame_hdr_->width, curr_frame_hdr_->height);
81 if (new_pic_size.IsEmpty())
kcwu 2015/09/02 10:09:44 How about DCHECK? IIUC, the parser never return fr
Pawel Osciak 2015/09/08 06:43:48 Misread the code, true, this is not needed.
82 return kDecodeError;
83
84 if (new_pic_size != pic_size_) {
85 DVLOG(1) << "New resolution: " << new_pic_size.ToString();
86 pic_size_ = new_pic_size;
87
88 for (auto& ref_frame : ref_frames_)
89 ref_frame = nullptr;
90
91 return kAllocateNewSurfaces;
92 }
93
94 state_ = kDecoding;
95 } else {
kcwu 2015/09/02 10:09:45 Theoretically the parser may return frames with re
Pawel Osciak 2015/09/08 06:43:48 Good point, this is new in VP9.
96 if (state_ != kDecoding) {
97 // Need a resume point.
98 curr_frame_hdr_.reset();
99 continue;
100 }
101 }
102
103 scoped_refptr<VP9Picture> pic = accelerator_->CreateVP9Picture();
104 if (!pic)
105 return kRanOutOfSurfaces;
106
107 pic->frame_hdr.reset(curr_frame_hdr_.release());
108
109 if (!DecodeAndOutputPicture(pic))
110 return kDecodeError;
111 }
112 }
113
114 void VP9Decoder::RefreshReferenceFrames(const scoped_refptr<VP9Picture>& pic) {
115 for (size_t i = 0; i < media::kVp9NumRefFrames; ++i) {
116 if (pic->frame_hdr->IsKeyframe() || pic->frame_hdr->RefreshFlag(i))
kcwu 2015/09/02 10:09:45 RefreshFlag should be enough. How about DCHECK_IMP
Pawel Osciak 2015/09/08 06:43:48 Correct, I had moved changing refresh flags to ano
117 ref_frames_[i] = pic;
118 }
119 }
120
121 bool VP9Decoder::DecodeAndOutputPicture(scoped_refptr<VP9Picture> pic) {
122 DCHECK(!pic_size_.IsEmpty());
123
124 media::Vp9FrameHeader* frame_hdr = pic->frame_hdr.get();
125 DCHECK(frame_hdr);
126
127 if (frame_hdr->width == 0 || frame_hdr->height == 0) {
kcwu 2015/09/02 10:09:45 DCHECK instead?
Pawel Osciak 2015/09/08 06:43:48 Acknowledged.
128 frame_hdr->width = pic_size_.width();
129 frame_hdr->height = pic_size_.height();
130 }
131
132 if (!accelerator_->SubmitDecode(pic, parser_.GetSegmentation(),
133 parser_.GetLoopFilter(), ref_frames_))
134 return false;
135
136 if (frame_hdr->show_frame) {
137 if (!accelerator_->OutputPicture(pic))
138 return false;
139 }
140
141 RefreshReferenceFrames(pic);
142 return true;
143 }
144
145 gfx::Size VP9Decoder::GetPicSize() const {
146 return pic_size_;
147 }
148
149 size_t VP9Decoder::GetRequiredNumOfPictures() const {
150 const size_t kPicsInPipeline = media::limits::kMaxVideoFrames + 2;
151 return media::kVp9NumRefFrames + kPicsInPipeline;
kcwu 2015/09/02 10:09:44 I don't understand these numbers from variable nam
Pawel Osciak 2015/09/08 06:43:48 We should ideally have the media::limits::kMaxVide
152 }
153
154 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698