1 // Copyright 2018 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 "media/gpu/vp8_reference_frame_vector.h"
6 
7 #include "media/gpu/vp8_picture.h"
8 
9 namespace media {
10 
Vp8ReferenceFrameVector()11 Vp8ReferenceFrameVector::Vp8ReferenceFrameVector() {
12   // TODO(posciak): Remove this once VP8Decoder is created on the same thread
13   // as its methods are called on.
14   DETACH_FROM_SEQUENCE(sequence_checker_);
15 }
16 
~Vp8ReferenceFrameVector()17 Vp8ReferenceFrameVector::~Vp8ReferenceFrameVector() {
18   // TODO(posciak): Add this once VP8Decoder is created on the same thread
19   // as its methods are called on.
20   // DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
21 }
22 
23 // Based on update_reference_frames() in libvpx: vp8/encoder/onyx_if.c
Refresh(scoped_refptr<VP8Picture> pic)24 void Vp8ReferenceFrameVector::Refresh(scoped_refptr<VP8Picture> pic) {
25   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
26   DCHECK(pic);
27 
28   bool keyframe = pic->frame_hdr->IsKeyframe();
29   const auto& frame_hdr = pic->frame_hdr;
30 
31   if (keyframe) {
32     reference_frames_[Vp8RefType::VP8_FRAME_LAST] = pic;
33     reference_frames_[Vp8RefType::VP8_FRAME_GOLDEN] = pic;
34     reference_frames_[Vp8RefType::VP8_FRAME_ALTREF] = pic;
35     return;
36   }
37 
38   if (frame_hdr->refresh_alternate_frame) {
39     reference_frames_[Vp8RefType::VP8_FRAME_ALTREF] = pic;
40   } else {
41     switch (frame_hdr->copy_buffer_to_alternate) {
42       case Vp8FrameHeader::COPY_LAST_TO_ALT:
43         DCHECK(reference_frames_[Vp8RefType::VP8_FRAME_LAST]);
44         reference_frames_[Vp8RefType::VP8_FRAME_ALTREF] =
45             reference_frames_[Vp8RefType::VP8_FRAME_LAST];
46         break;
47 
48       case Vp8FrameHeader::COPY_GOLDEN_TO_ALT:
49         DCHECK(reference_frames_[Vp8RefType::VP8_FRAME_GOLDEN]);
50         reference_frames_[Vp8RefType::VP8_FRAME_ALTREF] =
51             reference_frames_[Vp8RefType::VP8_FRAME_GOLDEN];
52         break;
53 
54       case Vp8FrameHeader::NO_ALT_REFRESH:
55         DCHECK(reference_frames_[Vp8RefType::VP8_FRAME_ALTREF]);
56         break;
57     }
58   }
59 
60   if (frame_hdr->refresh_golden_frame) {
61     reference_frames_[Vp8RefType::VP8_FRAME_GOLDEN] = pic;
62   } else {
63     switch (frame_hdr->copy_buffer_to_golden) {
64       case Vp8FrameHeader::COPY_LAST_TO_GOLDEN:
65         DCHECK(reference_frames_[Vp8RefType::VP8_FRAME_LAST]);
66         reference_frames_[Vp8RefType::VP8_FRAME_GOLDEN] =
67             reference_frames_[Vp8RefType::VP8_FRAME_LAST];
68         break;
69 
70       case Vp8FrameHeader::COPY_ALT_TO_GOLDEN:
71         DCHECK(reference_frames_[Vp8RefType::VP8_FRAME_ALTREF]);
72         reference_frames_[Vp8RefType::VP8_FRAME_GOLDEN] =
73             reference_frames_[Vp8RefType::VP8_FRAME_ALTREF];
74         break;
75 
76       case Vp8FrameHeader::NO_GOLDEN_REFRESH:
77         DCHECK(reference_frames_[Vp8RefType::VP8_FRAME_GOLDEN]);
78         break;
79     }
80   }
81 
82   if (frame_hdr->refresh_last)
83     reference_frames_[Vp8RefType::VP8_FRAME_LAST] = pic;
84   else
85     DCHECK(reference_frames_[Vp8RefType::VP8_FRAME_LAST]);
86 }
87 
Clear()88 void Vp8ReferenceFrameVector::Clear() {
89   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
90 
91   for (auto& f : reference_frames_)
92     f = nullptr;
93 }
94 
GetFrame(Vp8RefType type) const95 scoped_refptr<VP8Picture> Vp8ReferenceFrameVector::GetFrame(
96     Vp8RefType type) const {
97   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
98 
99   return reference_frames_[type];
100 }
101 
102 }  // namespace media
103