`
xiang37
  • 浏览: 429541 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

[续]Java调用DLL视频解帧,并保存第一关键帧到JPG格式文件

 
阅读更多

本篇文章的前一篇是采用FFmpeg解帧,并保持到JPG格式文件,其中使用了main函数对视频进行了解帧,本篇将针对Java如何调用来实现解帧并输出到文件。

 

一、使用VS2010将其改为Dll输出时,需要改变以下项目属性设置:

1、常规设置

 

2、库目录设置


 

3、预编译头设置



 

4、预处理设置


 

_INTEL
WIN32
_DEBUG
_CONSOLE
_Windows
_CRT_SECURE_NO_DEPRECATE

 
  二、基于上篇文章代码我们添加如下函数声明以及实现

 

 

 

_declspec(dllexport) int findFKeyFrame(char *videoFilePath, char *frameFile);

int findFKeyFrame(char *videoFilePath, char *frameFile)
{
	AVFormatContext *pFormatCtx = NULL;
	int             i,videoStream;
	AVCodecContext  *pCodecCtx;
	AVCodec         *pCodec;
	AVFrame         *pFrame;
	AVFrame         *pFrameRGB;
	int             numBytes;
	uint8_t         *buffer;
	AVPacket        packet;
	int             frameFinished;
	struct SwsContext *img_convert_ctx = NULL;

	av_register_all();
	
	// 检查参数以及视频能否解码
	if(avformat_open_input(&pFormatCtx, videoFilePath, NULL, NULL)!=0)
	{
		printf("can not open");
		return -1;
	}

	if(avformat_find_stream_info(pFormatCtx, NULL) < 0)
	{
		printf("can not find");
		return -1;
	}

	av_dump_format(pFormatCtx, -1, videoFilePath, 0);

	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 )
	{
		printf("not find videoStream");
		return -1;
	}

	pCodecCtx = pFormatCtx->streams[videoStream]->codec;

	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if ( pCodec == NULL )
	{
		return -1;
	}

	if( avcodec_open2(pCodecCtx, pCodec, NULL) < 0 )
	{
		return -1;
	}

	pFrame = av_frame_alloc();
	if( pFrame == NULL )
	{
		return -1;
	}

	pFrameRGB = av_frame_alloc();
	if( pFrameRGB == NULL )
	{
		return -1;
	}

	// 根据视频宽高设置帧大小
	numBytes = avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width, pCodecCtx->height);
	buffer = av_malloc(numBytes);
	avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
	
	img_convert_ctx = sws_getCachedContext(img_convert_ctx, pCodecCtx->width, pCodecCtx->height,
		pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_BICUBIC, NULL, NULL, NULL);

	i = 0;
	while( av_read_frame(pFormatCtx, &packet) >= 0 )
	{
		if( packet.stream_index == videoStream )
		{
			avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
			if ( frameFinished && pFrame->key_frame)
			{
				
				if (!img_convert_ctx )
				{
					fprintf(stderr, "Cannot initialize sws conversion context\n");
					exit(1);
				}

				sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
					pFrameRGB->data, pFrameRGB->linesize);

				if(i++<1)
				{
					saveFrameJpg(pFrameRGB->data[0],frameFile, i, pCodecCtx->width, pCodecCtx->height);
				}
			}
		}
		if(i > 5)
		{
			break;
		}
	}

	av_free_packet(&packet);
	
	av_free(buffer);
	av_free(pFrame);
	av_free(pFrameRGB);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);

	return 1;
}

 

 

编译项目,生成DLL,并拷贝其到Java调用类目录下。

 

三、编写Java代码调用DLL

       Java调用dll,肯定会用到JNI,但是此处使用比较常用地JNA框架来调用。JNA相关链接

       可从test包可以查看怎么使用指针类Pointer等等

      

       JNA代码实现如下:

package com.xiva.test.pic;

import java.io.UnsupportedEncodingException;

import com.sun.jna.Library;
import com.sun.jna.Memory;
import com.sun.jna.Native;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;

/**
 * 
 * <调用DLL读取视频的第一关键帧,并以JPG格式输出到文件>
 * @author xiva
 * @version [1.0, 2014-5-15]
 * @see [相关类/方法]
 * @since [产品、模块版本]
 */
public class ReadVideoKeyFrame
{
 
    public interface VideoDecoder extends Library {
        /**
         * 当前路径是在项目下,而不是bin输出目录下。
         */
        VideoDecoder INSTANCE = (VideoDecoder) Native.loadLibrary("VideoDecoder", VideoDecoder.class);

        public NativeLong findFKeyFrame(Pointer videoFilePath, Pointer frameFile);

    }
    
    public static void main(String[] args) throws UnsupportedEncodingException
    {
        final String ENCODING = "utf8";
        String fileName = "E:\\frame01.jpg";
        String path = "E:\\zookeeper.avi";
        
        Pointer videoFilePath =  new Memory(path.getBytes(ENCODING).length+1);
        Pointer frameFile =  new Memory(fileName.getBytes(ENCODING).length+1);
        
        videoFilePath.setString(0, path);
        frameFile.setString(0, fileName);
        
        NativeLong ret = VideoDecoder.INSTANCE.findFKeyFrame(videoFilePath, frameFile);
        System.out.println(ret);
    }
    
}

 

运行程序,可以看到解帧成功。



 

同样此处还是未解决如何集成其他地解码器,毕竟ffmpeg地解码能力有限;需要后续再次扩展。

 

 

  • 大小: 175.5 KB
  • 大小: 119 KB
  • 大小: 51.9 KB
  • 大小: 104 KB
  • 大小: 22.3 KB
分享到:
评论

相关推荐

    Java调用动态链接库(Java 调用 DLL)

    Java调用动态链接库(DLL)是Java编程中一个比较特殊的技术,主要涉及到Java与本地代码的交互。在Windows系统中,DLL(Dynamic Link Library)是实现函数复用的一种方式,它包含了一系列可供其他程序调用的函数或数据...

    Java调用DLL源代码

    Java调用DLL是Java开发中一个重要的技术主题,它允许Java程序与本地操作系统API或者其他C/C++编写的动态链接库进行交互。在Java中,有多种方法可以实现这个功能,其中最常用的是Java Native Interface (JNA) 和 ...

    Java调用Qt DLL

    Java调用Qt DLL是一个跨平台的技术实践,涉及到Java与C++之间的互操作性,其中Qt是一个流行的C++库,主要用于图形用户界面开发。这个主题主要包含以下几个知识点: 1. **JNI(Java Native Interface)**:JNI是Java...

    Java调用dll文件开源组件jar包及说明文档

    `JNative-1.3.2`是一个开源组件,专门设计用于帮助Java应用程序调用Windows平台上的DLL(动态链接库)文件,同时也支持Linux平台下的SO(共享对象)文件。下面我们将详细介绍这个组件的使用方法、工作原理及相关知识...

    非常好用java调用c++ dll文件demo

    Java调用C++ DLL文件是跨语言编程中的一个重要应用场景,特别是在既有Java代码库又有C++动态链接库的情况下。本文将详细讲解如何在Java程序中调用C++编写的DLL文件,以及一个可用的示例。 首先,理解Java与C++交互...

    JAVA调用C#写的DLL例子

    在 JAVA 中,我们可以使用 System.LoadLibrary 方法来加载我们的 DLL 文件,并使用 System.Runtime.InteropServices.DllImportAttribute 属性来调用我们的 DLL 文件。 public class Main { public native String ...

    Java调用dll实现des加密解密

    在IT行业中,有时我们需要在Java程序中使用非Java编写的库,例如DLL(动态链接库)文件,这在Windows环境中非常常见。本话题主要聚焦于如何在Java中调用DLL来实现DES(Data Encryption Standard)加密和解密操作。...

    Java调用Labview生成的DLL文件

    1、Labview生成Dll文件 2、Java通过Jnative第三方Jar包调用Labview生成的DLL文件 3、Java在Windows系统调用Labview生成的Dll的说明 有JNative的使用说明 直接下载,根据使用说明可以直接使用。

    在Java程序中使用JNative调用dll文件

    在Java程序中调用DLL(动态链接库)文件通常是通过JNI(Java Native Interface)来实现的,而JNative是JNI的一个封装库,它提供了一种更简洁的方式来调用C/C++编写的本地代码。这篇博客文章可能介绍了如何利用...

    java调用DLL:JNative

    假设我们需要编写一个Java程序,该程序调用名为`TestAppSvr.dll`的DLL文件中的`TestConnect()`函数来检测某个应用服务器的状态。`TestConnect()`函数接受三个参数:服务器IP地址、端口号以及是否启用数据压缩,并...

    java调用dll最简单的方法

    在Java中调用DLL(Dynamic Link Library)文件,可以使用Java的本地方法接口(JNI,Java Native Interface)来实现。JNI允许Java程序与本地代码进行交互,从而实现跨平台的功能。

    Java调用DLL例子

    Java本身并不直接支持DLL调用,但通过一些第三方库,我们可以实现这样的功能。本示例以"Java调用DLL例子"为主题,使用了JNative库作为接口来实现Java调用本地动态链接库。 JNative是一个开源的Java库,它提供了一种...

    [测试通过]JAVA调用第三方DLL的简单方法:JNA及DEMO

    在IT行业中,有时我们需要在Java程序中调用第三方的DLL(动态链接库)文件,这通常是C或C++编写的库。Java Native Access (JNA) 是一个流行的开源框架,它允许Java代码直接调用本机库函数,而无需编写JNI(Java ...

    java调用dll实现键盘的屏蔽

    Java本身不直接支持加载和调用本地库(如DLL),但是可以通过第三方库来实现。 描述中的“导入jna.jar将MaskKey.dll放到主目录下。执行zyl.java就可以了。”说明了实现这一功能的具体步骤: 1. **jna.jar**:Java ...

    java用JNA调用dll实例,包含各种参数调用

    你需要定义一个接口,该接口的每个方法对应DLL中的一个函数,然后使用`NativeLibrary`类加载DLL,并将接口实例化,这样就可以在Java中直接调用DLL函数了。 1. **基本数据类型**:JNA支持Java的基本数据类型如int、...

    java使用OpenCV从视频文件中获取帧

    因此,在使用Java和OpenCV从视频文件中获取帧时,需要确保视频文件格式正确并且ffmpeg已安装正确。 Java使用OpenCV从视频文件中获取帧是一个非常有用的技术,它可以应用于很多领域,例如视频监控、图像识别、视频...

    java dll文件调用的几种方式

    Java DLL文件调用是将Java程序与本地C/C++库集成的关键步骤,这对于利用Java的跨平台特性同时利用原生库的功能至关重要。在Java中,我们通常使用Java Native Interface (JNI)来实现对DLL文件的调用。下面将详细介绍...

    用java程序调用ffmpeg执行视频文件格式转换flv

    在本文中,我们将深入探讨如何使用Java程序调用FFmpeg执行视频文件格式转换,特别是将非FFmpeg原生支持的格式转换为FLV格式。FFmpeg是一个强大的多媒体处理工具,支持多种视频、音频格式的编码、解码和转换。在这个...

    java调用dll

    本文将基于提供的“java调用dll实例代码”,深入探讨如何在Java中集成DLL,包括关键步骤、涉及技术以及具体实现细节。 #### 核心概念:JNI与DLL - **JNI(Java Native Interface)**:是Java平台标准的一部分,它...

Global site tag (gtag.js) - Google Analytics