MAC编译ffmpeg+x264(IOS和android)(一)

前言

FFmpeg是一个很强大的垮平台的音视频处理库,它可用于Mac/windows/ios/android/linux等各个平台,FFmpeg库自身native代码实现了很多功能,也引入了其它的很多外部库,比如x264、fdk_aac、lamemp3等等,然后对这些外部库做封装,对外则提供了统一的接口。如下提供了尽量简单的方法编译用于这些平台的ffmpeg库(引入常用的x264、fdk_aac、lamemp3外部库)。

编译基础知识

编译一般分为本地编译和交叉编译,本地编译是相对于交叉编译而言的。本地编译一般指在PC上编译用于当前PC平台系统使用的程序或者库,交叉编译一般指在本地PC平台上用指定的交叉编译器编译用于其它嵌入式平台用的程序或者库,如在Mac平台上编译iOS平台用的FFmpeg库。每一个嵌入式平台都会提供PC平台的交叉编译工具链,他们都会有如下几个工具:

CC:C语言编译器
CXX:C++编译器
AS:汇编语言编译器
AR:打包器,将.o文件打包(CC/CXX/AS编译器生成的为.o文件)
LD:连接器,将库文件和.o文件连接成可执行程序(如.out文件)
NM:查看静态库文件中的符号表
GDB:调试工具
STRIP:通过优化减小可执行文件或者库文件体积
Objdump:查看静态库或者动态库的方法签名

如:

gcc -c main.cpp -I ./include
ar libmedia.a media.o
gcc -o main main.o -L media

make编译工具

通常我们通过命令编译的步骤如下:

// 生成中间文件
gcc -c  main.c
// 生成可执行文件(可执行程序 main;生成库的步骤也一样)
gcc -o main main.o

那如果工程有成千上万个文件,那么我们这样的命令就需要写成千上万变,显然是非常不方便的。make是一个非常强大的工具,它可以极大简化如上的编译命令,生成想要的库或者程序。基本如下:

  • make语法由configure文件(它为可执行文件)来配置
  • --prefix 指定编译生成的库或者可执行文件的路径
  • --host 指定最终要运行的平台
  • CC 指定交叉编译工具的路径
  • CFFLAGS 指定编译时所带的参数
  • LDFLAGS 指定连接过程中的参数
  • --disable-frontend 不编译可执行程序

执行过程如下:
当调用./configure .....命令时将会配置make的相关参数
当调用make ..... 或者make install 命令时,将会调用make工具进行编译连接并生成可执行程序或者库文件

编译mac平台下使用的ffmpeg库

1、homebrew(推荐)
2、make工具手动编译

IOS和android平台交叉编译工具

每个操作系统(MAC osx/windows/linux)都有提供ios和android平台的交叉编译工具链,这里以mac 系统为例,ios和android的交叉编译工具如下:
1、ios交叉编译工具路径
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
在这个路径下就有上面说的那些 cc,ar等工具,这里的cc实际上是指向了clang编译器
ios编译中bitcode
开启之后app性能会增加,关闭则有可能降低性能
xcrun -sdk iphoneos clang -arch arm64 意思就是调用clang编译器编译64位的源代码

2、android交叉编译工具路径
<安卓sdk/ndk-bundle路径>/toolchains/[aarch64-linux-android-4.9(编译64位arm,具体版本号根据安装的ndk版本确定)][arm-linux-androideabi-4.9(编译32位)]/prebuilt/darwin-x86_64/bin
在这个路径下就有上面那些cc,ar等工具

编译环境

  • ios&&mac
    Xcode:Version 11.4 (11E146)
  • android
    android-ndk-r20
  • 操作系统
    Mac os X:10.15.4 (19E266)

开始编译

这里的脚本是基于ijkplayer脚本经过改写而成,反复经历多次修改,ijkplayer是一个很优秀的国内开源库,github地址:ijkplayer开源地址

编译脚本地址:脚本地址

  • 下载脚本
git clone https://github.com/nldzsz/ffmpeg-build-scripts.git

一、 编译 ffmpeg for iOS

cd ffmpeg-build-scripts
./compile-ios.sh
  • 代码解读:

1、执行此脚本会先检查系统中是否安装 brew yasm gas-preprocessor.pl工具,如果没有则会自动安装;
接着会根据选择要编译的库自动下载ffmpeg/x264/mp3lame/fdk-aac等源码;如果不想编译对应的库,只需要将脚本./compile-ios.sh中LIBFLAGS所对应的设置为FALSE即可:

