关闭

Android_调用ffmpeg_把截取视频保存为ppm文件

791人阅读 评论(0) 收藏 举报
分类:

 

ppm文件是一种图像文件,有其自己的文件格式。
ppm文件由两个部分组成:第一个部分是三行ASCII码,这个部分决定了图像的存储
格式以及图像的特征;第二个部分就是图像的数据部分,图像就是由这个部分组成的。

ppm的第一部分由三行ASCII码组成
第一行是P2/P3/P6
第二行是图像的大小,先是列像素数,后是行像素数,中间有一个空格
第三行是一个介于1和65535之间的整数,而且必须是文本的,用来表示每一个像素
的一个分量用几个比特表示。

三行之后是图像的数据流,从左到右,从上到下。在进行图像数据存储的时候,需要进行
数据的格式,假如需要的像素值在0~255之间,那么在进行数据文件保存的时候,所写入
文件的值就必须是以%c的形式输入,而且数据之间没有明显的分离字符,图像处理软件会
自动地识别这些像素的值,并给予处理。

 

0A 是换行

 

 

#include <jni.h>
#include <stdio.h>
#include <android/log.h>
#include "com_test_jni_InterfaceForJNI.h"

#include <libavcodec/avcodec.h>
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavutil/avutil.h>
#include <libavutil/mem.h>
#include <libswscale/swscale.h>

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#define  LOG_TAG    "FFMPEG-JNI"
#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

void save_frame(AVFrame *pFrame, int width, int height, int iFrame);

#define VIDEO_PATH "/sdcard/video.mp4"
#define SAVE_FRAME_PATH  "/sdcard/video"

int isDebug = 0;

AVFormatContext *pFormatCtx; //这个结构体描述了一个媒体文件或媒体流的构成和基本信息
AVCodecContext *pCodecCtx; // 这是一个描述编解码器上下文的数据结构,包含了众多编解码器需要的参数信息
AVCodec *pCodec;

void JNICALL Java_com_test_jni_InterfaceForJNI_testJNI(JNIEnv * env,
		jobject obj) {
	LOGI("HELLO JNI");
	LOGI("version = %d", avcodec_version());

	int ret;
	int err;
	int i, videoindex;

	//注册所有的文件格式和编解码器的库,只需要调用一次
	av_register_all();
	LOGE("Registered formats");

	//打开视频文件。这个函数会读取视频文件头部信息并保存在AVFormatContext中
	err = avformat_open_input(&pFormatCtx, VIDEO_PATH, NULL, NULL);
	LOGE("Called open file");
	if (err != 0) {
		LOGE("Couldn't open file");
		return;
	}
	LOGE("Opened file");

	//给每个流的AVStream结构体赋值,其实该函数已经完整走完了解码流程
	if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
		LOGE("Unable to get stream info");
		return;
	}

	videoindex = -1;
	for (i = 0; i < pFormatCtx->nb_streams; i++)
		if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
			videoindex = i;
			break;
		}
	if (videoindex == -1) {
		LOGE("Didn't find a video stream!");
		return;
	}
	LOGE("find stream info!");

	//初始化编解码信息
	pCodecCtx = pFormatCtx->streams[videoindex]->codec;

	//根据编解码信息查找解码器
	pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
	if (pCodec == NULL) {
		LOGE("Could not found codec!");
		return;
	}
	LOGE("find codec!");

	//打开解码器
	if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
		LOGE("Could not open codec!");
		return;
	}
	LOGE("codec the video ok!");

	//如果参数为1,会报  Fatal signal 11 错误
	//av_dump_format(pFormatCtx, 0, VIDEO_PATH, 0);

	AVFrame *pFrame, *pFrameRGB;
	struct SwsContext *pSwsCtx;
	AVPacket packet;
	int pictureSize;
	int frameFinished;
	uint8_t *buf;

	pFrame = av_frame_alloc(); //为该帧图像分配内存 avcodec_alloc_frame 废弃
	pFrameRGB = av_frame_alloc(); //为该帧图像分配内存
	pictureSize = avpicture_get_size(PIX_FMT_BGR24, pCodecCtx->width,
			pCodecCtx->height);
	buf = (uint8_t*) av_malloc(pictureSize);

	LOGE("pictureSize: %d\n", pictureSize);

	//已经分配的空间的结构体AVPicture挂上一段用于保存数据的空间
	avpicture_fill((AVPicture *) pFrameRGB, buf, PIX_FMT_BGR24,
			pCodecCtx->width, pCodecCtx->height);

	//设置图像转换上下文
	pSwsCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
			pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
			PIX_FMT_BGR24, SWS_BICUBIC, NULL, NULL, NULL);

	i = 0;
	int flag = 0;
	//av_read_frame,读取码流中的音频若干帧或者视频一帧
	while (av_read_frame(pFormatCtx, &packet) >= 0 && flag < 2) {
		if (packet.stream_index == videoindex) {
			//的作用是解码一帧视频数据。输入一个压缩编码的结构体AVPacket,输出一个解码后的结构体AVFrame。该函数的声明位于libavcodec\avcodec.h
			avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
			LOGE("decode one frame: %d", frameFinished);

			//为0说明没有找到可以解压的帧
			if (frameFinished) {
				flag++;
				//将yuv格式转换为RGB32
				sws_scale(pSwsCtx, (const uint8_t* const *) pFrame->data,
						pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,
						pFrameRGB->linesize);
				//保存该帧图片为PPM格式
				save_frame(pFrameRGB, pCodecCtx->width, pCodecCtx->height, i);
			}
		}
		av_free_packet(&packet);
	}
	LOGE("decode finished!");
	sws_freeContext(pSwsCtx);
	av_free(pFrame);
	av_free(pFrameRGB);
	avcodec_close(pCodecCtx);
	avformat_close_input(&pFormatCtx);

}

