CentOS 下通过 JavaCPP 调用 FFMPEG

标签: centos javacpp ffmpeg | 发表时间:2014-08-06 01:38 | 作者:maoxiang
出处:http://blog.csdn.net

1. Java 与 FFMPEG

   FFMPEG 是一个广泛用于媒体处理的库,在Java的世界里,处理视频的能力相当弱,于是有很大需求需要Java 调用 FFMPEG。

  Java 调用C 的方式有很多,可以用最原始的JNI方式,也可以JNA方式,还可以是命令行。

   采用命令行的方式比较简单,不过有很大局限性,尤其是涉及到 视频的处理和分析的时候,比如要取出某个packet,然后进行处理。

 
    这里介绍的是用JavaCPP 调用 ffmpeg 库的方式,而不是命令行模式。

     JavaCPP的源码在这里:https://github.com/bytedeco/javacpp 


  基于JavaCPP的项目   

1)JavaCV,是做图形图像的,有人脸识别、增强现实AR 等开源算法,非常不错

    项目主页是:https://github.com/bytedeco/javacv 
  
 2)JavaAV 封装了FFMPEG的java 接口

    项目主页:https://github.com/hoary/JavaAV


2.  JavaCPP Presets


  为了方便使用,JavaCPP下面有个presets项目,主页是 https://github.com/bytedeco/javacpp-presets,将一些常用的项目都编译好了以方便使用。
    集成的项目包括:
• OpenCV 2.4.9 http://opencv.org/downloads.html
• FFmpeg 2.3.x http://ffmpeg.org/download.html
• FlyCapture 2.6.x http://ww2.ptgrey.com/sdk/flycap
• libdc1394 2.1.x or 2.2.x http://sourceforge.net/projects/libdc1394/files/
• libfreenect 0.5 https://github.com/OpenKinect/libfreenect
• videoInput 0.200 https://github.com/ofTheo/videoInput/tree/update2013
• ARToolKitPlus 2.3.0 https://launchpad.net/artoolkitplus
• flandmark 1.07 http://cmp.felk.cvut.cz/~uricamic/flandmark/#download
• FFTW 3.3.4 http://www.fftw.org/download.html
• GSL 1.16 http://www.gnu.org/software/gsl/#downloading
• LLVM 3.4.2 http://llvm.org/releases/download.html
• Leptonica 1.71 http://www.leptonica.org/download.html
• Tesseract 3.03-rc1 https://code.google.com/p/tesseract-ocr/

    包含的平台有:   android-arm, android-x86, linux-x86, linux-x86_64, macosx-x86_64, windows-x86, windows-x86_64,

  但需要注意:这里的 linux-x86_64 是 基于Fedora 平台的,无法在 CentOS下使用。


3. 在CentOS下编译
  1)安装JDK
  2)安装 apache-maven 2/3

  3) 安装 gcc,gcc+,gcc-c++,yasm

     yum -y install yasm gcc+ gcc-c++


  4)  获取源码

     git clone http://github.com/bytedeco/javacpp-presets
  5)  编译 ffmpeg 


     cd javacpp-presets/
    ./cppbuild.sh -platform linux-x86_64 install ffmpeg 


  6) 编译 jni 和 相关jar


      mvn install --projects ffmpeg

 
   7) 编译完成后,会在 ffmpeg 的lib上生成相关 .so ,javacpp-presets/targets 下生成相关的jar


4. 测试
   1) 将相关的 .so 复制到 /lib64 目录下,或者通过 -Djava.library.path 指定到.so 所在目录
   2) 拷贝一个实例用来测试,  

   

public class Tutorial01 {

	static void SaveFrame(AVFrame pFrame, int width, int height, int iFrame)
			throws IOException {
		// Open file
		OutputStream stream = new FileOutputStream("frame" + iFrame + ".ppm");

		// Write header
		stream.write(("P6\n" + width + " " + height + "\n255\n").getBytes());

		// Write pixel data
		BytePointer data = pFrame.data(0);
		byte[] bytes = new byte[width * 3];
		int l = pFrame.linesize(0);
		for (int y = 0; y < height; y++) {
			data.position(y * l).get(bytes);
			stream.write(bytes);
		}

		// Close file
		stream.close();
	}

