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

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

标准。

进行检索 找到xuggler官方主页:http://www.xuggle.com/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;

}

}

java 音频解码_java视频音频解码-封装xuggle-实现多种视频编码格式解码扩展相关推荐

  1. 视频编解码的理论和实践2:Ffmpeg视频编解码

    近几年,视频编解码技术在理论及应用方面都取得了重大的进展,越来越多的人想要了解编解码技术.因此,网易云信研发工程师为大家进行了归纳梳理,从理论及实践两个方面简单介绍视频编解码技术. 相关阅读推荐 &l ...

  2. java音频剪切_Java使用IO流实现音频的剪切和拼接

    需求:使用IO流将指定目录下的若干个音频文件的高潮部分,进行剪切,并重新拼接成一首新的音频文件 思路(以两首歌为例): 第一首歌有一个输入流对象bis1.第二首歌有一个输入流对象bis2,他们公用一条 ...

  3. java 音频格式_java – 音频格式的转换

    我在转换WAV文件的音频格式时遇到了麻烦. 我正在录制麦克风的声音,声音按以下格式录制: PCM_SIGNED 44100.0 Hz,16位,单声道,2字节/帧 我想将上面的格式转换为 ULAW 80 ...

  4. java音频教程_Java如何使用IO流实现音频的剪切和拼接的示例代码

    这篇文章主要为大家详细介绍了Java使用IO流实现音频的剪切和拼接,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 需求:使用IO流将指定目录下的若干个音频文件的高潮部分,进行剪切,并重新拼接成一首 ...

  5. java 音频对比_java – 比较两个不同的音频文件不起作用

    我想比较两个音频文件,例如mp3和wav.我使用 musicg来比较指纹. Wave record1 = new Wave(music1.toString()); Wave record2 = new ...

  6. java音频剪辑_Java混剪音频

    分享一个之前看过的程序,可以用来剪辑特定长度的音频,将它们混剪在一起,思路如下: 1.使用 FileInputStream 输入两个音频 2.使用 FileInputStream的skip(long ...

  7. java 音频 合成_java 音频 合成

    /** * 将两个wav音频文件合并成一个音频文件  * * @param srcFile1 *            源文件1 * @param srcFile2 *            源文件2 ...

  8. java 音频转换_java实现音频转换

    这里需要用到第三方 ffmpeg.exe package com.convertaudio; import java.io.File; import java.util.ArrayList; impo ...

  9. java音频压缩_java 压缩mp3 比特率

    下载:Xuggle_study(含xuggle jar).rar http://download.csdn.net/detail/shuzheng5201314/8711543 用.zip打开jar完 ...

最新文章

  1. OpenCv3 VideoCapture读取视频失败解决方法
  2. 数据库的日常管理经验浅谈
  3. 工作109:控制mode跳转
  4. docker集群理解
  5. ArcGIS制图技巧系列(1)还原真实的植被
  6. Linux下mail/mailx命令发送邮件
  7. Charles使用最全指南
  8. 信用卡分期年化利率计算方法
  9. 版本控制工具svn和git
  10. (Excel)如何使用Excel进行四舍六入数据修约
  11. 【群晖Nas开启WebDAV服务,路由器映射端口,实现Win10远程映射网路驱动器】
  12. 10个经典的公开数据集+免费下载链接
  13. Django模板渲染错误
  14. 粒子群优化能做相机标定吗
  15. 6360. 【NOIP2019模拟2019.9.18】最大菱形和(rhombus)
  16. linux 查看磁盘寿命,如何确定Linux下SSD的写周期数或预期寿命?
  17. 面向Python开发人员的综合置信区间全面理解
  18. 目标检测之五:随机权值平均(Stochastic Weight Averaging,SWA)---木有看懂
  19. extmail mysql数据库 重启_extmail数据库dspam表修复
  20. redhat linux 9.0 拷贝u盘的文件,Linux redhat 9.0 中挂载U盘的方法!

热门文章

  1. C#网页设计 - Web控件
  2. 影视动画制作中的后期渲染是什么意思?
  3. 数字图像处理学习笔记(七)——用Pycharm及MATLAB实现三种图像内插法(最近邻内插法、双线性内插法、双三次内插法)
  4. AutoCAD Civil 3D-创建道路模型(1 道路三要素)
  5. 前端开发者常用的构建工具
  6. SIP软交换相关介绍
  7. Ocelot(二)- 请求聚合
  8. Java+SSM+Jsp+Mysql实现Web汽车信息管理系统
  9. cadence SPB17.4 - add new custom title block
  10. 【专访】新奥“贫穷”贵公子王子峥