• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

asticode / go-astiav / 7666807443

26 Jan 2024 10:21AM UTC coverage: 87.176% (+2.2%) from 84.935%
7666807443

push

github

asticode
Replaced FrameData.Image() with FrameData.GuessImageFormat() + now handling premultiplied image formats

66 of 93 new or added lines in 2 files covered. (70.97%)

3 existing lines in 2 files now uncovered.

1482 of 1700 relevant lines covered (87.18%)

30.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.35
/frame_data.go
1
package astiav
2

3
//#include <stdint.h>
4
import "C"
5
import (
6
        "errors"
7
        "fmt"
8
        "image"
9
        "strings"
10
)
11

12
type FrameDataFrame interface {
13
        Height() int
14
        ImageBufferSize(align int) (int, error)
15
        ImageCopyToBuffer(b []byte, align int) (int, error)
16
        Linesize(i int) int
17
        PixelFormat() PixelFormat
18
        PlaneBytes(i int) []byte
19
        Width() int
20
}
21

22
var _ FrameDataFrame = (*frameDataFrame)(nil)
23

24
type frameDataFrame struct {
25
        f *Frame
26
}
27

NEW
28
func newFrameDataFrame(f *Frame) *frameDataFrame {
×
NEW
29
        return &frameDataFrame{f: f}
×
NEW
30
}
×
31

NEW
32
func (f *frameDataFrame) Height() int {
×
NEW
33
        return f.f.Height()
×
NEW
34
}
×
35

NEW
36
func (f *frameDataFrame) ImageBufferSize(align int) (int, error) {
×
NEW
37
        return f.f.ImageBufferSize(align)
×
NEW
38
}
×
39

NEW
40
func (f *frameDataFrame) ImageCopyToBuffer(b []byte, align int) (int, error) {
×
NEW
41
        return f.f.ImageCopyToBuffer(b, align)
×
NEW
42
}
×
43

NEW
44
func (f *frameDataFrame) Linesize(i int) int {
×
NEW
45
        return f.f.Linesize()[i]
×
NEW
46
}
×
47

NEW
48
func (f *frameDataFrame) PixelFormat() PixelFormat {
×
NEW
49
        return f.f.PixelFormat()
×
NEW
50
}
×
51

NEW
52
func (f *frameDataFrame) PlaneBytes(i int) []byte {
×
NEW
53
        return bytesFromC(func(size *cUlong) *C.uint8_t {
×
NEW
54
                *size = cUlong(int(f.f.c.linesize[i]) * f.f.Height())
×
NEW
55
                return f.f.c.data[i]
×
NEW
56
        })
×
57
}
58

NEW
59
func (f *frameDataFrame) Width() int {
×
NEW
60
        return f.f.Width()
×
UNCOV
61
}
×
62

63
type FrameData struct {
64
        f FrameDataFrame
65
}
66

67
func NewFrameData(f FrameDataFrame) *FrameData {
3✔
68
        return &FrameData{f: f}
3✔
69
}
3✔
70

71
func (d *FrameData) Bytes(align int) ([]byte, error) {
6✔
72
        switch {
6✔
73
        // Video
74
        case d.f.Height() > 0 && d.f.Width() > 0:
3✔
75
                // Get buffer size
3✔
76
                s, err := d.f.ImageBufferSize(align)
3✔
77
                if err != nil {
3✔
78
                        return nil, fmt.Errorf("astiav: getting image buffer size failed: %w", err)
×
79
                }
×
80

81
                // Invalid buffer size
82
                if s == 0 {
3✔
83
                        return nil, errors.New("astiav: invalid image buffer size")
×
84
                }
×
85

86
                // Create buffer
87
                b := make([]byte, s)
3✔
88

3✔
89
                // Copy image to buffer
3✔
90
                if _, err = d.f.ImageCopyToBuffer(b, align); err != nil {
3✔
91
                        return nil, fmt.Errorf("astiav: copying image to buffer failed: %w", err)
×
92
                }
×
93
                return b, nil
3✔
94
        }
95
        return nil, errors.New("astiav: frame type not implemented")
3✔
96
}
97

98
// Always returns non-premultiplied formats when dealing with alpha channels, however this might not
99
// always be accurate. In this case, use your own format in .ToImage()
100
func (d *FrameData) GuessImageFormat() (image.Image, error) {
69✔
101
        switch d.f.PixelFormat() {
69✔
102
        case PixelFormatGray8:
3✔
103
                return &image.Gray{}, nil
3✔
104
        case PixelFormatGray16Be:
3✔
105
                return &image.Gray16{}, nil
3✔
106
        case PixelFormatRgb0, PixelFormat0Rgb, PixelFormatRgb4, PixelFormatRgb8:
12✔
107
                return &image.RGBA{}, nil
12✔
108
        case PixelFormatRgba:
3✔
109
                return &image.NRGBA{}, nil
3✔
110
        case PixelFormatRgba64Be:
3✔
111
                return &image.NRGBA64{}, nil
3✔
112
        case PixelFormatYuva420P,
113
                PixelFormatYuva422P,
114
                PixelFormatYuva444P:
9✔
115
                return &image.NYCbCrA{}, nil
9✔
116
        case PixelFormatYuv410P,
117
                PixelFormatYuv411P, PixelFormatYuvj411P,
118
                PixelFormatYuv420P, PixelFormatYuvj420P,
119
                PixelFormatYuv422P, PixelFormatYuvj422P,
120
                PixelFormatYuv440P, PixelFormatYuvj440P,
121
                PixelFormatYuv444P, PixelFormatYuvj444P:
33✔
122
                return &image.YCbCr{}, nil
33✔
123
        }
124
        return nil, fmt.Errorf("astiav: pixel format %s not handled by Go", d.f.PixelFormat())
3✔
125
}
126