# libass使用Coretext还是fontconfig;TRUE代表使用CORETEXT,FALSE代表使用fontconfig
export USE_CORETEXT=FALSE
# 是否编译这些库;如果不编译将对应的值改为FALSE即可;如果ffmpeg对应的值为TRUE时,还会将其它库引入ffmpeg中,否则单独编译其它库
if [ $USE_CORETEXT = "TRUE" ];then
export LIBFLAGS=(
[ffmpeg]=TRUE [x264]=TRUE [fdkaac]=FALSE [mp3lame]=TRUE [fribidi]=TRUE [freetype]=TRUE [ass]=TRUE
)
else
export LIBFLAGS=(
[ffmpeg]=TRUE [x264]=TRUE [fdkaac]=FALSE [mp3lame]=TRUE [fribidi]=TRUE [freetype]=TRUE [expat]=TRUE [fontconfig]=TRUE [ass]=TRUE
)
fi

下载的源码会保存到extra的对应目录中,如果本地已有源码,则直接将源码拷贝到此目录中即可,不过名字要对应上,对应关系为 common.sh脚本中如下代码

# 各个源码的名字
LIBS[ffmpeg]=ffmpeg
LIBS[x264]=x264
LIBS[fdkaac]=fdk-aac
LIBS[mp3lame]=mp3lame
LIBS[fribidi]=fribidi
LIBS[freetype]=freetype
LIBS[expat]=expat
LIBS[fontconfig]=fontconfig
LIBS[ass]=ass

2、export FF_ALL_ARCHS_IOS="arm64 x86_64" 代表要编译的平台,默认会编译 arm64 x86_64两个平台的静态库

编译后的结果如下:


image.png

如果不做任何裁剪,可以看到默认的.a库还是挺大的,以上是编译的默认配置的库

  • 开启指定的选项

// 开启rtsp解析协议
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp"

export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp"

在ios项目中使用ffmpeg的.a库
1、直接将universal/lib目录拖进工程
2、配置头文件和库文件搜索路径,如下


image.png

3、添加外部库

libiconv.2.4.0.tbd
libz.1.2.5.tbd

如下:


image.png

二、编译ffmpeg for android

  • 1、编译so动态库
cd ffmpeg-build-scripts
./compile-android.sh
  • 备注:
    如果NDK是直接从浏览器下载的,编译的时候会弹出如下的提示:


    image.png

点击"仍然允许"即可。从android studio下载的则不会(来自Google的说法,未尝试过)

最后编译结果如下:


image.png

导入android工程,通过cmake方式导入


image.png

CMakeLists.txt文件导入ffmpeg动态库的关键代码如下:
设置ffmpeg头文件路径

set(SRC_DIR ${PROJECT_SOURCE_DIR}/src/main/cpp)
set(FFMPEG_INC ${SRC_DIR}/ffmpeg)
include_directories(${FFMPEG_INC})

设置ffmpeg.so动态库文件路径

# import ffmpeg library
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/src/main/jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
# ding yi jiang gai ku da bao jin app de lei xing
add_library(adMedia SHARED
        ${src_cpp}
        ${ffmpeg_demo}
        ${ffmpeg_common}
        ${com_cpp}
        ${opensles_cpp}
        )
target_link_libraries(adMedia android log
        OpenSLES
        mediandk
        avformat avcodec avfilter avutil swresample swscale
        ${log-lib}
    )

tips:编译动态库时没有加入fdk_aac库,因为还没找到去掉libfdk-aac.so.2.0.0后缀的办法,如果没有去掉后缀,引入安卓时会提示找不到"fdk-aac.so.2"的错误

  • 2、编译.so动态库
    动态库引入安卓如果有后缀,比如libfdk-aac.so.2.0.0就无法被安卓识别,目前也还没找到办法去掉这个后缀,不过现在ffmpeg已经内置了aac的编解码器,可以不用fdkaac了,不过也了解一下安卓对于静态库的引用方式

找到脚本compile-ffmpeg-android.sh,做如下修改
export FF_COMPILE_SHARED=FALSE
export FF_COMPILE_STATIC=TRUE
然后执行
./compile-ffmpeg-android.sh all

最终生成的静态库如下:

