1 /*
2  * Copyright (C) 2019 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 
17 #ifndef __BENCHMARK_COMMON_H__
18 #define __BENCHMARK_COMMON_H__
19 
20 #include <sys/stat.h>
21 #include <inttypes.h>
22 #include <mutex>
23 #include <queue>
24 #include <thread>
25 #include <iostream>
26 
27 #include <media/NdkMediaCodec.h>
28 #include <media/NdkMediaError.h>
29 
30 #include "Stats.h"
31 #define UNUSED(x) (void)(x)
32 
33 using namespace std;
34 
35 constexpr uint32_t kQueueDequeueTimeoutUs = 1000;
36 constexpr uint32_t kMaxCSDStrlen = 16;
37 constexpr uint32_t kMaxBufferSize = 1024 * 1024 * 16;
38 // Change in kDefaultAudioEncodeFrameSize should also be taken to
39 // AUDIO_ENCODE_DEFAULT_MAX_INPUT_SIZE present in Encoder.java
40 constexpr uint32_t kDefaultAudioEncodeFrameSize = 4096;
41 
42 template <typename T>
43 class CallBackQueue {
44   public:
CallBackQueue()45     CallBackQueue() {}
~CallBackQueue()46     ~CallBackQueue() {}
47 
push(T elem)48     void push(T elem) {
49         bool needsNotify = false;
50         {
51             lock_guard<mutex> lock(mMutex);
52             needsNotify = mQueue.empty();
53             mQueue.push(move(elem));
54         }
55         if (needsNotify) mQueueNotEmptyCondition.notify_one();
56     }
57 
pop()58     T pop() {
59         unique_lock<mutex> lock(mMutex);
60         if (mQueue.empty()) {
61             mQueueNotEmptyCondition.wait(lock, [this]() { return !mQueue.empty(); });
62         }
63         auto result = mQueue.front();
64         mQueue.pop();
65         return result;
66     }
67 
68   private:
69     mutex mMutex;
70     queue<T> mQueue;
71     condition_variable mQueueNotEmptyCondition;
72 };
73 
74 class CallBackHandle {
75   public:
CallBackHandle()76     CallBackHandle() : mSawError(false), mIsDone(false), mStats(nullptr) {
77         mStats = new Stats();
78     }
79 
~CallBackHandle()80     virtual ~CallBackHandle() {
81         if (mIOThread.joinable()) mIOThread.join();
82         if (mStats) delete mStats;
83     }
84 
85     void ioThread();
86 
87     // Implementation in child class (Decoder/Encoder)
onInputAvailable(AMediaCodec * codec,int32_t index)88     virtual void onInputAvailable(AMediaCodec *codec, int32_t index) {
89         (void)codec;
90         (void)index;
91     }
onFormatChanged(AMediaCodec * codec,AMediaFormat * format)92     virtual void onFormatChanged(AMediaCodec *codec, AMediaFormat *format) {
93         (void)codec;
94         (void)format;
95     }
onError(AMediaCodec * codec,media_status_t err)96     virtual void onError(AMediaCodec *codec, media_status_t err) {
97         (void)codec;
98         (void)err;
99     }
onOutputAvailable(AMediaCodec * codec,int32_t index,AMediaCodecBufferInfo * bufferInfo)100     virtual void onOutputAvailable(AMediaCodec *codec, int32_t index,
101                                    AMediaCodecBufferInfo *bufferInfo) {
102         (void)codec;
103         (void)index;
104         (void)bufferInfo;
105     }
106 
getStats()107     Stats *getStats() { return mStats; }
108 
109     // Keep a queue of all function callbacks.
110     typedef function<void()> IOTask;
111     CallBackQueue<IOTask> mIOQueue;
112     thread mIOThread;
113     bool mSawError;
114     bool mIsDone;
115 
116   protected:
117     Stats *mStats;
118 };
119 
120 // Async API's callback
121 void OnInputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index);
122 
123 void OnOutputAvailableCB(AMediaCodec *codec, void *userdata, int32_t index,
124                          AMediaCodecBufferInfo *bufferInfo);
125 
126 void OnFormatChangedCB(AMediaCodec *codec, void *userdata, AMediaFormat *format);
127 
128 void OnErrorCB(AMediaCodec *codec, void * /* userdata */, media_status_t err, int32_t actionCode,
129                const char *detail);
130 
131 // Utility to create and configure AMediaCodec
132 AMediaCodec *createMediaCodec(AMediaFormat *format, const char *mime, string codecName,
133                               bool isEncoder);
134 
135 #endif  // __BENCHMARK_COMMON_H__
136