void save_frame(AVFrame *pFrame, int width, int height, int iFrame) {
	FILE *pFile;
	char szFilename[32];
	int y;
	// Open file
	sprintf(szFilename, "%s/frame%d.ppm", SAVE_FRAME_PATH, iFrame);
	pFile = fopen(szFilename, "wb");
	if (pFile == NULL)
		return;
	// Write header
	fprintf(pFile, "P6\n%d %d\n255\n", width, height);
	// Write pixel data
	for (y = 0; y < height; y++)
		fwrite(pFrame->data[0] + y * pFrame->linesize[0], 1, width * 3, pFile);
	// Close file
	fclose(pFile);
}


 

 

 

 

 

 

 

 

 

 

0
0
查看评论

使用FFmpeg4android 实现视频 水印 剪切 压缩 旋转

翻看了一下自己的上一篇博客,7月5号写的......,瞬间不高兴了,写博客贵在坚持,而自己在这段时间确松懈下来了,实在不应该呀!罪过罪过! 最近这一段时间内,公司的项目迭代更新需要添加新的功能包括:视频的录制和压缩上传等....,这些功能中 视频压缩上传不是很好解决。大概花了我一周左右的时间去研究和...
  • wning1
  • wning1
  • 2016-07-25 23:42
  • 3121

ffmpeg截取一段视频中一段视频

ffmpeg  -i ./plutopr.mp4 -vcodec copy -acodec copy -ss 00:00:10 -to 00:00:15 ./cutout1.mp4 -y -ss time_off      &#...
  • u010095768
  • u010095768
  • 2015-06-27 18:31
  • 17436

ffmpg简介以及用它实现音频视频合并(java)

FFmpeg实现音视频文件合并    1.简介 FFmpeg是一个自由软件,可以运行音频和视频多种格式的录影、转档、流功能。     2.下载 源代码 git://git.libav.org/libav.git Windows编译版 http://ffm...
  • jinzheng069
  • jinzheng069
  • 2013-07-05 16:51
  • 5002

[Android]从视频流读取帧图像保存到本地

从视频流读取帧图像保存到本地在进行全景视频播放器开发的时候,遇到在不同的播放设备上颜色不一致的情况,故进行Debug。 首先想到的是,在不同的硬件平台上解码得到的视频帧数据是否有问题,故写了一个测试方法用于从视频流数据读取一帧保存到本地文件夹中。下面开始建立这样一个工程 新建New Projec...
  • zsytony
  • zsytony
  • 2016-04-07 21:09
  • 3607

NDK编译的最新ffmpeg,支持RTSP流

  • 2014-03-18 18:23
  • 3.15MB
  • 下载

Android 下FFmpeg打包so教程,2016年11月最新

1,准备工作 系统:ubuntu 下载地址:https://www.ubuntu.com/download Ndk : 本教程使用android-ndk-r12b 下载地址:http://www.androiddevtools.cn/ FFmpeg 下载地址http://ffmpeg.o...
  • zhaoyu813113552
  • zhaoyu813113552
  • 2016-10-27 10:47
  • 1604

利用FFmpeg玩转Android视频录制与压缩(一)

Android下利用FFmpeg玩转视频录制与压缩(一) 说明: 本库暂时是在秒拍开源库上做的二次开发,旨在开发简单好用高效的视频录制库。本篇文档只涉及Java层次逻辑,正在业余修炼c语言与JNI相关的东西,如果有幸写第二篇文章,那时将对其做更深入的剖析,如FFmpeg编译、JNI相关代码编写。...
  • mabeijianxi
  • mabeijianxi
  • 2017-03-19 00:02
  • 23531

Android_调用ffmpeg_把截取视频保存为ppm文件

ppm文件是一种图像文件,有其自己的文件格式。 ppm文件由两个部分组成:第一个部分是三行ASCII码,这个部分决定了图像的存储 格式以及图像的特征;第二个部分就是图像的数据部分,图像就是由这个部分组成的。 ppm的第一部分由三行ASCII码组成 第一行是P2/P3/P6 第二行是图像的大小,先...
  • u012587637
  • u012587637
  • 2015-07-10 11:19
  • 791

利用ffmpeg截取视频图像并保存为ppm和jpg图片格式

直接贴出代码:
  • rootusers
  • rootusers
  • 2014-11-12 09:25
  • 26448

ffmpeg将视频每帧画面保存为PPM格式图片,使用最新的ffmpeg官网15-7-2日更新的版本

1、注册所有文件格式和解码器 av_register_all(); 2、读取输入文件头,设置null自动检测格式 avformat_open_input(&pFormatCtx,argv[1], NULL,NULL) ; 3、获取流信息 avformat_find_stream_info(p...
  • shusexiaoniao
  • shusexiaoniao
  • 2015-07-13 11:36
  • 1160
    个人资料
    • 访问:316457次
    • 积分:4984
    • 等级:
    • 排名:第6751名
    • 原创:150篇
    • 转载:265篇
    • 译文:1篇
    • 评论:18条
    文章分类
    最新评论