Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
1
2
3
4
5
6
7
8
9
10
11
12
Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
PID: 4002, TID: 1253756, Thread name: (none), Queue name: com.apple.root.user-initiated-qos, QoS: 25
Backtrace:
4 ZFPlayerFramework 0x0000000107ddd5f4 -[IJKSDLGLView isApplicationActive] + 140
5 ZFPlayerFramework 0x0000000107ddddd0 -[IJKSDLGLView display:] + 68
6 ZFPlayerFramework 0x0000000107dddd68 __38-[IJKSDLGLView invalidateRenderBuffer]_block_invoke + 72
7 libdispatch.dylib 0x0000000116876338 _dispatch_call_block_and_release + 24
8 libdispatch.dylib 0x0000000116877730 _dispatch_client_callout + 16
9 libdispatch.dylib 0x0000000116888ec8 _dispatch_root_queue_drain + 716
10 libdispatch.dylib 0x0000000116889698 _dispatch_worker_thread2 + 152
11 libsystem_pthread.dylib 0x00000001bbd24b38 _pthread_wqthread + 212
12 libsystem_pthread.dylib 0x00000001bbd27740 start_wqthread + 8
解决方法: 如果有源码,直接把相关代码放在主线程
几乎所有ffmpeg高版本都会报这个错,这个3.4.6,和ijk用的3.4应该是很接近的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Undefined symbols for architecture arm64:
"_av_application_on_async_statistic", referenced from:
_call_inject_statistic in IJKMediaFramework(ijkasync.o)
"_av_application_on_async_read_speed", referenced from:
_call_inject_async_fill_speed in IJKMediaFramework(ijkasync.o)
"_ijkav_register_ijkio_protocol", referenced from:
_ijkav_register_all in IJKMediaFramework(allformats.o)
"_ijkav_register_ijklongurl_protocol", referenced from:
_ijkav_register_all in IJKMediaFramework(allformats.o)
"_ijkav_register_ijkhttphook_protocol", referenced from:
_ijkav_register_all in IJKMediaFramework(allformats.o)
"_ijkav_register_ijktcphook_protocol", referenced from:
_ijkav_register_all in IJKMediaFramework(allformats.o)
"_av_application_on_io_control", referenced from:
_ijkurlhook_call_inject in IJKMediaFramework(ijklivehook.o)
_ijkurlhook_call_inject in IJKMediaFramework(ijkurlhook.o)
_ijksegment_open in IJKMediaFramework(ijksegment.o)
_ijkio_urlhook_call_inject in IJKMediaFramework(ijkiourlhook.o)
"_ijkav_register_ijksegment_protocol", referenced from:
_ijkav_register_all in IJKMediaFramework(allformats.o)
"_ijkav_register_async_protocol", referenced from:
_ijkav_register_all in IJKMediaFramework(allformats.o)
"_av_application_open", referenced from:
_ffp_set_inject_opaque in IJKMediaFramework(ff_ffplay.o)
"_av_application_closep", referenced from:
_ffp_reset_internal in IJKMediaFramework(ff_ffplay.o)
_ffp_set_inject_opaque in IJKMediaFramework(ff_ffplay.o)
allformat.c
#define IJK_REGISTER_PROTOCOL(x) \
{ \
extern URLProtocol ijkimp_ff_##x##_protocol; \
int ijkav_register_##x##_protocol(URLProtocol *protocol, int protocol_size);\
ijkav_register_##x##_protocol(&ijkimp_ff_##x##_protocol, sizeof(URLProtocol)); \
}
#ifdef __ANDROID__
IJK_REGISTER_PROTOCOL(ijkmediadatasource);
#endif
IJK_REGISTER_PROTOCOL(ijkio);
IJK_REGISTER_PROTOCOL(async);
IJK_REGISTER_PROTOCOL(ijklongurl);
IJK_REGISTER_PROTOCOL(ijktcphook);
IJK_REGISTER_PROTOCOL(ijkhttphook);
IJK_REGISTER_PROTOCOL(ijksegment);
/* demuxers */
IJK_REGISTER_DEMUXER(ijklivehook);
1
这些并不是ffmpeg的东西, 而是ijk本身的
1
2
3
4
5
av_application_on_async_statistic
av_application_on_async_read_speed
av_application_on_io_control
av_application_open
av_application_closep
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
这个application相关的看到是在libavutil/application.h中的,但是3.4还存在,3.4.6就没有了?而且google这些符号,很少找到跟ffmpeg直接挂钩甚至相关联的,而都是跟ijk这个项目本身关联的,这就有点儿离谱。
为了验证这一点直接去下载3.4版本的源码看看,发现根本就没有appliation.c/application.h的存在
最后去确认ijk依赖的ffmpeg到底是哪里来的,看看init-ios.sh:
IJK_FFMPEG_UPSTREAM=https://github.com/Bilibili/FFmpeg.git
IJK_FFMPEG_FORK=https://github.com/Bilibili/FFmpeg.git
IJK_FFMPEG_COMMIT=ff3.4--ijk0.8.7--20180103--001
OMG!原来是bilibili自己的fork, 至此可以确定,如果自己去找ffmpeg源码直接build, 那显然是不会成功滴!!!
同时发现:
IJK_GASP_UPSTREAM=https://github.com/Bilibili/gas-preprocessor.git
gas-preprocessor也是他自己的fork
为什么首先不从这里排查?蠢呗!
在ijk
项目的这个issue下找到了兼容armv7的解决方案
1
2
3
4
5
6
7
180-194行
if ["FF_ARCH" = "arm64"]
then
FF_AS="gas-preprocessor.pl -arch aarch64 -- $FF_XCRUN_CC"
else
FF_AS="gas-preprocessor.pl -- $FF_XCRUN_CC"
fi
1
--as="$FF_AS" \ # 246行
pull-repo-base.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#! /usr/bin/env bash
REMOTE_REPO=$1
LOCAL_WORKSPACE=$2
if [ -z $REMOTE_REPO -o -z $LOCAL_WORKSPACE ]; then
echo "invalid call pull-repo.sh '$REMOTE_REPO' '$LOCAL_WORKSPACE'"
elif [ ! -d $LOCAL_WORKSPACE ]; then
git clone $REMOTE_REPO $LOCAL_WORKSPACE
else
cd $LOCAL_WORKSPACE
git fetch --all --tags
cd -
fi
pull-repo-ref.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#! /usr/bin/env bash
REMOTE_REPO=$1
LOCAL_WORKSPACE=$2
REF_REPO=$3
if [ -z $1 -o -z $2 -o -z $3 ]; then
echo "invalid call pull-repo.sh '$1' '$2' '$3'"
elif [ ! -d $LOCAL_WORKSPACE ]; then
git clone --reference $REF_REPO $REMOTE_REPO $LOCAL_WORKSPACE
cd $LOCAL_WORKSPACE
git repack -a
else
cd $LOCAL_WORKSPACE
git fetch --all --tags
cd -
fi
Init-ios.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#! /usr/bin/env bash
#
# Copyright (C) 2013-2015 Bilibili
# Copyright (C) 2013-2015 Zhang Rui <bbcallen@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# IJK_FFMPEG_UPSTREAM=git://git.videolan.org/ffmpeg.git
IJK_FFMPEG_UPSTREAM=https://github.com/Bilibili/FFmpeg.git
IJK_FFMPEG_FORK=https://github.com/Bilibili/FFmpeg.git
IJK_FFMPEG_COMMIT=ff3.4--ijk0.8.7--20180103--001
IJK_FFMPEG_LOCAL_REPO=extra/ffmpeg
IJK_GASP_UPSTREAM=https://github.com/Bilibili/gas-preprocessor.git
# gas-preprocessor backup
# https://github.com/Bilibili/gas-preprocessor.git
if [ "$IJK_FFMPEG_REPO_URL" != "" ]; then
IJK_FFMPEG_UPSTREAM=$IJK_FFMPEG_REPO_URL
IJK_FFMPEG_FORK=$IJK_FFMPEG_REPO_URL
fi
if [ "$IJK_GASP_REPO_URL" != "" ]; then
IJK_GASP_UPSTREAM=$IJK_GASP_REPO_URL
fi
set -e
TOOLS=tools
FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386"
FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64"
FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64"
FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS8_SDK
FF_TARGET=$1
function echo_ffmpeg_version() {
echo $IJK_FFMPEG_COMMIT
}
function pull_common() {
git --version
echo "== pull gas-preprocessor base =="
sh $TOOLS/pull-repo-base.sh $IJK_GASP_UPSTREAM extra/gas-preprocessor
echo "== pull ffmpeg base =="
sh $TOOLS/pull-repo-base.sh $IJK_FFMPEG_UPSTREAM $IJK_FFMPEG_LOCAL_REPO
}
function pull_fork() {
echo "== pull ffmpeg fork $1 =="
sh $TOOLS/pull-repo-ref.sh $IJK_FFMPEG_FORK ios/ffmpeg-$1 ${IJK_FFMPEG_LOCAL_REPO}
cd ios/ffmpeg-$1
git checkout ${IJK_FFMPEG_COMMIT} -B ijkplayer
cd -
}
function pull_fork_all() {
for ARCH in $FF_ALL_ARCHS
do
pull_fork $ARCH
done
}
function sync_ff_version() {
sed -i '' "s/static const char \*kIJKFFRequiredFFmpegVersion\ \=\ .*/static const char *kIJKFFRequiredFFmpegVersion = \"${IJK_FFMPEG_COMMIT}\";/g" ios/IJKMediaPlayer/IJKMediaPlayer/IJKFFMoviePlayerController.m
}
#----------
case "$FF_TARGET" in
ffmpeg-version)
echo_ffmpeg_version
;;
armv7|armv7s|arm64|i386|x86_64)
pull_common
pull_fork $FF_TARGET
;;
all|*)
pull_common
pull_fork_all
;;
esac
sync_ff_version
compile-ffmpeg.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#! /usr/bin/env bash
#
# Copyright (C) 2013-2014 Bilibili
# Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
#----------
# modify for your build tool
FF_ALL_ARCHS_IOS6_SDK="armv7 armv7s i386"
FF_ALL_ARCHS_IOS7_SDK="armv7 armv7s arm64 i386 x86_64"
FF_ALL_ARCHS_IOS8_SDK="arm64 armv7"
FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS8_SDK
#----------\
UNI_BUILD_ROOT=`pwd`
UNI_TMP="$UNI_BUILD_ROOT/tmp"
UNI_TMP_LLVM_VER_FILE="$UNI_TMP/llvm.ver.txt"
FF_TARGET=$1
FF_TARGET_EXTRA=$2
set -e
#----------
echo_archs() {
echo "===================="
echo "[*] check xcode version"
echo "===================="
echo "FF_ALL_ARCHS = $FF_ALL_ARCHS"
}
FF_LIBS="libavcodec libavfilter libavformat libavutil libswscale libswresample"
do_lipo_ffmpeg () {
LIB_FILE=$1
LIPO_FLAGS=
for ARCH in $FF_ALL_ARCHS
do
ARCH_LIB_FILE="$UNI_BUILD_ROOT/build/ffmpeg-$ARCH/output/lib/$LIB_FILE"
if [ -f "$ARCH_LIB_FILE" ]; then
LIPO_FLAGS="$LIPO_FLAGS $ARCH_LIB_FILE"
else
echo "skip $LIB_FILE of $ARCH";
fi
done
xcrun lipo -create $LIPO_FLAGS -output $UNI_BUILD_ROOT/build/universal/lib/$LIB_FILE
xcrun lipo -info $UNI_BUILD_ROOT/build/universal/lib/$LIB_FILE
}
SSL_LIBS="libcrypto libssl"
do_lipo_ssl () {
LIB_FILE=$1
LIPO_FLAGS=
for ARCH in $FF_ALL_ARCHS
do
ARCH_LIB_FILE="$UNI_BUILD_ROOT/build/openssl-$ARCH/output/lib/$LIB_FILE"
if [ -f "$ARCH_LIB_FILE" ]; then
LIPO_FLAGS="$LIPO_FLAGS $ARCH_LIB_FILE"
else
echo "skip $LIB_FILE of $ARCH";
fi
done
if [ "$LIPO_FLAGS" != "" ]; then
xcrun lipo -create $LIPO_FLAGS -output $UNI_BUILD_ROOT/build/universal/lib/$LIB_FILE
xcrun lipo -info $UNI_BUILD_ROOT/build/universal/lib/$LIB_FILE
fi
}
do_lipo_all () {
mkdir -p $UNI_BUILD_ROOT/build/universal/lib
echo "lipo archs: $FF_ALL_ARCHS"
for FF_LIB in $FF_LIBS
do
do_lipo_ffmpeg "$FF_LIB.a";
done
ANY_ARCH=
for ARCH in $FF_ALL_ARCHS
do
ARCH_INC_DIR="$UNI_BUILD_ROOT/build/ffmpeg-$ARCH/output/include"
if [ -d "$ARCH_INC_DIR" ]; then
if [ -z "$ANY_ARCH" ]; then
ANY_ARCH=$ARCH
cp -R "$ARCH_INC_DIR" "$UNI_BUILD_ROOT/build/universal/"
fi
UNI_INC_DIR="$UNI_BUILD_ROOT/build/universal/include"
mkdir -p "$UNI_INC_DIR/libavutil/$ARCH"
cp -f "$ARCH_INC_DIR/libavutil/avconfig.h" "$UNI_INC_DIR/libavutil/$ARCH/avconfig.h"
cp -f tools/avconfig.h "$UNI_INC_DIR/libavutil/avconfig.h"
cp -f "$ARCH_INC_DIR/libavutil/ffversion.h" "$UNI_INC_DIR/libavutil/$ARCH/ffversion.h"
cp -f tools/ffversion.h "$UNI_INC_DIR/libavutil/ffversion.h"
mkdir -p "$UNI_INC_DIR/libffmpeg/$ARCH"
cp -f "$ARCH_INC_DIR/libffmpeg/config.h" "$UNI_INC_DIR/libffmpeg/$ARCH/config.h"
cp -f tools/config.h "$UNI_INC_DIR/libffmpeg/config.h"
fi
done
for SSL_LIB in $SSL_LIBS
do
do_lipo_ssl "$SSL_LIB.a";
done
}
#----------
if [ "$FF_TARGET" = "armv7" -o "$FF_TARGET" = "armv7s" -o "$FF_TARGET" = "arm64" ]; then
echo_archs
sh tools/do-compile-ffmpeg.sh $FF_TARGET $FF_TARGET_EXTRA
do_lipo_all
elif [ "$FF_TARGET" = "i386" -o "$FF_TARGET" = "x86_64" ]; then
echo_archs
sh tools/do-compile-ffmpeg.sh $FF_TARGET $FF_TARGET_EXTRA
do_lipo_all
elif [ "$FF_TARGET" = "lipo" ]; then
echo_archs
do_lipo_all
elif [ "$FF_TARGET" = "all" ]; then
echo_archs
for ARCH in $FF_ALL_ARCHS
do
sh tools/do-compile-ffmpeg.sh $ARCH $FF_TARGET_EXTRA
done
do_lipo_all
elif [ "$FF_TARGET" = "check" ]; then
echo_archs
elif [ "$FF_TARGET" = "clean" ]; then
echo_archs
echo "=================="
for ARCH in $FF_ALL_ARCHS
do
echo "clean ffmpeg-$ARCH"
echo "=================="
cd ffmpeg-$ARCH && git clean -xdf && cd -
done
echo "clean build cache"
echo "================="
rm -rf build/ffmpeg-*
rm -rf build/openssl-*
rm -rf build/universal/include
rm -rf build/universal/lib
echo "clean success"
else
echo "Usage:"
echo " compile-ffmpeg.sh armv7|arm64|i386|x86_64"
echo " compile-ffmpeg.sh armv7s (obselete)"
echo " compile-ffmpeg.sh lipo"
echo " compile-ffmpeg.sh all"
echo " compile-ffmpeg.sh clean"
echo " compile-ffmpeg.sh check"
exit 1
fi
do-compile-ffmpeg.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#! /usr/bin/env bash
#
# Copyright (C) 2013-2014 Bilibili
# Copyright (C) 2013-2014 Zhang Rui <bbcallen@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This script is based on projects below
# https://github.com/kolyvan/kxmovie
# https://github.com/yixia/FFmpeg-Android
# http://git.videolan.org/?p=vlc-ports/android.git;a=summary
# https://github.com/kewlbear/FFmpeg-iOS-build-script/
#--------------------
echo "===================="
echo "[*] check host"
echo "===================="
set -e
#--------------------
# include
#--------------------
# common defines
FF_ARCH=$1
FF_BUILD_OPT=$2
echo "FF_ARCH=$FF_ARCH"
echo "FF_BUILD_OPT=$FF_BUILD_OPT"
if [ -z "$FF_ARCH" ]; then
echo "You must specific an architecture 'armv7, armv7s, arm64, i386, x86_64, ...'.\n"
exit 1
fi
FF_BUILD_ROOT=`pwd`
FF_TAGET_OS="darwin"
# ffmpeg build params
export COMMON_FF_CFG_FLAGS=
source $FF_BUILD_ROOT/../config/module.sh
FFMPEG_CFG_FLAGS=
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS $COMMON_FF_CFG_FLAGS"
# Optimization options (experts only):
# FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --disable-armv5te"
# FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --disable-armv6"
# FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --disable-armv6t2"
# Advanced options (experts only):
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --enable-cross-compile"
# --disable-symver may indicate a bug
# FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --disable-symver"
# Developer options (useful when working on FFmpeg itself):
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --disable-stripping"
##
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --arch=$FF_ARCH"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --target-os=$FF_TAGET_OS"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --enable-static"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --disable-shared"
FFMPEG_EXTRA_CFLAGS=
# i386, x86_64
FFMPEG_CFG_FLAGS_SIMULATOR=
FFMPEG_CFG_FLAGS_SIMULATOR="$FFMPEG_CFG_FLAGS_SIMULATOR --disable-asm"
FFMPEG_CFG_FLAGS_SIMULATOR="$FFMPEG_CFG_FLAGS_SIMULATOR --disable-mmx"
FFMPEG_CFG_FLAGS_SIMULATOR="$FFMPEG_CFG_FLAGS_SIMULATOR --assert-level=2"
# armv7, armv7s, arm64
FFMPEG_CFG_FLAGS_ARM=
FFMPEG_CFG_FLAGS_ARM="$FFMPEG_CFG_FLAGS_ARM --enable-pic"
FFMPEG_CFG_FLAGS_ARM="$FFMPEG_CFG_FLAGS_ARM --enable-neon"
case "$FF_BUILD_OPT" in
debug)
FFMPEG_CFG_FLAGS_ARM="$FFMPEG_CFG_FLAGS_ARM --disable-optimizations"
FFMPEG_CFG_FLAGS_ARM="$FFMPEG_CFG_FLAGS_ARM --enable-debug"
FFMPEG_CFG_FLAGS_ARM="$FFMPEG_CFG_FLAGS_ARM --disable-small"
;;
*)
FFMPEG_CFG_FLAGS_ARM="$FFMPEG_CFG_FLAGS_ARM --enable-optimizations"
FFMPEG_CFG_FLAGS_ARM="$FFMPEG_CFG_FLAGS_ARM --enable-debug"
FFMPEG_CFG_FLAGS_ARM="$FFMPEG_CFG_FLAGS_ARM --enable-small"
;;
esac
echo "build_root: $FF_BUILD_ROOT"
#--------------------
echo "===================="
echo "[*] check gas-preprocessor"
echo "===================="
FF_TOOLS_ROOT="$FF_BUILD_ROOT/../extra"
export PATH="$FF_TOOLS_ROOT/gas-preprocessor:$PATH"
echo "gasp: $FF_TOOLS_ROOT/gas-preprocessor/gas-preprocessor.pl"
#--------------------
echo "===================="
echo "[*] config arch $FF_ARCH"
echo "===================="
FF_BUILD_NAME="unknown"
FF_XCRUN_PLATFORM="iPhoneOS"
FF_XCRUN_OSVERSION=
FF_GASPP_EXPORT=
FF_DEP_OPENSSL_INC=
FF_DEP_OPENSSL_LIB=
FF_XCODE_BITCODE=
if [ "$FF_ARCH" = "i386" ]; then
FF_BUILD_NAME="ffmpeg-i386"
FF_BUILD_NAME_OPENSSL=openssl-i386
FF_XCRUN_PLATFORM="iPhoneSimulator"
FF_XCRUN_OSVERSION="-mios-simulator-version-min=6.0"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS $FFMPEG_CFG_FLAGS_SIMULATOR"
elif [ "$FF_ARCH" = "x86_64" ]; then
FF_BUILD_NAME="ffmpeg-x86_64"
FF_BUILD_NAME_OPENSSL=openssl-x86_64
FF_XCRUN_PLATFORM="iPhoneSimulator"
FF_XCRUN_OSVERSION="-mios-simulator-version-min=7.0"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS $FFMPEG_CFG_FLAGS_SIMULATOR"
elif [ "$FF_ARCH" = "armv7" ]; then
FF_BUILD_NAME="ffmpeg-armv7"
FF_BUILD_NAME_OPENSSL=openssl-armv7
FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0"
FF_XCODE_BITCODE="-fembed-bitcode"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS $FFMPEG_CFG_FLAGS_ARM"
# FFMPEG_CFG_CPU="--cpu=cortex-a8"
elif [ "$FF_ARCH" = "armv7s" ]; then
FF_BUILD_NAME="ffmpeg-armv7s"
FF_BUILD_NAME_OPENSSL=openssl-armv7s
FFMPEG_CFG_CPU="--cpu=swift"
FF_XCRUN_OSVERSION="-miphoneos-version-min=6.0"
FF_XCODE_BITCODE="-fembed-bitcode"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS $FFMPEG_CFG_FLAGS_ARM"
elif [ "$FF_ARCH" = "arm64" ]; then
FF_BUILD_NAME="ffmpeg-arm64"
FF_BUILD_NAME_OPENSSL=openssl-arm64
FF_XCRUN_OSVERSION="-miphoneos-version-min=7.0"
FF_XCODE_BITCODE="-fembed-bitcode"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS $FFMPEG_CFG_FLAGS_ARM"
FF_GASPP_EXPORT="GASPP_FIX_XCODE5=1"
else
echo "unknown architecture $FF_ARCH";
exit 1
fi
echo "build_name: $FF_BUILD_NAME"
echo "platform: $FF_XCRUN_PLATFORM"
echo "osversion: $FF_XCRUN_OSVERSION"
#--------------------
echo "===================="
echo "[*] make ios toolchain $FF_BUILD_NAME"
echo "===================="
FF_BUILD_SOURCE="$FF_BUILD_ROOT/$FF_BUILD_NAME"
FF_BUILD_PREFIX="$FF_BUILD_ROOT/build/$FF_BUILD_NAME/output"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --prefix=$FF_BUILD_PREFIX"
mkdir -p $FF_BUILD_PREFIX
echo "build_source: $FF_BUILD_SOURCE"
echo "build_prefix: $FF_BUILD_PREFIX"
#--------------------
echo "\n--------------------"
echo "[*] configurate ffmpeg"
echo "--------------------"
FF_XCRUN_SDK=`echo $FF_XCRUN_PLATFORM | tr '[:upper:]' '[:lower:]'`
FF_XCRUN_CC="xcrun -sdk $FF_XCRUN_SDK clang"
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS $FFMPEG_CFG_CPU"
FFMPEG_CFLAGS=
FFMPEG_CFLAGS="$FFMPEG_CFLAGS -arch $FF_ARCH"
FFMPEG_CFLAGS="$FFMPEG_CFLAGS $FF_XCRUN_OSVERSION"
FFMPEG_CFLAGS="$FFMPEG_CFLAGS $FFMPEG_EXTRA_CFLAGS"
FFMPEG_CFLAGS="$FFMPEG_CFLAGS $FF_XCODE_BITCODE"
FFMPEG_LDFLAGS="$FFMPEG_CFLAGS"
FFMPEG_DEP_LIBS=
#--------------------
echo "\n--------------------"
echo "[*] check OpenSSL"
echo "----------------------"
FFMPEG_DEP_OPENSSL_INC=$FF_BUILD_ROOT/build/$FF_BUILD_NAME_OPENSSL/output/include
FFMPEG_DEP_OPENSSL_LIB=$FF_BUILD_ROOT/build/$FF_BUILD_NAME_OPENSSL/output/lib
#--------------------
# with openssl
if [ -f "${FFMPEG_DEP_OPENSSL_LIB}/libssl.a" ]; then
FFMPEG_CFG_FLAGS="$FFMPEG_CFG_FLAGS --enable-openssl"
FFMPEG_CFLAGS="$FFMPEG_CFLAGS -I${FFMPEG_DEP_OPENSSL_INC}"
FFMPEG_DEP_LIBS="$FFMPEG_CFLAGS -L${FFMPEG_DEP_OPENSSL_LIB} -lssl -lcrypto"
fi
#--------------------
echo "\n--------------------"
echo "[*] configure"
echo "----------------------"
if [ ! -d $FF_BUILD_SOURCE ]; then
echo ""
echo "!! ERROR"
echo "!! Can not find FFmpeg directory for $FF_BUILD_NAME"
echo "!! Run 'sh init-ios.sh' first"
echo ""
exit 1
fi
# xcode configuration
export DEBUG_INFORMATION_FORMAT=dwarf-with-dsym
cd $FF_BUILD_SOURCE
if [ -f "./config.h" ]; then
echo 'reuse configure'
else
echo "config: $FFMPEG_CFG_FLAGS $FF_XCRUN_CC"
./configure \
$FFMPEG_CFG_FLAGS \
--cc="$FF_XCRUN_CC" \
$FFMPEG_CFG_CPU \
--extra-cflags="$FFMPEG_CFLAGS" \
--extra-cxxflags="$FFMPEG_CFLAGS" \
--extra-ldflags="$FFMPEG_LDFLAGS $FFMPEG_DEP_LIBS"
make clean
fi
#--------------------
echo "\n--------------------"
echo "[*] compile ffmpeg"
echo "--------------------"
cp config.* $FF_BUILD_PREFIX
make -j3 $FF_GASPP_EXPORT
make install
mkdir -p $FF_BUILD_PREFIX/include/libffmpeg
cp -f config.h $FF_BUILD_PREFIX/include/libffmpeg/config.h
1
https protocol not found, recompile FFmpeg with openssl, gnutls or securetransport enabled.
编辑config/module-default.sh:
1
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl"
重新build ffmpeg:
1
ERROR: openssl not found
1
2
3
4
5
6
7
./init-ios-openssl.sh
cd ios
# 在模块文件中添加一行配置 以启用 openssl 组件
echo 'export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl"' >> ../config/module.sh
./compile-ffmpeg.sh clean
./compile-openssl.sh all
./compile-ffmpeg.sh all
1
2
需要手动给 IJKMediaFramework 添加 libcrypto.a 和 libssl.a 文件
这俩库同样在ijkplayer-ios/ios/build/universal/lib下
1
另外文中还提到不推荐使用IJKMediaFrameworkWithSSL这个framework, 所以我也就不尝试这一方案
Done~~~
The world is quite!!!
如果打包遇到问题,参考这篇
1
大概就是要注释掉armv7下的两个编译头文件
LogLevel设置
#ifdef DEBUG
[IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_DEBUG];
#else
[IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_SILENT];
#endif
PlayOption 设置
1
2
3
4
ff_ffplay_options.h
{ "videotoolbox", "VideoToolbox: enable",
OPTION_OFFSET(videotoolbox), OPTION_INT(0, 0, 2) },
config.h
CONFIG_AVFILTER
Rotation
search rotate
硬解下旋转角度问题
解码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static void *SDL_RunThread(void *data)
{
@autoreleasepool {
SDL_Thread *thread = data;
pthread_setname_np(thread->name);
thread->retval = thread->func(thread->data);
return NULL;
}
}
static int video_thread(void *arg)
{
FFPlayer *ffp = (FFPlayer *)arg;
int ret = 0;
if (ffp->node_vdec) {
ret = ffpipenode_run_sync(ffp->node_vdec);
}
return ret;
}
ff_ffplay
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
int ffp_video_thread(FFPlayer *ffp)
{
return ffplay_video_thread(ffp);
}
static int ffplay_video_thread(void *arg)
{
FFPlayer *ffp = arg;
VideoState *is = ffp->is;
AVFrame *frame = av_frame_alloc();
double pts;
double duration;
int ret;
AVRational tb = is->video_st->time_base;
AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL);
int64_t dst_pts = -1;
int64_t last_dst_pts = -1;
int retry_convert_image = 0;
int convert_frame_count = 0;
#if CONFIG_AVFILTER
AVFilterGraph *graph = avfilter_graph_alloc();
AVFilterContext *filt_out = NULL, *filt_in = NULL;
int last_w = 0;
int last_h = 0;
enum AVPixelFormat last_format = -2;
int last_serial = -1;
int last_vfilter_idx = 0;
if (!graph) {
av_frame_free(&frame);
return AVERROR(ENOMEM);
}
#else
ffp_notify_msg2(ffp, FFP_MSG_VIDEO_ROTATION_CHANGED, ffp_get_video_rotate_degrees(ffp));
#endif
if (!frame) {
#if CONFIG_AVFILTER
avfilter_graph_free(&graph);
#endif
return AVERROR(ENOMEM);
}
for (;;) {
ret = get_video_frame(ffp, frame);
if (ret < 0)
goto the_end;
if (!ret)
continue;
if (ffp->get_frame_mode) {
if (!ffp->get_img_info || ffp->get_img_info->count <= 0) {
av_frame_unref(frame);
continue;
}
last_dst_pts = dst_pts;
if (dst_pts < 0) {
dst_pts = ffp->get_img_info->start_time;
} else {
dst_pts += (ffp->get_img_info->end_time - ffp->get_img_info->start_time) / (ffp->get_img_info->num - 1);
}
pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
pts = pts * 1000;
if (pts >= dst_pts) {
while (retry_convert_image <= MAX_RETRY_CONVERT_IMAGE) {
ret = convert_image(ffp, frame, (int64_t)pts, frame->width, frame->height);
if (!ret) {
convert_frame_count++;
break;
}
retry_convert_image++;
av_log(NULL, AV_LOG_ERROR, "convert image error retry_convert_image = %d\n", retry_convert_image);
}
retry_convert_image = 0;
if (ret || ffp->get_img_info->count <= 0) {
if (ret) {
av_log(NULL, AV_LOG_ERROR, "convert image abort ret = %d\n", ret);
ffp_notify_msg3(ffp, FFP_MSG_GET_IMG_STATE, 0, ret);
} else {
av_log(NULL, AV_LOG_INFO, "convert image complete convert_frame_count = %d\n", convert_frame_count);
}
goto the_end;
}
} else {
dst_pts = last_dst_pts;
}
av_frame_unref(frame);
continue;
}
#if CONFIG_AVFILTER
if ( last_w != frame->width
|| last_h != frame->height
|| last_format != frame->format
|| last_serial != is->viddec.pkt_serial
|| ffp->vf_changed
|| last_vfilter_idx != is->vfilter_idx) {
SDL_LockMutex(ffp->vf_mutex);
ffp->vf_changed = 0;
av_log(NULL, AV_LOG_DEBUG,
"Video frame changed from size:%dx%d format:%s serial:%d to size:%dx%d format:%s serial:%d\n",
last_w, last_h,
(const char *)av_x_if_null(av_get_pix_fmt_name(last_format), "none"), last_serial,
frame->width, frame->height,
(const char *)av_x_if_null(av_get_pix_fmt_name(frame->format), "none"), is->viddec.pkt_serial);
avfilter_graph_free(&graph);
graph = avfilter_graph_alloc();
if ((ret = configure_video_filters(ffp, graph, is, ffp->vfilters_list ? ffp->vfilters_list[is->vfilter_idx] : NULL, frame)) < 0) {
// FIXME: post error
SDL_UnlockMutex(ffp->vf_mutex);
goto the_end;
}
filt_in = is->in_video_filter;
filt_out = is->out_video_filter;
last_w = frame->width;
last_h = frame->height;
last_format = frame->format;
last_serial = is->viddec.pkt_serial;
last_vfilter_idx = is->vfilter_idx;
frame_rate = av_buffersink_get_frame_rate(filt_out);
SDL_UnlockMutex(ffp->vf_mutex);
}
ret = av_buffersrc_add_frame(filt_in, frame);
if (ret < 0)
goto the_end;
while (ret >= 0) {
is->frame_last_returned_time = av_gettime_relative() / 1000000.0;
ret = av_buffersink_get_frame_flags(filt_out, frame, 0);
if (ret < 0) {
if (ret == AVERROR_EOF)
is->viddec.finished = is->viddec.pkt_serial;
ret = 0;
break;
}
is->frame_last_filter_delay = av_gettime_relative() / 1000000.0 - is->frame_last_returned_time;
if (fabs(is->frame_last_filter_delay) > AV_NOSYNC_THRESHOLD / 10.0)
is->frame_last_filter_delay = 0;
tb = av_buffersink_get_time_base(filt_out);
#endif
duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0);
pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb);
ret = queue_picture(ffp, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial);
av_frame_unref(frame);
#if CONFIG_AVFILTER
}
#endif
if (ret < 0)
goto the_end;
}
the_end:
#if CONFIG_AVFILTER
avfilter_graph_free(&graph);
#endif
av_log(NULL, AV_LOG_INFO, "convert image convert_frame_count = %d\n", convert_frame_count);
av_frame_free(&frame);
return 0;
}
get_video_frame
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
static int get_video_frame(FFPlayer *ffp, AVFrame *frame)
{
VideoState *is = ffp->is;
int got_picture;
ffp_video_statistic_l(ffp);
if ((got_picture = decoder_decode_frame(ffp, &is->viddec, frame, NULL)) < 0)
return -1;
if (got_picture) {
double dpts = NAN;
if (frame->pts != AV_NOPTS_VALUE)
dpts = av_q2d(is->video_st->time_base) * frame->pts;
frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame);
if (ffp->framedrop>0 || (ffp->framedrop && get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER)) {
ffp->stat.decode_frame_count++;
if (frame->pts != AV_NOPTS_VALUE) {
double diff = dpts - get_master_clock(is);
if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD &&
diff - is->frame_last_filter_delay < 0 &&
is->viddec.pkt_serial == is->vidclk.serial &&
is->videoq.nb_packets) {
is->frame_drops_early++;
is->continuous_frame_drops_early++;
if (is->continuous_frame_drops_early > ffp->framedrop) {
is->continuous_frame_drops_early = 0;
} else {
ffp->stat.drop_frame_count++;
ffp->stat.drop_frame_rate = (float)(ffp->stat.drop_frame_count) / (float)(ffp->stat.decode_frame_count);
av_frame_unref(frame);
got_picture = 0;
}
}
}
}
}
return got_picture;
}
IJKFF_Pipenode
1
2
3
4
int ffpipenode_run_sync(IJKFF_Pipenode *node)
{
return node->func_run_sync(node);
}
软解码
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
// ffpipenode_ffplay_vdec.c
static IJKFF_Pipenode *func_open_video_decoder(IJKFF_Pipeline *pipeline, FFPlayer *ffp)
{
IJKFF_Pipenode* node = NULL;
IJKFF_Pipeline_Opaque *opaque = pipeline->opaque;
if (ffp->videotoolbox) {
node = ffpipenode_create_video_decoder_from_ios_videotoolbox(ffp);
if (!node)
ALOGE("vtb fail!!! switch to ffmpeg decode!!!! \n");
}
if (node == NULL) {
node = ffpipenode_create_video_decoder_from_ffplay(ffp);
ffp->stat.vdec_type = FFP_PROPV_DECODER_AVCODEC;
opaque->is_videotoolbox_open = false;
} else {
ffp->stat.vdec_type = FFP_PROPV_DECODER_VIDEOTOOLBOX;
opaque->is_videotoolbox_open = true;
}
ffp_notify_msg2(ffp, FFP_MSG_VIDEO_DECODER_OPEN, opaque->is_videotoolbox_open);
return node;
}
static int func_run_sync(IJKFF_Pipenode *node)
{
IJKFF_Pipenode_Opaque *opaque = node->opaque;
return ffp_video_thread(opaque->ffp);
}
硬解码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// ffpipenode_ios_videotoolbox_vdec.m
IJKFF_Pipenode *ffpipenode_create_video_decoder_from_ios_videotoolbox(FFPlayer *ffp)
{
if (!ffp || !ffp->is)
return NULL;
if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0){
return NULL;
}
IJKFF_Pipenode *node = ffpipenode_alloc(sizeof(IJKFF_Pipenode_Opaque));
if (!node)
return node;
memset(node, sizeof(IJKFF_Pipenode), 0);
VideoState *is = ffp->is;
IJKFF_Pipenode_Opaque *opaque = node->opaque;
node->func_destroy = func_destroy;
node->func_run_sync = func_run_sync;
opaque->ffp = ffp;
opaque->decoder = &is->viddec;
opaque->avctx = opaque->decoder->avctx;
switch (opaque->avctx->codec_id) {
case AV_CODEC_ID_H264:
case AV_CODEC_ID_HEVC:
if (ffp->vtb_async)
opaque->context = Ijk_VideoToolbox_Async_Create(ffp, opaque->avctx);
else
opaque->context = Ijk_VideoToolbox_Sync_Create(ffp, opaque->avctx);
break;
default:
ALOGI("Videotoolbox-pipeline:open_video_decoder: not H264 or H265\n");
goto fail;
}
if (opaque->context == NULL) {
ALOGE("could not init video tool box decoder !!!");
goto fail;
}
return node;
fail:
ffpipenode_free_p(&node);
return NULL;
}
static int func_run_sync(IJKFF_Pipenode *node)
{
IJKFF_Pipenode_Opaque *opaque = node->opaque;
int ret = videotoolbox_video_thread(opaque);
if (opaque->context) {
opaque->context->free(opaque->context->opaque);
free(opaque->context);
opaque->context = NULL;
}
return ret;
}
int videotoolbox_video_thread(void *arg)
{
IJKFF_Pipenode_Opaque* opaque = (IJKFF_Pipenode_Opaque*) arg;
FFPlayer *ffp = opaque->ffp;
VideoState *is = ffp->is;
Decoder *d = &is->viddec;
int ret = 0;
ffp_notify_msg2(ffp, FFP_MSG_VIDEO_ROTATION_CHANGED, ffp_get_video_rotate_degrees(ffp));
for (;;) {
if (is->abort_request || d->queue->abort_request) {
return -1;
}
@autoreleasepool {
ret = opaque->context->decode_frame(opaque->context->opaque);
}
if (ret < 0)
goto the_end;
if (!ret)
continue;
if (ret < 0)
goto the_end;
}
the_end:
return 0;
}
软解下绿条问题:
有声音,没画面问题
IJKSDLGLView.glActiveLock(NSRecursiveLock) deadlock
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
2022-01-06 15:08:27.457917+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.458228+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.458233+0800 UChat[95924:22731748] -[ZFIJKPlayerManager moviePlayBackStateDidChange:][323]播放器的播放状态变了,现在是播放状态 1: playing
2022-01-06 15:08:27.458878+0800 UChat[95924:22731748] -[ZFIJKPlayerManager moviePlayBackStateDidChange:][323]播放器的播放状态变了,现在是播放状态 1: playing
2022-01-06 15:08:27.459279+0800 UChat[95924:22732188] IJKSDLGLView: renderbufferStorage fromDrawable
2022-01-06 15:08:27.466031+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.466209+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.501004+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.501374+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.504189+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.504508+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.519912+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.520415+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.525057+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.525233+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.552961+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.553351+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.555744+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.556155+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.589242+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.589741+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.591478+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.591959+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.624124+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.624752+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.626726+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.627293+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.658698+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.659028+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.660433+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.660791+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.692476+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.692937+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.694497+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.695005+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.727914+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.728185+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.730678+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.731140+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.762100+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.762593+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.763960+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.764379+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.795579+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.795915+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.797098+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.797706+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.831422+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.831855+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
2022-01-06 15:08:27.833658+0800 UChat[95924:22732188] FerrisLogger[401]: try unlock
2022-01-06 15:08:27.834074+0800 UChat[95924:22732188] FerrisLogger[469] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} unlocked
2022-01-06 15:08:27.866251+0800 UChat[95924:22732188] FerrisLogger[383]: try lock
2022-01-06 15:08:27.867236+0800 UChat[95924:22732188] FerrisLogger[485] thread:<NSThread: 0x283af4400>{number = 19, name = (null)} locked
[App 541233404] 2022-1-6 15:08:27.870 isActive = false
2022-01-06 15:08:27.871549+0800 UChat[95924:22731748] IJKSDLGLView:applicationWillResignActive: 0
2022-01-06 15:08:27.871732+0800 UChat[95924:22731748] FerrisLogger[497] thread:<_NSMainThread: 0x2834f1200>{number = 1, name = main} try lock
从最后一条日志看,之所以死锁是因为通过不同线程去上锁
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
Main Thread Checker: UI API called on a background thread: -[UIViewController parentViewController]
PID: 7542, TID: 736672, Thread name: (none), Queue name: , QoS: 21
Backtrace:
4 Display 0x0000000113cee140 -[UIViewController(Navigation) _65087dc8_navigationController] + 96
5 TelegramUI 0x000000010bc4aac8 $s13ShortVideosUI0aB18PlayListControllerC03topdeF0ACSgvg + 52
6 TelegramUI 0x000000010bc4b474 $s13ShortVideosUI0aB18PlayListControllerC4play33_1CD561DC90F6F51A64ABE4239E26E599LLyyF + 188
7 TelegramUI 0x000000010bc5409c $s13ShortVideosUI0aB18PlayListControllerC13viewDidAppearyySbFy10UChatAudio0K22SessionActivationStateVcfU_ + 136
8 TelegramUI 0x000000010b856a7c $s10UChatAudio07ManagedB7SessionC4push05audioD4Type10outputMode4once14manualActivate10deactivate30headsetConnectionStatusChanged016availableOutputsQ014SwiftSignalKit10Disposable_pAA0cbdG0O_AA0bd6OutputI0OSbyAA0cbD7ControlCcAL0U0CyytAL7NoErrorOGycySbcySayAA0bdX0OG_AZSgtctFyycfU_yAA0cbdyL033_CA252FBF9780053B79A3CC60CAF2BEE2LLCcfU0_yycfU_ + 472
9 SwiftSignalKit 0x0000000114fab204 $sIeg_IeyB_TR + 48
10 libdispatch.dylib 0x000000019ce5efd0 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 8144
11 libdispatch.dylib 0x000000019ce60ac8 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 15048
12 libdispatch.dylib 0x000000019ce67c08 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 44040
13 libdispatch.dylib 0x000000019ce68734 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 46900
14 libdispatch.dylib 0x000000019ce72528 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 87336
15 libsystem_pthread.dylib 0x00000001e47b4908 _pthread_wqthread + 276
16 libsystem_pthread.dylib 0x00000001e47bb77c start_wqthread + 8
2022-01-07 11:29:21.089753+0800 UChat[7542:736672] [reports] Main Thread Checker: UI API called on a background thread: -[UIViewController parentViewController]
PID: 7542, TID: 736672, Thread name: (none), Queue name: , QoS: 21
Backtrace:
4 Display 0x0000000113cee140 -[UIViewController(Navigation) _65087dc8_navigationController] + 96
5 TelegramUI 0x000000010bc4aac8 $s13ShortVideosUI0aB18PlayListControllerC03topdeF0ACSgvg + 52
6 TelegramUI 0x000000010bc4b474 $s13ShortVideosUI0aB18PlayListControllerC4play33_1CD561DC90F6F51A64ABE4239E26E599LLyyF + 188
7 TelegramUI 0x000000010bc5409c $s13ShortVideosUI0aB18PlayListControllerC13viewDidAppearyySbFy10UChatAudio0K22SessionActivationStateVcfU_ + 136
8 TelegramUI 0x000000010b856a7c $s10UChatAudio07ManagedB7SessionC4push05audioD4Type10outputMode4once14manualActivate10deactivate30headsetConnectionStatusChanged016availableOutputsQ014SwiftSignalKit10Disposable_pAA0cbdG0O_AA0bd6OutputI0OSbyAA0cbD7ControlCcAL0U0CyytAL7NoErrorOGycySbcySayAA0bdX0OG_AZSgtctFyycfU_yAA0cbdyL033_CA252FBF9780053B79A3CC60CAF2BEE2LLCcfU0_yycfU_ + 472
9 SwiftSignalKit 0x0000000114fab204 $sIeg_IeyB_TR + 48
10 libdispatch.dylib 0x000000019ce5efd0 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 8144
11 libdispatch.dylib 0x000000019ce60ac8 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 15048
12 libdispatch.dylib 0x000000019ce67c08 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 44040
13 libdispatch.dylib 0x000000019ce68734 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 46900
14 libdispatch.dylib 0x000000019ce72528 8E662F82-B1E4-3E7E-A376-18E9755A8F51 + 87336
15 libsystem_pthread.dylib 0x00000001e47b4908 _pthread_wqthread + 276
16 libsystem_pthread.dylib 0x00000001e47bb77c start_wqthread + 8
ijkmp_pause()=0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xb0)
frame #0: 0x00000001e4cb9d48 AppleMetalGLRenderer`GLRResourceList::addFence(GLRResource*) + 24
frame #1: 0x00000001e4ccb3f4 AppleMetalGLRenderer`GLDContextRec::flushContextInternal() + 200
frame #2: 0x00000001ce9af374 GLEngine`glFinish_Exec + 124
* frame #3: 0x000000010531ad1c ZFPlayerFramework`__31-[IJKSDLGLView toggleGLPaused:]_block_invoke(.block_descriptor=0x0000000283c962b0, _paused=YES) at IJKSDLGLView.m:579:17
frame #4: 0x000000010531aebc ZFPlayerFramework`__31-[IJKSDLGLView toggleGLPaused:]_block_invoke.139(.block_descriptor=0x0000000282bc1300) at IJKSDLGLView.m:601:17
frame #5: 0x000000019ce5efd0 libdispatch.dylib`_dispatch_call_block_and_release + 32
frame #6: 0x000000019ce60ac8 libdispatch.dylib`_dispatch_client_callout + 20
frame #7: 0x000000019ce6e04c libdispatch.dylib`_dispatch_main_queue_callback_4CF + 836
frame #8: 0x000000019d1df1e4 CoreFoundation`__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
frame #9: 0x000000019d1d93b4 CoreFoundation`__CFRunLoopRun + 2508µ
frame #10: 0x000000019d1d84bc CoreFoundation`CFRunLoopRunSpecific + 600
frame #11: 0x00000001b3c5d820 GraphicsServices`GSEventRunModal + 164
frame #12: 0x000000019fb7c734 UIKitCore`-[UIApplication _run] + 1072
frame #13: 0x000000019fb81e10 UIKitCore`UIApplicationMain + 168
frame #14: 0x000000010036fbf8 UChat`main(argc=1, argv=0x000000016fa97900) at main.m:14:16
frame #15: 0x000000019ce9fe60 libdyld.dylib`start + 4
1
Thread 1: EXC_BAD_ACCESS (code=1, address=0xb0)