├── .gitignore
├── LICENSE
├── MediaCodecTest16
├── .classpath
├── .cproject
├── .project
├── AndroidManifest.xml
├── LICENSE
├── jni
│ ├── Android.mk
│ ├── Application.mk
│ ├── Effector.cpp
│ ├── Effector.h
│ ├── Utils.cpp
│ ├── Utils.h
│ ├── cnvavc.c
│ ├── jp_morihirosoft_mediacodectest16_MainActivity.cpp
│ └── jp_morihirosoft_mediacodectest16_MainActivity.h
├── project.properties
├── res
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── layout
│ │ └── main_activity.xml
│ └── values
│ │ └── strings.xml
└── src
│ └── jp
│ └── morihirosoft
│ └── mediacodectest16
│ ├── CameraView.java
│ ├── EffectView.java
│ ├── MainActivity.java
│ ├── MyRecorder.java
│ └── VideoParam.java
├── MediaCodecTest18
├── .classpath
├── .project
├── AndroidManifest.xml
├── LICENSE
├── project.properties
├── res
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── layout
│ │ └── main_activity.xml
│ └── values
│ │ └── strings.xml
└── src
│ └── jp
│ └── morihirosoft
│ └── mediacodectest18
│ ├── CameraView.java
│ ├── GlUtil.java
│ ├── InputSurface.java
│ ├── MainActivity.java
│ ├── MyRecorder.java
│ ├── MyRenderer.java
│ ├── RenderFbo.java
│ ├── RenderScreen.java
│ ├── RenderSrfTex.java
│ └── VideoParam.java
├── README.md
├── screenshot16.png
└── screenshot18.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # built application files
2 | *.apk
3 | *.ap_
4 |
5 | # files for the dex VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # generated files
12 | bin/
13 | gen/
14 | obj/
15 | libs/
16 |
17 | # Local configuration file (sdk path, etc)
18 | local.properties
19 |
20 | # Eclipse project files
21 | #.classpath
22 | #.project
23 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction, and
10 | distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright
13 | owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all other entities
16 | that control, are controlled by, or are under common control with that entity.
17 | For the purposes of this definition, "control" means (i) the power, direct or
18 | indirect, to cause the direction or management of such entity, whether by
19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20 | outstanding shares, or (iii) beneficial ownership of such entity.
21 |
22 | "You" (or "Your") shall mean an individual or Legal Entity exercising
23 | permissions granted by this License.
24 |
25 | "Source" form shall mean the preferred form for making modifications, including
26 | but not limited to software source code, documentation source, and configuration
27 | files.
28 |
29 | "Object" form shall mean any form resulting from mechanical transformation or
30 | translation of a Source form, including but not limited to compiled object code,
31 | generated documentation, and conversions to other media types.
32 |
33 | "Work" shall mean the work of authorship, whether in Source or Object form, made
34 | available under the License, as indicated by a copyright notice that is included
35 | in or attached to the work (an example is provided in the Appendix below).
36 |
37 | "Derivative Works" shall mean any work, whether in Source or Object form, that
38 | is based on (or derived from) the Work and for which the editorial revisions,
39 | annotations, elaborations, or other modifications represent, as a whole, an
40 | original work of authorship. For the purposes of this License, Derivative Works
41 | shall not include works that remain separable from, or merely link (or bind by
42 | name) to the interfaces of, the Work and Derivative Works thereof.
43 |
44 | "Contribution" shall mean any work of authorship, including the original version
45 | of the Work and any modifications or additions to that Work or Derivative Works
46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work
47 | by the copyright owner or by an individual or Legal Entity authorized to submit
48 | on behalf of the copyright owner. For the purposes of this definition,
49 | "submitted" means any form of electronic, verbal, or written communication sent
50 | to the Licensor or its representatives, including but not limited to
51 | communication on electronic mailing lists, source code control systems, and
52 | issue tracking systems that are managed by, or on behalf of, the Licensor for
53 | the purpose of discussing and improving the Work, but excluding communication
54 | that is conspicuously marked or otherwise designated in writing by the copyright
55 | owner as "Not a Contribution."
56 |
57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58 | of whom a Contribution has been received by Licensor and subsequently
59 | incorporated within the Work.
60 |
61 | 2. Grant of Copyright License.
62 |
63 | Subject to the terms and conditions of this License, each Contributor hereby
64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65 | irrevocable copyright license to reproduce, prepare Derivative Works of,
66 | publicly display, publicly perform, sublicense, and distribute the Work and such
67 | Derivative Works in Source or Object form.
68 |
69 | 3. Grant of Patent License.
70 |
71 | Subject to the terms and conditions of this License, each Contributor hereby
72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73 | irrevocable (except as stated in this section) patent license to make, have
74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75 | such license applies only to those patent claims licensable by such Contributor
76 | that are necessarily infringed by their Contribution(s) alone or by combination
77 | of their Contribution(s) with the Work to which such Contribution(s) was
78 | submitted. If You institute patent litigation against any entity (including a
79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80 | Contribution incorporated within the Work constitutes direct or contributory
81 | patent infringement, then any patent licenses granted to You under this License
82 | for that Work shall terminate as of the date such litigation is filed.
83 |
84 | 4. Redistribution.
85 |
86 | You may reproduce and distribute copies of the Work or Derivative Works thereof
87 | in any medium, with or without modifications, and in Source or Object form,
88 | provided that You meet the following conditions:
89 |
90 | You must give any other recipients of the Work or Derivative Works a copy of
91 | this License; and
92 | You must cause any modified files to carry prominent notices stating that You
93 | changed the files; and
94 | You must retain, in the Source form of any Derivative Works that You distribute,
95 | all copyright, patent, trademark, and attribution notices from the Source form
96 | of the Work, excluding those notices that do not pertain to any part of the
97 | Derivative Works; and
98 | If the Work includes a "NOTICE" text file as part of its distribution, then any
99 | Derivative Works that You distribute must include a readable copy of the
100 | attribution notices contained within such NOTICE file, excluding those notices
101 | that do not pertain to any part of the Derivative Works, in at least one of the
102 | following places: within a NOTICE text file distributed as part of the
103 | Derivative Works; within the Source form or documentation, if provided along
104 | with the Derivative Works; or, within a display generated by the Derivative
105 | Works, if and wherever such third-party notices normally appear. The contents of
106 | the NOTICE file are for informational purposes only and do not modify the
107 | License. You may add Your own attribution notices within Derivative Works that
108 | You distribute, alongside or as an addendum to the NOTICE text from the Work,
109 | provided that such additional attribution notices cannot be construed as
110 | modifying the License.
111 | You may add Your own copyright statement to Your modifications and may provide
112 | additional or different license terms and conditions for use, reproduction, or
113 | distribution of Your modifications, or for any such Derivative Works as a whole,
114 | provided Your use, reproduction, and distribution of the Work otherwise complies
115 | with the conditions stated in this License.
116 |
117 | 5. Submission of Contributions.
118 |
119 | Unless You explicitly state otherwise, any Contribution intentionally submitted
120 | for inclusion in the Work by You to the Licensor shall be under the terms and
121 | conditions of this License, without any additional terms or conditions.
122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of
123 | any separate license agreement you may have executed with Licensor regarding
124 | such Contributions.
125 |
126 | 6. Trademarks.
127 |
128 | This License does not grant permission to use the trade names, trademarks,
129 | service marks, or product names of the Licensor, except as required for
130 | reasonable and customary use in describing the origin of the Work and
131 | reproducing the content of the NOTICE file.
132 |
133 | 7. Disclaimer of Warranty.
134 |
135 | Unless required by applicable law or agreed to in writing, Licensor provides the
136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138 | including, without limitation, any warranties or conditions of TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140 | solely responsible for determining the appropriateness of using or
141 | redistributing the Work and assume any risks associated with Your exercise of
142 | permissions under this License.
143 |
144 | 8. Limitation of Liability.
145 |
146 | In no event and under no legal theory, whether in tort (including negligence),
147 | contract, or otherwise, unless required by applicable law (such as deliberate
148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be
149 | liable to You for damages, including any direct, indirect, special, incidental,
150 | or consequential damages of any character arising as a result of this License or
151 | out of the use or inability to use the Work (including but not limited to
152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153 | any and all other commercial damages or losses), even if such Contributor has
154 | been advised of the possibility of such damages.
155 |
156 | 9. Accepting Warranty or Additional Liability.
157 |
158 | While redistributing the Work or Derivative Works thereof, You may choose to
159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160 | other liability obligations and/or rights consistent with this License. However,
161 | in accepting such obligations, You may act only on Your own behalf and on Your
162 | sole responsibility, not on behalf of any other Contributor, and only if You
163 | agree to indemnify, defend, and hold each Contributor harmless for any liability
164 | incurred by, or claims asserted against, such Contributor by reason of your
165 | accepting any such warranty or additional liability.
166 |
167 | END OF TERMS AND CONDITIONS
168 |
169 | APPENDIX: How to apply the Apache License to your work
170 |
171 | To apply the Apache License to your work, attach the following boilerplate
172 | notice, with the fields enclosed by brackets "[]" replaced with your own
173 | identifying information. (Don't include the brackets!) The text should be
174 | enclosed in the appropriate comment syntax for the file format. We also
175 | recommend that a file or class name and description of purpose be included on
176 | the same "printed page" as the copyright notice for easier identification within
177 | third-party archives.
178 |
179 | Copyright [yyyy] [name of copyright owner]
180 |
181 | Licensed under the Apache License, Version 2.0 (the "License");
182 | you may not use this file except in compliance with the License.
183 | You may obtain a copy of the License at
184 |
185 | http://www.apache.org/licenses/LICENSE-2.0
186 |
187 | Unless required by applicable law or agreed to in writing, software
188 | distributed under the License is distributed on an "AS IS" BASIS,
189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190 | See the License for the specific language governing permissions and
191 | limitations under the License.
192 |
--------------------------------------------------------------------------------
/MediaCodecTest16/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/MediaCodecTest16/.cproject:
--------------------------------------------------------------------------------
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 |
--------------------------------------------------------------------------------
/MediaCodecTest16/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | MediaCodecTest16
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 |
14 |
15 | com.android.ide.eclipse.adt.ResourceManagerBuilder
16 |
17 |
18 |
19 |
20 | com.android.ide.eclipse.adt.PreCompilerBuilder
21 |
22 |
23 |
24 |
25 | org.eclipse.jdt.core.javabuilder
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.ApkBuilder
31 |
32 |
33 |
34 |
35 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
36 | full,incremental,
37 |
38 |
39 |
40 |
41 |
42 | com.android.ide.eclipse.adt.AndroidNature
43 | org.eclipse.jdt.core.javanature
44 | org.eclipse.cdt.core.cnature
45 | org.eclipse.cdt.core.ccnature
46 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
47 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
48 |
49 |
50 |
--------------------------------------------------------------------------------
/MediaCodecTest16/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
19 |
23 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/MediaCodecTest16/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction, and
10 | distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright
13 | owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all other entities
16 | that control, are controlled by, or are under common control with that entity.
17 | For the purposes of this definition, "control" means (i) the power, direct or
18 | indirect, to cause the direction or management of such entity, whether by
19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20 | outstanding shares, or (iii) beneficial ownership of such entity.
21 |
22 | "You" (or "Your") shall mean an individual or Legal Entity exercising
23 | permissions granted by this License.
24 |
25 | "Source" form shall mean the preferred form for making modifications, including
26 | but not limited to software source code, documentation source, and configuration
27 | files.
28 |
29 | "Object" form shall mean any form resulting from mechanical transformation or
30 | translation of a Source form, including but not limited to compiled object code,
31 | generated documentation, and conversions to other media types.
32 |
33 | "Work" shall mean the work of authorship, whether in Source or Object form, made
34 | available under the License, as indicated by a copyright notice that is included
35 | in or attached to the work (an example is provided in the Appendix below).
36 |
37 | "Derivative Works" shall mean any work, whether in Source or Object form, that
38 | is based on (or derived from) the Work and for which the editorial revisions,
39 | annotations, elaborations, or other modifications represent, as a whole, an
40 | original work of authorship. For the purposes of this License, Derivative Works
41 | shall not include works that remain separable from, or merely link (or bind by
42 | name) to the interfaces of, the Work and Derivative Works thereof.
43 |
44 | "Contribution" shall mean any work of authorship, including the original version
45 | of the Work and any modifications or additions to that Work or Derivative Works
46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work
47 | by the copyright owner or by an individual or Legal Entity authorized to submit
48 | on behalf of the copyright owner. For the purposes of this definition,
49 | "submitted" means any form of electronic, verbal, or written communication sent
50 | to the Licensor or its representatives, including but not limited to
51 | communication on electronic mailing lists, source code control systems, and
52 | issue tracking systems that are managed by, or on behalf of, the Licensor for
53 | the purpose of discussing and improving the Work, but excluding communication
54 | that is conspicuously marked or otherwise designated in writing by the copyright
55 | owner as "Not a Contribution."
56 |
57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58 | of whom a Contribution has been received by Licensor and subsequently
59 | incorporated within the Work.
60 |
61 | 2. Grant of Copyright License.
62 |
63 | Subject to the terms and conditions of this License, each Contributor hereby
64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65 | irrevocable copyright license to reproduce, prepare Derivative Works of,
66 | publicly display, publicly perform, sublicense, and distribute the Work and such
67 | Derivative Works in Source or Object form.
68 |
69 | 3. Grant of Patent License.
70 |
71 | Subject to the terms and conditions of this License, each Contributor hereby
72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73 | irrevocable (except as stated in this section) patent license to make, have
74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75 | such license applies only to those patent claims licensable by such Contributor
76 | that are necessarily infringed by their Contribution(s) alone or by combination
77 | of their Contribution(s) with the Work to which such Contribution(s) was
78 | submitted. If You institute patent litigation against any entity (including a
79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80 | Contribution incorporated within the Work constitutes direct or contributory
81 | patent infringement, then any patent licenses granted to You under this License
82 | for that Work shall terminate as of the date such litigation is filed.
83 |
84 | 4. Redistribution.
85 |
86 | You may reproduce and distribute copies of the Work or Derivative Works thereof
87 | in any medium, with or without modifications, and in Source or Object form,
88 | provided that You meet the following conditions:
89 |
90 | You must give any other recipients of the Work or Derivative Works a copy of
91 | this License; and
92 | You must cause any modified files to carry prominent notices stating that You
93 | changed the files; and
94 | You must retain, in the Source form of any Derivative Works that You distribute,
95 | all copyright, patent, trademark, and attribution notices from the Source form
96 | of the Work, excluding those notices that do not pertain to any part of the
97 | Derivative Works; and
98 | If the Work includes a "NOTICE" text file as part of its distribution, then any
99 | Derivative Works that You distribute must include a readable copy of the
100 | attribution notices contained within such NOTICE file, excluding those notices
101 | that do not pertain to any part of the Derivative Works, in at least one of the
102 | following places: within a NOTICE text file distributed as part of the
103 | Derivative Works; within the Source form or documentation, if provided along
104 | with the Derivative Works; or, within a display generated by the Derivative
105 | Works, if and wherever such third-party notices normally appear. The contents of
106 | the NOTICE file are for informational purposes only and do not modify the
107 | License. You may add Your own attribution notices within Derivative Works that
108 | You distribute, alongside or as an addendum to the NOTICE text from the Work,
109 | provided that such additional attribution notices cannot be construed as
110 | modifying the License.
111 | You may add Your own copyright statement to Your modifications and may provide
112 | additional or different license terms and conditions for use, reproduction, or
113 | distribution of Your modifications, or for any such Derivative Works as a whole,
114 | provided Your use, reproduction, and distribution of the Work otherwise complies
115 | with the conditions stated in this License.
116 |
117 | 5. Submission of Contributions.
118 |
119 | Unless You explicitly state otherwise, any Contribution intentionally submitted
120 | for inclusion in the Work by You to the Licensor shall be under the terms and
121 | conditions of this License, without any additional terms or conditions.
122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of
123 | any separate license agreement you may have executed with Licensor regarding
124 | such Contributions.
125 |
126 | 6. Trademarks.
127 |
128 | This License does not grant permission to use the trade names, trademarks,
129 | service marks, or product names of the Licensor, except as required for
130 | reasonable and customary use in describing the origin of the Work and
131 | reproducing the content of the NOTICE file.
132 |
133 | 7. Disclaimer of Warranty.
134 |
135 | Unless required by applicable law or agreed to in writing, Licensor provides the
136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138 | including, without limitation, any warranties or conditions of TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140 | solely responsible for determining the appropriateness of using or
141 | redistributing the Work and assume any risks associated with Your exercise of
142 | permissions under this License.
143 |
144 | 8. Limitation of Liability.
145 |
146 | In no event and under no legal theory, whether in tort (including negligence),
147 | contract, or otherwise, unless required by applicable law (such as deliberate
148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be
149 | liable to You for damages, including any direct, indirect, special, incidental,
150 | or consequential damages of any character arising as a result of this License or
151 | out of the use or inability to use the Work (including but not limited to
152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153 | any and all other commercial damages or losses), even if such Contributor has
154 | been advised of the possibility of such damages.
155 |
156 | 9. Accepting Warranty or Additional Liability.
157 |
158 | While redistributing the Work or Derivative Works thereof, You may choose to
159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160 | other liability obligations and/or rights consistent with this License. However,
161 | in accepting such obligations, You may act only on Your own behalf and on Your
162 | sole responsibility, not on behalf of any other Contributor, and only if You
163 | agree to indemnify, defend, and hold each Contributor harmless for any liability
164 | incurred by, or claims asserted against, such Contributor by reason of your
165 | accepting any such warranty or additional liability.
166 |
167 | END OF TERMS AND CONDITIONS
168 |
169 | APPENDIX: How to apply the Apache License to your work
170 |
171 | To apply the Apache License to your work, attach the following boilerplate
172 | notice, with the fields enclosed by brackets "[]" replaced with your own
173 | identifying information. (Don't include the brackets!) The text should be
174 | enclosed in the appropriate comment syntax for the file format. We also
175 | recommend that a file or class name and description of purpose be included on
176 | the same "printed page" as the copyright notice for easier identification within
177 | third-party archives.
178 |
179 | Copyright [yyyy] [name of copyright owner]
180 |
181 | Licensed under the Apache License, Version 2.0 (the "License");
182 | you may not use this file except in compliance with the License.
183 | You may obtain a copy of the License at
184 |
185 | http://www.apache.org/licenses/LICENSE-2.0
186 |
187 | Unless required by applicable law or agreed to in writing, software
188 | distributed under the License is distributed on an "AS IS" BASIS,
189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190 | See the License for the specific language governing permissions and
191 | limitations under the License.
192 |
--------------------------------------------------------------------------------
/MediaCodecTest16/jni/Android.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2013 MorihiroSoft
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 | LOCAL_PATH:= $(call my-dir)
17 |
18 | include $(CLEAR_VARS)
19 |
20 | LOCAL_ALLOW_UNDEFINED_SYMBOLS=false
21 |
22 | # Library name
23 | LOCAL_MODULE := MediaCodecTest16
24 |
25 | # Source files
26 | LOCAL_SRC_FILES := \
27 | Effector.cpp \
28 | Utils.cpp \
29 | cnvavc.c \
30 | jp_morihirosoft_mediacodectest16_MainActivity.cpp
31 |
32 | #
33 | LOCAL_CFLAGS := -Wall -Werror -Wno-deprecated
34 | LOCAL_LDLIBS := -llog -lm
35 |
36 | include $(BUILD_SHARED_LIBRARY)
37 |
--------------------------------------------------------------------------------
/MediaCodecTest16/jni/Application.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (C) 2013 MorihiroSoft
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 | # The ARMv7 is significanly faster due to the use of the hardware FPU
18 | APP_PLATFORM := android-9
19 | APP_ABI := armeabi-v7a
20 |
21 |
--------------------------------------------------------------------------------
/MediaCodecTest16/jni/Effector.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | #include "Effector.h"
17 |
18 | #define LOG_TAG "Effector"
19 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
20 | #if 0
21 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
22 | #else
23 | #define LOGI(...)
24 | #endif
25 |
26 | Effector::Effector(void)
27 | : mUtils(NULL)
28 | , mVideoWidth(0)
29 | , mVideoHeight(0)
30 | , mVideoArea(0)
31 | , mMaskP(NULL)
32 | {
33 | }
34 |
35 | Effector::~Effector(void)
36 | {
37 | quit();
38 | }
39 |
40 | int32_t Effector::init(Utils* utils, int32_t width, int32_t height, uint32_t* maskP)
41 | {
42 | mUtils = utils;
43 | mVideoWidth = width;
44 | mVideoHeight = height;
45 | mVideoArea = width * height;
46 | mMaskP = maskP;
47 | return 0;
48 | }
49 |
50 | int32_t Effector::quit(void)
51 | {
52 | return 0;
53 | }
54 |
55 | int32_t Effector::draw(uint8_t* src_yuv, uint32_t* dst_rgb)
56 | {
57 | mUtils->yuv_YUVtoRGB(src_yuv, dst_rgb);
58 |
59 | // Masking (effect sample)
60 | uint32_t* p = mMaskP;
61 | uint32_t* q = dst_rgb;
62 | for (int i=mVideoArea; i>0; i--) {
63 | if ((*p & 0xFF000000) != 0) {
64 | *q = *p;
65 | }
66 | p++;
67 | q++;
68 | }
69 |
70 | return 0;
71 | }
72 |
--------------------------------------------------------------------------------
/MediaCodecTest16/jni/Effector.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | #ifndef __EFFECTOR__
17 | #define __EFFECTOR__
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include "Utils.h"
28 |
29 | class Effector {
30 | protected:
31 | Utils* mUtils;
32 | int32_t mVideoWidth;
33 | int32_t mVideoHeight;
34 | int32_t mVideoArea;
35 | uint32_t* mMaskP;
36 |
37 | public:
38 | Effector(void);
39 | ~Effector(void);
40 | int32_t init(Utils* utils, int32_t width, int32_t height, uint32_t* maskP);
41 | int32_t quit(void);
42 | int32_t draw(uint8_t* src_yuv, uint32_t* dst_rgb);
43 | };
44 |
45 | #endif // __EFFECTOR__
46 |
--------------------------------------------------------------------------------
/MediaCodecTest16/jni/Utils.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "Utils.h"
23 |
24 | #define LOG_TAG "Utils"
25 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
26 | #if 0
27 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
28 | #else
29 | #define LOGI(...)
30 | #endif
31 |
32 | //---------------------------------------------------------------------
33 | // UTILS: PUBLIC METHODS
34 | //---------------------------------------------------------------------
35 | // Constructor
36 | Utils::Utils(int32_t width, int32_t height)
37 | {
38 | video_width = width;
39 | video_height = height;
40 | video_area = width * height;
41 |
42 | int32_t ret = yuv_init();
43 | if (ret != 0) {
44 | LOGE("%s(L=%d): yuv_init()=%d", __func__, __LINE__, ret);
45 | return;
46 | }
47 | }
48 |
49 | // Destructor
50 | Utils::~Utils()
51 | {
52 | int32_t ret = yuv_end();
53 | if (ret != 0) {
54 | LOGE("%s(L=%d): yuv_end()=%d", __func__, __LINE__, ret);
55 | return;
56 | }
57 | }
58 |
59 | //---------------------------------------------------------------------
60 | // YUV: PUBLIC METHODS
61 | //---------------------------------------------------------------------
62 | //
63 | int32_t Utils::yuv_init(void)
64 | {
65 | tmp_rgb = new uint32_t[video_area];
66 | if (tmp_rgb == NULL) {
67 | return -1;
68 | }
69 | tmp_yuv = new uint8_t[video_area * 3 / 2];
70 | if (tmp_yuv == NULL) {
71 | return -1;
72 | }
73 | return 0;
74 | }
75 |
76 | //
77 | int32_t Utils::yuv_end(void)
78 | {
79 | if (tmp_rgb != NULL) {
80 | delete[] tmp_rgb;
81 | tmp_rgb = NULL;
82 | }
83 | if (tmp_yuv != NULL) {
84 | delete[] tmp_yuv;
85 | tmp_yuv = NULL;
86 | }
87 | return 0;
88 | }
89 |
90 | // YUV(NV21)→ARGB(8888)
91 | uint32_t* Utils::yuv_YUVtoRGB(uint8_t* yuv, uint32_t* rgb32)
92 | {
93 | if (rgb32 == NULL) {
94 | rgb32 = tmp_rgb;
95 | }
96 | const uint32_t vw = video_width;
97 | const uint32_t vh = video_height;
98 | const uint32_t vw2 = vw >> 1;
99 | const uint32_t vh2 = vh >> 1;
100 | const uint32_t va = video_area;
101 | uint8_t* yP1 = &yuv[0];
102 | uint8_t* yP2 = &yuv[vw];
103 | uint8_t* vuP = &yuv[va];
104 | uint32_t* rgb32P1 = &rgb32[0];
105 | uint32_t* rgb32P2 = &rgb32[vw];
106 |
107 | for (uint32_t i=0; i262143 ? 262143 : r));
165 | g = (g<0 ? 0 : (g>262143 ? 262143 : g));
166 | b = (b<0 ? 0 : (b>262143 ? 262143 : b));
167 |
168 | return (uint32_t)(
169 | (0x00FF0000 & (r<< 6)) |
170 | (0x0000FF00 & (g>> 2)) |
171 | (0x000000FF & (b>>10)));
172 | }
173 |
174 | // ARGB(8888)→YUV(NV12)
175 | uint8_t* Utils::yuv_RGBtoNV12(uint32_t* rgb32, uint8_t* yuv)
176 | {
177 | const uint32_t vw = video_width;
178 | const uint32_t vh = video_height;
179 | const uint32_t va = video_area;
180 |
181 | int32_t yIndex = 0;
182 | int32_t uvIndex = va;
183 |
184 | for (uint32_t i=0,k=0; i> 16;
187 | const int32_t G = (rgb32[k] & 0x0000FF00) >> 8;
188 | const int32_t B = (rgb32[k] & 0x000000FF);
189 |
190 | const int32_t Y = (( 66*R + 129*G + 25*B + 128) >> 8) + 16;
191 | yuv[yIndex++] = (uint8_t) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
192 |
193 | if (i % 2 == 0 && j % 2 == 0) {
194 | const int32_t U = ((-38*R - 74*G + 112*B + 128) >> 8) + 128;
195 | const int32_t V = ((112*R - 94*G - 18*B + 128) >> 8) + 128;
196 | yuv[uvIndex++] = (uint8_t)((U<0) ? 0 : ((U > 255) ? 255 : U));
197 | yuv[uvIndex++] = (uint8_t)((V<0) ? 0 : ((V > 255) ? 255 : V));
198 | }
199 | }
200 | }
201 |
202 | return yuv;
203 | }
204 |
205 | // ARGB(8888)→YUV(NV21)
206 | uint8_t* Utils::yuv_RGBtoNV21(uint32_t* rgb32, uint8_t* yuv)
207 | {
208 | const uint32_t vw = video_width;
209 | const uint32_t vh = video_height;
210 | const uint32_t va = video_area;
211 |
212 | int32_t yIndex = 0;
213 | int32_t uvIndex = va;
214 |
215 | for (uint32_t i=0,k=0; i> 16;
218 | const int32_t G = (rgb32[k] & 0x0000FF00) >> 8;
219 | const int32_t B = (rgb32[k] & 0x000000FF);
220 |
221 | const int32_t Y = (( 66*R + 129*G + 25*B + 128) >> 8) + 16;
222 | yuv[yIndex++] = (uint8_t) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
223 |
224 | if (i % 2 == 0 && j % 2 == 0) {
225 | const int32_t V = ((112*R - 94*G - 18*B + 128) >> 8) + 128;
226 | const int32_t U = ((-38*R - 74*G + 112*B + 128) >> 8) + 128;
227 | yuv[uvIndex++] = (uint8_t)((V<0) ? 0 : ((V > 255) ? 255 : V));
228 | yuv[uvIndex++] = (uint8_t)((U<0) ? 0 : ((U > 255) ? 255 : U));
229 | }
230 | }
231 | }
232 |
233 | return yuv;
234 | }
235 |
236 | // ARGB(8888)→YUV(I420)
237 | uint8_t* Utils::yuv_RGBtoI420(uint32_t* rgb32, uint8_t* yuv)
238 | {
239 | const uint32_t vw = video_width;
240 | const uint32_t vh = video_height;
241 | const uint32_t va = video_area;
242 |
243 | int32_t yIndex = 0;
244 | int32_t uIndex = va;
245 | int32_t vIndex = va + va / 4;
246 |
247 | for (uint32_t i=0,k=0; i> 16;
250 | const int32_t G = (rgb32[k] & 0x0000FF00) >> 8;
251 | const int32_t B = (rgb32[k] & 0x000000FF);
252 |
253 | const int32_t Y = (( 66*R + 129*G + 25*B + 128) >> 8) + 16;
254 | yuv[yIndex++] = (uint8_t) ((Y < 0) ? 0 : ((Y > 255) ? 255 : Y));
255 |
256 | if (i % 2 == 0 && j % 2 == 0) {
257 | const int32_t U = ((-38*R - 74*G + 112*B + 128) >> 8) + 128;
258 | yuv[uIndex++] = (uint8_t)((U<0) ? 0 : ((U > 255) ? 255 : U));
259 |
260 | const int32_t V = ((112*R - 94*G - 18*B + 128) >> 8) + 128;
261 | yuv[vIndex++] = (uint8_t)((V<0) ? 0 : ((V > 255) ? 255 : V));
262 | }
263 | }
264 | }
265 |
266 | return yuv;
267 | }
268 |
--------------------------------------------------------------------------------
/MediaCodecTest16/jni/Utils.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | #ifndef __UTILS__
17 | #define __UTILS__
18 |
19 | //---------------------------------------------------------------------
20 | // Utilities
21 | //---------------------------------------------------------------------
22 | class Utils {
23 | //-----------------------------------------------------------------
24 | // UTILS
25 | //-----------------------------------------------------------------
26 | public:
27 | Utils(int32_t width, int32_t height);
28 | ~Utils();
29 |
30 | private:
31 | int32_t video_width;
32 | int32_t video_height;
33 | int32_t video_area;
34 |
35 | //-----------------------------------------------------------------
36 | // YUV
37 | //-----------------------------------------------------------------
38 | public:
39 | uint32_t* tmp_rgb;
40 | uint8_t* tmp_yuv;
41 |
42 | int32_t yuv_init(void);
43 | int32_t yuv_end(void);
44 | uint32_t* yuv_YUVtoRGB(uint8_t* yuv, uint32_t* rgb32=NULL);
45 | uint8_t* yuv_RGBtoYUV(uint32_t* rgb32, int32_t yuv_fmt=0, uint8_t* yuv=NULL);
46 |
47 | private:
48 | uint32_t yuv_YUVtoRGB_1(int32_t y, int32_t u, int32_t v);
49 | uint8_t* yuv_RGBtoNV12(uint32_t* rgb32, uint8_t* yuv);
50 | uint8_t* yuv_RGBtoNV21(uint32_t* rgb32, uint8_t* yuv);
51 | uint8_t* yuv_RGBtoI420(uint32_t* rgb32, uint8_t* yuv);
52 | };
53 |
54 | #endif // __UTILS__
55 |
--------------------------------------------------------------------------------
/MediaCodecTest16/jni/cnvavc.c:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include
26 | #define LOG_TAG "CNVAVC"
27 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
28 | #if 0
29 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
30 | #else
31 | #define LOGI(...)
32 | #endif
33 |
34 | #define BUF_SIZE (1024)
35 | #define INIT_FRAME_SIZE (1024)
36 | #define INIT_SPS_SIZE (256)
37 | #define INIT_PPS_SIZE (256)
38 |
39 | #pragma pack(1)
40 |
41 | //
42 | int32_t cnvavc(const char* src_path, const char* dst_path,
43 | int32_t video_w, int32_t video_h, int32_t fps)
44 | {
45 | const uint8_t START_PAT[] = {0x00,0x00,0x00,0x01};
46 | const uint8_t NAL_TYPE_MASK = 0x1F;
47 | const uint8_t NAL_TYPE_SPS = 0x07; // 0x67,0x27
48 | const uint8_t NAL_TYPE_PPS = 0x08; // 0x68,0x28
49 | const uint8_t NAL_TYPE_SYNC = 0x05; // 0x65,0x25
50 |
51 | //
52 | struct _frame_info {
53 | int32_t frame_idx;
54 | uint32_t addr;
55 | uint32_t size;
56 | uint8_t nal_type;
57 | };
58 |
59 | int32_t rcode = 0;
60 | FILE* src_fp = NULL;
61 | FILE* dst_fp = NULL;
62 | uint8_t* buf = NULL;
63 | uint8_t* bufP;
64 | uint32_t frame_info_cnt = 0;
65 | uint32_t frame_info_alc = 0;
66 | struct _frame_info* frame_infos = NULL;
67 | uint32_t full_frame_cnt = 0; // except SPS/PPS
68 | uint32_t sync_frame_cnt = 0;
69 | uint16_t sps_len = 0;
70 | uint32_t sps_alc = 0;
71 | uint8_t* sps_dat = NULL;
72 | uint16_t pps_len = 0;
73 | uint32_t pps_alc = 0;
74 | uint8_t* pps_dat = NULL;
75 | int32_t i, j;
76 | uint32_t num;
77 |
78 | do {
79 | //-------------------------------------------------------------
80 | // Phase 0 - Open/Create file and Others...
81 | //-------------------------------------------------------------
82 | frame_info_alc = INIT_FRAME_SIZE;
83 | sps_alc = INIT_SPS_SIZE;
84 | pps_alc = INIT_PPS_SIZE;
85 |
86 | // Allocate
87 | buf = (uint8_t *)malloc(sizeof(uint8_t) * BUF_SIZE);
88 | frame_infos = (struct _frame_info*)malloc(sizeof(struct _frame_info) * frame_info_alc);
89 | sps_dat = (uint8_t *)malloc(sizeof(uint8_t) * sps_alc);
90 | pps_dat = (uint8_t *)malloc(sizeof(uint8_t) * pps_alc);
91 | if (buf == NULL || frame_infos == NULL || sps_dat == NULL || pps_dat == NULL) {
92 | LOGE("%s(L=%d): malloc error", __func__, __LINE__);
93 | break;
94 | }
95 |
96 | // Open
97 | src_fp = fopen(src_path, "rb");
98 | if (src_fp == NULL) {
99 | LOGE("%s(L=%d): fopen error(src_path=%s)", __func__, __LINE__, src_path);
100 | break;
101 | }
102 |
103 | dst_fp = fopen(dst_path, "wb");
104 | if (dst_fp == NULL) {
105 | LOGE("%s(L=%d): fopen error(dst_path=%s)", __func__, __LINE__, dst_path);
106 | break;
107 | }
108 |
109 | //-------------------------------------------------------------
110 | // Phase 1 - Scan
111 | //-------------------------------------------------------------
112 | int32_t start_idx = 0;
113 | int32_t sps_flg = 0;
114 | int32_t pps_flg = 0;
115 |
116 | // Check frame address.
117 | uint32_t src_addr = 0;
118 | while(!feof(src_fp)) {
119 | num = fread(buf, 1, BUF_SIZE, src_fp);
120 | for (i=0,bufP=buf; i 0) {
159 | // Failure
160 | LOGE("%s(L=%d): Multiple SPS, src_addr=0x%08X, i=0x%08X", __func__, __LINE__, src_addr, i);
161 | rcode = -1;
162 | break;
163 | }
164 | sps_dat[sps_len++] = *bufP;
165 | sps_flg = 1;
166 | } else if (nal_type == NAL_TYPE_PPS) {
167 | frame_infos[frame_info_cnt].frame_idx = -2;
168 | if (pps_len > 0) {
169 | // Failure
170 | LOGE("%s(L=%d): Multiple PPS, src_addr=0x%08X, i=0x%08X", __func__, __LINE__, src_addr, i);
171 | rcode = -2;
172 | break;
173 | }
174 | pps_dat[pps_len++] = *bufP;
175 | pps_flg = 1;
176 | } else {
177 | frame_infos[frame_info_cnt].frame_idx = full_frame_cnt++;
178 | if (nal_type == NAL_TYPE_SYNC) {
179 | sync_frame_cnt++;
180 | }
181 | }
182 | frame_infos[frame_info_cnt].addr = src_addr + i - sizeof(START_PAT);
183 | frame_infos[frame_info_cnt].nal_type = nal_type;
184 | frame_info_cnt++;
185 | } else if (*bufP == START_PAT[start_idx]) {
186 | start_idx++;
187 | } else if (start_idx > 0 && *bufP != START_PAT[start_idx-1]) {
188 | start_idx = 0;
189 | }
190 | }
191 | src_addr += num;
192 | }
193 | // Failure ?
194 | if (rcode != 0) {
195 | LOGE("%s(L=%d): Failure", __func__, __LINE__);
196 | break;
197 | }
198 | if (sps_len == 0 || pps_len == 0) {
199 | LOGE("%s(L=%d): Failure, sps_len=%d, pps_len=%d", __func__, __LINE__, sps_len, pps_len);
200 | rcode = -3;
201 | break;
202 | }
203 |
204 | // Convert address to size.
205 | for (i=0; i variable size
321 | } box_stsd_avc1;
322 | } box_stsd = {
323 | htonl(sizeof(struct _stsd) + stsd_avc1_avcC_size),
324 | {'s','t','s','d'},
325 | htonl(0x00000000),
326 | htonl(1),
327 | {
328 | htonl(sizeof(struct _stsd_avc1) + stsd_avc1_avcC_size),
329 | {'a','v','c','1'},
330 | {0,},
331 | htons(1),
332 | 0,
333 | {0,},
334 | {0,},
335 | htons((short)video_w),
336 | htons((short)video_h),
337 | htonl(0x00480000),
338 | htonl(0x00480000),
339 | {0,},
340 | htons(1),
341 | 0,
342 | {0,},
343 | htons(24),
344 | htons(-1),
345 | },
346 | };
347 |
348 | struct _stts {
349 | uint32_t size;
350 | uint8_t kind[4];
351 | uint32_t version1_flags3;
352 | int32_t entry_count; // 1 (CFR)
353 | int32_t frames;
354 | int32_t duration; // 1
355 | } box_stts = {
356 | htonl(sizeof(struct _stts)),
357 | {'s','t','t','s'},
358 | htonl(0x00000000),
359 | htonl(1),
360 | htonl(full_frame_cnt),
361 | htonl(1),
362 | };
363 |
364 | struct _stss {
365 | uint32_t size;
366 | uint8_t kind[4];
367 | uint32_t version1_flags3;
368 | uint32_t sync_frames;
369 | // uint32_t sync_frame_location[sync_frames];
370 | } box_stss = {
371 | htonl(sizeof(struct _stss) + sizeof(uint32_t)*sync_frame_cnt),
372 | {'s','t','s','s'},
373 | htonl(0x00000000),
374 | htonl(sync_frame_cnt),
375 | // -> frame_infos[...] if(kind=SYNC_PAT)
376 | };
377 |
378 | struct _stsc {
379 | uint32_t size;
380 | uint8_t kind[4];
381 | uint32_t version1_flags3;
382 | int32_t entry_count; // 1
383 | uint32_t first_block; // 1
384 | uint32_t samples_frames; // 1
385 | uint32_t samples_description_id; // 1
386 | } box_stsc = {
387 | htonl(sizeof(struct _stsc)),
388 | {'s','t','s','c'},
389 | htonl(0x00000000),
390 | htonl(1),
391 | htonl(1),
392 | htonl(1),
393 | htonl(1),
394 | };
395 |
396 | struct _stsz {
397 | uint32_t size;
398 | uint8_t kind[4];
399 | uint32_t version1_flags3; // = 0
400 | int32_t block_byte_size_for_all; // 0 = different sizes
401 | uint32_t block_byte_sizes_count;
402 | // uint32_t block_byte_sizes[block_byte_sizes_count];
403 | } box_stsz = {
404 | htonl(sizeof(struct _stsz) + sizeof(uint32_t)*full_frame_cnt),
405 | {'s','t','s','z'},
406 | htonl(0x00000000),
407 | htonl(0),
408 | htonl(full_frame_cnt),
409 | // -> frame_infos[].size
410 | };
411 |
412 | struct _stco {
413 | uint32_t size;
414 | uint8_t kind[4];
415 | uint32_t version1_flags3;
416 | uint32_t offsets_count;
417 | // uint32_t offsets[offsets_count];
418 | } box_stco = {
419 | htonl(sizeof(struct _stco) + sizeof(uint32_t)*full_frame_cnt),
420 | {'s','t','c','o'},
421 | htonl(0x00000000),
422 | htonl(full_frame_cnt),
423 | // -> frame_infos[].addr
424 | };
425 |
426 | uint32_t var_size =
427 | sizeof(struct _stsd) + stsd_avc1_avcC_size +
428 | sizeof(struct _stts) +
429 | sizeof(struct _stss) + sizeof(uint32_t)*sync_frame_cnt +
430 | sizeof(struct _stsc) +
431 | sizeof(struct _stsz) + sizeof(uint32_t)*full_frame_cnt +
432 | sizeof(struct _stco) + sizeof(uint32_t)*full_frame_cnt;
433 |
434 | struct _udta {
435 | uint32_t size;
436 | uint8_t kind[4];
437 | struct _meta {
438 | uint32_t size;
439 | uint8_t kind[4];
440 | uint32_t version1_flags3; // = 0
441 | struct _meta_hdlr {
442 | uint32_t size;
443 | uint8_t kind[4];
444 | uint32_t version1_flags3; // = 0
445 | uint8_t QUICKTIME_type[4];
446 | uint8_t subtype[4];
447 | uint8_t QUICKTIME_manufacturer_reserved[4];
448 | uint32_t QUICKTIME_component_reserved_flags;
449 | uint32_t QUICKTIME_component_reserved_flags_mask;
450 | uint8_t component_type_name[1];
451 | } box_meta_hdlr;
452 | struct _ilst {
453 | uint32_t size;
454 | uint8_t kind[4];
455 | struct _apple_annotation {
456 | uint32_t size;
457 | uint8_t kind[4]; // 0xA9 + 'too'(= encoder)
458 | struct _data {
459 | uint32_t size;
460 | uint8_t kind[4];
461 | uint32_t version1_flags3; // 0x00 + 0x000001(= contains text)
462 | int32_t reserve[1];
463 | uint8_t annotation_text[10];
464 | } box_data;
465 | } box_apple_annotation;
466 | } box_ilst;
467 | } box_meta;
468 | } box_udta = {
469 | htonl(sizeof(struct _udta)),
470 | {'u','d','t','a'},
471 | {
472 | htonl(sizeof(struct _meta)),
473 | {'m','e','t','a'},
474 | htonl(0x00000000),
475 | {
476 | htonl(sizeof(struct _meta_hdlr)),
477 | {'h','d','l','r'},
478 | htonl(0x00000000),
479 | {0,},
480 | {'m','d','i','r'},
481 | {'a','p','p','l'},
482 | htonl(0),
483 | htonl(0),
484 | {0,},
485 | },
486 | {
487 | htonl(sizeof(struct _ilst)),
488 | {'i','l','s','t'},
489 | {
490 | htonl(sizeof(struct _apple_annotation)),
491 | {0xA9,'t','o','o'},
492 | {
493 | htonl(sizeof(struct _data)),
494 | {'d','a','t','a'},
495 | htonl(0x00000001),
496 | {0,},
497 | {'L','a','v','f','5','3','.','4','.','0'},
498 | },
499 | },
500 | },
501 | },
502 | };
503 |
504 | struct _moov {
505 | uint32_t size;
506 | uint8_t kind[4];
507 | struct _mvhd {
508 | uint32_t size;
509 | uint8_t kind[4];
510 | uint32_t version1_flags3;
511 | uint32_t created_mac_UTC_date;
512 | uint32_t modified_mac_UTC_date;
513 | int32_t timescale;
514 | int32_t duration;
515 | uint32_t user_playback_speed; // (0x00010000 = 1.0)
516 | uint16_t user_volume; // (0x0100 = 1.0)
517 | uint8_t reserve[10];
518 | uint32_t window_geometry_matrix_value_A; // (0x00010000 = 1.0)
519 | uint32_t window_geometry_matrix_value_B; // (0x00000000 = 0.0)
520 | uint32_t window_geometry_matrix_value_U; // (0x00000000 = 0.0)
521 | uint32_t window_geometry_matrix_value_C; // (0x00000000 = 0.0)
522 | uint32_t window_geometry_matrix_value_D; // (0x00010000 = 1.0)
523 | uint32_t window_geometry_matrix_value_V; // (0x00000000 = 0.0)
524 | uint32_t window_geometry_matrix_value_X; // (0x00000000 = 0.0)
525 | uint32_t window_geometry_matrix_value_Y; // (0x00000000 = 0.0)
526 | uint32_t window_geometry_matrix_value_W; // (0x40000000?)
527 | uint32_t reserve2[6];
528 | uint32_t next_track_id; // single track = 2
529 | } box_mvhd;
530 | struct _trak {
531 | uint32_t size;
532 | uint8_t kind[4];
533 | struct _tkhd {
534 | uint32_t size;
535 | uint8_t kind[4];
536 | uint32_t version1_flags3;
537 | uint32_t created_mac_UTC_date;
538 | uint32_t modified_mac_UTC_date;
539 | int32_t track_id; // first track = 1
540 | uint32_t reserve[1];
541 | int32_t duration;
542 | uint32_t reserve2[2];
543 | int16_t video_layer; // middle = 0
544 | int16_t alternate_group;
545 | uint16_t volume; // (0x0000 = 0.0)
546 | uint16_t reserve3[1];
547 | uint32_t video_geometry_matrix_value_A; // (0x00010000 = 1.0)
548 | uint32_t video_geometry_matrix_value_B; // (0x00000000 = 0.0)
549 | uint32_t video_geometry_matrix_value_U; // (0x00000000 = 0.0)
550 | uint32_t video_geometry_matrix_value_C; // (0x00000000 = 0.0)
551 | uint32_t video_geometry_matrix_value_D; // (0x00010000 = 1.0)
552 | uint32_t video_geometry_matrix_value_V; // (0x00000000 = 0.0)
553 | uint32_t video_geometry_matrix_value_X; // (0x00000000 = 0.0)
554 | uint32_t video_geometry_matrix_value_Y; // (0x00000000 = 0.0)
555 | uint32_t video_geometry_matrix_value_W; // (0x40000000?)
556 | uint32_t frame_width; // Fixed point
557 | uint32_t frame_height; // Fixed point
558 | } box_tkhd;
559 | struct _mdia {
560 | uint32_t size;
561 | uint8_t kind[4];
562 | struct _mdhd {
563 | uint32_t size;
564 | uint8_t kind[4];
565 | uint32_t version1_flags3;
566 | uint32_t created_mac_UTC_date;
567 | uint32_t modified_mac_UTC_date;
568 | int32_t timescale_fps;
569 | int32_t duration_frames;
570 | uint16_t language_code; // ISO-639-2
571 | uint16_t predefined;
572 | } box_mdhd;
573 | struct _hdlr {
574 | uint32_t size;
575 | uint8_t kind[4];
576 | uint32_t version1_flags3;
577 | uint32_t component_type;
578 | uint8_t subtype[4];
579 | uint32_t reserve[3];
580 | uint8_t component_name[13]; // "VideoHandler"
581 | } box_hdlr;
582 | struct _minf {
583 | uint32_t size;
584 | uint8_t kind[4];
585 | struct _vmhd {
586 | uint32_t size;
587 | uint8_t kind[4];
588 | uint32_t version1_flags3;
589 | uint16_t graphics_mode; // 0x0000 = copy
590 | uint16_t graphics_mode_color[3];
591 | } box_vmhd;
592 | struct _dinf {
593 | uint32_t size;
594 | uint8_t kind[4];
595 | struct _dref {
596 | uint32_t size;
597 | uint8_t kind[4];
598 | uint32_t version1_flags3;
599 | int32_t entry_count; // 1 = minimum
600 | struct _url {
601 | uint32_t size;
602 | uint8_t kind[4];
603 | uint32_t version1_flags3; // 1 = internal data
604 | } box_url;
605 | } box_dref;
606 | } box_dinf;
607 | struct _stbl {
608 | uint32_t size;
609 | uint8_t kind[4];
610 | // struct _stsd -> variable size
611 | // struct _stts -> variable size (fix?)
612 | // struct _stss -> variable size
613 | // struct _stsc -> variable size (fix?)
614 | // struct _stsz -> variable size
615 | // struct _stco -> variable size
616 | } box_stbl;
617 | } box_minf;
618 | } box_mdia;
619 | } box_trak;
620 | } box_moov = {
621 | htonl(sizeof(struct _moov) + var_size + sizeof(struct _udta)),
622 | {'m','o','o','v'},
623 | {
624 | htonl(sizeof(struct _mvhd)),
625 | {'m','v','h','d'},
626 | htonl(0x00000000),
627 | htonl(now),
628 | htonl(now),
629 | htonl(1000),
630 | htonl(duration),
631 | htonl(0x00010000),
632 | htons(0x0100),
633 | {0,},
634 | htonl(0x00010000),
635 | htonl(0x00000000),
636 | htonl(0x00000000),
637 | htonl(0x00000000),
638 | htonl(0x00010000),
639 | htonl(0x00000000),
640 | htonl(0x00000000),
641 | htonl(0x00000000),
642 | htonl(0x40000000),
643 | {0,},
644 | htonl(2),
645 | },
646 | {
647 | htonl(sizeof(struct _trak) + var_size),
648 | {'t','r','a','k'},
649 | {
650 | htonl(sizeof(struct _tkhd)),
651 | {'t','k','h','d'},
652 | htonl(0x0000000F),
653 | htonl(now),
654 | htonl(now),
655 | htonl(1),
656 | {0,},
657 | htonl(duration),
658 | {0,},
659 | htons(0),
660 | htons(0),
661 | htons(0x0000),
662 | {0,},
663 | htonl(0x00010000),
664 | htonl(0x00000000),
665 | htonl(0x00000000),
666 | htonl(0x00000000),
667 | htonl(0x00010000),
668 | htonl(0x00000000),
669 | htonl(0x00000000),
670 | htonl(0x00000000),
671 | htonl(0x40000000),
672 | htonl(video_w<<16),
673 | htonl(video_h<<16),
674 | },
675 | {
676 | htonl(sizeof(struct _mdia) + var_size),
677 | {'m','d','i','a'},
678 | {
679 | htonl(sizeof(struct _mdhd)),
680 | {'m','d','h','d'},
681 | htonl(0x00000000),
682 | htonl(now),
683 | htonl(now),
684 | htonl(fps),
685 | htonl(full_frame_cnt),
686 | // 0x55C4 = "und(Undetermined)"
687 | // -> ISO-639-2
688 | // u = 75h -(-60h)-> 15h -> 10101b
689 | // n = 6Eh -(-60h)-> 0Eh -> 01110b
690 | // d = 64h -(-60h)-> 04h -> 00100b
691 | // 10101:01110:00100b = 101:0101:1100:0100b = 55C4h
692 | htons(0x55C4),
693 | htons(0),
694 | },
695 | {
696 | htonl(sizeof(struct _hdlr)),
697 | {'h','d','l','r'},
698 | htonl(0x00000000),
699 | htonl(0),
700 | {'v','i','d','e'},
701 | {0,},
702 | {'V','i','d','e','o','H','a','n','d','l','e','r',0x0},
703 | },
704 | {
705 | htonl(sizeof(struct _minf) + var_size),
706 | {'m','i','n','f'},
707 | {
708 | htonl(sizeof(struct _vmhd)),
709 | {'v','m','h','d'},
710 | htonl(0x00000001),
711 | htons(0x0000),
712 | {htons(0x0000),htons(0x0000),htons(0x0000)},
713 | },
714 | {
715 | htonl(sizeof(struct _dinf)),
716 | {'d','i','n','f'},
717 | {
718 | htonl(sizeof(struct _dref)),
719 | {'d','r','e','f'},
720 | htonl(0x00000000),
721 | htonl(1),
722 | {
723 | htonl(sizeof(struct _url)),
724 | {'u','r','l',' '},
725 | htonl(0x00000001),
726 | },
727 | },
728 | },
729 | {
730 | htonl(sizeof(struct _stbl) + var_size),
731 | {'s','t','b','l'},
732 | // struct _stsd -> variable size
733 | // struct _stts -> variable size (fix?)
734 | // struct _stss -> variable size
735 | // struct _stsc -> variable size (fix?)
736 | // struct _stsz -> variable size
737 | // struct _stco -> variable size
738 | },
739 | },
740 | },
741 | },
742 | };
743 |
744 | //
745 | dst_addr += fwrite(&box_moov, sizeof(box_moov), 1, dst_fp) * sizeof(box_moov);
746 | dst_addr += fwrite(&box_stsd, sizeof(box_stsd), 1, dst_fp) * sizeof(box_stsd);
747 | dst_addr += fwrite(&box_stsd_avc1_avcC_part1, sizeof(box_stsd_avc1_avcC_part1), 1, dst_fp) * sizeof(box_stsd_avc1_avcC_part1);
748 | dst_addr += fwrite(sps_dat, 1, sps_len, dst_fp);
749 | dst_addr += fwrite(&box_stsd_avc1_avcC_part2, sizeof(box_stsd_avc1_avcC_part2), 1, dst_fp) * sizeof(box_stsd_avc1_avcC_part2);
750 | dst_addr += fwrite(pps_dat, 1, pps_len, dst_fp);
751 | dst_addr += fwrite(&box_stts, sizeof(box_stts), 1, dst_fp) * sizeof(box_stts);
752 | {
753 | dst_addr += fwrite(&box_stss, sizeof(box_stss), 1, dst_fp) * sizeof(box_stss);
754 | uint32_t tmp;
755 | for (i=0; i= 0) {
769 | tmp = htonl(tmp);
770 | dst_addr += fwrite(&tmp, sizeof(tmp), 1, dst_fp) * sizeof(tmp);
771 | tmp = 0;
772 | }
773 | }
774 | }
775 | {
776 | dst_addr += fwrite(&box_stco, sizeof(box_stco), 1, dst_fp) * sizeof(box_stco);
777 | uint32_t org = dst_addr + sizeof(uint32_t)*full_frame_cnt + sizeof(box_udta) + 8/*sizeof(box_mdat)*/;
778 | uint32_t tmp = 0;
779 | for (i=0; i= 0) {
784 | dst_addr += fwrite(&tmp, sizeof(tmp), 1, dst_fp) * sizeof(tmp);
785 | tmp = 0;
786 | }
787 | }
788 | }
789 | dst_addr += fwrite(&box_udta, sizeof(box_udta), 1, dst_fp) * sizeof(box_udta);
790 | }
791 |
792 | // Dst: MDAT
793 | {
794 | struct _mdat {
795 | uint32_t size;
796 | uint8_t kind[4];
797 | //uint8_t sample_data[full_frame_cnt];
798 | } box_mdat = {
799 | htonl(sizeof(struct _mdat) + src_addr),
800 | {'m','d','a','t'},
801 | };
802 | dst_addr += fwrite(&box_mdat, sizeof(box_mdat), 1, dst_fp) * sizeof(box_mdat);
803 |
804 | // Src -> Dst
805 | uint32_t tmp = 0;
806 | uint32_t cnt = 0;
807 | for (i=0,j=0; i 0) {
811 | if (j == 0) {
812 | j = frame_infos[i].size;
813 | tmp = htonl(j);
814 | dst_addr += fwrite(&tmp, sizeof(tmp), 1, dst_fp) * sizeof(tmp);
815 | cnt = sizeof(tmp);
816 | }
817 | if (cnt > 0) {
818 | if (num >= cnt) {
819 | bufP += cnt;
820 | num -= cnt;
821 | cnt = 0;
822 | } else {
823 | bufP += num;
824 | cnt -= num;
825 | num = 0;
826 | }
827 | } else if (num >= j) {
828 | dst_addr += fwrite(bufP, 1, j, dst_fp);
829 | bufP += j;
830 | num -= j;
831 | j = 0;
832 | i++;
833 | } else {
834 | dst_addr += fwrite(bufP, 1, num, dst_fp);
835 | bufP += num;
836 | j -= num;
837 | num = 0;
838 | }
839 | }
840 | }
841 | }
842 | } while(0);
843 |
844 | //
845 | if (src_fp != NULL) {
846 | fclose(src_fp);
847 | }
848 | if (dst_fp != NULL) {
849 | fclose(dst_fp);
850 | }
851 | if (buf != NULL) {
852 | free(buf);
853 | }
854 | if (frame_infos != NULL) {
855 | free(frame_infos);
856 | }
857 | if (sps_dat != NULL) {
858 | free(sps_dat);
859 | }
860 | if (pps_dat != NULL) {
861 | free(pps_dat);
862 | }
863 | return rcode;
864 | }
865 |
--------------------------------------------------------------------------------
/MediaCodecTest16/jni/jp_morihirosoft_mediacodectest16_MainActivity.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | #include "stdio.h"
17 |
18 | #include "jp_morihirosoft_mediacodectest16_MainActivity.h"
19 | #include "Utils.h"
20 | #include "Effector.h"
21 |
22 | #define LOG_TAG "JNI"
23 | #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
24 | #if 0
25 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
26 | #else
27 | #define LOGI(...)
28 | #endif
29 |
30 | #if 1
31 | #ifdef __cplusplus
32 | extern "C" {
33 | #endif
34 | extern int32_t cnvavc(const char* src_path, const char* dst_path,
35 | int32_t video_w, int32_t video_h, int32_t fps);
36 | #ifdef __cplusplus
37 | }
38 | #endif
39 | #endif
40 |
41 | //---------------------------------------------------------------------
42 | // Static data
43 | //---------------------------------------------------------------------
44 | static bool sFacingFront = false;
45 | static int32_t sVideoW = 0;
46 | static int32_t sVideoH = 0;
47 | static int32_t sFps = 0;
48 | static uint32_t sDataSize = 0;
49 | static uint8_t* sDataP = NULL;
50 | static uint32_t* sMaskP = NULL;
51 |
52 | static Utils* sUtils = NULL;
53 | static Effector* sEffector = NULL;
54 |
55 | //---------------------------------------------------------------------
56 | //
57 | //---------------------------------------------------------------------
58 | jint JNI_OnLoad(JavaVM* vm, void* reserved)
59 | {
60 | return JNI_VERSION_1_6;
61 | }
62 |
63 | void JNI_OnUnload(JavaVM* vm, void* reserved)
64 | {
65 | }
66 |
67 | //---------------------------------------------------------------------
68 | //
69 | //---------------------------------------------------------------------
70 | /** . */
71 | JNIEXPORT jint JNICALL Java_jp_morihirosoft_mediacodectest16_MainActivity_native_1init
72 | (JNIEnv* env, jclass clazz, jboolean jFacingFront, jint jVideoW, jint jVideoH, jint jFps, jintArray jMask)
73 | {
74 | if (jVideoW <= 0 || jVideoH <= 0 || jFps <= 0 || jMask == NULL) {
75 | return -1;
76 | }
77 |
78 | sFacingFront = jFacingFront;
79 | sVideoW = jVideoW;
80 | sVideoH = jVideoH;
81 | sFps = jFps;
82 |
83 | if (sDataP != NULL) {
84 | delete[] sDataP;
85 | }
86 | sDataSize = sVideoW * sVideoH * 3 / 2;
87 | sDataP = new uint8_t[sDataSize];
88 |
89 | uint32_t* maskP = (uint32_t*)(env->GetIntArrayElements(jMask, NULL));
90 | if (sMaskP != NULL) {
91 | delete[] sMaskP;
92 | }
93 | sMaskP = new uint32_t[sVideoW * sVideoH];
94 | memcpy(sMaskP, maskP, sizeof(uint32_t) * sVideoW * sVideoH);
95 | env->ReleaseIntArrayElements(jMask, (jint*)maskP, JNI_ABORT);
96 |
97 | sUtils = new Utils(jVideoW, jVideoH);
98 | sEffector = new Effector();
99 |
100 | return sEffector->init(sUtils, sVideoW, sVideoH, sMaskP);
101 | }
102 |
103 | /** . */
104 | JNIEXPORT jint JNICALL Java_jp_morihirosoft_mediacodectest16_MainActivity_native_1quit
105 | (JNIEnv* env, jclass clazz)
106 | {
107 | jint rcode = sEffector->quit();
108 |
109 | if (sUtils != NULL) {
110 | delete sUtils;
111 | sUtils = NULL;
112 | }
113 | if (sEffector != NULL) {
114 | delete sEffector;
115 | sEffector = NULL;
116 | }
117 |
118 | sVideoW = 0;
119 | sVideoH = 0;
120 | sDataSize = 0;
121 | if (sDataP != NULL) {
122 | delete[] sDataP;
123 | sDataP = NULL;
124 | }
125 | if (sMaskP != NULL) {
126 | delete[] sMaskP;
127 | sMaskP = NULL;
128 | }
129 |
130 | return rcode;
131 | }
132 |
133 | /** . */
134 | JNIEXPORT jint JNICALL Java_jp_morihirosoft_mediacodectest16_MainActivity_native_1draw
135 | (JNIEnv* env, jclass clazz, jbyteArray jSrcYuv, jintArray jDstRgb, jint jDstYuvFmt, jbyteArray jDstYuv)
136 | {
137 | if (sVideoW <= 0 || sVideoH <= 0 || sDataP == NULL) {
138 | return -1;
139 | }
140 |
141 | uint8_t* srcYuvP = (uint8_t*)(env->GetByteArrayElements(jSrcYuv, NULL));
142 | uint32_t* dstRgbP = (uint32_t*)(env->GetIntArrayElements(jDstRgb, NULL));
143 | uint8_t* dstYuvP = NULL;
144 | if (jDstYuv != NULL) {
145 | dstYuvP = (uint8_t*)(env->GetByteArrayElements(jDstYuv, NULL));
146 | }
147 |
148 | // H-FLIP?
149 | if (sFacingFront) {
150 | // only for NV21
151 | const int32_t w1 = sVideoW;
152 | const int32_t h1 = sVideoH;
153 | const int32_t wh = w1 / 2;
154 | const int32_t hh = h1 / 2;
155 | const int32_t w2 = w1 * 2;
156 | uint8_t* sy = srcYuvP;
157 | uint8_t* dy = sDataP + w1 - 1;
158 | unsigned short* suv = ((unsigned short*)srcYuvP) + wh * h1;
159 | unsigned short* duv = ((unsigned short*)sDataP) + wh * h1 + wh - 1;
160 | // Y
161 | for (int32_t y=h1; y>0; y--) {
162 | for (int32_t x=w1; x>0; x--) {
163 | *dy-- = *sy++;
164 | }
165 | dy += w2;
166 | }
167 | // U/V
168 | for (int32_t y=hh; y>0; y--) {
169 | for (int32_t x=wh; x>0; x--) {
170 | *duv-- = *suv++;
171 | }
172 | duv += w1;
173 | }
174 | } else {
175 | memcpy(sDataP, srcYuvP, sizeof(uint8_t) * sDataSize);
176 | }
177 |
178 | jint rcode = sEffector->draw(sDataP, dstRgbP);
179 | if (rcode == 0) {
180 | // for Video recording
181 | if (dstYuvP != NULL) {
182 | sUtils->yuv_RGBtoYUV(dstRgbP, jDstYuvFmt, dstYuvP);
183 | }
184 | }
185 |
186 | env->ReleaseByteArrayElements(jSrcYuv, (jbyte*)srcYuvP, JNI_ABORT);
187 | env->ReleaseIntArrayElements(jDstRgb, (jint*)dstRgbP, 0);
188 | if (jDstYuv != NULL) {
189 | env->ReleaseByteArrayElements(jDstYuv, (jbyte*)dstYuvP, 0);
190 | }
191 |
192 | return rcode;
193 | }
194 |
195 | /** . */
196 | JNIEXPORT jint JNICALL Java_jp_morihirosoft_mediacodectest16_MainActivity_native_1cnvavc
197 | (JNIEnv* env, jclass clazz, jstring jSrcPath, jstring jDstPath)
198 | {
199 | const char* src_path = env->GetStringUTFChars(jSrcPath, NULL);
200 | const char* dst_path = env->GetStringUTFChars(jDstPath, NULL);
201 |
202 | jint rcode = cnvavc(src_path, dst_path, sVideoW, sVideoH, sFps);
203 |
204 | if (src_path != NULL) {
205 | env->ReleaseStringUTFChars(jSrcPath, src_path);
206 | }
207 | if (dst_path != NULL) {
208 | env->ReleaseStringUTFChars(jDstPath, dst_path);
209 | }
210 |
211 | return rcode;
212 | }
213 |
--------------------------------------------------------------------------------
/MediaCodecTest16/jni/jp_morihirosoft_mediacodectest16_MainActivity.h:
--------------------------------------------------------------------------------
1 | /* DO NOT EDIT THIS FILE - it is machine generated */
2 | #include
3 | /* Header for class jp_morihirosoft_mediacodectest16_MainActivity */
4 |
5 | #ifndef _Included_jp_morihirosoft_mediacodectest16_MainActivity
6 | #define _Included_jp_morihirosoft_mediacodectest16_MainActivity
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 | #undef jp_morihirosoft_mediacodectest16_MainActivity_DEBUG
11 | #define jp_morihirosoft_mediacodectest16_MainActivity_DEBUG 0L
12 | /*
13 | * Class: jp_morihirosoft_mediacodectest16_MainActivity
14 | * Method: native_init
15 | * Signature: (ZIII[I)I
16 | */
17 | JNIEXPORT jint JNICALL Java_jp_morihirosoft_mediacodectest16_MainActivity_native_1init
18 | (JNIEnv *, jclass, jboolean, jint, jint, jint, jintArray);
19 |
20 | /*
21 | * Class: jp_morihirosoft_mediacodectest16_MainActivity
22 | * Method: native_quit
23 | * Signature: ()I
24 | */
25 | JNIEXPORT jint JNICALL Java_jp_morihirosoft_mediacodectest16_MainActivity_native_1quit
26 | (JNIEnv *, jclass);
27 |
28 | /*
29 | * Class: jp_morihirosoft_mediacodectest16_MainActivity
30 | * Method: native_draw
31 | * Signature: ([B[II[B)I
32 | */
33 | JNIEXPORT jint JNICALL Java_jp_morihirosoft_mediacodectest16_MainActivity_native_1draw
34 | (JNIEnv *, jclass, jbyteArray, jintArray, jint, jbyteArray);
35 |
36 | /*
37 | * Class: jp_morihirosoft_mediacodectest16_MainActivity
38 | * Method: native_cnvavc
39 | * Signature: (Ljava/lang/String;Ljava/lang/String;)I
40 | */
41 | JNIEXPORT jint JNICALL Java_jp_morihirosoft_mediacodectest16_MainActivity_native_1cnvavc
42 | (JNIEnv *, jclass, jstring, jstring);
43 |
44 | #ifdef __cplusplus
45 | }
46 | #endif
47 | #endif
48 |
--------------------------------------------------------------------------------
/MediaCodecTest16/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-16
15 |
--------------------------------------------------------------------------------
/MediaCodecTest16/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MorihiroSoft/Android_MediaCodecTest/66667e1776d685f719e0f1243c394114d604a19d/MediaCodecTest16/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/MediaCodecTest16/res/layout/main_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
17 |
18 |
22 |
23 |
24 |
28 |
29 |
35 |
36 |
42 |
43 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/MediaCodecTest16/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MediaCodecTest(API16)
5 | Record
6 | Stop
7 | Playback
8 |
9 |
--------------------------------------------------------------------------------
/MediaCodecTest16/src/jp/morihirosoft/mediacodectest16/CameraView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | package jp.morihirosoft.mediacodectest16;
17 |
18 | import android.content.Context;
19 | import android.hardware.Camera;
20 | import android.util.AttributeSet;
21 | import android.view.SurfaceHolder;
22 | import android.view.SurfaceView;
23 | import android.view.ViewGroup.LayoutParams;
24 |
25 | class CameraView extends SurfaceView implements
26 | SurfaceHolder.Callback,
27 | Camera.PreviewCallback
28 | {
29 | //---------------------------------------------------------------------
30 | // INTERFACE
31 | //---------------------------------------------------------------------
32 | interface CameraPreviewBuffer {
33 | abstract byte[] getBuffer();
34 | abstract void onPreviewFrame(byte[] data);
35 | }
36 |
37 | //---------------------------------------------------------------------
38 | // MEMBERS
39 | //---------------------------------------------------------------------
40 | private final VideoParam mVideoParam = VideoParam.getInstance();
41 |
42 | private boolean mIsResumed = false;
43 | private boolean mIsCreated = false;
44 | private CameraPreviewBuffer mCameraPreviewBuffer = null;
45 | private Camera mCamera = null;
46 |
47 | //---------------------------------------------------------------------
48 | // PUBLIC METHODS
49 | //---------------------------------------------------------------------
50 | public CameraView(Context context) {
51 | super(context);
52 | init();
53 | }
54 |
55 | public CameraView(Context context, AttributeSet attrs) {
56 | super(context, attrs);
57 | init();
58 | }
59 |
60 | public CameraView(Context context, AttributeSet attrs, int defStyle) {
61 | super(context, attrs, defStyle);
62 | init();
63 | }
64 |
65 | public void setup(CameraPreviewBuffer previewbuffer) {
66 | mCameraPreviewBuffer = previewbuffer;
67 | }
68 |
69 | public void resume() {
70 | mIsResumed = true;
71 | startCamera();
72 | }
73 |
74 | public void pause() {
75 | mIsResumed = false;
76 | stopCamera();
77 | }
78 |
79 | @Override
80 | public void surfaceCreated(SurfaceHolder holder) {
81 | mIsCreated = true;
82 | startCamera();
83 | }
84 |
85 | @Override
86 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
87 | if (mCameraPreviewBuffer == null) {
88 | throw new IllegalStateException("mCameraPreviewBuffer=null");
89 | }
90 | if (mCamera != null) {
91 | mCamera.stopPreview();
92 |
93 | if (width > mVideoParam.mSize.width || height > mVideoParam.mSize.height) {
94 | LayoutParams lparam = getLayoutParams();
95 | lparam.width = mVideoParam.mSize.width;
96 | lparam.height = mVideoParam.mSize.height;
97 | setLayoutParams(lparam);
98 | }
99 |
100 | mCamera.addCallbackBuffer(mCameraPreviewBuffer.getBuffer());
101 | mCamera.setPreviewCallbackWithBuffer(this);
102 | mCamera.startPreview();
103 | }
104 | }
105 |
106 | @Override
107 | public void surfaceDestroyed(SurfaceHolder holder) {
108 | mIsCreated = false;
109 | stopCamera();
110 |
111 | }
112 |
113 | @Override
114 | public void onPreviewFrame(byte[] data, Camera camera) {
115 | mCameraPreviewBuffer.onPreviewFrame(data);
116 | camera.addCallbackBuffer(mCameraPreviewBuffer.getBuffer());
117 | }
118 |
119 | //---------------------------------------------------------------------
120 | // PRIVATE...
121 | //---------------------------------------------------------------------
122 | private void init() {
123 | if (Camera.getNumberOfCameras() < 1) {
124 | throw new UnsupportedOperationException("No camera");
125 | }
126 | getHolder().addCallback(this);
127 | }
128 |
129 | private void startCamera() {
130 | if (mCameraPreviewBuffer == null) {
131 | throw new IllegalStateException("mCameraPreviewBuffer=null");
132 | }
133 | if (mIsCreated && mIsResumed && mCamera == null) {
134 | try {
135 | mCamera = Camera.open(mVideoParam.mCameraId);
136 | Camera.Parameters cp = mCamera.getParameters();
137 | cp.setPreviewSize(mVideoParam.mSize.width, mVideoParam.mSize.height);
138 | cp.setPreviewFpsRange(
139 | mVideoParam.mFpsRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
140 | mVideoParam.mFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
141 | mCamera.setParameters(cp);
142 | mCamera.addCallbackBuffer(mCameraPreviewBuffer.getBuffer());
143 | mCamera.setPreviewCallbackWithBuffer(this);
144 | mCamera.setPreviewDisplay(getHolder());
145 | mCamera.startPreview();
146 | } catch (Exception e) {
147 | e.printStackTrace();
148 | throw new RuntimeException("setup camera");
149 | }
150 | }
151 | }
152 |
153 | private void stopCamera() {
154 | if (mCamera != null) {
155 | mCamera.stopPreview();
156 | mCamera.setPreviewCallback(null);
157 | mCamera.release();
158 | mCamera = null;
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/MediaCodecTest16/src/jp/morihirosoft/mediacodectest16/EffectView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | package jp.morihirosoft.mediacodectest16;
17 |
18 | import android.content.Context;
19 | import android.graphics.Canvas;
20 | import android.graphics.Color;
21 | import android.graphics.Paint;
22 | import android.util.AttributeSet;
23 | import android.view.SurfaceHolder;
24 | import android.view.SurfaceView;
25 |
26 | class EffectView extends SurfaceView implements
27 | SurfaceHolder.Callback,
28 | Runnable
29 | {
30 | //---------------------------------------------------------------------
31 | // MEMBERS
32 | //---------------------------------------------------------------------
33 | private boolean mIsResumed = false;
34 | private boolean mIsCreated = false;
35 | private Thread mThread = null;
36 | private SurfaceHolder mHolder = null;
37 | private int mSurfaceW = 0;
38 | private int mSurfaceH = 0;
39 | private int mImageW = 0;
40 | private int mImageH = 0;
41 | private int[][] mImagePix = null;
42 | private int[] mImageIdx = null;
43 |
44 | //---------------------------------------------------------------------
45 | // PUBLIC MRTHODS
46 | //---------------------------------------------------------------------
47 | public EffectView(Context context) {
48 | super(context);
49 | init();
50 | }
51 |
52 | public EffectView(Context context, AttributeSet attrs) {
53 | super(context, attrs);
54 | init();
55 | }
56 |
57 | public EffectView(Context context, AttributeSet attrs, int defStyle) {
58 | super(context, attrs, defStyle);
59 | init();
60 | }
61 |
62 | @Override
63 | public void surfaceCreated(SurfaceHolder holder) {
64 | mIsCreated = true;
65 | startThread();
66 | }
67 |
68 | @Override
69 | public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
70 | mHolder = holder;
71 | mSurfaceW = width;
72 | mSurfaceH = height;
73 | }
74 |
75 | @Override
76 | public void surfaceDestroyed(SurfaceHolder holder) {
77 | mIsCreated = false;
78 | stopThread();
79 | }
80 |
81 | public void setup(int image_w, int image_h, int[][] image_pix, int[] image_idx) {
82 | mImageW = image_w;
83 | mImageH = image_h;
84 | mImagePix = image_pix;
85 | mImageIdx = image_idx;
86 | }
87 |
88 | public void resume() {
89 | mIsResumed = true;
90 | startThread();
91 | }
92 |
93 | public void pause() {
94 | mIsResumed = false;
95 | stopThread();
96 | }
97 |
98 | public void run() {
99 | Canvas canvas;
100 | Paint paint = new Paint();
101 |
102 | while(mThread != null){
103 | if (mHolder == null || mSurfaceW < 1 || mSurfaceH < 1) {
104 | continue;
105 | }
106 | int idx = 0;
107 | try {
108 | synchronized (mImageIdx) {
109 | mImageIdx.wait();
110 | idx = mImageIdx[0];
111 | }
112 | } catch (InterruptedException e) {
113 | e.printStackTrace();
114 | throw new RuntimeException();
115 | }
116 |
117 | canvas = mHolder.lockCanvas();
118 | if (canvas == null) {
119 | continue;
120 | }
121 |
122 | canvas.drawColor(Color.GRAY);
123 |
124 | float s;
125 | if (mSurfaceW * mImageH < mSurfaceH * mImageW) {
126 | s = (float)mSurfaceW / (float)mImageW;
127 | } else {
128 | s = (float)mSurfaceH / (float)mImageH;
129 | }
130 | canvas.scale(s, s);
131 | canvas.drawBitmap(mImagePix[idx], 0, mImageW, 0, 0, mImageW, mImageH, false, paint);
132 |
133 | mHolder.unlockCanvasAndPost(canvas);
134 | }
135 | }
136 |
137 | //---------------------------------------------------------------------
138 | // PRIVATE...
139 | //---------------------------------------------------------------------
140 | private void init() {
141 | getHolder().addCallback(this);
142 | }
143 |
144 | private void startThread() {
145 | if (mIsCreated && mIsResumed && mThread == null) {
146 | mThread = new Thread(this);
147 | mThread.start();
148 | }
149 | }
150 |
151 | private void stopThread() {
152 | if (mThread != null) {
153 | mThread = null;
154 | }
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/MediaCodecTest16/src/jp/morihirosoft/mediacodectest16/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | package jp.morihirosoft.mediacodectest16;
17 |
18 | import android.app.Activity;
19 | import android.content.Intent;
20 | import android.graphics.Bitmap;
21 | import android.graphics.Canvas;
22 | import android.graphics.Color;
23 | import android.graphics.Paint;
24 | import android.graphics.PorterDuff;
25 | import android.graphics.PorterDuffXfermode;
26 | import android.graphics.RectF;
27 | import android.net.Uri;
28 | import android.os.Bundle;
29 | import android.view.View;
30 | import android.view.Window;
31 | import android.view.WindowManager;
32 | import android.widget.Button;
33 |
34 | public class MainActivity extends Activity implements
35 | View.OnClickListener,
36 | CameraView.CameraPreviewBuffer
37 | {
38 | //---------------------------------------------------------------------
39 | // NATIVE METHODS
40 | //---------------------------------------------------------------------
41 | static {
42 | System.loadLibrary("MediaCodecTest16");
43 | }
44 | native public static int native_init(boolean f, int w, int h, int fps, int[] mask);
45 | native public static int native_quit();
46 | native public static int native_draw(byte[] src_yuv, int[] dst_rgb, int dst_yuv_fmt, byte[] dst_yuv);
47 | native public static int native_cnvavc(String src_path, String dst_path);
48 |
49 | //---------------------------------------------------------------------
50 | // MEMBERS
51 | //---------------------------------------------------------------------
52 | private final VideoParam mVideoParam = VideoParam.getInstance();
53 |
54 | private CameraView mCameraView = null;
55 | private EffectView mEffectView = null;
56 | private Button mBtnStart = null;
57 | private Button mBtnStop = null;
58 | private Button mBtnPlay = null;
59 |
60 | private MyRecorder mRecorder = null;
61 |
62 | private byte[] mSrcYuv = null;
63 | private int[][] mDstRgb = {null,null};
64 | private byte[][] mDstYuv = {null,null};
65 | private int[] mDstIdx = {0};
66 | private int[] mMask = null;
67 |
68 | //---------------------------------------------------------------------
69 | // PUBLIC / PROTECTED METHODS
70 | //---------------------------------------------------------------------
71 | @Override
72 | protected void onCreate(Bundle savedInstanceState) {
73 | super.onCreate(savedInstanceState);
74 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
75 | requestWindowFeature(Window.FEATURE_NO_TITLE);
76 | setContentView(R.layout.main_activity);
77 |
78 | mCameraView = (CameraView)findViewById(R.id.cameraview);
79 | mEffectView = (EffectView)findViewById(R.id.effectview);
80 | mBtnStart = (Button)findViewById(R.id.start);
81 | mBtnStop = (Button)findViewById(R.id.stop);
82 | mBtnPlay = (Button)findViewById(R.id.play);
83 |
84 | mBtnStart.setOnClickListener(this);
85 | mBtnStop.setOnClickListener(this);
86 | mBtnPlay.setOnClickListener(this);
87 |
88 | mBtnStart.setEnabled(true);
89 | mBtnStop.setEnabled(false);
90 |
91 | mCameraView.setup(this);
92 |
93 | // Buffers
94 | final int vw = mVideoParam.mSize.width;
95 | final int vh = mVideoParam.mSize.height;
96 | final int rgb_size = vw * vh;
97 | final int yuv_size = vw * vh * 3 / 2;
98 | mSrcYuv = new byte[yuv_size];
99 | mDstRgb[0] = new int[rgb_size];
100 | mDstRgb[1] = new int[rgb_size];
101 | mDstYuv[0] = new byte[yuv_size];
102 | mDstYuv[1] = new byte[yuv_size];
103 | mMask = new int[rgb_size];
104 |
105 | // for Effect sample
106 | Bitmap b = Bitmap.createBitmap(vw, vh, Bitmap.Config.ARGB_8888);
107 | Canvas c = new Canvas(b);
108 | Paint p = new Paint();
109 | p.setStyle(Paint.Style.FILL);
110 | p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
111 | c.drawColor(Color.BLUE);
112 | c.drawOval(new RectF(0,0,vw,vh), p);
113 | b.getPixels(mMask, 0, vw, 0, 0, vw, vh);
114 | }
115 |
116 | @Override
117 | protected void onResume() {
118 | super.onResume();
119 |
120 | final int vw = mVideoParam.mSize.width;
121 | final int vh = mVideoParam.mSize.height;
122 | final int fps = mVideoParam.getMaxFps();
123 |
124 | // CameraView
125 | mCameraView.resume();
126 |
127 | // JNI
128 | if (native_init(mVideoParam.mFacingFront, vw, vh, fps, mMask) !=0) {
129 | native_quit();
130 | }
131 |
132 | // EffectView
133 | mEffectView.setup(vw, vh, mDstRgb, mDstIdx);
134 | mEffectView.resume();
135 | mEffectView.setZOrderMediaOverlay(true);
136 | mEffectView.setZOrderOnTop(true);
137 | mEffectView.getParent().bringChildToFront(mEffectView);
138 |
139 | // Video
140 | // -> not auto restart
141 | }
142 |
143 | @Override
144 | protected void onPause() {
145 | // Video
146 | stopVideo();
147 |
148 | // EffectView
149 | mEffectView.pause();
150 |
151 | // JNI
152 | native_quit();
153 |
154 | // CameraView
155 | mCameraView.pause();
156 |
157 | super.onPause();
158 | }
159 |
160 | @Override
161 | public void onClick(View v) {
162 | switch(v.getId()) {
163 | case R.id.start:
164 | startVideo();
165 | break;
166 | case R.id.stop:
167 | stopVideo();
168 | break;
169 | case R.id.play:
170 | playVideo();
171 | break;
172 | }
173 | }
174 |
175 | @Override
176 | public byte[] getBuffer() {
177 | return mSrcYuv;
178 | }
179 |
180 | @Override
181 | public void onPreviewFrame(byte[] src_yuv) {
182 | final int idx = 1 - mDstIdx[0];
183 |
184 | if (mRecorder == null) {
185 | native_draw(src_yuv, mDstRgb[idx], 0, null);
186 | } else {
187 | native_draw(src_yuv, mDstRgb[idx], mRecorder.getColorFormat(), mDstYuv[idx]);
188 | mRecorder.offerEncoder(mDstYuv[idx]);
189 | }
190 |
191 | synchronized (mDstIdx) {
192 | mDstIdx[0] = idx;
193 | mDstIdx.notify();
194 | }
195 | }
196 |
197 | //---------------------------------------------------------------------
198 | // PRIVATE METHODS
199 | //---------------------------------------------------------------------
200 | private void startVideo() {
201 | mBtnStart.setEnabled(false);
202 | mBtnStop.setEnabled(true);
203 | if (mRecorder == null) {
204 | mRecorder = new MyRecorder();
205 | if (mRecorder.start() != 0) {
206 | stopVideo();
207 | return;
208 | }
209 | }
210 | }
211 |
212 | private void stopVideo() {
213 | mBtnStart.setEnabled(true);
214 | mBtnStop.setEnabled(false);
215 | if (mRecorder != null) {
216 | mRecorder.stop();
217 | mRecorder = null;
218 | }
219 | }
220 |
221 | private void playVideo() {
222 | Uri uri = Uri.parse("file://"+mVideoParam.mOutput);
223 | Intent i = new Intent(Intent.ACTION_VIEW, uri);
224 | i.setDataAndType(uri, "video/mp4");
225 | startActivity(i);
226 | }
227 | }
228 |
--------------------------------------------------------------------------------
/MediaCodecTest16/src/jp/morihirosoft/mediacodectest16/MyRecorder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | package jp.morihirosoft.mediacodectest16;
17 |
18 | import java.io.BufferedOutputStream;
19 | import java.io.File;
20 | import java.io.FileOutputStream;
21 | import java.io.IOException;
22 | import java.nio.ByteBuffer;
23 |
24 | import android.media.MediaCodec;
25 | import android.media.MediaCodecInfo;
26 | import android.media.MediaFormat;
27 |
28 | public class MyRecorder {
29 | //---------------------------------------------------------------------
30 | // CONSTANTS
31 | //---------------------------------------------------------------------
32 | private static final int ColorFormat_NV12 = 1;
33 | private static final int ColorFormat_NV21 = 2;
34 | private static final int ColorFormat_I420 = 3;
35 |
36 | private static final int[][] ColorFormatList = {
37 | {ColorFormat_NV12, MediaCodecInfo.CodecCapabilities.COLOR_TI_FormatYUV420PackedSemiPlanar},
38 | {ColorFormat_NV21, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420SemiPlanar},
39 | {ColorFormat_I420, MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Planar},
40 | };
41 |
42 | //---------------------------------------------------------------------
43 | // MEMBERS
44 | //---------------------------------------------------------------------
45 | private final VideoParam mVideoParam = VideoParam.getInstance();
46 | private final String mFileMp4 = mVideoParam.mOutput;
47 | private final String mFileTmp = mFileMp4+".tmp";
48 |
49 | private MediaCodec mMediaCodec = null;
50 | private int mColorFormat = 0;
51 | private BufferedOutputStream mOutput = null;
52 |
53 | //---------------------------------------------------------------------
54 | // PUBLIC METHODS
55 | //---------------------------------------------------------------------
56 | public MyRecorder() {
57 | File f1 = new File(mFileTmp);
58 | if (!f1.exists()) {
59 | try {
60 | f1.createNewFile();
61 | } catch (IOException e) {
62 | e.printStackTrace();
63 | }
64 | }
65 |
66 | File f2 = new File(mFileMp4);
67 | if (!f2.exists()) {
68 | try {
69 | f2.createNewFile();
70 | } catch (IOException e) {
71 | e.printStackTrace();
72 | }
73 | }
74 | }
75 |
76 | public int start() {
77 | // MediaCodec, ColorFormat
78 | mMediaCodec = MediaCodec.createEncoderByType(mVideoParam.mMime);
79 | MediaFormat mediaFormat = MediaFormat.createVideoFormat(
80 | mVideoParam.mMime, mVideoParam.mSize.width, mVideoParam.mSize.height);
81 | mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE,
82 | mVideoParam.mBps);
83 | mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE,
84 | mVideoParam.getMaxFps());
85 | mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL,
86 | mVideoParam.mIfi);
87 | int col_fmt = -1;
88 | for (int[] colorFormat : ColorFormatList) {
89 | try {
90 | mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT, colorFormat[1]);
91 | mMediaCodec.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
92 | col_fmt = colorFormat[0];
93 | } catch (Exception e) {
94 | continue;
95 | }
96 | }
97 | if (col_fmt < 0) {
98 | mMediaCodec.release();
99 | throw new UnsupportedOperationException("Not found color format");
100 | }
101 | mColorFormat = col_fmt;
102 | mMediaCodec.start();
103 |
104 | //
105 | try {
106 | mOutput = new BufferedOutputStream(new FileOutputStream(mFileTmp));
107 | } catch (Exception e){
108 | e.printStackTrace();
109 | return -1;
110 | }
111 | return 0;
112 | }
113 |
114 | public void stop() {
115 | mMediaCodec.stop();
116 | mMediaCodec.release();
117 | mMediaCodec = null;
118 | mColorFormat = 0;
119 | try {
120 | mOutput.flush();
121 | mOutput.close();
122 | } catch (Exception e){
123 | e.printStackTrace();
124 | }
125 | mOutput = null;
126 |
127 | // Convert
128 | int rcode = MainActivity.native_cnvavc(mFileTmp, mFileMp4);
129 | if (rcode != 0) {
130 | throw new RuntimeException("native_cnvavc()="+rcode);
131 | }
132 | }
133 |
134 | public void offerEncoder(byte[] in) {
135 | if (mMediaCodec == null) {
136 | return;
137 | }
138 | try {
139 | ByteBuffer[] iBufs = mMediaCodec.getInputBuffers();
140 | ByteBuffer[] oBufs = mMediaCodec.getOutputBuffers();
141 |
142 | int iIdx = mMediaCodec.dequeueInputBuffer(-1);
143 | if (iIdx >= 0) {
144 | ByteBuffer iBuf = iBufs[iIdx];
145 | iBuf.clear();
146 | iBuf.put(in);
147 | mMediaCodec.queueInputBuffer(iIdx, 0, in.length, 0, 0);
148 | }
149 |
150 | MediaCodec.BufferInfo bufInfo = new MediaCodec.BufferInfo();
151 | int oIdx = mMediaCodec.dequeueOutputBuffer(bufInfo,0);
152 | while (oIdx >= 0) {
153 | ByteBuffer oBuf = oBufs[oIdx];
154 | byte[] out = new byte[bufInfo.size];
155 | oBuf.get(out);
156 | mOutput.write(out, 0, out.length);
157 | mMediaCodec.releaseOutputBuffer(oIdx, false);
158 | oIdx = mMediaCodec.dequeueOutputBuffer(bufInfo, 0);
159 | }
160 | } catch (Throwable t) {
161 | t.printStackTrace();
162 | }
163 | }
164 |
165 | public int getColorFormat() {
166 | return mColorFormat;
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/MediaCodecTest16/src/jp/morihirosoft/mediacodectest16/VideoParam.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
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 | package jp.morihirosoft.mediacodectest16;
17 |
18 | import android.graphics.ImageFormat;
19 | import android.hardware.Camera;
20 | import android.hardware.Camera.Size;
21 | import android.os.Environment;
22 | import android.util.Log;
23 |
24 | public class VideoParam {
25 | private static final String TAG = "VideoParam";
26 |
27 | //---------------------------------------------------------------------
28 | // CONSTANTS
29 | //---------------------------------------------------------------------
30 | private static final int VIDEO_W = 640;
31 | private static final int VIDEO_H = 480;
32 | private static final int FPS = 30;
33 | private static final String MIME = "video/avc";
34 | private static final int BPS = 4194304; // 0x400000
35 | private static final int IFI = 5;
36 | private static final String SDCARD = Environment.getExternalStorageDirectory().getPath();
37 | private static final String OUTPUT = SDCARD + "/video.mp4";
38 |
39 | //---------------------------------------------------------------------
40 | // MEMBERS
41 | //---------------------------------------------------------------------
42 | public final int mCameraId;
43 | public final boolean mFacingFront;
44 | public final Size mSize;
45 | public final int[] mFpsRange;
46 | public final String mMime = MIME;
47 | public final int mBps = BPS;
48 | public final int mIfi = IFI;
49 | public final String mOutput = OUTPUT;
50 |
51 | //---------------------------------------------------------------------
52 | // SINGLETON
53 | //---------------------------------------------------------------------
54 | private static volatile VideoParam sInstance = null;
55 | private static final Object sSyncObj = new Object();
56 |
57 | public static VideoParam getInstance() {
58 | if (sInstance == null) {
59 | synchronized (sSyncObj) {
60 | if (sInstance == null) {
61 | sInstance = new VideoParam();
62 | }
63 | }
64 | }
65 | return sInstance;
66 | }
67 |
68 | private VideoParam() {
69 | int num = Camera.getNumberOfCameras();
70 | if (num < 1) {
71 | throw new UnsupportedOperationException("No camera");
72 | }
73 |
74 | // Id
75 | mCameraId = 0;
76 |
77 | Camera.Parameters cp = null;
78 | try {
79 | Camera c = Camera.open(mCameraId);
80 | cp = c.getParameters();
81 | c.release();
82 | } catch (Exception e) {
83 | throw new RuntimeException();
84 | }
85 |
86 | final Camera.CameraInfo ci = new Camera.CameraInfo();
87 | Camera.getCameraInfo(mCameraId, ci);
88 |
89 | // Facing
90 | mFacingFront = (ci.facing == Camera.CameraInfo.CAMERA_FACING_FRONT);
91 |
92 | // Size
93 | Size size = null;
94 | for (Camera.Size s : cp.getSupportedPreviewSizes()) {
95 | if (s.width == VIDEO_W && s.height == VIDEO_H) {
96 | size = s;
97 | }
98 | }
99 | if (size == null) {
100 | throw new UnsupportedOperationException(
101 | String.format("Not support size: %dx%d",VIDEO_W,VIDEO_H));
102 | }
103 | mSize = size;
104 |
105 | // Frame rate
106 | int[] fps = null;
107 | for (int[] s : cp.getSupportedPreviewFpsRange()) {
108 | if (s[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] >= FPS*1000) {
109 | fps = s;
110 | }
111 | }
112 | if (fps == null) {
113 | throw new UnsupportedOperationException(
114 | String.format("Not support fps: %d",FPS));
115 | }
116 | mFpsRange = fps;
117 |
118 | // Format (check only)
119 | final int img_fmt = cp.getPreviewFormat();
120 | switch (img_fmt) {
121 | case ImageFormat.NV21:
122 | break;
123 | case ImageFormat.YUY2:
124 | throw new UnsupportedOperationException(
125 | "Not supported: ImageFormat=YUY2");
126 | case ImageFormat.YV12:
127 | throw new UnsupportedOperationException(
128 | "Not supported: ImageFormat=YV12");
129 | default:
130 | throw new UnsupportedOperationException(
131 | "Not supported: ImageFormat=???("+img_fmt+")");
132 | }
133 |
134 | //
135 | Log.i(TAG, "CameraId = "+mCameraId);
136 | Log.i(TAG, "FacingFront = "+mFacingFront);
137 | Log.i(TAG, "Size = "+mSize.width+"x"+mSize.height);
138 | Log.i(TAG, "FpsRange = {"+
139 | mFpsRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]+","+
140 | mFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]+"}");
141 | Log.i(TAG, "ImageFormat = NV21");
142 | }
143 |
144 | //---------------------------------------------------------------------
145 | // PUBLIC METHODS
146 | //---------------------------------------------------------------------
147 | public int getMaxFps() {
148 | return mFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] / 1000;
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/MediaCodecTest18/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/MediaCodecTest18/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | MediaCodecTest18
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/MediaCodecTest18/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
18 |
21 |
22 |
26 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/MediaCodecTest18/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction, and
10 | distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright
13 | owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all other entities
16 | that control, are controlled by, or are under common control with that entity.
17 | For the purposes of this definition, "control" means (i) the power, direct or
18 | indirect, to cause the direction or management of such entity, whether by
19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20 | outstanding shares, or (iii) beneficial ownership of such entity.
21 |
22 | "You" (or "Your") shall mean an individual or Legal Entity exercising
23 | permissions granted by this License.
24 |
25 | "Source" form shall mean the preferred form for making modifications, including
26 | but not limited to software source code, documentation source, and configuration
27 | files.
28 |
29 | "Object" form shall mean any form resulting from mechanical transformation or
30 | translation of a Source form, including but not limited to compiled object code,
31 | generated documentation, and conversions to other media types.
32 |
33 | "Work" shall mean the work of authorship, whether in Source or Object form, made
34 | available under the License, as indicated by a copyright notice that is included
35 | in or attached to the work (an example is provided in the Appendix below).
36 |
37 | "Derivative Works" shall mean any work, whether in Source or Object form, that
38 | is based on (or derived from) the Work and for which the editorial revisions,
39 | annotations, elaborations, or other modifications represent, as a whole, an
40 | original work of authorship. For the purposes of this License, Derivative Works
41 | shall not include works that remain separable from, or merely link (or bind by
42 | name) to the interfaces of, the Work and Derivative Works thereof.
43 |
44 | "Contribution" shall mean any work of authorship, including the original version
45 | of the Work and any modifications or additions to that Work or Derivative Works
46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work
47 | by the copyright owner or by an individual or Legal Entity authorized to submit
48 | on behalf of the copyright owner. For the purposes of this definition,
49 | "submitted" means any form of electronic, verbal, or written communication sent
50 | to the Licensor or its representatives, including but not limited to
51 | communication on electronic mailing lists, source code control systems, and
52 | issue tracking systems that are managed by, or on behalf of, the Licensor for
53 | the purpose of discussing and improving the Work, but excluding communication
54 | that is conspicuously marked or otherwise designated in writing by the copyright
55 | owner as "Not a Contribution."
56 |
57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58 | of whom a Contribution has been received by Licensor and subsequently
59 | incorporated within the Work.
60 |
61 | 2. Grant of Copyright License.
62 |
63 | Subject to the terms and conditions of this License, each Contributor hereby
64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65 | irrevocable copyright license to reproduce, prepare Derivative Works of,
66 | publicly display, publicly perform, sublicense, and distribute the Work and such
67 | Derivative Works in Source or Object form.
68 |
69 | 3. Grant of Patent License.
70 |
71 | Subject to the terms and conditions of this License, each Contributor hereby
72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73 | irrevocable (except as stated in this section) patent license to make, have
74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75 | such license applies only to those patent claims licensable by such Contributor
76 | that are necessarily infringed by their Contribution(s) alone or by combination
77 | of their Contribution(s) with the Work to which such Contribution(s) was
78 | submitted. If You institute patent litigation against any entity (including a
79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80 | Contribution incorporated within the Work constitutes direct or contributory
81 | patent infringement, then any patent licenses granted to You under this License
82 | for that Work shall terminate as of the date such litigation is filed.
83 |
84 | 4. Redistribution.
85 |
86 | You may reproduce and distribute copies of the Work or Derivative Works thereof
87 | in any medium, with or without modifications, and in Source or Object form,
88 | provided that You meet the following conditions:
89 |
90 | You must give any other recipients of the Work or Derivative Works a copy of
91 | this License; and
92 | You must cause any modified files to carry prominent notices stating that You
93 | changed the files; and
94 | You must retain, in the Source form of any Derivative Works that You distribute,
95 | all copyright, patent, trademark, and attribution notices from the Source form
96 | of the Work, excluding those notices that do not pertain to any part of the
97 | Derivative Works; and
98 | If the Work includes a "NOTICE" text file as part of its distribution, then any
99 | Derivative Works that You distribute must include a readable copy of the
100 | attribution notices contained within such NOTICE file, excluding those notices
101 | that do not pertain to any part of the Derivative Works, in at least one of the
102 | following places: within a NOTICE text file distributed as part of the
103 | Derivative Works; within the Source form or documentation, if provided along
104 | with the Derivative Works; or, within a display generated by the Derivative
105 | Works, if and wherever such third-party notices normally appear. The contents of
106 | the NOTICE file are for informational purposes only and do not modify the
107 | License. You may add Your own attribution notices within Derivative Works that
108 | You distribute, alongside or as an addendum to the NOTICE text from the Work,
109 | provided that such additional attribution notices cannot be construed as
110 | modifying the License.
111 | You may add Your own copyright statement to Your modifications and may provide
112 | additional or different license terms and conditions for use, reproduction, or
113 | distribution of Your modifications, or for any such Derivative Works as a whole,
114 | provided Your use, reproduction, and distribution of the Work otherwise complies
115 | with the conditions stated in this License.
116 |
117 | 5. Submission of Contributions.
118 |
119 | Unless You explicitly state otherwise, any Contribution intentionally submitted
120 | for inclusion in the Work by You to the Licensor shall be under the terms and
121 | conditions of this License, without any additional terms or conditions.
122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of
123 | any separate license agreement you may have executed with Licensor regarding
124 | such Contributions.
125 |
126 | 6. Trademarks.
127 |
128 | This License does not grant permission to use the trade names, trademarks,
129 | service marks, or product names of the Licensor, except as required for
130 | reasonable and customary use in describing the origin of the Work and
131 | reproducing the content of the NOTICE file.
132 |
133 | 7. Disclaimer of Warranty.
134 |
135 | Unless required by applicable law or agreed to in writing, Licensor provides the
136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138 | including, without limitation, any warranties or conditions of TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140 | solely responsible for determining the appropriateness of using or
141 | redistributing the Work and assume any risks associated with Your exercise of
142 | permissions under this License.
143 |
144 | 8. Limitation of Liability.
145 |
146 | In no event and under no legal theory, whether in tort (including negligence),
147 | contract, or otherwise, unless required by applicable law (such as deliberate
148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be
149 | liable to You for damages, including any direct, indirect, special, incidental,
150 | or consequential damages of any character arising as a result of this License or
151 | out of the use or inability to use the Work (including but not limited to
152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153 | any and all other commercial damages or losses), even if such Contributor has
154 | been advised of the possibility of such damages.
155 |
156 | 9. Accepting Warranty or Additional Liability.
157 |
158 | While redistributing the Work or Derivative Works thereof, You may choose to
159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160 | other liability obligations and/or rights consistent with this License. However,
161 | in accepting such obligations, You may act only on Your own behalf and on Your
162 | sole responsibility, not on behalf of any other Contributor, and only if You
163 | agree to indemnify, defend, and hold each Contributor harmless for any liability
164 | incurred by, or claims asserted against, such Contributor by reason of your
165 | accepting any such warranty or additional liability.
166 |
167 | END OF TERMS AND CONDITIONS
168 |
169 | APPENDIX: How to apply the Apache License to your work
170 |
171 | To apply the Apache License to your work, attach the following boilerplate
172 | notice, with the fields enclosed by brackets "[]" replaced with your own
173 | identifying information. (Don't include the brackets!) The text should be
174 | enclosed in the appropriate comment syntax for the file format. We also
175 | recommend that a file or class name and description of purpose be included on
176 | the same "printed page" as the copyright notice for easier identification within
177 | third-party archives.
178 |
179 | Copyright [yyyy] [name of copyright owner]
180 |
181 | Licensed under the Apache License, Version 2.0 (the "License");
182 | you may not use this file except in compliance with the License.
183 | You may obtain a copy of the License at
184 |
185 | http://www.apache.org/licenses/LICENSE-2.0
186 |
187 | Unless required by applicable law or agreed to in writing, software
188 | distributed under the License is distributed on an "AS IS" BASIS,
189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190 | See the License for the specific language governing permissions and
191 | limitations under the License.
192 |
--------------------------------------------------------------------------------
/MediaCodecTest18/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-18
15 |
--------------------------------------------------------------------------------
/MediaCodecTest18/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MorihiroSoft/Android_MediaCodecTest/66667e1776d685f719e0f1243c394114d604a19d/MediaCodecTest18/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/MediaCodecTest18/res/layout/main_activity.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
18 |
19 |
25 |
26 |
32 |
33 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/MediaCodecTest18/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MediaCodecTest(API18)
5 | Record
6 | Stop
7 | Playback
8 |
9 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/CameraView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import android.content.Context;
20 | import android.hardware.Camera;
21 | import android.opengl.GLSurfaceView;
22 | import android.util.AttributeSet;
23 |
24 | class CameraView extends GLSurfaceView {
25 | //---------------------------------------------------------------------
26 | // MEMBERS
27 | //---------------------------------------------------------------------
28 | private final VideoParam mVideoParam = VideoParam.getInstance();
29 |
30 | private Camera mCamera = null;
31 | private MyRenderer mRenderer = null;
32 | private MyRecorder mRecorder = null;
33 |
34 | //---------------------------------------------------------------------
35 | // PUBLIC METHODS
36 | //---------------------------------------------------------------------
37 | public CameraView(Context context) {
38 | super(context);
39 | init();
40 | }
41 |
42 | public CameraView(Context context, AttributeSet attrs) {
43 | super(context, attrs);
44 | init();
45 | }
46 |
47 | @Override
48 | public void onResume() {
49 | initCamera();
50 | super.onResume();
51 | }
52 |
53 | @Override
54 | public void onPause() {
55 | quitCamera();
56 | super.onPause();
57 | }
58 |
59 | public void startVideo() {
60 | if (mRecorder == null) {
61 | mRecorder = new MyRecorder();
62 | mRecorder.prepareEncoder();
63 | mRenderer.setRecorder(mRecorder);
64 | }
65 | }
66 |
67 | public void stopVideo() {
68 | if (mRecorder != null) {
69 | mRecorder.stop();
70 | mRecorder = null;
71 | mRenderer.setRecorder(null);
72 | }
73 | }
74 |
75 | //---------------------------------------------------------------------
76 | // PRIVATE...
77 | //---------------------------------------------------------------------
78 | private void init() {
79 | setEGLContextClientVersion(2);
80 | mRenderer = new MyRenderer(this);
81 | setRenderer(mRenderer);
82 | setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
83 | }
84 |
85 | private void initCamera() {
86 | if (mCamera == null) {
87 | try {
88 | mCamera = Camera.open(mVideoParam.mCameraId);
89 | Camera.Parameters cp = mCamera.getParameters();
90 | cp.setPreviewSize(mVideoParam.mSize.width, mVideoParam.mSize.height);
91 | cp.setPreviewFpsRange(
92 | mVideoParam.mFpsRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX],
93 | mVideoParam.mFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]);
94 | mCamera.setParameters(cp);
95 | mRenderer.setCamera(mCamera);
96 | } catch (Exception e) {
97 | e.printStackTrace();
98 | throw new RuntimeException("setup camera");
99 | }
100 | }
101 | }
102 |
103 | private void quitCamera() {
104 | if (mCamera != null) {
105 | mCamera.stopPreview();
106 | mCamera.release();
107 | mCamera = null;
108 | mRenderer.setCamera(null);
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/GlUtil.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import java.nio.ByteBuffer;
20 | import java.nio.ByteOrder;
21 | import java.nio.FloatBuffer;
22 |
23 | import android.opengl.EGL14;
24 | import android.opengl.GLES20;
25 | import android.opengl.Matrix;
26 | import android.util.Log;
27 |
28 | class GlUtil {
29 | private static final String TAG = "GlUtil";
30 |
31 | public static FloatBuffer createSquareVtx() {
32 | final float vtx[] = {
33 | // XYZ, UV
34 | -1f, 1f, 0f, 0f, 1f,
35 | -1f, -1f, 0f, 0f, 0f,
36 | 1f, 1f, 0f, 1f, 1f,
37 | 1f, -1f, 0f, 1f, 0f,
38 | };
39 | ByteBuffer bb = ByteBuffer.allocateDirect(4 * vtx.length);
40 | bb.order(ByteOrder.nativeOrder());
41 | FloatBuffer fb = bb.asFloatBuffer();
42 | fb.put(vtx);
43 | fb.position(0);
44 | return fb;
45 | }
46 |
47 | public static float[] createIdentityMtx() {
48 | float[] m = new float[16];
49 | Matrix.setIdentityM(m, 0);
50 | return m;
51 | }
52 |
53 | public static int createProgram(String vertexSource, String fragmentSource) {
54 | int vs = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
55 | int fs = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
56 | int program = GLES20.glCreateProgram();
57 | GLES20.glAttachShader(program, vs);
58 | GLES20.glAttachShader(program, fs);
59 | GLES20.glLinkProgram(program);
60 | //
61 | int[] linkStatus = new int[1];
62 | GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
63 | if (linkStatus[0] != GLES20.GL_TRUE) {
64 | Log.e(TAG, "Could not link program:");
65 | Log.e(TAG, GLES20.glGetProgramInfoLog(program));
66 | GLES20.glDeleteProgram(program);
67 | program = 0;
68 | }
69 | //
70 | return program;
71 | }
72 |
73 | public static int loadShader(int shaderType, String source) {
74 | int shader = GLES20.glCreateShader(shaderType);
75 | GLES20.glShaderSource(shader, source);
76 | GLES20.glCompileShader(shader);
77 | //
78 | int[] compiled = new int[1];
79 | GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
80 | if (compiled[0] == 0) {
81 | Log.e(TAG, "Could not compile shader(TYPE=" + shaderType + "):");
82 | Log.e(TAG, GLES20.glGetShaderInfoLog(shader));
83 | GLES20.glDeleteShader(shader);
84 | shader = 0;
85 | }
86 | //
87 | return shader;
88 | }
89 |
90 | public static void checkGlError(String op) {
91 | int error;
92 | while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
93 | Log.e(TAG, op + ": glGetError: 0x" + Integer.toHexString(error));
94 | throw new RuntimeException("glGetError encountered (see log)");
95 | }
96 | }
97 |
98 | public static void checkEglError(String op) {
99 | int error;
100 | while ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) {
101 | Log.e(TAG, op + ": eglGetError: 0x" + Integer.toHexString(error));
102 | throw new RuntimeException("eglGetError encountered (see log)");
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/InputSurface.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import android.opengl.EGL14;
20 | import android.opengl.EGLConfig;
21 | import android.opengl.EGLContext;
22 | import android.opengl.EGLDisplay;
23 | import android.opengl.EGLExt;
24 | import android.opengl.EGLSurface;
25 | import android.view.Surface;
26 |
27 | class InputSurface {
28 | //---------------------------------------------------------------------
29 | // CONSTANTS
30 | //---------------------------------------------------------------------
31 | private static final int EGL_RECORDABLE_ANDROID = 0x3142;
32 |
33 | //---------------------------------------------------------------------
34 | // MEMBERS
35 | //---------------------------------------------------------------------
36 | private Surface mSurface = null;
37 | private EGLDisplay mEGLDisplay = null;
38 | private EGLContext mEGLContext = null;
39 | private EGLSurface mEGLSurface = null;
40 |
41 | //---------------------------------------------------------------------
42 | // PUBLIC METHODS
43 | //---------------------------------------------------------------------
44 | public InputSurface(Surface surface) {
45 | if (surface == null) {
46 | throw new NullPointerException();
47 | }
48 | mSurface = surface;
49 | eglSetup();
50 | }
51 |
52 | public void release() {
53 | EGL14.eglDestroySurface(mEGLDisplay, mEGLSurface);
54 | EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
55 | EGL14.eglReleaseThread();
56 | EGL14.eglTerminate(mEGLDisplay);
57 |
58 | mSurface.release();
59 |
60 | mSurface = null;
61 | mEGLDisplay = null;
62 | mEGLContext = null;
63 | mEGLSurface = null;
64 | }
65 |
66 | public Surface getSurface() {
67 | return mSurface;
68 | }
69 |
70 | public void makeCurrent() {
71 | if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
72 | throw new RuntimeException("eglMakeCurrent failed");
73 | }
74 | }
75 |
76 | public boolean swapBuffers() {
77 | return EGL14.eglSwapBuffers(mEGLDisplay, mEGLSurface);
78 | }
79 |
80 | public void setPresentationTime(long nsecs) {
81 | EGLExt.eglPresentationTimeANDROID(mEGLDisplay, mEGLSurface, nsecs);
82 | }
83 |
84 | //---------------------------------------------------------------------
85 | // PRIVATE...
86 | //---------------------------------------------------------------------
87 | private void eglSetup() {
88 | mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
89 | if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
90 | throw new RuntimeException("unable to get EGL14 display");
91 | }
92 | int[] version = new int[2];
93 | if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
94 | mEGLDisplay = null;
95 | throw new RuntimeException("unable to initialize EGL14");
96 | }
97 |
98 | int[] attribList = {
99 | EGL14.EGL_RED_SIZE, 8,
100 | EGL14.EGL_GREEN_SIZE, 8,
101 | EGL14.EGL_BLUE_SIZE, 8,
102 | EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
103 | EGL_RECORDABLE_ANDROID, 1,
104 | EGL14.EGL_NONE
105 | };
106 | EGLConfig[] configs = new EGLConfig[1];
107 | int[] numConfigs = new int[1];
108 | if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
109 | numConfigs, 0)) {
110 | throw new RuntimeException("unable to find RGB888+recordable ES2 EGL config");
111 | }
112 |
113 | int[] attrib_list = {
114 | EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
115 | EGL14.EGL_NONE
116 | };
117 | mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.eglGetCurrentContext(),
118 | attrib_list, 0);
119 | GlUtil.checkEglError("eglCreateContext");
120 | if (mEGLContext == null) {
121 | throw new RuntimeException("null context");
122 | }
123 |
124 | int[] surfaceAttribs = {
125 | EGL14.EGL_NONE
126 | };
127 | mEGLSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, configs[0], mSurface,
128 | surfaceAttribs, 0);
129 | GlUtil.checkEglError("eglCreateWindowSurface");
130 | if (mEGLSurface == null) {
131 | throw new RuntimeException("surface was null");
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/MainActivity.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import android.app.Activity;
20 | import android.content.Intent;
21 | import android.net.Uri;
22 | import android.os.Bundle;
23 | import android.view.View;
24 | import android.view.Window;
25 | import android.view.WindowManager;
26 | import android.widget.Button;
27 |
28 | public class MainActivity extends Activity implements
29 | View.OnClickListener
30 | {
31 | //---------------------------------------------------------------------
32 | // MEMBERS
33 | //---------------------------------------------------------------------
34 | private CameraView mCameraView = null;
35 | private Button mBtnStart = null;
36 | private Button mBtnStop = null;
37 | private Button mBtnPlay = null;
38 |
39 | //---------------------------------------------------------------------
40 | // PUBLIC METHODS
41 | //---------------------------------------------------------------------
42 | @Override
43 | protected void onCreate(Bundle savedInstanceState) {
44 | super.onCreate(savedInstanceState);
45 | getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
46 | requestWindowFeature(Window.FEATURE_NO_TITLE);
47 | setContentView(R.layout.main_activity);
48 |
49 | mCameraView = (CameraView)findViewById(R.id.cameraview);
50 | mBtnStart = (Button)findViewById(R.id.start);
51 | mBtnStop = (Button)findViewById(R.id.stop);
52 | mBtnPlay = (Button)findViewById(R.id.play);
53 |
54 | mBtnStart.setOnClickListener(this);
55 | mBtnStop.setOnClickListener(this);
56 | mBtnPlay.setOnClickListener(this);
57 |
58 | mBtnStart.setEnabled(true);
59 | mBtnStop.setEnabled(false);
60 | }
61 |
62 | @Override
63 | protected void onResume() {
64 | super.onResume();
65 | mCameraView.onResume();
66 | }
67 |
68 | @Override
69 | protected void onPause() {
70 | stopVideo();
71 | mCameraView.onPause();
72 | super.onPause();
73 | }
74 |
75 | @Override
76 | public void onClick(View v) {
77 | switch(v.getId()) {
78 | case R.id.start:
79 | startVideo();
80 | break;
81 | case R.id.stop:
82 | stopVideo();
83 | break;
84 | case R.id.play:
85 | playVideo();
86 | break;
87 | }
88 | }
89 |
90 | //---------------------------------------------------------------------
91 | // PRIVATE...
92 | //---------------------------------------------------------------------
93 | private void startVideo() {
94 | mBtnStart.setEnabled(false);
95 | mBtnStop.setEnabled(true);
96 | mCameraView.startVideo();
97 | }
98 |
99 | private void stopVideo() {
100 | mBtnStart.setEnabled(true);
101 | mBtnStop.setEnabled(false);
102 | mCameraView.stopVideo();
103 | }
104 |
105 | private void playVideo() {
106 | Uri uri = Uri.parse("file://"+VideoParam.getInstance().mOutput);
107 | Intent i = new Intent(Intent.ACTION_VIEW, uri);
108 | i.setDataAndType(uri, "video/mp4");
109 | startActivity(i);
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/MyRecorder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import java.nio.ByteBuffer;
20 |
21 | import android.media.MediaCodec;
22 | import android.media.MediaCodecInfo;
23 | import android.media.MediaFormat;
24 | import android.media.MediaMuxer;
25 | import android.util.Log;
26 |
27 | public class MyRecorder {
28 | //---------------------------------------------------------------------
29 | // MEMBERS
30 | //---------------------------------------------------------------------
31 | private final VideoParam mVideoParam = VideoParam.getInstance();
32 |
33 | private MediaCodec mMediaCodec = null;
34 | private InputSurface mInputSurface = null;
35 | private MediaCodec.BufferInfo mBufferInfo = null;
36 | private MediaMuxer mMediaMuxer = null;
37 | private int mTrackIndex = -1;
38 | private boolean mMuxerStarted = false;
39 | private int mTotalSize = 0; //TODO: DEBUG
40 |
41 | //---------------------------------------------------------------------
42 | // PUBLIC METHODS
43 | //---------------------------------------------------------------------
44 | public MyRecorder() {
45 | }
46 |
47 | public void prepareEncoder() {
48 | if (mMediaCodec != null || mInputSurface != null) {
49 | throw new RuntimeException("prepareEncoder called twice?");
50 | }
51 |
52 | mBufferInfo = new MediaCodec.BufferInfo();
53 | try {
54 | MediaFormat format = MediaFormat.createVideoFormat(
55 | mVideoParam.mMime,
56 | mVideoParam.mSize.width,
57 | mVideoParam.mSize.height);
58 | format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
59 | MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
60 | format.setInteger(MediaFormat.KEY_BIT_RATE, mVideoParam.mBps);
61 | format.setInteger(MediaFormat.KEY_FRAME_RATE, mVideoParam.getMaxFps());
62 | format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, mVideoParam.mIfi);
63 |
64 | mMediaCodec = MediaCodec.createEncoderByType(mVideoParam.mMime);
65 | mMediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
66 |
67 | mMediaMuxer = new MediaMuxer(mVideoParam.mOutput,
68 | MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4);
69 | mMuxerStarted = false;
70 | } catch (Exception e) {
71 | releaseEncoder();
72 | throw (RuntimeException)e;
73 | }
74 | }
75 |
76 | public boolean firstTimeSetup() {
77 | if (!isRecording() || mInputSurface != null) {
78 | return false;
79 | }
80 | try {
81 | mInputSurface = new InputSurface(mMediaCodec.createInputSurface());
82 | mMediaCodec.start();
83 | } catch (Exception e) {
84 | releaseEncoder();
85 | throw (RuntimeException)e;
86 | }
87 | return true;
88 | }
89 |
90 | public boolean isRecording() {
91 | return mMediaCodec != null;
92 | }
93 |
94 | public void makeCurrent() {
95 | mInputSurface.makeCurrent();
96 | }
97 |
98 | synchronized public void swapBuffers() {
99 | if (!isRecording()) {
100 | return;
101 | }
102 | drainEncoder(false);
103 | mInputSurface.swapBuffers();
104 | mInputSurface.setPresentationTime(System.nanoTime());
105 | }
106 |
107 | synchronized public void stop() {
108 | drainEncoder(true);
109 | releaseEncoder();
110 | }
111 |
112 | //---------------------------------------------------------------------
113 | // PRIVATE...
114 | //---------------------------------------------------------------------
115 | private void releaseEncoder() {
116 | if (mMediaCodec != null) {
117 | mMediaCodec.stop();
118 | mMediaCodec.release();
119 | mMediaCodec = null;
120 | }
121 | if (mInputSurface != null) {
122 | mInputSurface.release();
123 | mInputSurface = null;
124 | }
125 | if (mMediaMuxer != null) {
126 | mMediaMuxer.stop();
127 | mMediaMuxer.release();
128 | mMediaMuxer = null;
129 | }
130 | }
131 |
132 | private void drainEncoder(boolean endOfStream) {
133 | if (endOfStream) {
134 | mMediaCodec.signalEndOfInputStream();
135 | }
136 | ByteBuffer[] encoderOutputBuffers = mMediaCodec.getOutputBuffers();
137 | while (true) {
138 | int encoderStatus = mMediaCodec.dequeueOutputBuffer(mBufferInfo, 0);
139 | if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
140 | if (!endOfStream) {
141 | break;
142 | }
143 | } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
144 | encoderOutputBuffers = mMediaCodec.getOutputBuffers();
145 | } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
146 | if (mMuxerStarted) {
147 | throw new RuntimeException("format changed twice");
148 | }
149 | MediaFormat newFormat = mMediaCodec.getOutputFormat();
150 | mTrackIndex = mMediaMuxer.addTrack(newFormat);
151 | mMediaMuxer.start();
152 | mMuxerStarted = true;
153 | } else {
154 | ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
155 | if (encodedData == null) {
156 | throw new RuntimeException("encoderOutputBuffer " + encoderStatus + " was null");
157 | }
158 | if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
159 | mBufferInfo.size = 0;
160 | }
161 | if (mBufferInfo.size != 0) {
162 | if (!mMuxerStarted) {
163 | throw new RuntimeException("muxer hasn't started");
164 | }
165 | encodedData.position(mBufferInfo.offset);
166 | encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
167 |
168 | boolean calc_time = true; //TODO: DEBUG
169 | if (calc_time) {
170 | long t0 = System.currentTimeMillis();
171 | mMediaMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
172 | mTotalSize += mBufferInfo.size;
173 | long dt = System.currentTimeMillis() - t0;
174 | if (dt>50) Log.e("DEBUG", String.format("XXX: dt=%d, size=%.2f",dt,(float)mTotalSize/1024/1024));
175 | } else {
176 | mMediaMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
177 | }
178 | }
179 | mMediaCodec.releaseOutputBuffer(encoderStatus, false);
180 | if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
181 | break;
182 | }
183 | }
184 | }
185 | }
186 | }
187 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/MyRenderer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import java.io.IOException;
20 |
21 | import javax.microedition.khronos.egl.EGLConfig;
22 | import javax.microedition.khronos.opengles.GL10;
23 |
24 | import android.graphics.SurfaceTexture;
25 | import android.hardware.Camera;
26 | import android.opengl.GLES11Ext;
27 | import android.opengl.GLES20;
28 | import android.opengl.GLSurfaceView;
29 |
30 | class MyRenderer implements
31 | GLSurfaceView.Renderer,
32 | SurfaceTexture.OnFrameAvailableListener
33 | {
34 | //---------------------------------------------------------------------
35 | // MEMBERS
36 | //---------------------------------------------------------------------
37 | private final VideoParam mVideoParam = VideoParam.getInstance();
38 | private final float[] mTexMtx = GlUtil.createIdentityMtx();
39 |
40 | private final CameraView mView;
41 |
42 | private Camera mCamera = null;
43 | private SurfaceTexture mSrfTex = null;
44 | private int mSrfTexId = -1;
45 | private int mFboTexId = -1;
46 | private boolean updateSurface = false;
47 | private RenderFbo mRenderFbo = null;
48 | private RenderScreen mRenderScreen = null;
49 | private RenderSrfTex mRenderSrfTex = null;
50 |
51 | //---------------------------------------------------------------------
52 | // PUBLIC METHODS
53 | //---------------------------------------------------------------------
54 | public MyRenderer(CameraView view) {
55 | mView = view;
56 | }
57 |
58 | public void setCamera(Camera camera) {
59 | mCamera = camera;
60 | }
61 |
62 | public void setRecorder(MyRecorder recorder) {
63 | synchronized(this) {
64 | if (recorder != null) {
65 | mRenderSrfTex = new RenderSrfTex(
66 | mVideoParam.mSize.width, mVideoParam.mSize.height,
67 | mFboTexId, recorder);
68 | } else {
69 | mRenderSrfTex = null;
70 | }
71 | }
72 | }
73 |
74 | public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
75 | GlUtil.checkGlError("onSurfaceCreated_S");
76 |
77 | GLES20.glDisable(GLES20.GL_DEPTH_TEST);
78 | GLES20.glDisable(GLES20.GL_CULL_FACE);
79 | GLES20.glDisable(GLES20.GL_BLEND);
80 |
81 | int[] textures = new int[1];
82 | GLES20.glGenTextures(1, textures, 0);
83 | mSrfTexId = textures[0];
84 |
85 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
86 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mSrfTexId);
87 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
88 | GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
89 | GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
90 | GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
91 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
92 | GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
93 | GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
94 | GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
95 |
96 | mSrfTex = new SurfaceTexture(mSrfTexId);
97 | mSrfTex.setOnFrameAvailableListener(this);
98 | try {
99 | mCamera.setPreviewTexture(mSrfTex);
100 | } catch (IOException t) {
101 | }
102 | synchronized(this) {
103 | updateSurface = false;
104 | }
105 | mCamera.startPreview();
106 |
107 | mRenderFbo = new RenderFbo(
108 | mVideoParam.mSize.width, mVideoParam.mSize.height, mSrfTexId);
109 | mFboTexId = mRenderFbo.getFboTexId();
110 | mRenderScreen = new RenderScreen(
111 | mVideoParam.mSize.width, mVideoParam.mSize.height, mFboTexId);
112 | GlUtil.checkGlError("onSurfaceCreated_E");
113 | }
114 |
115 | public void onSurfaceChanged(GL10 glUnused, int width, int height) {
116 | GlUtil.checkGlError("onSurfaceChanged_S");
117 | mRenderScreen.setSize(width, height);
118 | GlUtil.checkGlError("onSurfaceChanged_E");
119 | }
120 |
121 | public void onFrameAvailable(SurfaceTexture surface) {
122 | synchronized(this) {
123 | updateSurface = true;
124 | }
125 | mView.requestRender();
126 | }
127 |
128 | public void onDrawFrame(GL10 glUnused) {
129 | GlUtil.checkGlError("onDrawFrame_S");
130 | synchronized(this) {
131 | if (updateSurface) {
132 | mSrfTex.updateTexImage();
133 | mSrfTex.getTransformMatrix(mTexMtx);
134 | updateSurface = false;
135 | }
136 | }
137 | mRenderFbo.draw(mTexMtx);
138 | mRenderScreen.draw();
139 | if (mRenderSrfTex != null) {
140 | mRenderSrfTex.draw();
141 | }
142 | GlUtil.checkGlError("onDrawFrame_E");
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/RenderFbo.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import java.nio.FloatBuffer;
20 |
21 | import android.opengl.GLES11Ext;
22 | import android.opengl.GLES20;
23 | import android.opengl.Matrix;
24 | import android.os.SystemClock;
25 |
26 | class RenderFbo {
27 | //---------------------------------------------------------------------
28 | // MEMBERS
29 | //---------------------------------------------------------------------
30 | private final FloatBuffer mVtxBuf = GlUtil.createSquareVtx();
31 | private final float[] mPosMtx = GlUtil.createIdentityMtx();
32 | private final float[] mPMtx = GlUtil.createIdentityMtx();
33 | private final float[] mVMtx = GlUtil.createIdentityMtx();
34 | private final float[] mMMtx = GlUtil.createIdentityMtx();
35 | private final float[] mWMtx = GlUtil.createIdentityMtx();
36 | private final int[] mFboId = new int[]{0};
37 | private final int[] mRboId = new int[]{0};
38 | private final int[] mTexId = new int[]{0};
39 |
40 | private final int mSrfTexW;
41 | private final int mSrfTexH;
42 | private final int mSrfTexId;
43 |
44 | private int mProgram = -1;
45 | private int maPositionHandle = -1;
46 | private int maTexCoordHandle = -1;
47 | private int muPosMtxHandle = -1;
48 | private int muTexMtxHandle = -1;
49 | private int muSamplerHandle = -1;
50 |
51 | //---------------------------------------------------------------------
52 | // PUBLIC METHODS
53 | //---------------------------------------------------------------------
54 | public RenderFbo(int w, int h, int id) {
55 | mSrfTexW = w;
56 | mSrfTexH = h;
57 | mSrfTexId = id;
58 |
59 | initGL();
60 | initFBO();
61 | }
62 |
63 | public int getFboTexId() {
64 | return mTexId[0];
65 | }
66 |
67 | public void draw(final float[] tex_mtx) {
68 | GlUtil.checkGlError("draw_S");
69 |
70 | //TODO: for sample.
71 | boolean for_sample = true;
72 | if (for_sample) {
73 | long time = SystemClock.uptimeMillis() % 7200L;
74 | float angle = 0.05f * ((int) time);
75 | Matrix.setRotateM(mWMtx, 0, angle, 0, 0, 1);
76 | Matrix.multiplyMM(mPosMtx, 0, mWMtx, 0, mMMtx, 0);
77 | Matrix.multiplyMM(mPosMtx, 0, mVMtx, 0, mPosMtx, 0);
78 | Matrix.multiplyMM(mPosMtx, 0, mPMtx, 0, mPosMtx, 0);
79 | } else {
80 | Matrix.multiplyMM(mPosMtx, 0, mMMtx, 0, mVMtx, 0);
81 | Matrix.multiplyMM(mPosMtx, 0, mPMtx, 0, mPosMtx, 0);
82 | }
83 |
84 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFboId[0]);
85 |
86 | GLES20.glViewport(0, 0, mSrfTexW, mSrfTexH);
87 |
88 | GLES20.glClearColor(0f, 0f, 0f, 1f);
89 | GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
90 |
91 | GLES20.glUseProgram(mProgram);
92 |
93 | mVtxBuf.position(0);
94 | GLES20.glVertexAttribPointer(maPositionHandle,
95 | 3, GLES20.GL_FLOAT, false, 4*(3+2), mVtxBuf);
96 | GLES20.glEnableVertexAttribArray(maPositionHandle);
97 |
98 | mVtxBuf.position(3);
99 | GLES20.glVertexAttribPointer(maTexCoordHandle,
100 | 2, GLES20.GL_FLOAT, false, 4*(3+2), mVtxBuf);
101 | GLES20.glEnableVertexAttribArray(maTexCoordHandle);
102 |
103 | GLES20.glUniformMatrix4fv(muPosMtxHandle, 1, false, mPosMtx, 0);
104 | GLES20.glUniformMatrix4fv(muTexMtxHandle, 1, false, tex_mtx, 0);
105 | GLES20.glUniform1i(muSamplerHandle, 0);
106 |
107 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
108 | GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mSrfTexId);
109 |
110 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
111 |
112 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
113 | GlUtil.checkGlError("draw_E");
114 | }
115 |
116 | //---------------------------------------------------------------------
117 | // PRIVATE...
118 | //---------------------------------------------------------------------
119 | private void initGL() {
120 | GlUtil.checkGlError("initGL_S");
121 |
122 | final String vertexShader =
123 | //
124 | "attribute vec4 aPosition;\n" +
125 | "attribute vec4 aTexCoord;\n" +
126 | "uniform mat4 uPosMtx;\n" +
127 | "uniform mat4 uTexMtx;\n" +
128 | "varying vec2 vTexCoord;\n" +
129 | "void main() {\n" +
130 | " gl_Position = uPosMtx * aPosition;\n" +
131 | " vTexCoord = (uTexMtx * aTexCoord).xy;\n" +
132 | "}\n";
133 | final String fragmentShader =
134 | //
135 | "#extension GL_OES_EGL_image_external : require\n" +
136 | "precision mediump float;\n" +
137 | "uniform samplerExternalOES uSampler;\n" +
138 | "varying vec2 vTexCoord;\n" +
139 | "void main() {\n" +
140 | " gl_FragColor = texture2D(uSampler, vTexCoord);\n" +
141 | "}\n";
142 | mProgram = GlUtil.createProgram(vertexShader, fragmentShader);
143 | maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
144 | maTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "aTexCoord");
145 | muPosMtxHandle = GLES20.glGetUniformLocation(mProgram, "uPosMtx");
146 | muTexMtxHandle = GLES20.glGetUniformLocation(mProgram, "uTexMtx");
147 | muSamplerHandle = GLES20.glGetUniformLocation(mProgram, "uSampler");
148 |
149 | float ratio = (float)mSrfTexW/(float)mSrfTexH;
150 | Matrix.perspectiveM(mPMtx, 0, 45, ratio, 1, 10);
151 |
152 | Matrix.setLookAtM(mVMtx, 0,
153 | 0f, 0f, 2f, // eye
154 | 0f, 0f, 0f, // center
155 | 0f, 1f, 0f); // up
156 |
157 | Matrix.setIdentityM(mMMtx, 0);
158 | if (mSrfTexW > mSrfTexH) {
159 | Matrix.scaleM(mMMtx, 0, 1f, (float)mSrfTexH/(float)mSrfTexW, 1f);
160 | } else {
161 | Matrix.scaleM(mMMtx, 0, (float)mSrfTexW/(float)mSrfTexH, 1f, 1f);
162 | }
163 |
164 | GlUtil.checkGlError("initGL_E");
165 | }
166 |
167 | private void initFBO() {
168 | GlUtil.checkGlError("initFBO_S");
169 |
170 | GLES20.glGenFramebuffers(1, mFboId, 0);
171 | GLES20.glGenRenderbuffers(1, mRboId, 0);
172 | GLES20.glGenTextures(1, mTexId, 0);
173 |
174 | GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, mRboId[0]);
175 | GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER,
176 | GLES20.GL_DEPTH_COMPONENT16, mSrfTexW, mSrfTexH);
177 |
178 | GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFboId[0]);
179 | GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER,
180 | GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, mRboId[0]);
181 |
182 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
183 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTexId[0]);
184 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
185 | GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
186 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
187 | GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
188 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
189 | GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
190 | GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D,
191 | GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
192 |
193 | GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA,
194 | mSrfTexW, mSrfTexH, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);
195 |
196 | GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
197 | GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, mTexId[0], 0);
198 |
199 | if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER) !=
200 | GLES20.GL_FRAMEBUFFER_COMPLETE) {
201 | throw new RuntimeException("glCheckFramebufferStatus()");
202 | }
203 |
204 | GlUtil.checkGlError("initFBO_E");
205 | }
206 | }
207 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/RenderScreen.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import java.nio.FloatBuffer;
20 |
21 | import android.opengl.GLES20;
22 | import android.opengl.Matrix;
23 |
24 | class RenderScreen {
25 | //---------------------------------------------------------------------
26 | // MEMBERS
27 | //---------------------------------------------------------------------
28 | private final FloatBuffer mVtxBuf = GlUtil.createSquareVtx();
29 | private final float[] mPosMtx = GlUtil.createIdentityMtx();
30 |
31 | private final int mFboTexW;
32 | private final int mFboTexH;
33 | private final int mFboTexId;
34 |
35 | private int mProgram = -1;
36 | private int maPositionHandle = -1;
37 | private int maTexCoordHandle = -1;
38 | private int muPosMtxHandle = -1;
39 | private int muSamplerHandle = -1;
40 |
41 | private int mScreenW = -1;
42 | private int mScreenH = -1;
43 |
44 | //---------------------------------------------------------------------
45 | // PUBLIC METHODS
46 | //---------------------------------------------------------------------
47 | public RenderScreen(int w, int h, int id) {
48 | mFboTexW = w;
49 | mFboTexH = h;
50 | mFboTexId = id;
51 |
52 | initGL();
53 | }
54 |
55 | public void setSize(int w, int h) {
56 | mScreenW = w;
57 | mScreenH = h;
58 |
59 | Matrix.setIdentityM(mPosMtx, 0);
60 | if (mFboTexW * mScreenH < mFboTexH * mScreenW) {
61 | Matrix.scaleM(mPosMtx, 0,
62 | (float)mFboTexW*((float)mScreenH/(float)mFboTexH)/(float)mScreenW, 1f, 1f);
63 | } else {
64 | Matrix.scaleM(mPosMtx, 0,
65 | 1f, (float)mFboTexH*((float)mScreenW/(float)mFboTexW)/(float)mScreenH, 1f);
66 | }
67 | }
68 |
69 | public void draw() {
70 | if (mScreenW <= 0 || mScreenH <= 0) {
71 | return;
72 | }
73 | GlUtil.checkGlError("draw_S");
74 |
75 | GLES20.glViewport(0, 0, mScreenW, mScreenH);
76 |
77 | GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1f);
78 | GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
79 |
80 | GLES20.glUseProgram(mProgram);
81 |
82 | mVtxBuf.position(0);
83 | GLES20.glVertexAttribPointer(maPositionHandle,
84 | 3, GLES20.GL_FLOAT, false, 4*(3+2), mVtxBuf);
85 | GLES20.glEnableVertexAttribArray(maPositionHandle);
86 |
87 | mVtxBuf.position(3);
88 | GLES20.glVertexAttribPointer(maTexCoordHandle,
89 | 2, GLES20.GL_FLOAT, false, 4*(3+2), mVtxBuf);
90 | GLES20.glEnableVertexAttribArray(maTexCoordHandle);
91 |
92 | GLES20.glUniformMatrix4fv(muPosMtxHandle, 1, false, mPosMtx, 0);
93 | GLES20.glUniform1i(muSamplerHandle, 0);
94 |
95 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
96 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFboTexId);
97 |
98 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
99 |
100 | GlUtil.checkGlError("draw_E");
101 | }
102 |
103 | //---------------------------------------------------------------------
104 | // PRIVATE...
105 | //---------------------------------------------------------------------
106 | private void initGL() {
107 | GlUtil.checkGlError("initGL_S");
108 |
109 | final String vertexShader =
110 | //
111 | "attribute vec4 aPosition;\n" +
112 | "attribute vec4 aTexCoord;\n" +
113 | "uniform mat4 uPosMtx;\n" +
114 | "varying vec2 vTexCoord;\n" +
115 | "void main() {\n" +
116 | " gl_Position = uPosMtx * aPosition;\n" +
117 | " vTexCoord = aTexCoord.xy;\n" +
118 | "}\n";
119 | final String fragmentShader =
120 | //
121 | "precision mediump float;\n" +
122 | "uniform sampler2D uSampler;\n" +
123 | "varying vec2 vTexCoord;\n" +
124 | "void main() {\n" +
125 | " gl_FragColor = texture2D(uSampler, vTexCoord);\n" +
126 | "}\n";
127 | mProgram = GlUtil.createProgram(vertexShader, fragmentShader);
128 | maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
129 | maTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "aTexCoord");
130 | muPosMtxHandle = GLES20.glGetUniformLocation(mProgram, "uPosMtx");
131 | muSamplerHandle = GLES20.glGetUniformLocation(mProgram, "uSampler");
132 |
133 | GlUtil.checkGlError("initGL_E");
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/RenderSrfTex.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import java.nio.FloatBuffer;
20 |
21 | import android.opengl.EGL14;
22 | import android.opengl.EGLContext;
23 | import android.opengl.EGLDisplay;
24 | import android.opengl.EGLSurface;
25 | import android.opengl.GLES20;
26 |
27 | class RenderSrfTex {
28 | //---------------------------------------------------------------------
29 | // MEMBERS
30 | //---------------------------------------------------------------------
31 | private final FloatBuffer mVtxBuf = GlUtil.createSquareVtx();
32 |
33 | private final int mFboTexW;
34 | private final int mFboTexH;
35 | private final int mFboTexId;
36 | private final MyRecorder mRecorder;
37 |
38 | private int mProgram = -1;
39 | private int maPositionHandle = -1;
40 | private int maTexCoordHandle = -1;
41 | private int muSamplerHandle = -1;
42 |
43 | private EGLDisplay mSavedEglDisplay = null;
44 | private EGLSurface mSavedEglDrawSurface = null;
45 | private EGLSurface mSavedEglReadSurface = null;
46 | private EGLContext mSavedEglContext = null;
47 |
48 | //---------------------------------------------------------------------
49 | // PUBLIC METHODS
50 | //---------------------------------------------------------------------
51 | public RenderSrfTex(int w, int h, int id, MyRecorder recorder) {
52 | mFboTexW = w;
53 | mFboTexH = h;
54 | mFboTexId = id;
55 | mRecorder = recorder;
56 | }
57 |
58 | public void draw() {
59 | saveRenderState();
60 | {
61 | GlUtil.checkGlError("draw_S");
62 |
63 | if (mRecorder.firstTimeSetup()) {
64 | mRecorder.makeCurrent();
65 | initGL();
66 | } else {
67 | mRecorder.makeCurrent();
68 | }
69 |
70 | GLES20.glViewport(0, 0, mFboTexW, mFboTexH);
71 |
72 | GLES20.glClearColor(0f, 0f, 0f, 1f);
73 | GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
74 |
75 | GLES20.glUseProgram(mProgram);
76 |
77 | mVtxBuf.position(0);
78 | GLES20.glVertexAttribPointer(maPositionHandle,
79 | 3, GLES20.GL_FLOAT, false, 4*(3+2), mVtxBuf);
80 | GLES20.glEnableVertexAttribArray(maPositionHandle);
81 |
82 | mVtxBuf.position(3);
83 | GLES20.glVertexAttribPointer(maTexCoordHandle,
84 | 2, GLES20.GL_FLOAT, false, 4*(3+2), mVtxBuf);
85 | GLES20.glEnableVertexAttribArray(maTexCoordHandle);
86 |
87 | GLES20.glUniform1i(muSamplerHandle, 0);
88 |
89 | GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
90 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mFboTexId);
91 |
92 | GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
93 |
94 | mRecorder.swapBuffers();
95 |
96 | GlUtil.checkGlError("draw_E");
97 | }
98 | restoreRenderState();
99 | }
100 |
101 | //---------------------------------------------------------------------
102 | // PRIVATE...
103 | //---------------------------------------------------------------------
104 | private void initGL() {
105 | GlUtil.checkGlError("initGL_S");
106 |
107 | final String vertexShader =
108 | //
109 | "attribute vec4 aPosition;\n" +
110 | "attribute vec4 aTexCoord;\n" +
111 | "varying vec2 vTexCoord;\n" +
112 | "void main() {\n" +
113 | " gl_Position = aPosition;\n" +
114 | " vTexCoord = aTexCoord.xy;\n" +
115 | "}\n";
116 | final String fragmentShader =
117 | //
118 | "precision mediump float;\n" +
119 | "uniform sampler2D uSampler;\n" +
120 | "varying vec2 vTexCoord;\n" +
121 | "void main() {\n" +
122 | " gl_FragColor = texture2D(uSampler, vTexCoord);\n" +
123 | "}\n";
124 | mProgram = GlUtil.createProgram(vertexShader, fragmentShader);
125 | maPositionHandle = GLES20.glGetAttribLocation(mProgram, "aPosition");
126 | maTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "aTexCoord");
127 | muSamplerHandle = GLES20.glGetUniformLocation(mProgram, "uSampler");
128 |
129 | GLES20.glDisable(GLES20.GL_DEPTH_TEST);
130 | GLES20.glDisable(GLES20.GL_CULL_FACE);
131 | GLES20.glDisable(GLES20.GL_BLEND);
132 |
133 | GlUtil.checkGlError("initGL_E");
134 | }
135 |
136 | private void saveRenderState() {
137 | mSavedEglDisplay = EGL14.eglGetCurrentDisplay();
138 | mSavedEglDrawSurface = EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW);
139 | mSavedEglReadSurface = EGL14.eglGetCurrentSurface(EGL14.EGL_READ);
140 | mSavedEglContext = EGL14.eglGetCurrentContext();
141 | }
142 |
143 | private void restoreRenderState() {
144 | if (!EGL14.eglMakeCurrent(
145 | mSavedEglDisplay,
146 | mSavedEglDrawSurface,
147 | mSavedEglReadSurface,
148 | mSavedEglContext)) {
149 | throw new RuntimeException("eglMakeCurrent failed");
150 | }
151 | }
152 | }
153 |
--------------------------------------------------------------------------------
/MediaCodecTest18/src/jp/morihirosoft/mediacodectest18/VideoParam.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (C) 2013 MorihiroSoft
3 | * Copyright 2013 Google Inc. All Rights Reserved.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package jp.morihirosoft.mediacodectest18;
18 |
19 | import android.graphics.ImageFormat;
20 | import android.hardware.Camera;
21 | import android.hardware.Camera.Size;
22 | import android.media.MediaCodecInfo;
23 | import android.media.MediaCodecList;
24 | import android.os.Environment;
25 | import android.util.Log;
26 |
27 | public class VideoParam {
28 | private static final boolean DEBUG = true;
29 | private static final String TAG = "VideoParam";
30 |
31 | //---------------------------------------------------------------------
32 | // CONSTANTS
33 | //---------------------------------------------------------------------
34 | private static final int VIDEO_W = 640;
35 | private static final int VIDEO_H = 480;
36 | private static final int FPS = 30;
37 | private static final String MIME = "video/avc";
38 | private static final int BPS = 4*1024*1024;
39 | private static final int IFI = 5;
40 | private static final String SDCARD = Environment.getExternalStorageDirectory().getPath();
41 | private static final String OUTPUT = SDCARD + "/video.mp4";
42 |
43 | //---------------------------------------------------------------------
44 | // MEMBERS
45 | //---------------------------------------------------------------------
46 | public final int mCameraId;
47 | public final boolean mFacingFront;
48 | public final Size mSize;
49 | public final int[] mFpsRange;
50 | public final String mMime;
51 | public final int mBps = BPS;
52 | public final int mIfi = IFI;
53 | public final String mOutput = OUTPUT;
54 |
55 | //---------------------------------------------------------------------
56 | // SINGLETON
57 | //---------------------------------------------------------------------
58 | private static volatile VideoParam sInstance = null;
59 | private static final Object sSyncObj = new Object();
60 |
61 | public static VideoParam getInstance() {
62 | if (sInstance == null) {
63 | synchronized (sSyncObj) {
64 | if (sInstance == null) {
65 | sInstance = new VideoParam();
66 | }
67 | }
68 | }
69 | return sInstance;
70 | }
71 |
72 | private VideoParam() {
73 | // Id
74 | int camera_num = Camera.getNumberOfCameras();
75 | if (DEBUG) Log.d(TAG, "CameraNum = "+camera_num);
76 | if (camera_num < 1) {
77 | throw new UnsupportedOperationException("No camera");
78 | }
79 | mCameraId = 0;
80 | Log.i(TAG, "mCameraId = "+mCameraId);
81 |
82 | Camera.Parameters cp = null;
83 | try {
84 | Camera c = Camera.open(mCameraId);
85 | cp = c.getParameters();
86 | c.release();
87 | } catch (Exception e) {
88 | throw new RuntimeException();
89 | }
90 | final Camera.CameraInfo ci = new Camera.CameraInfo();
91 | Camera.getCameraInfo(mCameraId, ci);
92 |
93 | // Facing
94 | mFacingFront = (ci.facing == Camera.CameraInfo.CAMERA_FACING_FRONT);
95 | Log.i(TAG, "mFacingFront = "+mFacingFront);
96 |
97 | // Size
98 | Size size = null;
99 | for (Camera.Size s : cp.getSupportedPreviewSizes()) {
100 | if (DEBUG) Log.d(TAG, "Size = "+s.width+"x"+s.height);
101 | if (s.width == VIDEO_W && s.height == VIDEO_H) {
102 | size = s;
103 | }
104 | }
105 | if (size == null) {
106 | throw new UnsupportedOperationException(
107 | String.format("Not support size: %dx%d",VIDEO_W,VIDEO_H));
108 | }
109 | mSize = size;
110 | Log.i(TAG, "mSize = "+mSize.width+"x"+mSize.height);
111 |
112 | // Frame rate
113 | int[] fps = null;
114 | for (int[] f : cp.getSupportedPreviewFpsRange()) {
115 | if (DEBUG) Log.d(TAG, "FpsRange = {"+
116 | f[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]+","+
117 | f[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]+"}");
118 | if (f[Camera.Parameters.PREVIEW_FPS_MAX_INDEX] >= FPS*1000) {
119 | fps = f;
120 | }
121 | }
122 | if (fps == null) {
123 | throw new UnsupportedOperationException(
124 | String.format("Not support fps: %d",FPS));
125 | }
126 | mFpsRange = fps;
127 | Log.i(TAG, "mFpsRange = {"+
128 | mFpsRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]+","+
129 | mFpsRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]+"}");
130 |
131 | // Format (check only)
132 | final int img_fmt = cp.getPreviewFormat();
133 | switch (img_fmt) {
134 | case ImageFormat.NV21:
135 | Log.i(TAG, "mImageFormat = NV21");
136 | break;
137 | case ImageFormat.YUY2:
138 | throw new UnsupportedOperationException(
139 | "Not supported: ImageFormat=YUY2");
140 | case ImageFormat.YV12:
141 | throw new UnsupportedOperationException(
142 | "Not supported: ImageFormat=YV12");
143 | default:
144 | throw new UnsupportedOperationException(
145 | "Not supported: ImageFormat=???("+img_fmt+")");
146 | }
147 |
148 | // MIME
149 | String mime = null;
150 | int codec_num = MediaCodecList.getCodecCount();
151 | for (int i=0; i
48 |
49 | Unless required by applicable law or agreed to in writing, software
50 | distributed under the License is distributed on an "AS IS" BASIS,
51 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
52 | See the License for the specific language governing permissions and
53 | limitations under the License.
54 |
--------------------------------------------------------------------------------
/screenshot16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MorihiroSoft/Android_MediaCodecTest/66667e1776d685f719e0f1243c394114d604a19d/screenshot16.png
--------------------------------------------------------------------------------
/screenshot18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MorihiroSoft/Android_MediaCodecTest/66667e1776d685f719e0f1243c394114d604a19d/screenshot18.png
--------------------------------------------------------------------------------