静态ffmpeg库的引入方式
1、将相关库拖入对应目录
2、配置CMakeLists.txt
设置ffmpeg头文件路径和动态库一样

set(SRC_DIR {PROJECT_SOURCE_DIR}/src/main/cpp) set(FFMPEG_INC{SRC_DIR}/ffmpeg)
include_directories(${FFMPEG_INC})
设置ffmpeg 相关静态库文件路径

# import ffmpeg library
# import ffmpeg library
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/src/main/jniLibs/${CMAKE_ANDROID_ARCH_ABI} -lm -lz")
# ding yi jiang gai ku da bao jin app de lei xing
add_library(adMedia SHARED
        ${src_cpp}
        ${ffmpeg_demo}
        ${ffmpeg_common}
        ${com_cpp}
        ${opensles_cpp}
        )
target_link_libraries(adMedia android log
        OpenSLES
        mediandk
        # for dynamic
#        avformat avcodec avfilter avutil swresample swscale
        # for static
        libavformat.a libavcodec.a libavfilter.a libavutil.a libswresample.a libswscale.a libfdk-aac.a libx264.a libmp3lame.a
        ${log-lib}
    )
  • 注意:这里和动态库不一样的就是多加了-lm -lz的标记和写入完整的库名包括后缀

三、编译ffmpeg for mac

  • homebrew编译
    1、homebrew安装ffmpeg for mac
brew install ffmpeg

会自动安装最新的ffmpeg,如果没有安装homebrew,则使用如下命令安装

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

homebrew卸载ffmpeg

brew uninstall ffmpeg
  • 手动编译
    homebrew安装ffmpeg的好处是简单,不足是无法自定义ffmpeg的配置,如果修改了ffmpeg的源码,则必须要通过手动方式安装ffmpeg
cd ffmpeg-build-scripts
./compile-pc.sh mac

会生成ffmpeg.a库,如下:


image.png
  • 将ffmpeg导入xcode命令行工程
    这里是一个简单的command line工程,如下方式设置ffmpeg


    2.jpg
3.jpg

注意第二张图,需要添加如下额外的库,不然会出现错误。

FFmpeg许可协议

在使用开源代码时要清除开源代码所使用的的许可协议,因为可能涉及到一定的法律风险。常见的开源许可协议:

  • BSD/MIT/APPACHE
    可以为所欲为的许可协议
  • GPL
    全称(GNU General Public License)。产品中要有一份文档说明使用了GPL协,只要是使用到它的代码自身的代码也要全部开源
  • LGPL
    全称(GNU Lesser General Public License)。产品中要有一份文档说明使用了LGPL协议,使用它的代码自身代码不需要开源。但如果修改了它的代码,则修改的部分要开源出来

ffmpeg关于协议的configure参数为

Licensing options:
  --enable-gpl             allow use of GPL code, the resulting libs
                           and binaries will be under GPL [no]
  --enable-version3        upgrade (L)GPL to version 3 [no]
  --enable-nonfree         allow use of nonfree code, the resulting libs
                           and binaries will be unredistributable [no]

1、ffmpeg协议默认为LGPL v2.1+
2、如果ffmpeg引入了x264库或者使用GPL的模块,那么ffmpeg将变成GPL许可协议,需要开启--enable-gpl
3、ffmpeg使用了gmp、libaribb24等基于LGPL v3的模块,则需要开启--enable-version3
4、如果ffmpeg引入了fdk-aac等和GPL不兼容的外部库,则需要开启--enable-nonfree,编译后ffmpeg变成unredistributable

具体参考官网
许可协议文档1
许可协议介绍

遇到问题

  • ios&&mac遇到问题
    1、x264库相关函数找不到
