ffmpegandroid(ffmpeg Android 视频读取)
本篇文章给大家谈谈ffmpegandroid,以及ffmpeg Android 视频读取对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、android ffmpeg视频添加字幕和配音
- 2、如何在Android上集成ffmpeg
- 3、如何用Android NDK编译FFmpeg
- 4、Android使用FFmpeg播放视频(二):音频播放
- 5、如何在Android用FFmpeg+SDL2.0解码显示图像
android ffmpeg视频添加字幕和配音
使用ffmpeg三方:
兼容处理android10的不能操作二进制文件流问题;
1、添拿颤拍加字幕
主要命令:-i videoPath.mp4 -q 5 -vf ass=subtitle.ass -y outPath.mp4
其中-q 5命令是为了生成的视频不会很模糊
2、添加字幕和配音
ffmpeg在特定的时间混合一个或多个音频,参考文章
如何在指定的时间点向视频插入配音文件即音频文件,参考文章消羡
主要洞闭命令:ffmpeg -y -i video1.mp4 -i audio1.mp3 -i audio2.mp3 -filter_complex "[1]atrim=0:5,adelay=3000|3000[aud1];[2]atrim=0:6,adelay=10000|10000[aud2];[aud1][aud2]amix=2,apad,atrim=0:20[a]" -map 0:v -map "[a]" -c:v copy -ac 2 output.mp4
如何在Android上集成ffmpeg
环境要求Vitamio3.0是使用AndroidNDKr8b版本带闹编译生成的,所以建议也使用此版本的NDK编译您改写过的FFmpeg,根据开发者的反馈,使用其它版本的NDK可能导致很多问题甚至塌镇崩溃。编译生成FFmpeg首先,从我们的GitHub网址:/yixia/FFmpeg-Android下载一份FFmpeg-Android库的拷贝,根据自己的需求对FFmpeg-Android.sh进行适当修改。最常见的场景是编译FFmpeg中你的程序需要的某几个特定模块,其它大部分不需要动。这种情况下,只需要在shell脚本下修改FFMPEG_FLAGS,所有可用参数都在FFmpeg的配置脚本里有详细说明,可通过configure--help查阅。个别情况下,如果需要为FFmpeg打补丁,那可能会麻烦些。我假定你自己已经知道了要怎么做。简言之,你只要懂FFmpeg-Android.sh或者编写自己的编译/生成脚本即可。最后,在bash中运行FFmpeg-Android.sh脚本,既然是bash脚本,也许可能在zsh中运行。打包libarm.so在VitamioBundle中找到res/raw/libarm.so这个文件:=fileres/raw/libarm.sores/raw/libarm.so:7-ziparchivedata,version0.3如你所见,它是个7-zip压缩文件,因此可以直接将其解压到随便哪里后,用你自团行粗己在前一步生成的libffmpeg.so替换其中原来的每个libffmpeg.so。60armv661vfp70armv771neon最后,将替换后的数据照原样重新打包成libarm.so即可。
如何用Android NDK编译FFmpeg
android的NDK开发需要在linux下进行:
因为需要把C/C++编写的代码生悉袭成能在arm上运行的.so文件,这就需要用到交叉编译环境,而交叉编虚消译需要在linux系统下才能完成。
安装android-ndk开发包,这个开发包可以在google android 官网下载: 通过这个开发包的工具才能将android jni 的C/C++的代码编译成库
android应用程序开发环境: 包括eclipse、java、 android sdk、 adt等。
NDK编译步骤:
a.选择 ndk 自带的例子 hello-jni ,我的位于E:\android-ndk-r5\samples\hello-jni( 根据具体的安装位置而定 ) 。
b.运行 cygwin ,输入命令 cd /cygdrive/e/android-ndk-r5/samples/hello-jni ,进入到 E:\android-ndk-r5\samples\hello-jni 目录。
c.输入 $NDK/ndk-build ,执行睁誉兄成功后,它会自动生成一个 libs 目录,把编译生成的 .so 文件放在里面。 ($NDK是调用我们之前配置好的环境变量, ndk-build 是调用 ndk 的编译程序 )
d.此时去 hello-jni 的 libs 目录下看有没有生成的 .so 文件,如果有,ndk 就运行正常啦。
[img]Android使用FFmpeg播放视频(二):音频播放
Android使用FFmpeg播放视频(一):视频播放
Android NDK开发:利用汪闭OpenSL ES实现声音播放
这里我创建了两个JNI函数,一个是播放的,一个是释放的如下:
这里我在用于播困让裂放的JNI函数中依次初始化了FFmpeg和OpenSLES
其中初始化FFmpeg的函数中的逻辑其实和使用FFmpeg播放视滑裤频画面中的逻辑差不多,主要区别就是要找到音频的索引以及后面对于解析音频的一些配置;而初始化OpenSLES基本就和之前使用OpenSLES播放PCM数据是一样的,具体如下:
最后再加入释放资源的逻辑即可
这里的案例源码是和之前播放视频画面的分开了
如何在Android用FFmpeg+SDL2.0解码显示图像
创建山改一个VideoPicture结构体用来保存解码出来的图像。
LOCAL_PATH := $(call my-dir)
###########################
#
# SDL shared library
#
###########################
include $(CLEAR_VARS)
LOCAL_MODULE := SDL2
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
LOCAL_SRC_FILES := \
$(subst $(LOCAL_PATH)/,, \
$(wildcard $(LOCAL_PATH)/src/*.c) \
$(wildcard $(LOCAL_PATH)/src/audio/*.c) \
$(wildcard $(LOCAL_PATH)/src/audio/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/audio/dummy/*.c) \
$(LOCAL_PATH)/src/atomic/SDL_atomic.c \
$(LOCAL_PATH)/src/atomic/SDL_spinlock.c.arm \
$(wildcard $(LOCAL_PATH)/src/core/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \
$(wildcard $(LOCAL_PATH)/src/dynapi/*.c) \
$(wildcard $(LOCAL_PATH)/岁汪src/events/*.c) \
$(wildcard $(LOCAL_PATH)/src/file/*.c) \
$(wildcard $(LOCAL_PATH)/src/haptic/*.c) \
$(wildcard $(LOCAL_PATH)/src/haptic/dummy/*.c) \
$(wildcard $(LOCAL_PATH)/src/joystick/*.c) \
$(wildcard $(LOCAL_PATH)/src/joystick/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \
$(wildcard $(LOCAL_PATH)/src/power/*.c) \
$(wildcard $(LOCAL_PATH)/src/power/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/filesystem/逗雀判dummy/*.c) \
$(wildcard $(LOCAL_PATH)/src/render/*.c) \
$(wildcard $(LOCAL_PATH)/src/render/*/*.c) \
$(wildcard $(LOCAL_PATH)/src/stdlib/*.c) \
$(wildcard $(LOCAL_PATH)/src/thread/*.c) \
$(wildcard $(LOCAL_PATH)/src/thread/pthread/*.c) \
$(wildcard $(LOCAL_PATH)/src/timer/*.c) \
$(wildcard $(LOCAL_PATH)/src/timer/unix/*.c) \
$(wildcard $(LOCAL_PATH)/src/video/*.c) \
$(wildcard $(LOCAL_PATH)/src/video/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/test/*.c))
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
include $(BUILD_SHARED_LIBRARY)
###########################
#
# SDL static library
#
###########################
#LOCAL_MODULE := SDL2_static
#LOCAL_MODULE_FILENAME := libSDL2
#LOCAL_SRC_FILES += $(LOCAL_PATH)/src/main/android/SDL_android_main.c
#LOCAL_LDLIBS :=
#LOCAL_EXPORT_LDLIBS := -Wl,--undefined=Java_org_libsdl_app_SDLActivity_nativeInit -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
#include $(BUILD_STATIC_LIBRARY)
二、参考[原]如何在Android用FFmpeg解码图像, 在工程中新建一个ffmpeg文件夹,将与ffmpeg相关的头文件include进来。ffmpeg文件夹下的Android.mk内容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := /path/to/build/ffmpeg/libffmpeg.so
include $(PREBUILT_SHARED_LIBRARY)
三、新建player文件夹,用来编写解码与显示文件。player.c文件内容:
/*
* SDL_Lesson.c
*
* Created on: Aug 12, 2014
* Author: clarck
*/
#include jni.h
#include android/native_window_jni.h
#include "SDL.h"
#include "SDL_thread.h"
#include "SDL_events.h"
#include "../include/logger.h"
#include "../ffmpeg/include/libavcodec/avcodec.h"
#include "../ffmpeg/include/libavformat/avformat.h"
#include "../ffmpeg/include/libavutil/pixfmt.h"
#include "../ffmpeg/include/libswscale/swscale.h"
int main(int argc, char *argv[]) {
char *file_path = argv[1];
LOGI("file_path:%s", file_path);
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame, *pFrameYUV;
AVPacket *packet;
uint8_t *out_buffer;
SDL_Texture *bmp = NULL;
SDL_Window *screen = NULL;
SDL_Rect rect;
SDL_Event event;
static struct SwsContext *img_convert_ctx;
int videoStream, i, numBytes;
int ret, got_picture;
av_register_all();
pFormatCtx = avformat_alloc_context();
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
LOGE("Could not initialize SDL - %s. \n", SDL_GetError());
exit(1);
}
if (avformat_open_input(pFormatCtx, file_path, NULL, NULL) != 0) {
LOGE("can't open the file. \n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) 0) {
LOGE("Could't find stream infomation.\n");
return -1;
}
videoStream = 1;
for (i = 0; i pFormatCtx-nb_streams; i++) {
if (pFormatCtx-streams[i]-codec-codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
}
}
LOGI("videoStream:%d", videoStream);
if (videoStream == -1) {
LOGE("Didn't find a video stream.\n");
return -1;
}
pCodecCtx = pFormatCtx-streams[videoStream]-codec;
pCodec = avcodec_find_decoder(pCodecCtx-codec_id);
if (pCodec == NULL) {
LOGE("Codec not found.\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) 0) {
LOGE("Could not open codec.\n");
return -1;
}
pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
//---------------------------init sdl---------------------------//
screen = SDL_CreateWindow("My Player Window", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, pCodecCtx-width, pCodecCtx-height,
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(screen, -1, 0);
bmp = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING, pCodecCtx-width, pCodecCtx-height);
//-------------------------------------------------------------//
img_convert_ctx = sws_getContext(pCodecCtx-width, pCodecCtx-height,
pCodecCtx-pix_fmt, pCodecCtx-width, pCodecCtx-height,
AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx-width,
pCodecCtx-height);
out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P,
pCodecCtx-width, pCodecCtx-height);
rect.x = 0;
rect.y = 0;
rect.w = pCodecCtx-width;
rect.h = pCodecCtx-height;
int y_size = pCodecCtx-width * pCodecCtx-height;
packet = (AVPacket *) malloc(sizeof(AVPacket));
av_new_packet(packet, y_size);
av_dump_format(pFormatCtx, 0, file_path, 0);
while (av_read_frame(pFormatCtx, packet) = 0) {
if (packet-stream_index == videoStream) {
ret = avcodec_decode_video2(pCodecCtx, pFrame, got_picture,
packet);
if (ret 0) {
LOGE("decode error.\n");
return -1;
}
LOGI("got_picture:%d", got_picture);
if (got_picture) {
sws_scale(img_convert_ctx,
(uint8_t const * const *) pFrame-data,
pFrame-linesize, 0, pCodecCtx-height, pFrameYUV-data,
pFrameYUV-linesize);
////iPitch 计算yuv一行数据占的字节数
SDL_UpdateTexture(bmp, rect, pFrameYUV-data[0], pFrameYUV-linesize[0]);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, bmp, rect, rect);
SDL_RenderPresent(renderer);
}
SDL_Delay(50);
}
av_free_packet(packet);
SDL_PollEvent(event);
switch (event.type) {
case SDL_QUIT:
SDL_Quit();
exit(0);
break;
default:
break;
}
}
SDL_DestroyTexture(bmp);
av_free(out_buffer);
av_free(pFrameYUV);
avcodec_close(pCodecCtx);
avformat_close_input(pFormatCtx);
return 0;
}
四、编写player文件夹下面的Android makefile,内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := player
SDL_PATH := ../SDL
FFMPEG_PATH := ../ffmpeg
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(SDL_PATH)/include
LOCAL_C_INCLUDES += $(LOCAL_PATH)/$(FFMPEG_PATH)/include
# Add your application source files here...
LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c
LOCAL_SRC_FILES += player.c
LOCAL_SHARED_LIBRARIES := SDL2
LOCAL_SHARED_LIBRARIES += ffmpeg
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog
include $(BUILD_SHARED_LIBRARY)
五、修改SDLActivity.java文件内容,用来加载libffmpeg.so以及libplayer.so,以及修改用来解码的文件路径。
// Load the .so
static {
System.loadLibrary("ffmpeg");
System.loadLibrary("SDL2");
//System.loadLibrary("SDL2_image");
//System.loadLibrary("SDL2_mixer");
//System.loadLibrary("SDL2_net");
//System.loadLibrary("SDL2_ttf");
System.loadLibrary("player");
}
/**
Simple nativeInit() runnable
*/
class SDLMain implements Runnable {
@Override
public void run() {
// Runs SDL_main()
String sdcard = Environment.getExternalStorageDirectory().getAbsolutePath();
SDLActivity.nativeInit("/sdcard/a.mp4");
//Log.v("SDL", "SDL thread terminated");
}
}
关于ffmpegandroid和ffmpeg Android 视频读取的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。