	public static void main(String[] args) throws IOException {
		AVFormatContext pFormatCtx = new AVFormatContext(null);
		int i, videoStream;
		AVCodecContext pCodecCtx = null;
		AVCodec pCodec = null;
		AVFrame pFrame = null;
		AVFrame pFrameRGB = null;
		AVPacket packet = new AVPacket();
		int[] frameFinished = new int[1];
		int numBytes;
		BytePointer buffer = null;

		AVDictionary optionsDict = null;
		SwsContext sws_ctx = null;

		if (args.length < 1) {
			args = new String[] { "/root/test.ts" };
			// System.out.println("Please provide a movie file");
			// System.exit(-1);
		}
		// Register all formats and codecs
		av_register_all();

		// Open video file
		if (avformat_open_input(pFormatCtx, args[0], null, null) != 0) {
			System.exit(-1); // Couldn't open file
		}

		// Retrieve stream information
		if (avformat_find_stream_info(pFormatCtx, (PointerPointer) null) < 0) {
			System.exit(-1); // Couldn't find stream information
		}

		// Dump information about file onto standard error
		av_dump_format(pFormatCtx, 0, args[0], 0);

		// Find the first video stream
		videoStream = -1;
		for (i = 0; i < pFormatCtx.nb_streams(); i++) {
			if (pFormatCtx.streams(i).codec().codec_type() == AVMEDIA_TYPE_VIDEO) {
				videoStream = i;
				break;
			}
		}
		if (videoStream == -1) {
			System.exit(-1); // Didn't find a video stream
		}

		// Get a pointer to the codec context for the video stream
		pCodecCtx = pFormatCtx.streams(videoStream).codec();

		// Find the decoder for the video stream
		pCodec = avcodec_find_decoder(pCodecCtx.codec_id());
		if (pCodec == null) {
			System.err.println("Unsupported codec!");
			System.exit(-1); // Codec not found
		}
		// Open codec
		if (avcodec_open2(pCodecCtx, pCodec, optionsDict) < 0) {
			System.exit(-1); // Could not open codec
		}

		// Allocate video frame
		pFrame = av_frame_alloc();

		// Allocate an AVFrame structure
		pFrameRGB = av_frame_alloc();
		if (pFrameRGB == null) {
			System.exit(-1);
		}

		// Determine required buffer size and allocate buffer
		numBytes = avpicture_get_size(AV_PIX_FMT_RGB24, pCodecCtx.width(),
				pCodecCtx.height());
		buffer = new BytePointer(av_malloc(numBytes));

		sws_ctx = sws_getContext(pCodecCtx.width(), pCodecCtx.height(),
				pCodecCtx.pix_fmt(), pCodecCtx.width(), pCodecCtx.height(),
				AV_PIX_FMT_RGB24, SWS_BILINEAR, null, null,
				(DoublePointer) null);

		// Assign appropriate parts of buffer to image planes in pFrameRGB
		// Note that pFrameRGB is an AVFrame, but AVFrame is a superset
		// of AVPicture
		avpicture_fill(new AVPicture(pFrameRGB), buffer, AV_PIX_FMT_RGB24,
				pCodecCtx.width(), pCodecCtx.height());

		// Read frames and save first five frames to disk
		i = 0;
		while (av_read_frame(pFormatCtx, packet) >= 0) {
			// Is this a packet from the video stream?
			if (packet.stream_index() == videoStream) {
				// Decode video frame
				avcodec_decode_video2(pCodecCtx, pFrame, frameFinished, packet);

				// Did we get a video frame?
				if (frameFinished[0] != 0) {
					// Convert the image from its native format to RGB
					sws_scale(sws_ctx, pFrame.data(), pFrame.linesize(), 0,
							pCodecCtx.height(), pFrameRGB.data(),
							pFrameRGB.linesize());

					// Save the frame to disk
					if (++i <= 5) {
						SaveFrame(pFrameRGB, pCodecCtx.width(),
								pCodecCtx.height(), i);
					}
				}
			}

			// Free the packet that was allocated by av_read_frame
			av_free_packet(packet);
		}

		// Free the RGB image
		av_free(buffer);
		av_free(pFrameRGB);

		// Free the YUV frame
		av_free(pFrame);

		// Close the codec
		avcodec_close(pCodecCtx);

		// Close the video file
		avformat_close_input(pFormatCtx);

		System.exit(0);
	}
}

4)运行实例,得到输出结果:
   
Input #0, mpegts, from '/root/test.ts':
  Duration: 00:03:20.02, start: 0.056778, bitrate: 1455 kb/s
  Program 1
    Metadata:
      service_name    : jVideo
      service_provider: jTeam
    Stream #0:0[0x100]: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p, 960x540 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:1[0x101]: Audio: aac ([15][0][0][0] / 0x000F), 44100 Hz, stereo, fltp, 66 kb/s



作者:maoxiang 发表于2014-8-5 17:38:32 原文链接
阅读:86 评论:0 查看评论

相关 [centos javacpp ffmpeg] 推荐:

