博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java视频音频解码-封装xuggle-实现多种视频编码格式解码扩展
阅读量:4319 次
发布时间:2019-06-06

本文共 9751 字,大约阅读时间需要 32 分钟。

    手头做一个视频相关项目,但是客户发来的测试视频(avi格式) 现有组件不能解码。现有

视频解码组件方案有基于JMF和opencv Jni调用。远远不能满足目前市面上玲琅满目的各种视频编码

标准。

    进行检索 找到xuggler官方主页:  对5.4版本进行简单封装,实现现有组件接口。需要slf4j包支持。实现了从现有组件只能支持摄像头和特定编码AVI文件到多种编码格式视频解码的支持。

    经过测试至少支持 flv mov avi mpg wmv mp4 mkv 这些格式的视频解码。

实现代码如下:  

package edu.zjut.framecollector;import java.awt.image.BufferedImage;import java.io.File;import javax.media.ControllerEvent;import javax.media.ControllerListener;import javax.swing.JFileChooser;import com.xuggle.xuggler.Global;import com.xuggle.xuggler.ICodec;import com.xuggle.xuggler.IContainer;import com.xuggle.xuggler.IPacket;import com.xuggle.xuggler.IPixelFormat;import com.xuggle.xuggler.IStream;import com.xuggle.xuggler.IStreamCoder;import com.xuggle.xuggler.IVideoPicture;import com.xuggle.xuggler.IVideoResampler;import com.xuggle.xuggler.Utils;/** * @author 田旭园 E-mail: tianxuyuan@yahoo.com.cn * @version 1.0 创建时间:2012-8-14 下午07:11:02 * @说明 AVI视频采集 解码 可对多种格式音频视频进行解码编码 http://blog.xuggle.com/ * @说明 JMF和opencv对各种视频编码格式的 不给力 学习AVIFrameCollector.java,进行对xuggler简单封装使用 * @说明 不需要有安装JMF 但是需要导入xuggle-xuggler-5.4.jar 和 slf4j库 */public class AVIFrameCollectorOnXuggle extends FrameCollector implements		ControllerListener {	private int step = 1;	IContainer container = null;	IStreamCoder videoCoder = null;	IPacket packet;	long firstTimestampInStream = Global.NO_PTS;	long systemClockStartTime = 0;	int videoStreamId = -1;	String filename;	IVideoResampler resampler = null;	@Override	public void close() {		if (videoCoder != null) {			videoCoder.close();			videoCoder = null;		}		if (container != null) {			container.close();			container = null;		}	}	@Override	public BufferedImage getCurrentFrame() {		BufferedImage javaImage = null;		while (container.readNextPacket(packet) >= 0) {			/*			 * Now we have a packet, let's see if it belongs to our video stream			 */			if (packet.getStreamIndex() == videoStreamId) {				/*				 * We allocate a new picture to get the data out of Xuggler				 */				IVideoPicture picture = IVideoPicture.make(videoCoder						.getPixelType(), videoCoder.getWidth(), videoCoder						.getHeight());				int offset = 0;				while (offset < packet.getSize()) {					/*					 * Now, we decode the video, checking for any errors.					 */					int bytesDecoded = videoCoder.decodeVideo(picture, packet,							offset);					if (bytesDecoded < 0)						throw new RuntimeException(								"got error decoding video in: " + filename);					offset += bytesDecoded;					/*					 * Some decoders will consume data in a packet, but will not					 * be able to construct a full video picture yet. Therefore					 * you should always check if you got a complete picture					 * from the decoder					 */					if (picture.isComplete()) {						IVideoPicture newPic = picture;						/*						 * If the resampler is not null, that means we didn't						 * get the video in BGR24 format and need to convert it						 * into BGR24 format.						 */						if (resampler != null) {							// we must resample							newPic = IVideoPicture.make(resampler									.getOutputPixelFormat(),									picture.getWidth(), picture.getHeight());							if (resampler.resample(newPic, picture) < 0)								throw new RuntimeException(										"could not resample video from: "												+ filename);						}						if (newPic.getPixelType() != IPixelFormat.Type.BGR24)							throw new RuntimeException("could not decode video"									+ " as BGR 24 bit data in: " + filename);						/**						 * We could just display the images as quickly as we						 * decode them, but it turns out we can decode a lot						 * faster than you think.						 * 						 * So instead, the following code does a poor-man's						 * version of trying to match up the frame-rate						 * requested for each IVideoPicture with the system						 * clock time on your computer.						 * 						 * Remember that all Xuggler IAudioSamples and						 * IVideoPicture objects always give timestamps in						 * Microseconds, relative to the first decoded item. If						 * instead you used the packet timestamps, they can be						 * in different units depending on your IContainer, and						 * IStream and things can get hairy quickly.						 */						if (firstTimestampInStream == Global.NO_PTS) {							// This is our first time through							firstTimestampInStream = picture.getTimeStamp();							// get the starting clock time so we can hold up							// frames							// until the right time.							systemClockStartTime = System.currentTimeMillis();						} else {							long systemClockCurrentTime = System									.currentTimeMillis();							long millisecondsClockTimeSinceStartofVideo = systemClockCurrentTime									- systemClockStartTime;							// compute how long for this frame since the first							// frame in the							// stream.							// remember that IVideoPicture and IAudioSamples							// timestamps are							// always in MICROSECONDS,							// so we divide by 1000 to get milliseconds.							long millisecondsStreamTimeSinceStartOfVideo = (picture									.getTimeStamp() - firstTimestampInStream) / 1000;							final long millisecondsTolerance = 50; // and we							// give							// ourselfs							// 50 ms of							// tolerance							final long millisecondsToSleep = (millisecondsStreamTimeSinceStartOfVideo - (millisecondsClockTimeSinceStartofVideo + millisecondsTolerance));							if (millisecondsToSleep > 0) {								try {									Thread.sleep(millisecondsToSleep);								} catch (InterruptedException e) {									// we might get this when the user closes									// the dialog box, so									// just return from the method.									return null;								}							}						}						// And finally, convert the BGR24 to an Java buffered						// image						javaImage = Utils.videoPictureToImage(newPic);						return javaImage;					}				}			} else {				/*				 * This packet isn't part of our video stream, so we just				 * silently drop it.				 */				do {				} while (false);			}		}		return javaImage;	}	@Override	public FrameCollectorMode getMode() {		return FrameCollectorMode.AVI_FILE;	}	/**	 * 

* 使用用户定义的连接参数打开AVI视频文件。 *

* * @param fileURL * AVI视频文件的地址 * @param strStep * 指定avi文件的播放速度,即每次跳帧的步进,调用时请注意给定的字符串要可以转换为整型。 1为正常速度,2为两倍速度,.... * @return true,如果成功打开,否则返回false * @since 1.0 */ @Override public boolean open(String fileURL, String strStep) { // fileURL="file:/F:/组件和项目/图像质量诊断工程/vedio/视频文件/亮度1.avi"; // 打开AVI视频文件 if (fileURL == null) { return open(); } if ((fileURL.substring(0, 6)).equals("file:/")) { fileURL = fileURL.substring(6); // System.out.println(" dfsfjasjf "+fileURL); } try { step = Integer.parseInt(strStep); } catch (NumberFormatException ex) { step = 1; } return setupPlayer(fileURL); } /** *

* 通过打开对话框打开指定AVI视频文件。 *

* * @return true,如果成功打开,否则返回false * @since 1.0 */ @Override public boolean open() { // 从文件对话框中选择AVI文件 JFileChooser chooser = new JFileChooser(); chooser.setAcceptAllFileFilterUsed(false); int result = chooser.showOpenDialog(null); if (result == JFileChooser.CANCEL_OPTION) { return false; } File file = chooser.getSelectedFile(); String fileURL = null; try { fileURL = file.getAbsolutePath(); System.out.println(fileURL); } catch (Exception e) { return false; } // 打开AVI视频文件 return setupPlayer(fileURL); } @Override public void controllerUpdate(ControllerEvent arg0) { // TODO Auto-generated method stub } /** *

* Initialize the Player object. *

* * @param fileURL * The selected file's URL * @return true if set up the player successfully, false otherwise */ private boolean setupPlayer(String filename) { this.filename = filename; System.out.println(filename + " =============="); // Let's make sure that we can actually convert video pixel formats. if (!IVideoResampler .isSupported(IVideoResampler.Feature.FEATURE_COLORSPACECONVERSION)) throw new RuntimeException("you must install the GPL version" + " of Xuggler (with IVideoResampler support) for " + "this demo to work"); // Create a Xuggler container object container = IContainer.make(); // Open up the container if (container.open(filename, IContainer.Type.READ, null) < 0) throw new IllegalArgumentException("could not open file: " + filename); // query how many streams the call to open found int numStreams = container.getNumStreams(); // and iterate through the streams to find the first video stream for (int i = 0; i < numStreams; i++) { // Find the stream object IStream stream = container.getStream(i); // Get the pre-configured decoder that can decode this stream; IStreamCoder coder = stream.getStreamCoder(); if (coder.getCodecType() == ICodec.Type.CODEC_TYPE_VIDEO) { videoStreamId = i; videoCoder = coder; break; } } if (videoStreamId == -1) throw new RuntimeException( "could not find video stream in container: " + filename); /* * Now we have found the video stream in this file. Let's open up our * decoder so it can do work. */ if (videoCoder.open() < 0) throw new RuntimeException( "could not open video decoder for container: " + filename); if (videoCoder.getPixelType() != IPixelFormat.Type.BGR24) { // if this stream is not in BGR24, we're going to need to // convert it. The VideoResampler does that for us. resampler = IVideoResampler.make(videoCoder.getWidth(), videoCoder .getHeight(), IPixelFormat.Type.BGR24, videoCoder .getWidth(), videoCoder.getHeight(), videoCoder .getPixelType()); if (resampler == null) throw new RuntimeException("could not create color space " + "resampler for: " + filename); } /* * Now, we start walking through the container looking at each packet. */ packet = IPacket.make(); return true; }}

  

转载于:https://www.cnblogs.com/tianxuyuan/archive/2012/08/14/2638896.html

你可能感兴趣的文章
Linux 防火墙
查看>>
android 自定义图片圆形进度条
查看>>
互联网金融P2P主业务场景自动化测试
查看>>
array_filter函数的应用
查看>>
梅西确定代言 中国首秀牵手Mate 8
查看>>
html,body
查看>>
一个Brushes笔画应用ios源码完整版
查看>>
IOS 网络浅析-(七 JSON解析之三方JSONKit)
查看>>
image的srcset属性
查看>>
vs + Qt 环境下配置QCustomPlot编译不通过
查看>>
simplorer使用 simlink的 svpwm模块
查看>>
j.c.Warnsdorff马踏棋盘算法
查看>>
[C#-SQLite] SQLite一些奇怪的问题
查看>>
Map的遍历
查看>>
VC中常用文件操作(三)
查看>>
C#中WebService 的 Timer定时器过段时间后自动停止运行
查看>>
nginx 配置rewrite
查看>>
hibernate中cache二级缓存问题
查看>>
My third day of OpenCV
查看>>
Java并发计数器探秘
查看>>