• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (C) 2022 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #include <cinttypes>
19 #include <cstdint>
20 #include <memory>
21 
22 #include "perfetto/base/logging.h"
23 #include "perfetto/ext/base/string_utils.h"
24 #include "perfetto/protozero/field.h"
25 #include "src/trace_processor/importers/common/args_tracker.h"
26 #include "src/trace_processor/importers/common/slice_tracker.h"
27 #include "src/trace_processor/importers/common/track_compressor.h"
28 #include "src/trace_processor/importers/common/track_tracker.h"
29 #include "src/trace_processor/importers/common/tracks.h"
30 #include "src/trace_processor/importers/ftrace/virtio_video_tracker.h"
31 #include "src/trace_processor/storage/trace_storage.h"
32 #include "src/trace_processor/types/variadic.h"
33 
34 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
35 #include "protos/perfetto/trace/ftrace/virtio_video.pbzero.h"
36 
37 namespace perfetto::trace_processor {
38 
39 namespace {
40 using protos::pbzero::FtraceEvent;
41 using protos::pbzero::VirtioVideoCmdDoneFtraceEvent;
42 using protos::pbzero::VirtioVideoCmdFtraceEvent;
43 using protos::pbzero::VirtioVideoResourceQueueDoneFtraceEvent;
44 using protos::pbzero::VirtioVideoResourceQueueFtraceEvent;
45 using protozero::ConstBytes;
46 
47 /* VIRTIO_VIDEO_QUEUE_TYPE_INPUT */
48 constexpr uint64_t kVirtioVideoQueueTypeInput = 0x100;
49 
50 /* VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT */
51 constexpr uint64_t kVirtioVideoQueueTypeOutput = 0x101;
52 
53 constexpr int64_t kVirtioVideoCmdDuration = 100000;
54 
NameForQueueType(uint32_t queue_type)55 const char* NameForQueueType(uint32_t queue_type) {
56   switch (queue_type) {
57     case kVirtioVideoQueueTypeInput:
58       return "INPUT";
59     case kVirtioVideoQueueTypeOutput:
60       return "OUTPUT";
61     default:
62       return "Unknown";
63   }
64   PERFETTO_FATAL("For GCC");
65 }
66 
67 constexpr auto kQueueEventBlueprint = TrackCompressor::SliceBlueprint(
68     "virtio_video_queue_event",
69     tracks::Dimensions(tracks::UintDimensionBlueprint("virtio_stream_id"),
70                        tracks::UintDimensionBlueprint("virtio_queue_type")),
__anonafaa8efd0202(uint32_t stream_id, uint32_t queue_type) 71     tracks::FnNameBlueprint([](uint32_t stream_id, uint32_t queue_type) {
72       return base::StackString<255>("virtio_video stream #%" PRIu32 " %s",
73                                     stream_id, NameForQueueType(queue_type));
74     }));
75 
76 constexpr auto kCommandBlueprint = TrackCompressor::SliceBlueprint(
77     "virtio_video_command",
78     tracks::Dimensions(tracks::UintDimensionBlueprint("virtio_stream_id"),
79                        tracks::UintDimensionBlueprint("is_response")),
__anonafaa8efd0302(uint32_t stream_id, uint32_t is_response) 80     tracks::FnNameBlueprint([](uint32_t stream_id, uint32_t is_response) {
81       const char* suffix = is_response ? "Responses" : "Requests";
82       return base::StackString<64>("virtio_video stream #%u %s", stream_id,
83                                    suffix);
84     }));
85 
86 }  // namespace
87 
VirtioVideoTracker(TraceProcessorContext * context)88 VirtioVideoTracker::VirtioVideoTracker(TraceProcessorContext* context)
89     : context_(context),
90       unknown_id_(context->storage->InternString("Unknown")),
91       input_queue_id_(context->storage->InternString("INPUT")),
92       output_queue_id_(context->storage->InternString("OUTPUT")),
93       fields_string_ids_(*context->storage) {
94   TraceStorage& storage = *context_->storage;
95 
96   command_names_.Insert(0x100, storage.InternString("QUERY_CAPABILITY"));
97   command_names_.Insert(0x101, storage.InternString("STREAM_CREATE"));
98   command_names_.Insert(0x102, storage.InternString("STREAM_DESTROY"));
99   command_names_.Insert(0x103, storage.InternString("STREAM_DRAIN"));
100   command_names_.Insert(0x104, storage.InternString("RESOURCE_CREATE"));
101   command_names_.Insert(0x105, storage.InternString("RESOURCE_QUEUE"));
102   command_names_.Insert(0x106, storage.InternString("RESOURCE_DESTROY_ALL"));
103   command_names_.Insert(0x107, storage.InternString("QUEUE_CLEAR"));
104   command_names_.Insert(0x108, storage.InternString("GET_PARAMS"));
105   command_names_.Insert(0x109, storage.InternString("SET_PARAMS"));
106   command_names_.Insert(0x10a, storage.InternString("QUERY_CONTROL"));
107   command_names_.Insert(0x10b, storage.InternString("GET_CONTROL"));
108   command_names_.Insert(0x10c, storage.InternString("SET_CONTROL"));
109   command_names_.Insert(0x10d, storage.InternString("GET_PARAMS_EXT"));
110   command_names_.Insert(0x10e, storage.InternString("SET_PARAMS_EXT"));
111 }
112 
113 VirtioVideoTracker::~VirtioVideoTracker() = default;
114 
ParseVirtioVideoEvent(uint64_t fld_id,int64_t timestamp,const ConstBytes & blob)115 void VirtioVideoTracker::ParseVirtioVideoEvent(uint64_t fld_id,
116                                                int64_t timestamp,
117                                                const ConstBytes& blob) {
118   switch (fld_id) {
119     case FtraceEvent::kVirtioVideoResourceQueueFieldNumber: {
120       VirtioVideoResourceQueueFtraceEvent::Decoder pb_evt(blob);
121 
122       base::StackString<64> name("Resource #%d", pb_evt.resource_id());
123       StringId name_id = context_->storage->InternString(name.string_view());
124 
125       TrackId begin_id = context_->track_compressor->InternBegin(
126           kQueueEventBlueprint,
127           tracks::Dimensions(pb_evt.stream_id(), pb_evt.queue_type()),
128           static_cast<int64_t>(pb_evt.resource_id()));
129       context_->slice_tracker->Begin(timestamp, begin_id, kNullStringId,
130                                      name_id);
131       break;
132     }
133     case FtraceEvent::kVirtioVideoResourceQueueDoneFieldNumber: {
134       VirtioVideoResourceQueueDoneFtraceEvent::Decoder pb_evt(blob);
135 
136       TrackId end_id = context_->track_compressor->InternEnd(
137           kQueueEventBlueprint,
138           tracks::Dimensions(pb_evt.stream_id(), pb_evt.queue_type()),
139           static_cast<int64_t>(pb_evt.resource_id()));
140       context_->slice_tracker->End(
141           timestamp, end_id, {}, {},
142           [this, &pb_evt](ArgsTracker::BoundInserter* args) {
143             this->AddCommandSliceArgs(&pb_evt, args);
144           });
145       break;
146     }
147     case FtraceEvent::kVirtioVideoCmdFieldNumber: {
148       VirtioVideoCmdFtraceEvent::Decoder pb_evt(blob);
149       AddCommandSlice(timestamp, pb_evt.stream_id(), pb_evt.type(), false);
150       break;
151     }
152     case FtraceEvent::kVirtioVideoCmdDoneFieldNumber: {
153       VirtioVideoCmdDoneFtraceEvent::Decoder pb_evt(blob);
154       AddCommandSlice(timestamp, pb_evt.stream_id(), pb_evt.type(), true);
155       break;
156     }
157   }
158 }
159 
FieldsStringIds(TraceStorage & storage)160 VirtioVideoTracker::FieldsStringIds::FieldsStringIds(TraceStorage& storage)
161     : stream_id(storage.InternString("stream_id")),
162       resource_id(storage.InternString("resource_id")),
163       queue_type(storage.InternString("queue_type")),
164       data_size0(storage.InternString("data_size0")),
165       data_size1(storage.InternString("data_size1")),
166       data_size2(storage.InternString("data_size2")),
167       data_size3(storage.InternString("data_size3")),
168       timestamp(storage.InternString("timestamp")) {}
169 
AddCommandSlice(int64_t timestamp,uint32_t stream_id,uint64_t type,bool response)170 void VirtioVideoTracker::AddCommandSlice(int64_t timestamp,
171                                          uint32_t stream_id,
172                                          uint64_t type,
173                                          bool response) {
174   const StringId* cmd_name_id = command_names_.Find(type);
175   if (!cmd_name_id) {
176     cmd_name_id = &unknown_id_;
177   }
178 
179   TrackId track_id = context_->track_compressor->InternScoped(
180       kCommandBlueprint, tracks::Dimensions(stream_id, response), timestamp,
181       kVirtioVideoCmdDuration);
182   context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId,
183                                   *cmd_name_id, kVirtioVideoCmdDuration);
184 }
185 
AddCommandSliceArgs(protos::pbzero::VirtioVideoResourceQueueDoneFtraceEvent::Decoder * pb_evt,ArgsTracker::BoundInserter * args)186 void VirtioVideoTracker::AddCommandSliceArgs(
187     protos::pbzero::VirtioVideoResourceQueueDoneFtraceEvent::Decoder* pb_evt,
188     ArgsTracker::BoundInserter* args) {
189   StringId queue_type_id;
190   switch (pb_evt->queue_type()) {
191     case kVirtioVideoQueueTypeInput: {
192       queue_type_id = input_queue_id_;
193       break;
194     }
195     case kVirtioVideoQueueTypeOutput: {
196       queue_type_id = output_queue_id_;
197       break;
198     }
199     default: {
200       queue_type_id = unknown_id_;
201       break;
202     }
203   }
204 
205   args->AddArg(fields_string_ids_.stream_id,
206                Variadic::Integer(pb_evt->stream_id()));
207   args->AddArg(fields_string_ids_.resource_id,
208                Variadic::Integer(pb_evt->resource_id()));
209   args->AddArg(fields_string_ids_.queue_type, Variadic::String(queue_type_id));
210   args->AddArg(fields_string_ids_.data_size0,
211                Variadic::Integer(pb_evt->data_size0()));
212   args->AddArg(fields_string_ids_.data_size1,
213                Variadic::Integer(pb_evt->data_size1()));
214   args->AddArg(fields_string_ids_.data_size2,
215                Variadic::Integer(pb_evt->data_size2()));
216   args->AddArg(fields_string_ids_.data_size3,
217                Variadic::Integer(pb_evt->data_size3()));
218   args->AddArg(fields_string_ids_.timestamp,
219                Variadic::UnsignedInteger(pb_evt->timestamp()));
220 }
221 
222 }  // namespace perfetto::trace_processor
223