利用av_frame_clone可以将一个frame clone后,其实也只是v_frame_alloc()+av_frame_ref()。但是有时候在音频帧的clone后不知道为什么会导致了返回了NULL。这个时候就懵逼了。这个debug进去后发现了一个问题,就是channel_layout没有设置导致的。这个因为是我手动设置解码器,所以忘记弄了,这个一般直接读取的话没有那个错误。
假如你用ffmpeg解码后再进行编码,不知为什么如果源过快时候会发现画面卡顿,音频声音差,只要你将输入源sleep,情况明显改善。这时,其实是内存污染作怪。在ffmpeg里面,解码后的avframe内存还是归ffmpeg管理,当你每次读包解码时候,过快这样就会导致那种情况了。你要做的是用av_frame_clone,那样的话那个就可以了。
假如你将一个音频文件转码成aac文件结尾的文件,这个时候你会发现有个问题是,不知道为什么文件的播放时间总是会比我们实际的时间会长,而且这种长度会随着本来的音频时间长度成线性关系增加。这时,你可能会怀疑自己的编码是不是哪里出了问题。但事实上不是,那是因为aac文件播放本来就有adts,而在ffmpeg里面计算aac文件播放的duration时间,跟踪源码发现ffmpeg里面计算文件是长度是对比视频跟音频的长度,取其最大的。代码如下
static void estimate_timings_from_bit_rate(AVFormatContext *ic)
{
int64_t filesize, duration;
int i, show_warning = 0;
AVStream *st;
/* if bit_rate is already set, we believe it */
if (ic->bit_rate <= 0) {
int64_t bit_rate = 0;
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if (st->codecpar->bit_rate <= 0 && st->internal->avctx->bit_rate > 0)
st->codecpar->bit_rate = st->internal->avctx->bit_rate;
if (st->codecpar->bit_rate > 0) {
if (INT64_MAX - st->codecpar->bit_rate < bit_rate) {
bit_rate = 0;
break;
}
bit_rate += st->codecpar->bit_rate;
} else if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && st->codec_info_nb_frames > 1) {
// If we have a videostream with packets but without a bitrate
// then consider the sum not known
bit_rate = 0;
break;
}
}
ic->bit_rate = bit_rate;
}
/* if duration is already set, we believe it */
if (ic->duration == AV_NOPTS_VALUE &&
ic->bit_rate != 0) {
filesize = ic->pb ? avio_size(ic->pb) : 0;
if (filesize > ic->internal->data_offset) {
filesize -= ic->internal->data_offset;
for (i = 0; i < ic->nb_streams; i++) {
st = ic->streams[i];
if ( st->time_base.num <= INT64_MAX / ic->bit_rate
&& st->duration == AV_NOPTS_VALUE) {
duration = av_rescale(8 * filesize, st->time_base.den,
ic->bit_rate *
(int64_t) st->time_base.num);
st->duration = duration;
show_warning = 1;
}
}
}
}
if (show_warning)
av_log(ic, AV_LOG_WARNING,
"Estimating duration from bitrate, this may be inaccurate\n");
}
在ffmpeg里面,假如你试过用avformat_open_input去读取rtmp流,而rtmp流不正确,这时不得不等待2分钟,通过网上的搜索,我们看到很多设置timeout,但我不知道是不是只有我这里会这样,我设置timeout后,连正确的流也拉取不了,最后一直查找资料跟debug发现我设置的参数是错误的,应该是rw_timeout,设置后,终于能正常时间内连接。
Queue input is backward in time,在ffmpeg里面,假如你用音频编码aac的时候,可能遇到这个警告。源代码如下:
if(afq->frame_count && new[-1].pts >= new->pts)
av_log(afq->avctx, AV_LOG_WARNING, "Queue input is backward in time\n");
1.编码的nbsample不对
2.pts不对
linux编译Android,利用sdk编译./ndk-build NDK_PROJECT_PATH=/home/zoring/sour/libyuv APP_BUILD_SCRIPT=/home/zoring/sour/libyuv/Android.mk
上面NDK_PROJECT_PATH是指文件的文件
APP_BUILD_SCRIPT是Android.mk的位置。
基本用这个可以编译好MP3lame的
另外附上x264编译的
#!/bin/bash
NDK=$HOME/sour/android-ndk-r10d
SYSROOT=$NDK/platforms/android-9/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
export PLATFORM=$NDK/platforms/android-8/arch-arm
function build_one
{
./configure --prefix=$PREFIX \
--enable-static \
--enable-shared \
--enable-pic \
--disable-asm \
--disable-cli \
--host=arm-linux \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$PLATFORM
make clean
make -j8
make install
sudo ldconfig
}
CPU=arm
PREFIX=$HOME/sour/FFmpeg-release-3.2/android/$CPU
ADDI_CFLAGS="-marm"
build_one
#!/bin/bash
NDK=$HOME/sour/android-ndk-r10d
SYSROOT=$NDK/platforms/android-9/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-doc \
--enable-gpl \
--enable-nonfree \
--enable-pthreads \
--enable-libx264 \
--enable-libmp3lame \
--disable-symver \
--enable-yasm --enable-asm --enable-neon --enable-mmx --enable-mmxext --enable-sse --enable-sse2 --enable-sse3 --enable-ssse3 --enable-sse4 --enable-sse42 --enable-avx --enable-avx2 --enable-inline-asm --enable-fma3 --enable-fma4 --enable-jni --enable-mediacodec \
--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
--extra-cflags="-I $HOME/sour/FFmpeg-release-3.2/android/$CPU/include/" \
--extra-ldflags="-L $HOME/sour/FFmpeg-release-3.2/android/$CPU/lib/" \
--enable-neon
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one
后面是ios的shell
#!/bin/sh
# directories
SOURCE="ffmpeg-3.3"
FAT="FFmpeg-iOS"
SCRATCH="scratch"
# must be an absolute path
THIN=`pwd`/"thin"
X264=/Users/administrator/Desktop/FFmpeg-iOS-build-script/x264
LAME=/Users/administrator/Desktop/FFmpeg-iOS-build-script/lame
#X264=`pwd`/"x264"
#FDK_AAC=`pwd`/"fdk-aac"
#LAME=`pwd`/"lame"
echo "hello x264 $X264"
echo "hello lame $LAME"
CONFIGURE_FLAGS="--enable-cross-compile --disable-debug --disable-programs --enable-yasm --enable-asm --eanble-neon --enable-mmx --enable-mmxext --enable-sse --enable-sse2 --enable-sse3 --enable-ssse3 --enable-sse4 --enable-sse42 --enable-avx --enable-avx2 --enable-inline-asm \
--disable-doc --enable-pic --enable-videotoolbox --disable-ffmpeg --disable-ffplay --disable-ffserver --enable-pthreads --disable-debug --enable-fma3 --enable-fma4"
#---新加MP3---
if [ "$LAME" ]
echo "走lame1"
then
echo "走lame2"
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-gpl --enable-libmp3lame"
echo "走lame3"
fi
#---新加MP3---
if [ "$X264" ]
then
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-gpl --enable-libx264"
fi
if [ "$FDK_AAC" ]
then
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-gpl --enable-nonfree --enable-libfdk-aac"
fi
# avresample
#CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-avresample"
ARCHS="arm64 armv7 x86_64 i386"
COMPILE="y"
LIPO="y"
DEPLOYMENT_TARGET="6.0"
if [ "$*" ]
then
if [ "$*" = "lipo" ]
then
# skip compile
COMPILE=
else
ARCHS="$*"
if [ $# -eq 1 ]
then
# skip lipo
LIPO=
fi
fi
fi
if [ "$COMPILE" ]
then
if [ ! `which yasm` ]
then
echo 'Yasm not found'
if [ ! `which brew` ]
then
echo 'Homebrew not found. Trying to install...'
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" \
|| exit 1
fi
echo 'Trying to install Yasm...'
brew install yasm || exit 1
fi
if [ ! `which gas-preprocessor.pl` ]
then
echo 'gas-preprocessor.pl not found. Trying to install...'
(curl -L https://github.com/libav/gas-preprocessor/raw/master/gas-preprocessor.pl \
-o /usr/local/bin/gas-preprocessor.pl \
&& chmod +x /usr/local/bin/gas-preprocessor.pl) \
|| exit 1
fi
if [ ! -r $SOURCE ]
then
echo 'FFmpeg source not found. Trying to download...'
curl http://www.ffmpeg.org/releases/$SOURCE.tar.bz2 | tar xj \
|| exit 1
fi
CWD=`pwd`
for ARCH in $ARCHS
do
echo "building $ARCH..."
mkdir -p "$SCRATCH/$ARCH"
cd "$SCRATCH/$ARCH"
CFLAGS="-arch $ARCH"
if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64" ]
then
PLATFORM="iPhoneSimulator"
CFLAGS="$CFLAGS -mios-simulator-version-min=$DEPLOYMENT_TARGET"
else
PLATFORM="iPhoneOS"
CFLAGS="$CFLAGS -mios-version-min=$DEPLOYMENT_TARGET -fembed-bitcode"
if [ "$ARCH" = "arm64" ]
then
EXPORT="GASPP_FIX_XCODE5=1"
fi
fi
XCRUN_SDK=`echo $PLATFORM | tr '[:upper:]' '[:lower:]'`
CC="xcrun -sdk $XCRUN_SDK clang"
# force "configure" to use "gas-preprocessor.pl" (FFmpeg 3.3)
if [ "$ARCH" = "arm64" ]
then
AS="gas-preprocessor.pl -arch aarch64 -- $CC"
else
AS="$CC"
fi
CXXFLAGS="$CFLAGS"
LDFLAGS="$CFLAGS"
#---新加MP3---
if [ "$LAME" ]
then
CFLAGS="$CFLAGS -I$LAME/include"
LDFLAGS="$LDFLAGS -L$LAME/lib"
fi
#---新加MP3---
if [ "$X264" ]
then
CFLAGS="$CFLAGS -I$X264/include"
LDFLAGS="$LDFLAGS -L$X264/lib"
fi
if [ "$FDK_AAC" ]
then
CFLAGS="$CFLAGS -I$FDK_AAC/include"
LDFLAGS="$LDFLAGS -L$FDK_AAC/lib"
fi
echo "hello root CFLAGS:$CFLAGS"
echo "hello root CONFIGURE_FLAGS:$CONFIGURE_FLAGS"
echo "hello root LDFLAGS:$LDFLAGS"
TMPDIR=${TMPDIR/%\/} $CWD/$SOURCE/configure \
--target-os=darwin \
--arch=$ARCH \
--cc="$CC" \
--as="$AS" \
$CONFIGURE_FLAGS \
--extra-cflags="$CFLAGS" \
--extra-ldflags="$LDFLAGS" \
--prefix="$THIN/$ARCH" \
|| exit 1
make -j3 install $EXPORT || exit 1
cd $CWD
done
fi
if [ "$LIPO" ]
then
echo "building fat binaries..."
mkdir -p $FAT/lib
set - $ARCHS
CWD=`pwd`
cd $THIN/$1/lib
for LIB in *.a
do
cd $CWD
echo lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB 1>&2
lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB || exit 1
done
cd $CWD
cp -rf $THIN/$1/include $FAT
fi
echo Done
linux编译Android,利用sdk编译./ndk-build NDK_PROJECT_PATH=/home/zoring/sour/libyuv APP_BUILD_SCRIPT=/home/zoring/sour/libyuv/Android.mk
上面NDK_PROJECT_PATH是指文件的文件
APP_BUILD_SCRIPT是Android.mk的位置。
基本用这个可以编译好MP3lame的
另外附上x264编译的
在一个项目重构里面,发现声音急促,以及声音断续,一开始以为pts不对,但发现不对。pts是正确的,那么剩下的代码都是根据之前的项目的用的,那么出现逻辑上的错误也很少可能,只能是内存污染。但我是用new的,应该不存在的。最后发现用av_frame_clone解决了问题,这个问题我猜测是ffmpeg内部有个内存管理的,类似于c++的自动内存管理,所以才会导致内存的污染问题出现。
网上的一些cbr说法里面,你会发现不管用,在官网那里提供那里的命令时候输出为ts时也是不管用,很多误人子弟的说这样。
ffmpeg -i /home/zoring/45.ts -b 4000k -minrate 4000k -maxrate 4000k -bufsize 1835k -vcodec libx264 -f mpegts -muxrate 4000K -y trailer.ts
亲测可用。
有时你会看到那个null(libx264)而不是那个详细信息,这个是因为av_dump_format在avformat_write_header之后。