summaryrefslogtreecommitdiffstats
path: root/include/media/stagefright/YUVImage.h
blob: 4e98618948a68b3e02e4397c9bff03f49bfb8263 (plain)
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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// A container class to hold YUV data and provide various utilities,
// e.g. to set/get pixel values.
// Supported formats:
//  - YUV420 Planar
//  - YUV420 Semi Planar
//
//  Currently does not support variable strides.
//
//  Implementation: Two simple abstractions are done to simplify access
//  to YUV channels for different formats:
//  - initializeYUVPointers() sets up pointers (mYdata, mUdata, mVdata) to
//  point to the right start locations of the different channel data depending
//  on the format.
//  - getOffsets() returns the correct offset for the different channels
//  depending on the format.
//  Location of any pixel's YUV channels can then be easily computed using these.
//

#ifndef YUV_IMAGE_H_

#define YUV_IMAGE_H_

#include <stdint.h>
#include <cstring>

namespace android {

class Rect;

class YUVImage {
public:
    // Supported YUV formats
    enum YUVFormat {
        YUV420Planar,
        YUV420SemiPlanar
    };

    // Constructs an image with the given size, format. Also allocates and owns
    // the required memory.
    YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height);

    // Constructs an image with the given size, format. The memory is provided
    // by the caller and we don't own it.
    YUVImage(YUVFormat yuvFormat, int32_t width, int32_t height, uint8_t *buffer);

    // Destructor to delete the memory if it owns it.
    ~YUVImage();

    // Returns the size of the buffer required to store the YUV data for the given
    // format and geometry. Useful when the caller wants to allocate the requisite
    // memory.
    static size_t bufferSize(YUVFormat yuvFormat, int32_t width, int32_t height);

    int32_t width() const {return mWidth;}
    int32_t height() const {return mHeight;}

    // Returns true if pixel is the range [0, width-1] x [0, height-1]
    // and false otherwise.
    bool validPixel(int32_t x, int32_t y) const;

    // Get the pixel YUV value at pixel (x,y).
    // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
    // Returns true if get was successful and false otherwise.
    bool getPixelValue(int32_t x, int32_t y,
            uint8_t *yPtr, uint8_t *uPtr, uint8_t *vPtr) const;

    // Set the pixel YUV value at pixel (x,y).
    // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
    // Returns true if set was successful and false otherwise.
    bool setPixelValue(int32_t x, int32_t y,
            uint8_t yValue, uint8_t uValue, uint8_t vValue);

    // Uses memcpy to copy an entire row of data
    static void fastCopyRectangle420Planar(
            const Rect& srcRect,
            int32_t destStartX, int32_t destStartY,
            const YUVImage &srcImage, YUVImage &destImage);

    // Uses memcpy to copy an entire row of data
    static void fastCopyRectangle420SemiPlanar(
            const Rect& srcRect,
            int32_t destStartX, int32_t destStartY,
            const YUVImage &srcImage, YUVImage &destImage);

    // Tries to use memcopy to copy entire rows of data.
    // Returns false if fast copy is not possible for the passed image formats.
    static bool fastCopyRectangle(
            const Rect& srcRect,
            int32_t destStartX, int32_t destStartY,
            const YUVImage &srcImage, YUVImage &destImage);

    // Convert the given YUV value to RGB.
    void yuv2rgb(uint8_t yValue, uint8_t uValue, uint8_t vValue,
        uint8_t *r, uint8_t *g, uint8_t *b) const;

    // Write the image to a human readable PPM file.
    // Returns true if write was succesful and false otherwise.
    bool writeToPPM(const char *filename) const;

private:
    // YUV Format of the image.
    YUVFormat mYUVFormat;

    int32_t mWidth;
    int32_t mHeight;

    // Pointer to the memory buffer.
    uint8_t *mBuffer;

    // Boolean telling whether we own the memory buffer.
    bool mOwnBuffer;

    // Pointer to start of the Y data plane.
    uint8_t *mYdata;

    // Pointer to start of the U data plane. Note that in case of interleaved formats like
    // YUV420 semiplanar, mUdata points to the start of the U data in the UV plane.
    uint8_t *mUdata;

    // Pointer to start of the V data plane. Note that in case of interleaved formats like
    // YUV420 semiplanar, mVdata points to the start of the V data in the UV plane.
    uint8_t *mVdata;

    // Initialize the pointers mYdata, mUdata, mVdata to point to the right locations for
    // the given format and geometry.
    // Returns true if initialize was succesful and false otherwise.
    bool initializeYUVPointers();

    // For the given pixel location, this returns the offset of the location of y, u and v
    // data from the corresponding base pointers -- mYdata, mUdata, mVdata.
    // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
    // Returns true if getting offsets was succesful and false otherwise.
    bool getOffsets(int32_t x, int32_t y,
        int32_t *yOffset, int32_t *uOffset, int32_t *vOffset) const;

    // Returns the offset increments incurred in going from one data row to the next data row
    // for the YUV channels. Note that this corresponds to data rows and not pixel rows.
    // E.g. depending on formats, U/V channels may have only one data row corresponding
    // to two pixel rows.
    bool getOffsetIncrementsPerDataRow(
        int32_t *yDataOffsetIncrement,
        int32_t *uDataOffsetIncrement,
        int32_t *vDataOffsetIncrement) const;

    // Given the offset return the address of the corresponding channel's data.
    uint8_t* getYAddress(int32_t offset) const;
    uint8_t* getUAddress(int32_t offset) const;
    uint8_t* getVAddress(int32_t offset) const;

    // Given the pixel location, returns the address of the corresponding channel's data.
    // Note that the range of x is [0, width-1] and the range of y is [0, height-1].
    bool getYUVAddresses(int32_t x, int32_t y,
        uint8_t **yAddr, uint8_t **uAddr, uint8_t **vAddr) const;

    // Disallow implicit casting and copying.
    YUVImage(const YUVImage &);
    YUVImage &operator=(const YUVImage &);
};

}  // namespace android

#endif  // YUV_IMAGE_H_