CentOS 下通过 JavaCPP 调用 FFMPEG

- - CSDN博客综合推荐文章
   FFMPEG 是一个广泛用于媒体处理的库,在Java的世界里,处理视频的能力相当弱,于是有很大需求需要Java 调用 FFMPEG.   Java 调用C 的方式有很多,可以用最原始的JNI方式,也可以JNA方式,还可以是命令行.    采用命令行的方式比较简单,不过有很大局限性,尤其是涉及到 视频的处理和分析的时候,比如要取出某个packet,然后进行处理.

ffmpeg轉檔

- - SSORC.twSSORC.tw
ffmpeg 是一個命令列工具,用來對視訊檔案轉換格式. -i = 來源影片 (後面的參數先不接的話可以查看來源影片的詳細資訊,可供想要轉成什麼品質的參考). -vcodec = video code (如果要保留原格式就用 -vcodec copy). -acoder = audio code  (如果要保留原格式就用 -vcodec copy).

CentOS配置RPMForge源

- - 启光博客
  之前以发过一篇Linux安装配置网易的第三方源的文章,不过网易源与CentOS自带的官方源中的软件有时候还是感觉不够多,特别是桌面版用户应该深有体会,这个时候你就需要RPMForge,RPMForge被CentOS社区认为是最安全也是最稳定的一个软件仓库,拥有10000多种的软件包.   呵呵,好像有点给RPMForge做广告的感觉.

centos 使用fedora源

- - C++博客_首页
可以从该处理下 http://fedoraproject.org/wiki/EPEL包.   http://dl.fedoraproject.org/pub/epel/ 目录下查找:.   http://dl.fedoraproject.org/pub/epel/6/x86_64/下.

centos 6.2 关闭 IPV6

- - CSDN博客系统运维推荐文章
在现在的Linux上IPv6已经在默认安装下被支持,但是对于一些对IPv6支持不是很好的应用服务器来说,开启了IPv6反而会影响服务器的网络性能,毕竟现在的网络交换设备不是IPv6的. 如何判断系统是否开了ipv6. 第二,也可以通过查看开启的端口. 既然确定开启了之后,那怎样才能关闭呢. 我用的是centos6.2 没有找到/etc/modprobe.conf 文件,所以我就直接vi了一个,并加了两行.

ffmpeg裁剪合并视频

- - inJava
这里裁剪是指时间轴裁剪,不是空间裁剪. 比如说,你想把视频的从一分20秒开始,30秒的视频裁剪出来,保存成一个视频. ffmpeg提供简单的命令参数:. -ss 开始时间,如: 00:00:20,表示从20秒开始;. -t 时长,如: 00:00:10,表示截取10秒长的视频;. -i 输入,后面是空格,紧跟着就是输入视频文件;.

CentOS 6.0 正式发布

- Power - cnBeta.COM
CentOS 是一个企业级的 Linux 发行版本,它源于上游操作系统提供者免费公开的源代码. CentOS 完全遵守上游供应商的再发行政策,并且以百分之百的软件兼容性为目标. (CentOS 对组件的修改主要是去除上游供应商的商标及美工图. )CentOS 6.0 与以往的发行版本有很大改动. CentOS 6.0 是用一个较新的建设系统所建造出来的,而函数库亦被检定可兼容上游的二元档.

centos linux 服务器安全

- - 操作系统 - ITeye博客
我们必须明白:最小的权限+最少的服务=最大的安全. 所以,无论是配置任何服务器,我们都必须把不用的服务关闭、把系统权限设置到最小话,这样才能保证服务器最大的安全. 下面是CentOS服务器安全设置,供大家参考. 一、注释掉系统不需要的用户和用户组. 注意:不建议直接删除,当你需要某个用户时,自己重新添加会很麻烦.

CentOS 7 网卡bond - 简书

- -
/etc/sysconfig/network-scripts/目录,修改ifcfg-em1和ifcfg-em2网口配置文件. 其中NAME与DEVICE修改成对应的网卡,随后创建bond网卡文件. ifcfg-bond0,内容如下:. 心跳口bond如法炮制,完成后重启network服务. systemctl restart network,发现无法正常重启,查看日志.

玩转 FFmpeg 的 7 个小技巧

- mk - OSMSG
FFmpeg堪称音频和视频应用程序的瑞士军刀,提供了丰富的选项和灵活性.很多时候用户为了看视频和听音乐都安装了ffmeg.更多关于ffmeg的详细介绍:here,可以通过ffmpeg -formats查看FFmpeg支持的视音频格式,左侧若是E表明可以编码,D表明可以解码. 本文着重介绍命令行下ffmeg的7个技巧:.