-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfingerprint.go
140 lines (115 loc) · 3.37 KB
/
fingerprint.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2020 Pexeso Inc. All rights reserved.
package pex
// #include <stdlib.h>
// #include <pex/sdk/lock.h>
// #include <pex/sdk/fingerprint.h>
import "C"
import (
"encoding/json"
"errors"
"unsafe"
)
// FingerprintType is a bit flag specifying one or more fingerprint types.
type FingerprintType int
func (x *FingerprintType) UnmarshalJSON(data []byte) error {
var temp string
if err := json.Unmarshal(data, &temp); err != nil {
return err
}
switch temp {
case "video":
*x = FingerprintTypeVideo
case "audio":
*x = FingerprintTypeAudio
case "melody":
*x = FingerprintTypeMelody
default:
return errors.New("invalid fingerprint_type value")
}
return nil
}
const (
FingerprintTypeVideo FingerprintType = 1
FingerprintTypeAudio FingerprintType = 2
FingerprintTypeMelody FingerprintType = 4
FingerprintTypeAll = FingerprintTypeVideo | FingerprintTypeAudio | FingerprintTypeMelody
)
// Fingerprint is how the SDK identifies a piece of digital content.
// It can be generated from a media file or from a memory buffer. The
// content must be encoded in one of the supported formats and must be
// longer than 1 second.
type Fingerprint struct {
b []byte
}
func (x *Fingerprint) Dump() []byte {
return x.b
}
func NewFingerprint(b []byte) *Fingerprint {
return &Fingerprint{
b: b,
}
}
type fingerprinter struct {
c *C.Pex_Client
}
// FingerprintFile is used to generate a fingerprint from a
// file stored on a disk. The path parameter must be a path
// to a valid file in supported format. The types parameter
// specifies which types of fingerprints to create. If not
// types are provided, FingerprintTypeAll is assumed.
func (x *fingerprinter) FingerprintFile(path string, types ...FingerprintType) (*Fingerprint, error) {
return x.newFingerprint([]byte(path), true, reduceTypes(types))
}
// FingerprintBuffer is used to generate a fingerprint from a
// media file loaded in memory as a byte slice. The types parameter
// specifies which types of fingerprints to create. If not
// types are provided, FingerprintTypeAll is assumed.
func (x *fingerprinter) FingerprintBuffer(buffer []byte, types ...FingerprintType) (*Fingerprint, error) {
return x.newFingerprint(buffer, false, reduceTypes(types))
}
func reduceTypes(in []FingerprintType) (out FingerprintType) {
if len(in) == 0 {
return FingerprintTypeAll
}
for _, t := range in {
out = out | t
}
return out
}
func (x *fingerprinter) newFingerprint(input []byte, isFile bool, typ FingerprintType) (*Fingerprint, error) {
C.Pex_Lock()
defer C.Pex_Unlock()
status := C.Pex_Status_New()
if status == nil {
panic("out of memory")
}
defer C.Pex_Status_Delete(&status)
ft := C.Pex_Buffer_New()
if ft == nil {
panic("out of memory")
}
if isFile {
cFile := C.CString(string(input))
defer C.free(unsafe.Pointer(cFile))
C.Pex_FingerprintFile(x.c, cFile, ft, status, C.int(typ))
} else {
buf := C.Pex_Buffer_New()
if buf == nil {
panic("out of memory")
}
defer C.Pex_Buffer_Delete(&buf)
data := unsafe.Pointer(&input[0])
size := C.size_t(len(input))
C.Pex_Buffer_Set(buf, data, size)
C.Pex_FingerprintBuffer(x.c, buf, ft, status, C.int(typ))
}
if err := statusToError(status); err != nil {
C.Pex_Buffer_Delete(&ft)
return nil, err
}
data := C.Pex_Buffer_GetData(ft)
size := C.int(C.Pex_Buffer_GetSize(ft))
return &Fingerprint{
b: C.GoBytes(data, size),
}, nil
}