ld: warning: could not create compact unwind for _ff_init_vlc_sparse: stack subq instruction is too different from dwarf stack size
ld: warning: could not create compact unwind for _ff_init_2d_vlc_rl: stack subq instruction is too different from dwarf stack size
ld: warning: could not create compact unwind for _ff_rl_init_vlc: stack subq instruction is too different from dwarf stack size
Undefined symbols for architecture x86_64:
  "_x264_encoder_close", referenced from:
      _X264_close in libavcodec.a(libx264.o)
  "_x264_picture_init", referenced from:
      _X264_frame in libavcodec.a(libx264.o)
  "_x264_encoder_reconfig", referenced from:
      _X264_frame in libavcodec.a(libx264.o)
  "_x264_encoder_open_157", referenced from:
      _X264_init in libavcodec.a(libx264.o)
  "_x264_encoder_encode", referenced from:
      _X264_frame in libavcodec.a(libx264.o)
  "_x264_param_default", referenced from:
      _X264_init in libavcodec.a(libx264.o)
  "_x264_param_apply_fastfirstpass", referenced from:
      _X264_init in libavcodec.a(libx264.o)
  "_x264_levels", referenced from:
      _X264_init in libavcodec.a(libx264.o)
  "_x264_param_default_preset", referenced from:
      _X264_init in libavcodec.a(libx264.o)
  "_x264_param_apply_profile", referenced from:
      _X264_init in libavcodec.a(libx264.o)
  "_x264_param_parse", referenced from:
      _X264_init in libavcodec.a(libx264.o)
  "_x264_encoder_delayed_frames", referenced from:
      _X264_frame in libavcodec.a(libx264.o)
  "_x264_encoder_headers", referenced from:
      _X264_init in libavcodec.a(libx264.o)
  "_x264_encoder_maximum_delayed_frames", referenced from:
      _X264_init in libavcodec.a(libx264.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (us

编译的libx264.a也要一并添加进去(如果是用的libxrzffmpeg.a则不需要加)

2、ffmpeg 4.0编译fdk-aac时遇到的错误
libavcodec/libfdk-aacenc.c:292:34: error: ‘AACENC_InfoStruct {aka struct <anonymous>}’ has no member named ‘encoderDelay’ #93
换成4.2,解决了此问题

3、xcode环境不全时编译ffmpeg 提示 No working C compiler found.
执行如下命令:

xcode-select --install # Install Command Line Tools if you haven't already.
sudo xcode-select --switch /Library/Developer/CommandLineTools # Enable command line tools
# Change the path if you installed Xcode somewhere else.
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

4、编译x264时,如果提示Found no assembler Minimum version is nasm-2.13
说明系统的nasm版本过低,重新安装即可

brew reinstall nasm

5、ffmpeg引用错误
必须要添加如下对应的库,否则可能会出现对应的错误,如下:
libiconv.2.4.0.tbd,libz.1.2.5.tbd

Undefined symbols for architecture xxx
"deflateInit2", referenced from:
_encode_frame in libavcodec.a(pngenc.o)
"_crc32", referenced from:
_encode_frame in libavcodec.a(pngenc.o)
"_deflateReset", referenced from:
_encode_frame in libavcodec.a(lclenc.o)
_encode_frame in libavcodec.a(zmbvenc.o)
"_compress", referenced from:
.......

Security.framework

Undefined symbols for architecture x86_64:
  "_SSLClose", referenced from:
      _tls_open in libavformat.a(tls_securetransport.o)
      _tls_close in libavformat.a(tls_securetransport.o)
  "_SSLCopyPeerTrust", referenced from:
......

VideoDecodeAcceleration.framework

Undefined symbols for architecture x86_64:
  "_VDADecoderCreate", referenced from:
      _ff_vda_create_decoder in libavcodec.a(vda_h264.o)
      _ff_vda_default_init in libavcodec.a(vda_h264.o)
  "_VDADecoderDecode", referenced from:
.....

AudioToolbox.framework

Undefined symbols for architecture x86_64:
  "_AudioConverterDispose", referenced from:
      _ffat_close_decoder in libavcodec.a(audiotoolboxdec.o)
      _ffat_close_encoder in libavcodec.a(audiotoolboxenc.o)
  "_AudioConverterFillComplexBuffer", referenced from:
....

CoreMedia.framework

Undefined symbols for architecture x86_64:
  "_CMBlockBufferCopyDataBytes", referenced from:
      _vtenc_frame in libavcodec.a(videotoolboxenc.o)
  "_CMBlockBufferCreateWithMemoryBlock", referenced from:
      _videotoolbox_common_end_frame in libavcodec.a(videotoolbox.o)
  "_CMSampleBufferCreate", referenced from:
.....

CoreFoundation.framework

Undefined symbols for architecture x86_64:
  "_CFArrayCreateMutableCopy", referenced from:
      _tls_open in libavformat.a(tls_securetransport.o)
  "_CFArrayGetCount", referenced from:
      _vtenc_frame in libavcodec.a(videotoolboxenc.o)
......

CoreVideo.framework

Undefined symbols for architecture x86_64:
  "_CVBufferSetAttachments", referenced from:
      _vtenc_send_frame in libavcodec.a(videotoolboxenc.o)
  "_CVPixelBufferCreateWithPlanarBytes", referenced from:
      _vtenc_send_frame in libavcodec.a(videotoolboxenc.o)
....

VideoToolbox.framework

Undefined symbols for architecture x86_64:
  "_VTCompressionSessionCompleteFrames", referenced from:
      _vtenc_init in libavcodec.a(videotoolboxenc.o)
      _vtenc_frame in libavcodec.a(videotoolboxenc.o)
  "_VTCompressionSessionCreate", referenced from:
.....

libz.tbd

Undefined symbols for architecture x86_64:
  "_compress", referenced from:
      _encode_strip in libavcodec.a(tiffenc.o)
  "_compress2", referenced from:
      _flashsv2_encode_frame in libavcodec.a(flashsv2enc.o)
      _flashsv_encode_frame in libavcodec.a(flashsvenc.o)
  "_deflate", referenced from:
....

liblzma.tbd

Undefined symbols for architecture x86_64:
  "_lzma_code", referenced from:
      _decode_frame in libavcodec.a(tiff.o)
  "_lzma_end", referenced from:
      _decode_frame in libavcodec.a(tiff.o)
....

libbz2.tbd

Undefined symbols for architecture x86_64:
  "_BZ2_bzDecompress", referenced from:
      _matroska_decode_buffer in libavformat.a(matroskadec.o)
  "_BZ2_bzDecompressEnd", referenced from:
....

libiconv.tbd

Undefined symbols for architecture x86_64:
  "_iconv", referenced from:
      _avcodec_decode_subtitle2 in libavcodec.a(utils.o)
  "_iconv_close", referenced from:
      _avcodec_open2 in libavcodec.a(utils.o)
....

libz.tbd

Undefined symbols for architecture x86_64:
  "_compress", referenced from:
      _encode_strip in libavcodec.a(tiffenc.o)
  "_compress2", referenced from:
      _flashsv2_encode_frame in libavcodec.a(flashsv2enc.o)
      _flashsv_encode_frame in libavcodec.a(flashsvenc.o)
  "_deflate", referenced from:
.....

6、"stack_not_16_byte_aligned_error"错误
此错误为mac osX 10.15.4 (19E266)和Version 11.4 (11E146)编译环境下新产生问题。在编译CFlags=添加 "-fno-stack-check" 即可,如下:

# fixbug:mac osX 10.15.4 (19E266)和Version 11.4 (11E146)编译时产生错误"stack_not_16_byte_aligned_error"
# 添加 "-fno-stack-check" 即可
FF_EXTRA_CFLAGS="-fno-stack-check"
  • android 问题
    待补充。。。。。

因为编译脚本不停的在更新,所以上面MAC/IOS/Android工程需要引用的其它库可能有有需要增加的地方,最新的请参考ffmpeg的demo中的配置 ffmpeg-demo地址,那个工程的配置我会实时更新,按照demo中工程配置肯定不会出错

源代码地址

编译脚本地址:
https://github.com/nldzsz/ffmpeg-build-scripts.git
ffmpeg地址:
https://github.com/FFmpeg/FFmpeg.git
http://ffmpeg.org/releases/ffmpeg-4.2.tar.bz2
x264地址:
https://git.videolan.org/git/x264.git
http://download.videolan.org/x264/snapshots/x264-snapshot-20190809-2245-stable.tar.bz2(备注:该地址每天都会按照日期20190809增加一份拷贝,其它不变)
lame地址:
https://sourceforge.net/projects/lame/files/lame/3.100/lame-3.100.tar.gz
https://jaist.dl.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz
fdk-aac地址:
https://github.com/mstorsjo/fdk-aac
https://sourceforge.net/p/opencore-amr/fdk-aac/ci/v2.0.0/tarball
https://jaist.dl.sourceforge.net/project/opencore-amr/fdk-aac/fdk-aac-2.0.0.tar.gz

参考文章

1、[FFmpeg零基础(2)-FFmpeg的编译]https://juejin.im/post/5af3bef5f265da0b9d783ae3
2、xrun命令介绍
3、https://github.com/kewlbear
4、ijkplayer
5、gas-preprocessor
6、https://github.com/kewlbear/FFmpeg-iOS-build-script

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345