1 /*
2  * Copyright 2015 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 SOFT_MPEG2_H_
18 
19 #define SOFT_MPEG2_H_
20 
21 #include <media/stagefright/omx/SoftVideoDecoderOMXComponent.h>
22 #include <sys/time.h>
23 
24 namespace android {
25 
26 #define ivd_aligned_malloc(alignment, size) memalign(alignment, size)
27 #define ivd_aligned_free(buf) free(buf)
28 
29 /** Number of entries in the time-stamp array */
30 #define MAX_TIME_STAMPS 64
31 
32 /** Maximum number of cores supported by the codec */
33 #define CODEC_MAX_NUM_CORES 4
34 
35 #define CODEC_MAX_WIDTH     1920
36 
37 #define CODEC_MAX_HEIGHT    1088
38 
39 /** Input buffer size */
40 #define INPUT_BUF_SIZE (1024 * 1024)
41 
42 #define MIN(a, b) ((a) < (b)) ? (a) : (b)
43 
44 /** Used to remove warnings about unused parameters */
45 #define UNUSED(x) ((void)(x))
46 
47 /** Get time */
48 #define GETTIME(a, b) gettimeofday(a, b);
49 
50 /** Compute difference between start and end */
51 #define TIME_DIFF(start, end, diff) \
52     diff = (((end).tv_sec - (start).tv_sec) * 1000000) + \
53             ((end).tv_usec - (start).tv_usec);
54 
55 struct SoftMPEG2 : public SoftVideoDecoderOMXComponent {
56     SoftMPEG2(
57             const char *name, const OMX_CALLBACKTYPE *callbacks,
58             OMX_PTR appData, OMX_COMPONENTTYPE **component);
59 
60 protected:
61     virtual ~SoftMPEG2();
62 
63     virtual void onQueueFilled(OMX_U32 portIndex);
64     virtual void onPortFlushCompleted(OMX_U32 portIndex);
65     virtual void onReset();
66     virtual int getColorAspectPreference();
67     virtual OMX_ERRORTYPE internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR params);
68 private:
69     // Number of input and output buffers
70     enum {
71         kNumBuffers = 8
72     };
73 
74     iv_obj_t *mCodecCtx;         // Codec context
75     iv_mem_rec_t *mMemRecords;   // Memory records requested by the codec
76     size_t mNumMemRecords;       // Number of memory records requested by the codec
77 
78     size_t mNumCores;            // Number of cores to be uesd by the codec
79 
80     struct timeval mTimeStart;   // Time at the start of decode()
81     struct timeval mTimeEnd;     // Time at the end of decode()
82 
83     // Internal buffer to be used to flush out the buffers from decoder
84     uint8_t *mFlushOutBuffer;
85 
86     // Status of entries in the timestamp array
87     bool mTimeStampsValid[MAX_TIME_STAMPS];
88 
89     // Timestamp array - Since codec does not take 64 bit timestamps,
90     // they are maintained in the plugin
91     OMX_S64 mTimeStamps[MAX_TIME_STAMPS];
92 
93 #ifdef FILE_DUMP_ENABLE
94     char mInFile[200];
95 #endif /* FILE_DUMP_ENABLE */
96 
97     OMX_COLOR_FORMATTYPE mOmxColorFormat;    // OMX Color format
98     IV_COLOR_FORMAT_T mIvColorFormat;        // Ittiam Color format
99 
100     bool mIsInFlush;        // codec is flush mode
101     bool mReceivedEOS;      // EOS is receieved on input port
102     bool mInitNeeded;
103     uint32_t mNewWidth;
104     uint32_t mNewHeight;
105     // The input stream has changed to a different resolution, which is still supported by the
106     // codec. So the codec is switching to decode the new resolution.
107     bool mChangingResolution;
108     bool mFlushNeeded;
109     bool mSignalledError;
110     bool mWaitForI;
111     size_t mStride;
112 
113     status_t initDecoder();
114     status_t deInitDecoder();
115     status_t setFlushMode();
116     status_t setParams(size_t stride);
117     void logVersion();
118     status_t setNumCores();
119     status_t resetDecoder();
120     status_t resetPlugin();
121     status_t reInitDecoder();
122 
123     bool setDecodeArgs(
124             ivd_video_decode_ip_t *ps_dec_ip,
125             ivd_video_decode_op_t *ps_dec_op,
126             OMX_BUFFERHEADERTYPE *inHeader,
127             OMX_BUFFERHEADERTYPE *outHeader,
128             size_t timeStampIx);
129 
130     bool getSeqInfo();
131 
132     DISALLOW_EVIL_CONSTRUCTORS(SoftMPEG2);
133 };
134 
135 #ifdef FILE_DUMP_ENABLE
136 
137 #define INPUT_DUMP_PATH     "/sdcard/media/mpeg2d_input"
138 #define INPUT_DUMP_EXT      "m2v"
139 
140 #define GENERATE_FILE_NAMES() {                         \
141     GETTIME(&mTimeStart, NULL);                         \
142     strcpy(mInFile, "");                                \
143     sprintf(mInFile, "%s_%ld.%ld.%s", INPUT_DUMP_PATH,  \
144             mTimeStart.tv_sec, mTimeStart.tv_usec,      \
145             INPUT_DUMP_EXT);                            \
146 }
147 
148 #define CREATE_DUMP_FILE(m_filename) {                  \
149     FILE *fp = fopen(m_filename, "wb");                 \
150     if (fp != NULL) {                                   \
151         fclose(fp);                                     \
152     } else {                                            \
153         ALOGD("Could not open file %s", m_filename);    \
154     }                                                   \
155 }
156 #define DUMP_TO_FILE(m_filename, m_buf, m_size)         \
157 {                                                       \
158     FILE *fp = fopen(m_filename, "ab");                 \
159     if (fp != NULL && m_buf != NULL) {                  \
160         int i;                                          \
161         i = fwrite(m_buf, 1, m_size, fp);               \
162         ALOGD("fwrite ret %d to write %d", i, m_size);  \
163         if (i != (int)m_size) {                         \
164             ALOGD("Error in fwrite, returned %d", i);   \
165             perror("Error in write to file");           \
166         }                                               \
167         fclose(fp);                                     \
168     } else {                                            \
169         ALOGD("Could not write to file %s", m_filename);\
170     }                                                   \
171 }
172 #else /* FILE_DUMP_ENABLE */
173 #define INPUT_DUMP_PATH
174 #define INPUT_DUMP_EXT
175 #define OUTPUT_DUMP_PATH
176 #define OUTPUT_DUMP_EXT
177 #define GENERATE_FILE_NAMES()
178 #define CREATE_DUMP_FILE(m_filename)
179 #define DUMP_TO_FILE(m_filename, m_buf, m_size)
180 #endif /* FILE_DUMP_ENABLE */
181 
182 } // namespace android
183 
184 #endif  // SOFT_MPEG2_H_
185