File: HalideFilters.cpp

package info (click to toggle)
halide 21.0.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 55,752 kB
  • sloc: cpp: 289,334; ansic: 22,751; python: 7,486; makefile: 4,299; sh: 2,508; java: 1,549; javascript: 282; pascal: 207; xml: 127; asm: 9
file content (168 lines) | stat: -rw-r--r-- 6,045 bytes parent folder | download | duplicates (4)
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
#include <android/bitmap.h>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <jni.h>

#include <algorithm>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "native", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, "native", __VA_ARGS__)

#include "AndroidBufferUtilities.h"
#include "HalideRuntime.h"
#include "YuvBufferT.h"
#include "deinterleave.h"
#include "edge_detect.h"

#define DEBUG 1

// Extern functions from the Halide runtime that are not exposed in
// HalideRuntime.h.
extern "C" int halide_host_cpu_count();
extern "C" int64_t halide_current_time_ns();

// Override Halide's print to use LOGD and also print the time.
extern "C" void halide_print(void *, const char *msg) {
    static int64_t t0 = halide_current_time_ns();
    int64_t t1 = halide_current_time_ns();
    LOGD("%d: %s\n", (int)(t1 - t0) / 1000000, msg);
    t0 = t1;
}

extern "C" {

bool checkEqualExtents(YuvBufferT *src, YuvBufferT *dst) {
    if (src->luma().width() != dst->luma().width() ||
        src->luma().height() != dst->luma().height() ||
        src->chromaU().width() != dst->chromaU().width() ||
        src->chromaU().height() != dst->chromaU().height() ||
        src->chromaV().width() != dst->chromaV().width() ||
        src->chromaV().height() != dst->chromaV().height()) {

        LOGE("failed: src and dst extents must be equal.\n\t"
             "src extents: luma: %d, %d, chromaU: %d, %d, chromaV: %d, %d.\n\t"
             "dst extents: luma: %d, %d, chromaU: %d, %d, chromaV: %d, %d.",
             src->luma().width(), src->luma().height(),
             src->chromaU().width(), src->chromaU().height(),
             src->chromaV().width(), src->chromaV().height(),
             dst->luma().width(), dst->luma().height(),
             dst->chromaU().width(), dst->chromaU().height(),
             dst->chromaV().width(), dst->chromaV().height());
        return false;
    } else {
        return true;
    }
}

JNIEXPORT bool JNICALL Java_com_example_helloandroidcamera2_HalideFilters_copyHalide(
    JNIEnv *env, jobject obj, jlong srcYuvBufferTHandle, jlong dstYuvBufferTHandle) {
    if (srcYuvBufferTHandle == 0L || dstYuvBufferTHandle == 0L) {
        LOGE("copyHalide failed: src and dst must not be null");
        return false;
    }

    YuvBufferT *src = reinterpret_cast<YuvBufferT *>(srcYuvBufferTHandle);
    YuvBufferT *dst = reinterpret_cast<YuvBufferT *>(dstYuvBufferTHandle);

    if (!checkEqualExtents(src, dst)) {
        return false;
    }

    YuvBufferT::ChromaStorage srcChromaStorage = src->chromaStorage();
    YuvBufferT::ChromaStorage dstChromaStorage = dst->chromaStorage();

    bool succeeded;
    int halideErrorCode;

    // Use Halide deinterleave if the source chroma is interleaved and destination chroma is planar.
    // Other, fall back to slow copy.
    if ((srcChromaStorage == YuvBufferT::ChromaStorage::kInterleavedUFirst ||
         srcChromaStorage == YuvBufferT::ChromaStorage::kInterleavedVFirst) &&
        (dstChromaStorage == YuvBufferT::ChromaStorage::kPlanarPackedUFirst ||
         dstChromaStorage == YuvBufferT::ChromaStorage::kPlanarPackedVFirst ||
         dstChromaStorage == YuvBufferT::ChromaStorage::kPlanarGeneric)) {

        // Copy the luma channel directly.
        dst->luma().copy_from(src->luma());

        // Use Halide to deinterleave the chroma channels.
        auto srcInterleavedChroma = src->interleavedChromaView();
        auto dstPlanarChromaU = dst->chromaU();
        auto dstPlanarChromaV = dst->chromaV();
        if (srcChromaStorage == YuvBufferT::ChromaStorage::kInterleavedUFirst) {
            halideErrorCode = deinterleave(srcInterleavedChroma,
                                           dstPlanarChromaU,
                                           dstPlanarChromaV);
        } else {
            halideErrorCode = deinterleave(srcInterleavedChroma,
                                           dstPlanarChromaV,
                                           dstPlanarChromaU);
        }
        succeeded = (halideErrorCode != halide_error_code_success);
        if (halideErrorCode != halide_error_code_success) {
            LOGE("deinterleave failed with error code: %d", halideErrorCode);
        }
    } else {
        (*dst).copy_from(*src);
    }

    return succeeded;
}

JNIEXPORT bool JNICALL Java_com_example_helloandroidcamera2_HalideFilters_edgeDetectHalide(
    JNIEnv *env, jobject obj, jlong srcYuvBufferTHandle, jlong dstYuvBufferTHandle) {
    if (srcYuvBufferTHandle == 0L || dstYuvBufferTHandle == 0L) {
        LOGE("edgeDetectHalide failed: src and dst must not be null");
        return false;
    }

    YuvBufferT *src = reinterpret_cast<YuvBufferT *>(srcYuvBufferTHandle);
    YuvBufferT *dst = reinterpret_cast<YuvBufferT *>(dstYuvBufferTHandle);

    if (!checkEqualExtents(src, dst)) {
        return false;
    }

    static bool first_call = true;
    static unsigned counter = 0;
    static unsigned times[16];
    if (first_call) {
        LOGD("According to Halide, host system has %d cpus\n",
             halide_host_cpu_count());
        first_call = false;
        for (int t = 0; t < 16; t++) {
            times[t] = 0;
        }
    }

    // Set chrominance to 128 to appear grayscale.
    dst->fillUV(128, 128);

    auto srcLuma = src->luma();
    auto dstLuma = dst->luma();
    int64_t t1 = halide_current_time_ns();
    int err = edge_detect(srcLuma, dstLuma);
    if (err != halide_error_code_success) {
        LOGE("edge_detect failed with error code: %d", err);
    }

    int64_t t2 = halide_current_time_ns();
    unsigned elapsed_us = (t2 - t1) / 1000;

    times[counter & 15] = elapsed_us;
    counter++;
    unsigned min = times[0];
    for (int i = 1; i < 16; i++) {
        if (times[i] < min) {
            min = times[i];
        }
    }
    LOGD("Time taken: %d us (minimum: %d us)", elapsed_us, min);

    return (err != halide_error_code_success);
}

}  // extern "C"