query MPV astats node directly in C for efficiency

This commit is contained in:
Drew Weymouth
2024-07-23 17:38:43 -07:00
parent 1814e2a6a3
commit 02e5c784b3
5 changed files with 73 additions and 13 deletions
+49
View File
@@ -0,0 +1,49 @@
#include <mpv/client.h>
#include <stdlib.h>
#include <string.h>
int mpv_get_peaks(mpv_handle* handle, double* lPeak, double* rPeak, double* lRMS, double* rRMS) {
mpv_node result;
int ret = mpv_get_property(handle, "af-metadata/astats", MPV_FORMAT_NODE, &result);
if (ret != MPV_ERROR_SUCCESS) {
return ret;
}
if (result.format != MPV_FORMAT_NODE_MAP) {
return MPV_ERROR_PROPERTY_FORMAT;
}
int found = 0;
for (int i = 0; found < 4 && i < result.u.list->num; i++) {
if (strcmp("lavfi.astats.1.Peak_level", result.u.list->keys[i]) == 0) {
if (result.u.list->values[i].format != MPV_FORMAT_STRING) {
return MPV_ERROR_PROPERTY_FORMAT;
}
*lPeak = atof(result.u.list->values[i].u.string);
found++;
}
if (strcmp("lavfi.astats.2.Peak_level", result.u.list->keys[i]) == 0) {
if (result.u.list->values[i].format != MPV_FORMAT_STRING) {
return MPV_ERROR_PROPERTY_FORMAT;
}
*rPeak = atof(result.u.list->values[i].u.string);
found++;
}
if (strcmp("lavfi.astats.1.RMS_level", result.u.list->keys[i]) == 0) {
if (result.u.list->values[i].format != MPV_FORMAT_STRING) {
return MPV_ERROR_PROPERTY_FORMAT;
}
*lRMS = atof(result.u.list->values[i].u.string);
found++;
}
if (strcmp("lavfi.astats.2.RMS_level", result.u.list->keys[i]) == 0) {
if (result.u.list->values[i].format != MPV_FORMAT_STRING) {
return MPV_ERROR_PROPERTY_FORMAT;
}
*rRMS = atof(result.u.list->values[i].u.string);
found++;
}
}
mpv_free_node_contents(&result);
return MPV_ERROR_SUCCESS;
}
+19
View File
@@ -0,0 +1,19 @@
package mpv
// #include <mpv/client.h>
// int mpv_get_peaks(mpv_handle* handle, double* lPeak, double* rPeak, double* lRMS, double* rRMS);
import "C"
import (
"github.com/dweymouth/go-mpv"
)
// rather than querying peaks through m.mpv.GetProperty which necessitates
// converting the MPV node to a Go map, we can do so in C with no Go allocations
func (m *Player) getPeaks() (float64, float64, float64, float64, error) {
var lPeak, rPeak, lRMS, rRMS C.double
ret := int(C.mpv_get_peaks((*C.mpv_handle)(m.mpv.MPVHandle()), &lPeak, &rPeak, &lRMS, &rRMS))
if err := mpv.NewError(ret); err != nil {
return 0, 0, 0, 0, err
}
return float64(lPeak), float64(rPeak), float64(lRMS), float64(rRMS), nil
}
+2 -10
View File
@@ -455,19 +455,11 @@ func (p *Player) GetPeaks() (float64, float64, float64, float64) {
if p.status.State != player.Playing {
return nInf, nInf, nInf, nInf
}
prop, err := p.mpv.GetProperty("af-metadata/astats", mpv.FORMAT_NODE)
lPeak, rPeak, lRMS, rRMS, err := p.getPeaks()
if err != nil {
return nInf, nInf, nInf, nInf
}
m := prop.(*mpv.Node).Data.(map[string]*mpv.Node)
if lPeakNode, ok := m["lavfi.astats.1.Peak_level"]; ok {
lPeak, _ := strconv.ParseFloat(lPeakNode.Data.(string), 64)
rPeak, _ := strconv.ParseFloat(m["lavfi.astats.2.Peak_level"].Data.(string), 64)
lRMS, _ := strconv.ParseFloat(m["lavfi.astats.1.RMS_level"].Data.(string), 64)
rRMS, _ := strconv.ParseFloat(m["lavfi.astats.2.RMS_level"].Data.(string), 64)
return lPeak, rPeak, lRMS, rRMS
}
return nInf, nInf, nInf, nInf
return lPeak, rPeak, lRMS, rRMS
}
// sets the state and invokes callbacks, if triggered