127
func (d *FrameData) imageYCbCrSubsampleRatio() image.YCbCrSubsampleRatio {
6✔
128
        name := d.f.PixelFormat().Name()
6✔
129
        for s, r := range map[string]image.YCbCrSubsampleRatio{
6✔
130
                "410": image.YCbCrSubsampleRatio410,
6✔
131
                "411": image.YCbCrSubsampleRatio411,
6✔
132
                "420": image.YCbCrSubsampleRatio420,
6✔
133
                "422": image.YCbCrSubsampleRatio422,
6✔
134
                "440": image.YCbCrSubsampleRatio440,
6✔
135
                "444": image.YCbCrSubsampleRatio444,
6✔
136
        } {
27✔
137
                if strings.Contains(name, s) {
27✔
138
                        return r
6✔
139
                }
6✔
140
        }
141
        return image.YCbCrSubsampleRatio444
×
142
}
143

144
func (d *FrameData) copyPlaneBytes(i int, s *[]uint8) {
48✔
145
        b := d.f.PlaneBytes(i)
48✔
146
        if len(b) > cap(*s) {
96✔
147
                *s = make([]uint8, len(b))
48✔
148
        }
48✔
149
        copy(*s, b)
48✔
150
}
151

152
func (d *FrameData) toImagePix(pix *[]uint8, stride *int, rect *image.Rectangle) {
27✔
153
        d.copyPlaneBytes(0, pix)
27✔
154
        if v := d.f.Linesize(0); *stride != v {
54✔
155
                *stride = v
27✔
156
        }
27✔
157
        if w, h := d.f.Width(), d.f.Height(); rect.Dy() != w || rect.Dx() != h {
54✔
158
                *rect = image.Rect(0, 0, w, h)
27✔
159
        }
27✔
160
}
161

162
func (d *FrameData) toImageYCbCr(y, cb, cr *[]uint8, yStride, cStride *int, subsampleRatio *image.YCbCrSubsampleRatio, rect *image.Rectangle) {
6✔
163
        d.copyPlaneBytes(0, y)
6✔
164
        d.copyPlaneBytes(1, cb)
6✔
165
        d.copyPlaneBytes(2, cr)
6✔
166
        if v := d.f.Linesize(0); *yStride != v {
12✔
167
                *yStride = v
6✔
168
        }
6✔
169
        if v := d.f.Linesize(1); *cStride != v {
12✔
170
                *cStride = v
6✔
171
        }
6✔
172
        if v := d.imageYCbCrSubsampleRatio(); *subsampleRatio != v {
9✔
173
                *subsampleRatio = v
3✔
174
        }
3✔
175
        if w, h := d.f.Width(), d.f.Height(); rect.Dy() != w || rect.Dx() != h {
12✔
176
                *rect = image.Rect(0, 0, w, h)
6✔
177
        }
6✔
178
}
179

180
func (d *FrameData) toImageYCbCrA(y, cb, cr, a *[]uint8, yStride, cStride, aStride *int, subsampleRatio *image.YCbCrSubsampleRatio, rect *image.Rectangle) {
3✔
181
        d.toImageYCbCr(y, cb, cr, yStride, cStride, subsampleRatio, rect)
3✔
182
        d.copyPlaneBytes(3, a)
3✔
183
        if v := d.f.Linesize(3); *aStride != v {
6✔
184
                *aStride = v
3✔
185
        }
3✔
186
}
187

188
func (d *FrameData) ToImage(dst image.Image) error {
33✔
189
        if v, ok := dst.(*image.Alpha); ok {
36✔
190
                d.toImagePix(&v.Pix, &v.Stride, &v.Rect)
3✔
191
        } else if v, ok := dst.(*image.Alpha16); ok {
36✔
192
                d.toImagePix(&v.Pix, &v.Stride, &v.Rect)
3✔
193
        } else if v, ok := dst.(*image.CMYK); ok {
33✔
194
                d.toImagePix(&v.Pix, &v.Stride, &v.Rect)
3✔
195
        } else if v, ok := dst.(*image.Gray); ok {
30✔
196
                d.toImagePix(&v.Pix, &v.Stride, &v.Rect)
3✔
197
        } else if v, ok := dst.(*image.Gray16); ok {
27✔
198
                d.toImagePix(&v.Pix, &v.Stride, &v.Rect)
3✔
199
        } else if v, ok := dst.(*image.NRGBA); ok {
24✔
200
                d.toImagePix(&v.Pix, &v.Stride, &v.Rect)
3✔
201
        } else if v, ok := dst.(*image.NRGBA64); ok {
21✔
202
                d.toImagePix(&v.Pix, &v.Stride, &v.Rect)
3✔
203
        } else if v, ok := dst.(*image.NYCbCrA); ok {
18✔
204
                d.toImageYCbCrA(&v.Y, &v.Cb, &v.Cr, &v.A, &v.YStride, &v.CStride, &v.AStride, &v.SubsampleRatio, &v.Rect)
3✔
205
        } else if v, ok := dst.(*image.RGBA); ok {
15✔
206
                d.toImagePix(&v.Pix, &v.Stride, &v.Rect)
3✔
207
        } else if v, ok := dst.(*image.RGBA64); ok {
12✔
208
                d.toImagePix(&v.Pix, &v.Stride, &v.Rect)
3✔
209
        } else if v, ok := dst.(*image.YCbCr); ok {
9✔
210
                d.toImageYCbCr(&v.Y, &v.Cb, &v.Cr, &v.YStride, &v.CStride, &v.SubsampleRatio, &v.Rect)
3✔
211
        } else {
3✔
NEW
212
                return errors.New("astiav: image format is not handled")
×
213
        }
×
214
        return nil
33✔
215
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc