Home ijkplayer troubleshooting
Post
Cancel

ijkplayer troubleshooting

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

硬解下旋转角度问题

PullRequest

解码

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;
}

软解下绿条问题:

issue

有声音,没画面问题

issue

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)
This post is licensed under CC BY 4.0 by the author.