• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "host-common/address_space_host_media.h"
16 #include "host-common/vm_operations.h"
17 #include "base/AlignedBuf.h"
18 
19 #define AS_DEVICE_DEBUG 0
20 
21 #if AS_DEVICE_DEBUG
22 #define AS_DEVICE_DPRINT(fmt,...) fprintf(stderr, "%s:%d " fmt "\n", __func__, __LINE__, ##__VA_ARGS__);
23 #else
24 #define AS_DEVICE_DPRINT(fmt,...)
25 #endif
26 
27 namespace android {
28 namespace emulation {
29 
30 enum class DecoderType : uint8_t {
31     Vpx = 0,
32     H264 = 1,
33 };
34 
AddressSpaceHostMediaContext(uint64_t phys_addr,const address_space_device_control_ops * ops,bool fromSnapshot)35 AddressSpaceHostMediaContext::AddressSpaceHostMediaContext(uint64_t phys_addr, const address_space_device_control_ops* ops,
36         bool fromSnapshot) : mControlOps(ops) {
37     // The memory is allocated in the snapshot load if called from a snapshot load().
38     if (!fromSnapshot) {
39         mGuestAddr = phys_addr;
40         allocatePages(phys_addr, kNumPages);
41     }
42 }
43 
~AddressSpaceHostMediaContext()44 AddressSpaceHostMediaContext::~AddressSpaceHostMediaContext() {
45     deallocatePages(mGuestAddr, kNumPages);
46 }
47 
perform(AddressSpaceDevicePingInfo * info)48 void AddressSpaceHostMediaContext::perform(AddressSpaceDevicePingInfo *info) {
49     handleMediaRequest(info);
50 }
51 
getDeviceType() const52 AddressSpaceDeviceType AddressSpaceHostMediaContext::getDeviceType() const {
53     return AddressSpaceDeviceType::Media;
54 }
55 
save(base::Stream * stream) const56 void AddressSpaceHostMediaContext::save(base::Stream* stream) const {
57     AS_DEVICE_DPRINT("Saving Host Media snapshot");
58     stream->putBe64(mGuestAddr);
59     int numActiveDecoders = 0;
60     if (mVpxDecoder != nullptr) {
61         ++ numActiveDecoders;
62     }
63     if (mH264Decoder != nullptr) {
64         ++ numActiveDecoders;
65     }
66 
67     stream->putBe32(numActiveDecoders);
68     if (mVpxDecoder != nullptr) {
69         AS_DEVICE_DPRINT("Saving VpxDecoder snapshot");
70         stream->putBe32((uint32_t)DecoderType::Vpx);
71         mVpxDecoder->save(stream);
72     }
73     if (mH264Decoder != nullptr) {
74         AS_DEVICE_DPRINT("Saving H264Decoder snapshot");
75         stream->putBe32((uint32_t)DecoderType::H264);
76         mH264Decoder->save(stream);
77     }
78 }
79 
load(base::Stream * stream)80 bool AddressSpaceHostMediaContext::load(base::Stream* stream) {
81     deallocatePages(mGuestAddr, kNumPages);
82     AS_DEVICE_DPRINT("Loading Host Media snapshot");
83     mGuestAddr = stream->getBe64();
84     allocatePages(mGuestAddr, kNumPages);
85 
86     int numActiveDecoders = stream->getBe32();
87     for (int i = 0; i < numActiveDecoders; ++i) {
88         stream->getBe32();
89         // TODO: Add support for virtio-gpu-as-video-decode
90         // switch (t) {
91         // case DecoderType::Vpx:
92         //     AS_DEVICE_DPRINT("Loading VpxDecoder snapshot");
93         //     mVpxDecoder.reset(new MediaVpxDecoder);
94         //     mVpxDecoder->load(stream);
95         //     break;
96         // case DecoderType::H264:
97         //     AS_DEVICE_DPRINT("Loading H264Decoder snapshot");
98         //     mH264Decoder.reset(MediaH264Decoder::create());
99         //     mH264Decoder->load(stream);
100         //     break;
101         // default:
102         //     break;
103         // }
104     }
105     return true;
106 }
107 
allocatePages(uint64_t phys_addr,int num_pages)108 void AddressSpaceHostMediaContext::allocatePages(uint64_t phys_addr, int num_pages) {
109     mHostBuffer = android::aligned_buf_alloc(kAlignment, num_pages * 4096);
110     mControlOps->add_memory_mapping(
111         phys_addr, mHostBuffer, num_pages * 4096);
112     AS_DEVICE_DPRINT("Allocating host memory for media context: guest_addr 0x%" PRIx64 ", 0x%" PRIx64,
113                      (uint64_t)phys_addr, (uint64_t)mHostBuffer);
114 }
115 
deallocatePages(uint64_t phys_addr,int num_pages)116 void AddressSpaceHostMediaContext::deallocatePages(uint64_t phys_addr,
117                                                    int num_pages) {
118     if (mHostBuffer == nullptr) {
119         return;
120     }
121 
122     mControlOps->remove_memory_mapping(phys_addr, mHostBuffer,
123                                        num_pages * 4096);
124     android::aligned_buf_free(mHostBuffer);
125     mHostBuffer = nullptr;
126     AS_DEVICE_DPRINT(
127             "De-Allocating host memory for media context: guest_addr 0x%" PRIx64
128             ", 0x%" PRIx64,
129             (uint64_t)phys_addr, (uint64_t)mHostBuffer);
130 }
131 
132 // static
getMediaCodecType(uint64_t metadata)133 MediaCodecType AddressSpaceHostMediaContext::getMediaCodecType(uint64_t metadata) {
134     // Metadata has the following structure:
135     // - Upper 8 bits has the codec type (MediaCodecType)
136     // - Lower 56 bits has metadata specifically for that codec
137     //
138     // We need to hand the data off to the right codec depending on which
139     // codec type we get.
140     uint8_t ret = (uint8_t)(metadata >> (64 - 8));
141     return ret > static_cast<uint8_t>(MediaCodecType::Max) ?
142             MediaCodecType::Max : (MediaCodecType)ret;
143 }
144 
145 // static
getMediaOperation(uint64_t metadata)146 MediaOperation AddressSpaceHostMediaContext::getMediaOperation(uint64_t metadata) {
147     // Metadata has the following structure:
148     // - Upper 8 bits has the codec type (MediaCodecType)
149     // - Lower 56 bits has metadata specifically for that codec
150     //
151     // We need to hand the data off to the right codec depending on which
152     // codec type we get.
153     uint8_t ret = (uint8_t)(metadata & 0xFF);
154     return ret > static_cast<uint8_t>(MediaOperation::Max) ?
155             MediaOperation::Max : (MediaOperation)ret;
156 }
157 
getAddrSlot(uint64_t metadata)158 static uint64_t getAddrSlot(uint64_t metadata) {
159     uint64_t ret = metadata << 8;  // get rid of typecode
160     ret = ret >> 16;               // get rid of opcode
161     return ret;
162 }
163 
handleMediaRequest(AddressSpaceDevicePingInfo * info)164 void AddressSpaceHostMediaContext::handleMediaRequest(AddressSpaceDevicePingInfo *info) {
165     auto codecType = getMediaCodecType(info->metadata);
166     auto op = getMediaOperation(info->metadata);
167     auto slot = getAddrSlot(info->metadata);
168     uint64_t offSetAddr = slot << 20;
169 
170     AS_DEVICE_DPRINT("Got media request (type=%u, op=%u, slot=%lld)",
171                      static_cast<uint8_t>(codecType), static_cast<uint8_t>(op),
172                      (long long)(getAddrSlot(info->metadata)));
173 
174     switch (codecType) {
175         case MediaCodecType::VP8Codec:
176         case MediaCodecType::VP9Codec:
177             // if (!mVpxDecoder) {
178             //     mVpxDecoder.reset(new MediaVpxDecoder);
179             // }
180             mVpxDecoder->handlePing(
181                     codecType, op,
182                     (uint8_t*)(mControlOps->get_host_ptr(info->phys_addr)) +
183                             offSetAddr);
184             break;
185         case MediaCodecType::H264Codec:
186             // if (!mH264Decoder) {
187             //     mH264Decoder.reset(MediaH264Decoder::create());
188             // }
189             mH264Decoder->handlePing(
190                     codecType, op,
191                     (uint8_t*)(mControlOps->get_host_ptr(info->phys_addr)) +
192                             offSetAddr);
193             break;
194         default:
195             AS_DEVICE_DPRINT("codec type %d not implemented", (int)codecType);
196             break;
197     }
198 }
199 
200 }  // namespace emulation
201 }  // namespace android
202