1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 //#define LOG_NDEBUG 0
17 #define LOG_TAG "C2SoftDav1dDump"
18 #include "C2SoftDav1dDump.h"
19 
20 namespace android {
21 
22 // Flag to enable dumping the bitsteram and the decoded pictures to files.
23 static const bool ENABLE_DUMPING_FILES_DEFAULT = true;
24 static const char ENABLE_DUMPING_FILES_PROPERTY[] = "debug.dav1d.enabledumping";
25 
26 // The number of frames to dump to a file
27 static const int NUM_FRAMES_TO_DUMP_DEFAULT = INT_MAX;
28 static const char NUM_FRAMES_TO_DUMP_PROPERTY[] = "debug.dav1d.numframestodump";
29 
30 // start dumping from this frame
31 static const int STARTING_FRAME_TO_DUMP_DEFAULT = 0;
32 static const char STARTING_FRAME_TO_DUMP_PROPERTY[] = "debug.dav1d.startingframetodump";
33 
initDumping()34 void C2SoftDav1dDump::initDumping() {
35     nsecs_t now = systemTime();
36     snprintf(mInDataFileName, kFileNameLength, "%s_%" PRId64 "d.%s", DUMP_FILE_PATH, now,
37              INPUT_DATA_DUMP_EXT);
38     snprintf(mInSizeFileName, kFileNameLength, "%s_%" PRId64 "d.%s", DUMP_FILE_PATH, now,
39              INPUT_SIZE_DUMP_EXT);
40     snprintf(mDav1dOutYuvFileName, kFileNameLength, "%s_%" PRId64 "dx.%s", DUMP_FILE_PATH, now,
41              OUTPUT_YUV_DUMP_EXT);
42 
43     mFramesToDump =
44             android::base::GetIntProperty(NUM_FRAMES_TO_DUMP_PROPERTY, NUM_FRAMES_TO_DUMP_DEFAULT);
45     mFirstFrameToDump = android::base::GetIntProperty(STARTING_FRAME_TO_DUMP_PROPERTY,
46                                                       STARTING_FRAME_TO_DUMP_DEFAULT);
47     bool enableDumping = android::base::GetBoolProperty(ENABLE_DUMPING_FILES_PROPERTY,
48                                                         ENABLE_DUMPING_FILES_DEFAULT);
49     ALOGD("enableDumping = %d, mFramesToDump = %d", enableDumping, mFramesToDump);
50 
51     if (enableDumping) {
52         mInDataFile = fopen(mInDataFileName, "wb");
53         if (mInDataFile == nullptr) {
54             ALOGD("Could not open file %s", mInDataFileName);
55         }
56 
57         mInSizeFile = fopen(mInSizeFileName, "wb");
58         if (mInSizeFile == nullptr) {
59             ALOGD("Could not open file %s", mInSizeFileName);
60         }
61 
62         mDav1dOutYuvFile = fopen(mDav1dOutYuvFileName, "wb");
63         if (mDav1dOutYuvFile == nullptr) {
64             ALOGD("Could not open file %s", mDav1dOutYuvFileName);
65         }
66     }
67 }
68 
destroyDumping()69 void C2SoftDav1dDump::destroyDumping() {
70     if (mInDataFile != nullptr) {
71         fclose(mInDataFile);
72         mInDataFile = nullptr;
73     }
74 
75     if (mInSizeFile != nullptr) {
76         fclose(mInSizeFile);
77         mInSizeFile = nullptr;
78     }
79 
80     if (mDav1dOutYuvFile != nullptr) {
81         fclose(mDav1dOutYuvFile);
82         mDav1dOutYuvFile = nullptr;
83     }
84 }
85 
dumpInput(uint8_t * ptr,int size)86 void C2SoftDav1dDump::dumpInput(uint8_t* ptr, int size) {
87     if (mInDataFile) {
88         int ret = fwrite(ptr, 1, size, mInDataFile);
89 
90         if (ret != size) {
91             ALOGE("Error in fwrite %s, requested %d, returned %d", mInDataFileName, size, ret);
92         }
93     }
94 
95     // Dump the size per inputBuffer if dumping is enabled.
96     if (mInSizeFile) {
97         int ret = fwrite(&size, 1, 4, mInSizeFile);
98 
99         if (ret != 4) {
100             ALOGE("Error in fwrite %s, requested %d, returned %d", mInSizeFileName, 4, ret);
101         }
102     }
103 }
104 
105 template <typename T>
dumpOutput(const T * srcY,const T * srcU,const T * srcV,size_t srcYStride,size_t srcUStride,size_t srcVStride,int width,int height)106 void C2SoftDav1dDump::dumpOutput(const T* srcY, const T* srcU, const T* srcV, size_t srcYStride,
107                                  size_t srcUStride, size_t srcVStride, int width, int height) {
108     mOutputCount++;
109     FILE* fp_out = mDav1dOutYuvFile;
110     int typeSize = sizeof(T);
111     if (fp_out && mOutputCount >= mFirstFrameToDump &&
112         mOutputCount <= (mFirstFrameToDump + mFramesToDump - 1)) {
113         for (int i = 0; i < height; i++) {
114             int ret =
115                     fwrite((uint8_t*)srcY + i * srcYStride * typeSize, 1, width * typeSize, fp_out);
116             if (ret != width * typeSize) {
117                 ALOGE("Error in fwrite, requested %d, returned %d", width * typeSize, ret);
118                 break;
119             }
120         }
121 
122         for (int i = 0; i < height / 2; i++) {
123             int ret = fwrite((uint8_t*)srcU + i * srcUStride * typeSize, 1, width * typeSize / 2,
124                              fp_out);
125             if (ret != width * typeSize / 2) {
126                 ALOGE("Error in fwrite, requested %d, returned %d", width * typeSize / 2, ret);
127                 break;
128             }
129         }
130 
131         for (int i = 0; i < height / 2; i++) {
132             int ret = fwrite((uint8_t*)srcV + i * srcVStride * typeSize, 1, width * typeSize / 2,
133                              fp_out);
134             if (ret != width * typeSize / 2) {
135                 ALOGE("Error in fwrite, requested %d, returned %d", width * typeSize / 2, ret);
136                 break;
137             }
138         }
139     }
140 }
141 
writeDav1dOutYuvFile(const Dav1dPicture & p)142 void C2SoftDav1dDump::writeDav1dOutYuvFile(const Dav1dPicture& p) {
143     if (mDav1dOutYuvFile != NULL) {
144         uint8_t* ptr;
145         const int hbd = p.p.bpc > 8;
146 
147         ptr = (uint8_t*)p.data[0];
148         for (int y = 0; y < p.p.h; y++) {
149             int iSize = p.p.w << hbd;
150             int ret = fwrite(ptr, 1, iSize, mDav1dOutYuvFile);
151             if (ret != iSize) {
152                 ALOGE("Error in fwrite %s, requested %d, returned %d", mDav1dOutYuvFileName, iSize,
153                       ret);
154                 break;
155             }
156 
157             ptr += p.stride[0];
158         }
159 
160         if (p.p.layout != DAV1D_PIXEL_LAYOUT_I400) {
161             // u/v
162             const int ss_ver = p.p.layout == DAV1D_PIXEL_LAYOUT_I420;
163             const int ss_hor = p.p.layout != DAV1D_PIXEL_LAYOUT_I444;
164             const int cw = (p.p.w + ss_hor) >> ss_hor;
165             const int ch = (p.p.h + ss_ver) >> ss_ver;
166             for (int pl = 1; pl <= 2; pl++) {
167                 ptr = (uint8_t*)p.data[pl];
168                 for (int y = 0; y < ch; y++) {
169                     int iSize = cw << hbd;
170                     int ret = fwrite(ptr, 1, cw << hbd, mDav1dOutYuvFile);
171                     if (ret != iSize) {
172                         ALOGE("Error in fwrite %s, requested %d, returned %d", mDav1dOutYuvFileName,
173                               iSize, ret);
174                         break;
175                     }
176                     ptr += p.stride[1];
177                 }
178             }
179         }
180     }
181 }
182 
183 template void C2SoftDav1dDump::dumpOutput<uint8_t>(const uint8_t* srcY, const uint8_t* srcU,
184                                                    const uint8_t* srcV, size_t srcYStride,
185                                                    size_t srcUStride, size_t srcVStride, int width,
186                                                    int height);
187 template void C2SoftDav1dDump::dumpOutput<uint16_t>(const uint16_t* srcY, const uint16_t* srcU,
188                                                     const uint16_t* srcV, size_t srcYStride,
189                                                     size_t srcUStride, size_t srcVStride, int width,
190                                                     int height);
191 }  // namespace android