xref: /aosp_15_r20/external/perfetto/src/trace_processor/importers/ftrace/virtio_video_tracker.cc (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
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 <cstdint>
19 #include <functional>
20 #include <memory>
21 
22 #include "perfetto/ext/base/hash.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/async_track_set_tracker.h"
27 #include "src/trace_processor/importers/common/slice_tracker.h"
28 #include "src/trace_processor/importers/ftrace/virtio_video_tracker.h"
29 
30 #include "protos/perfetto/trace/ftrace/ftrace_event.pbzero.h"
31 #include "protos/perfetto/trace/ftrace/virtio_video.pbzero.h"
32 #include "src/trace_processor/storage/trace_storage.h"
33 
34 namespace perfetto {
35 namespace trace_processor {
36 
37 namespace {
38 using protos::pbzero::FtraceEvent;
39 using protos::pbzero::VirtioVideoCmdDoneFtraceEvent;
40 using protos::pbzero::VirtioVideoCmdFtraceEvent;
41 using protos::pbzero::VirtioVideoResourceQueueDoneFtraceEvent;
42 using protos::pbzero::VirtioVideoResourceQueueFtraceEvent;
43 using protozero::ConstBytes;
44 using TrackSetId = AsyncTrackSetTracker::TrackSetId;
45 
46 /* VIRTIO_VIDEO_QUEUE_TYPE_INPUT */
47 constexpr uint64_t kVirtioVideoQueueTypeInput = 0x100;
48 
49 /* VIRTIO_VIDEO_QUEUE_TYPE_OUTPUT */
50 constexpr uint64_t kVirtioVideoQueueTypeOutput = 0x101;
51 
52 constexpr int64_t kVirtioVideoCmdDuration = 100000;
53 }  // namespace
54 
VirtioVideoTracker(TraceProcessorContext * context)55 VirtioVideoTracker::VirtioVideoTracker(TraceProcessorContext* context)
56     : context_(context),
57       unknown_id_(context->storage->InternString("Unknown")),
58       input_queue_id_(context->storage->InternString("INPUT")),
59       output_queue_id_(context->storage->InternString("OUTPUT")),
60       fields_string_ids_(*context->storage) {
61   TraceStorage& storage = *context_->storage;
62 
63   command_names_.Insert(0x100, storage.InternString("QUERY_CAPABILITY"));
64   command_names_.Insert(0x101, storage.InternString("STREAM_CREATE"));
65   command_names_.Insert(0x102, storage.InternString("STREAM_DESTROY"));
66   command_names_.Insert(0x103, storage.InternString("STREAM_DRAIN"));
67   command_names_.Insert(0x104, storage.InternString("RESOURCE_CREATE"));
68   command_names_.Insert(0x105, storage.InternString("RESOURCE_QUEUE"));
69   command_names_.Insert(0x106, storage.InternString("RESOURCE_DESTROY_ALL"));
70   command_names_.Insert(0x107, storage.InternString("QUEUE_CLEAR"));
71   command_names_.Insert(0x108, storage.InternString("GET_PARAMS"));
72   command_names_.Insert(0x109, storage.InternString("SET_PARAMS"));
73   command_names_.Insert(0x10a, storage.InternString("QUERY_CONTROL"));
74   command_names_.Insert(0x10b, storage.InternString("GET_CONTROL"));
75   command_names_.Insert(0x10c, storage.InternString("SET_CONTROL"));
76   command_names_.Insert(0x10d, storage.InternString("GET_PARAMS_EXT"));
77   command_names_.Insert(0x10e, storage.InternString("SET_PARAMS_EXT"));
78 }
79 
80 VirtioVideoTracker::~VirtioVideoTracker() = default;
81 
ParseVirtioVideoEvent(uint64_t fld_id,int64_t timestamp,const ConstBytes & blob)82 void VirtioVideoTracker::ParseVirtioVideoEvent(uint64_t fld_id,
83                                                int64_t timestamp,
84                                                const ConstBytes& blob) {
85   switch (fld_id) {
86     case FtraceEvent::kVirtioVideoResourceQueueFieldNumber: {
87       VirtioVideoResourceQueueFtraceEvent::Decoder pb_evt(blob.data, blob.size);
88 
89       uint64_t hash = base::Hasher::Combine(
90           pb_evt.stream_id(), pb_evt.resource_id(), pb_evt.queue_type());
91 
92       base::StackString<64> name("Resource #%" PRIu32, pb_evt.resource_id());
93       StringId name_id = context_->storage->InternString(name.string_view());
94 
95       TrackSetId track_set_id =
96           InternOrCreateBufferTrack(pb_evt.stream_id(), pb_evt.queue_type());
97       TrackId begin_id = context_->async_track_set_tracker->Begin(
98           track_set_id, static_cast<int64_t>(hash));
99       context_->slice_tracker->Begin(timestamp, begin_id, kNullStringId,
100                                      name_id);
101       break;
102     }
103     case FtraceEvent::kVirtioVideoResourceQueueDoneFieldNumber: {
104       VirtioVideoResourceQueueDoneFtraceEvent::Decoder pb_evt(blob.data,
105                                                               blob.size);
106 
107       uint64_t hash = base::Hasher::Combine(
108           pb_evt.stream_id(), pb_evt.resource_id(), pb_evt.queue_type());
109 
110       TrackSetId track_set_id =
111           InternOrCreateBufferTrack(pb_evt.stream_id(), pb_evt.queue_type());
112 
113       TrackId end_id = context_->async_track_set_tracker->End(
114           track_set_id, static_cast<int64_t>(hash));
115       context_->slice_tracker->End(
116           timestamp, end_id, {}, {},
117           [this, &pb_evt](ArgsTracker::BoundInserter* args) {
118             this->AddCommandSliceArgs(&pb_evt, args);
119           });
120       break;
121     }
122     case FtraceEvent::kVirtioVideoCmdFieldNumber: {
123       VirtioVideoCmdFtraceEvent::Decoder pb_evt(blob.data, blob.size);
124       AddCommandSlice(timestamp, pb_evt.stream_id(), pb_evt.type(), false);
125       break;
126     }
127     case FtraceEvent::kVirtioVideoCmdDoneFieldNumber: {
128       VirtioVideoCmdDoneFtraceEvent::Decoder pb_evt(blob.data, blob.size);
129       AddCommandSlice(timestamp, pb_evt.stream_id(), pb_evt.type(), true);
130       break;
131     }
132   }
133 }
134 
FieldsStringIds(TraceStorage & storage)135 VirtioVideoTracker::FieldsStringIds::FieldsStringIds(TraceStorage& storage)
136     : stream_id(storage.InternString("stream_id")),
137       resource_id(storage.InternString("resource_id")),
138       queue_type(storage.InternString("queue_type")),
139       data_size0(storage.InternString("data_size0")),
140       data_size1(storage.InternString("data_size1")),
141       data_size2(storage.InternString("data_size2")),
142       data_size3(storage.InternString("data_size3")),
143       timestamp(storage.InternString("timestamp")) {}
144 
InternOrCreateBufferTrack(int32_t stream_id,uint32_t queue_type)145 TrackSetId VirtioVideoTracker::InternOrCreateBufferTrack(int32_t stream_id,
146                                                          uint32_t queue_type) {
147   const char* queue_name;
148 
149   switch (queue_type) {
150     case kVirtioVideoQueueTypeInput: {
151       queue_name = "INPUT";
152       break;
153     }
154     case kVirtioVideoQueueTypeOutput: {
155       queue_name = "OUTPUT";
156       break;
157     }
158     default: {
159       queue_name = "Unknown";
160       break;
161     }
162   }
163 
164   base::StackString<64> track_name("virtio_video stream #%" PRId32 " %s",
165                                    stream_id, queue_name);
166   StringId track_name_id =
167       context_->storage->InternString(track_name.string_view());
168   return context_->async_track_set_tracker->InternGlobalTrackSet(track_name_id);
169 }
170 
AddCommandSlice(int64_t timestamp,uint32_t stream_id,uint64_t type,bool response)171 void VirtioVideoTracker::AddCommandSlice(int64_t timestamp,
172                                          uint32_t stream_id,
173                                          uint64_t type,
174                                          bool response) {
175   const StringId* cmd_name_id = command_names_.Find(type);
176   if (!cmd_name_id) {
177     cmd_name_id = &unknown_id_;
178   }
179 
180   const char* suffix = response ? "Responses" : "Requests";
181 
182   base::StackString<64> track_name("virtio_video stream #%" PRId32 " %s",
183                                    stream_id, suffix);
184   StringId track_name_id =
185       context_->storage->InternString(track_name.string_view());
186 
187   TrackSetId track_set_id =
188       context_->async_track_set_tracker->InternGlobalTrackSet(track_name_id);
189 
190   TrackId track_id = context_->async_track_set_tracker->Scoped(
191       track_set_id, timestamp, kVirtioVideoCmdDuration);
192 
193   context_->slice_tracker->Scoped(timestamp, track_id, kNullStringId,
194                                   *cmd_name_id, kVirtioVideoCmdDuration);
195 }
196 
AddCommandSliceArgs(protos::pbzero::VirtioVideoResourceQueueDoneFtraceEvent::Decoder * pb_evt,ArgsTracker::BoundInserter * args)197 void VirtioVideoTracker::AddCommandSliceArgs(
198     protos::pbzero::VirtioVideoResourceQueueDoneFtraceEvent::Decoder* pb_evt,
199     ArgsTracker::BoundInserter* args) {
200   StringId queue_type_id;
201   switch (pb_evt->queue_type()) {
202     case kVirtioVideoQueueTypeInput: {
203       queue_type_id = input_queue_id_;
204       break;
205     }
206     case kVirtioVideoQueueTypeOutput: {
207       queue_type_id = output_queue_id_;
208       break;
209     }
210     default: {
211       queue_type_id = unknown_id_;
212       break;
213     }
214   }
215 
216   args->AddArg(fields_string_ids_.stream_id,
217                Variadic::Integer(pb_evt->stream_id()));
218   args->AddArg(fields_string_ids_.resource_id,
219                Variadic::Integer(pb_evt->resource_id()));
220   args->AddArg(fields_string_ids_.queue_type, Variadic::String(queue_type_id));
221   args->AddArg(fields_string_ids_.data_size0,
222                Variadic::Integer(pb_evt->data_size0()));
223   args->AddArg(fields_string_ids_.data_size1,
224                Variadic::Integer(pb_evt->data_size1()));
225   args->AddArg(fields_string_ids_.data_size2,
226                Variadic::Integer(pb_evt->data_size2()));
227   args->AddArg(fields_string_ids_.data_size3,
228                Variadic::Integer(pb_evt->data_size3()));
229   args->AddArg(fields_string_ids_.timestamp,
230                Variadic::UnsignedInteger(pb_evt->timestamp()));
231 }
232 
233 }  // namespace trace_processor
234 }  // namespace perfetto
235