GStreamer Video Analytics (GVA) Plugin
audio_frame.h
Go to the documentation of this file.
1 /*******************************************************************************
2  * Copyright (C) 2018-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  ******************************************************************************/
6 
13 #pragma once
14 
15 #include "audio_event.h"
16 
17 #include "metadata/gva_json_meta.h"
19 
20 #include <gst/audio/audio.h>
21 #include <gst/audio/gstaudiometa.h>
22 #include <gst/gstbuffer.h>
23 
24 #include <algorithm>
25 #include <assert.h>
26 #include <functional>
27 #include <memory>
28 #include <stdexcept>
29 #include <string>
30 #include <vector>
31 
32 namespace GVA {
33 
42 class AudioFrame {
43  protected:
48  GstBuffer *buffer;
49 
53  std::unique_ptr<GstAudioInfo, std::function<void(GstAudioInfo *)>> info;
54 
55  public:
62  AudioFrame(GstBuffer *buffer, GstAudioInfo *info)
63  : buffer(buffer), info(gst_audio_info_copy(info), gst_audio_info_free) {
64  if (not buffer or not info) {
65  throw std::invalid_argument("GVA::AudioFrame: buffer or info nullptr");
66  }
67  }
68 
74  AudioFrame(GstBuffer *buffer, const GstCaps *caps) : buffer(buffer) {
75  if (not buffer or not caps) {
76  throw std::invalid_argument("GVA::AudioFrame: buffer or caps nullptr");
77  }
78  info = std::unique_ptr<GstAudioInfo, std::function<void(GstAudioInfo *)>>(gst_audio_info_new(),
79  gst_audio_info_free);
80  if (!gst_audio_info_from_caps(info.get(), caps)) {
81  throw std::runtime_error("GVA::AudioFrame: gst_audio_info_from_caps failed");
82  }
83  }
84 
91  AudioFrame(GstBuffer *buffer) : buffer(buffer) {
92  if (not buffer)
93  throw std::invalid_argument("GVA::AudioFrame: buffer is nullptr");
94 
95  GstAudioMeta *meta = audio_meta();
96  if (not meta)
97  throw std::logic_error("GVA::AudioFrame: audio_meta() is nullptr");
98 
99  info = std::unique_ptr<GstAudioInfo, std::function<void(GstAudioInfo *)>>(gst_audio_info_new(),
100  gst_audio_info_free);
101  if (not info.get())
102  throw std::logic_error("GVA::AudioFrame: gst_audio_info_new() failed");
103 
104  memcpy(info.get(), &meta->info, sizeof(meta->info));
105  }
106 
111  GstAudioMeta *audio_meta() {
112  return gst_buffer_get_audio_meta(buffer);
113  }
114 
119  GstAudioInfo *audio_info() {
120  return info.get();
121  }
122 
127  std::vector<AudioEvent> events() {
128  return get_events();
129  }
130 
135  const std::vector<AudioEvent> events() const {
136  return get_events();
137  }
138 
143  std::vector<Tensor> tensors() {
144  return get_tensors();
145  }
146 
151  const std::vector<Tensor> tensors() const {
152  return get_tensors();
153  }
154 
159  std::vector<std::string> messages() {
160  std::vector<std::string> json_messages;
161  GstGVAJSONMeta *meta = NULL;
162  gpointer state = NULL;
163  GType meta_api_type = g_type_from_name(GVA_JSON_META_API_NAME);
164  while ((meta = (GstGVAJSONMeta *)gst_buffer_iterate_meta_filtered(buffer, &state, meta_api_type))) {
165  json_messages.emplace_back(meta->message);
166  }
167  return json_messages;
168  }
169 
178  AudioEvent add_event(long start_time, long end_time, std::string label = std::string(), double confidence = 0.0) {
179 
180  GstGVAAudioEventMeta *meta = gst_gva_buffer_add_audio_event_meta(buffer, label.c_str(), start_time, end_time);
181 
182  // Add detection tensor
183  GstStructure *detection = gst_structure_new("detection", "start_timestamp", G_TYPE_LONG, start_time,
184  "end_timestamp", G_TYPE_LONG, end_time, NULL);
185  if (confidence) {
186  gst_structure_set(detection, "confidence", G_TYPE_DOUBLE, confidence, NULL);
187  }
188  gst_gva_audio_event_meta_add_param(meta, detection);
189 
190  return AudioEvent(meta);
191  }
192 
198  const GstMetaInfo *meta_info = gst_meta_get_info(GVA_TENSOR_META_IMPL_NAME);
199 
200  if (!gst_buffer_is_writable(buffer))
201  throw std::runtime_error("Buffer is not writable.");
202 
203  GstGVATensorMeta *tensor_meta = (GstGVATensorMeta *)gst_buffer_add_meta(buffer, meta_info, NULL);
204 
205  return Tensor(tensor_meta->data);
206  }
207 
212  void add_message(const std::string &message) {
213  const GstMetaInfo *meta_info = gst_meta_get_info(GVA_JSON_META_IMPL_NAME);
214 
215  if (!gst_buffer_is_writable(buffer))
216  throw std::runtime_error("Buffer is not writable.");
217 
218  GstGVAJSONMeta *json_meta = (GstGVAJSONMeta *)gst_buffer_add_meta(buffer, meta_info, NULL);
219  json_meta->message = g_strdup(message.c_str());
220  }
221 
226  void remove_event(const AudioEvent &event) {
227  if (!gst_buffer_is_writable(buffer))
228  throw std::runtime_error("Buffer is not writable.");
229 
230  if (!gst_buffer_remove_meta(buffer, (GstMeta *)event._meta())) {
231  throw std::out_of_range("GVA::AudioFrame: AudioEvent doesn't belong to this frame");
232  }
233  }
234 
239  void remove_tensor(const Tensor &tensor) {
240  GstGVATensorMeta *meta = NULL;
241  gpointer state = NULL;
242  while ((meta = GST_GVA_TENSOR_META_ITERATE(buffer, &state))) {
243  if (meta->data == tensor._structure) {
244  if (!gst_buffer_is_writable(buffer))
245  throw std::runtime_error("Buffer is not writable.");
246 
247  if (gst_buffer_remove_meta(buffer, (GstMeta *)meta))
248  return;
249  }
250  }
251  throw std::out_of_range("GVA::AudioFrame: Tensor doesn't belong to this frame");
252  }
253 
254  private:
255  std::vector<AudioEvent> get_events() const {
256  std::vector<AudioEvent> events;
257  GstMeta *meta = NULL;
258  gpointer state = NULL;
259 
260  while ((meta = gst_buffer_iterate_meta_filtered(buffer, &state, GST_GVA_AUDIO_EVENT_META_API_TYPE)))
261  events.emplace_back((GstGVAAudioEventMeta *)meta);
262  return events;
263  }
264 
265  std::vector<Tensor> get_tensors() const {
266  std::vector<Tensor> tensors;
267  GstGVATensorMeta *meta = NULL;
268  gpointer state = NULL;
269  GType meta_api_type = g_type_from_name("GstGVATensorMetaAPI");
270  while ((meta = (GstGVATensorMeta *)gst_buffer_iterate_meta_filtered(buffer, &state, meta_api_type)))
271  tensors.emplace_back(meta->data);
272  return tensors;
273  }
274 };
275 
276 } // namespace GVA
GVA::AudioFrame::info
std::unique_ptr< GstAudioInfo, std::function< void(GstAudioInfo *)> > info
GstAudioInfo containing actual audio information for this AudioFrame.
Definition: audio_frame.h:53
GVA::AudioFrame::events
const std::vector< AudioEvent > events() const
Get AudioEvent objects attached to AudioFrame.
Definition: audio_frame.h:135
GVA::AudioEvent::_meta
GstGVAAudioEventMeta * _meta() const
Internal function, don't use or use with caution.
Definition: audio_event.h:156
GstGVAAudioEventMeta
Definition: gva_audio_event_meta.h:29
GVA::AudioFrame::messages
std::vector< std::string > messages()
Get messages attached to this AudioFrame.
Definition: audio_frame.h:159
GVA::AudioFrame::remove_event
void remove_event(const AudioEvent &event)
Remove AudioEvent.
Definition: audio_frame.h:226
GVA::AudioFrame::remove_tensor
void remove_tensor(const Tensor &tensor)
Remove Tensor.
Definition: audio_frame.h:239
audio_event.h
This file contains GVA::AudioEvent class to control audio event for particular GVA::AudioFrame with G...
GVA::AudioFrame::add_event
AudioEvent add_event(long start_time, long end_time, std::string label=std::string(), double confidence=0.0)
Attach AudioEvent to this AudioFrame. This function takes ownership of event_tensor,...
Definition: audio_frame.h:178
GVA::AudioFrame::buffer
GstBuffer * buffer
GstBuffer with inference results metadata attached (Gstreamer pipeline's GstBuffer,...
Definition: audio_frame.h:48
GVA::AudioFrame
This class represents audio frame - object for working with AudioEvent and Tensor objects which belon...
Definition: audio_frame.h:42
GVA::AudioFrame::tensors
std::vector< Tensor > tensors()
Get Tensor objects attached to AudioFrame.
Definition: audio_frame.h:143
GVA::AudioFrame::audio_info
GstAudioInfo * audio_info()
Get GstAudioInfo of this AudioFrame. This is preferrable way of getting audio information.
Definition: audio_frame.h:119
gva_tensor_meta.h
This file contains helper functions to control _GstGVATensorMeta instances.
GVA::AudioFrame::tensors
const std::vector< Tensor > tensors() const
Get Tensor objects attached to AudioFrame.
Definition: audio_frame.h:151
_GstGVATensorMeta
This struct represents raw tensor metadata and contains instance of parent GstMeta and fields describ...
Definition: gva_tensor_meta.h:64
GVA::AudioFrame::audio_meta
GstAudioMeta * audio_meta()
Get audio metadata of buffer.
Definition: audio_frame.h:111
GVA::Tensor::_structure
GstStructure * _structure
ptr to GstStructure that contains all tensor (inference results) data & info.
Definition: tensor.h:358
GVA::AudioFrame::add_message
void add_message(const std::string &message)
Attach message to this AudioFrame.
Definition: audio_frame.h:212
gva_json_meta.h
This file contains helper functions to control _GstGVAJSONMeta instances.
GVA::Tensor
This class represents tensor - map-like storage for inference result information, such as output blob...
Definition: tensor.h:38
GVA::AudioFrame::AudioFrame
AudioFrame(GstBuffer *buffer, const GstCaps *caps)
Construct AudioFrame instance from GstBuffer and GstCaps.
Definition: audio_frame.h:74
GVA::AudioFrame::AudioFrame
AudioFrame(GstBuffer *buffer, GstAudioInfo *info)
Construct AudioFrame instance from GstBuffer and GstAudioInfo. This is preferred way of creating Audi...
Definition: audio_frame.h:62
GVA::AudioFrame::add_tensor
Tensor add_tensor()
Attach empty Tensor to this AudioFrame.
Definition: audio_frame.h:197
GVA::AudioEvent
This class represents audio event - object describing audio event detection result (segment) and cont...
Definition: audio_event.h:45
GVA::AudioFrame::AudioFrame
AudioFrame(GstBuffer *buffer)
Construct AudioFrame instance from GstBuffer. Audio information will be obtained from buffer....
Definition: audio_frame.h:91
GVA::AudioFrame::events
std::vector< AudioEvent > events()
Get AudioEvent objects attached to AudioFrame.
Definition: audio_frame.h:127
_GstGVATensorMeta::data
GstStructure * data
Definition: gva_tensor_meta.h:66