利用ffmpeg把一帧原始视频数据转换成jpg格式的图片

利用ffmpeg对一帧原始的视频数据转换成jpg格式的图片,保存到本地,用于Android显示

#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>


extern "C" {
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
#include <libavfilter/avfilter.h>
#include <libavutil/pixfmt.h>
#include <libavcodec/jni.h>
}

extern "C" {

int encodejpg(const char *out_file,AVFrame *picture,AVCodecContext *pVideoCodecCtx);

jint
Java_org_videolan_libvlc_LibVLC_fjpg(JNIEnv *env, jobject obj, jstring input_jstr, jstring save_jstr) {
	const char *file_name = env->GetStringUTFChars(input_jstr, NULL);
	const char *save_name = env->GetStringUTFChars(save_jstr, NULL);
        av_register_all();
        avformat_network_init();
        int videoStream = -1;
        AVFormatContext *pVideoFormatCtx = NULL;
        //pFormatCtx = avformat_alloc_context();
        if (avformat_open_input(&pVideoFormatCtx, file_name, NULL, NULL) != 0) {
        	return -1; // Couldn't open file
        }

        if (avformat_find_stream_info(pVideoFormatCtx, NULL) < 0) {
    	    return -1;
        }
	for (int i = 0; i < pVideoFormatCtx->nb_streams; i++) {
		if (pVideoFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
			videoStream = i;
		}
	}
	AVCodecParameters *pCodecPar = pVideoFormatCtx->streams[videoStream]->codecpar;
	AVCodec *pCodec = avcodec_find_decoder(pCodecPar->codec_id);
	if(pCodec == NULL) return -1;
	AVCodecContext *pVideoCodecCtx = avcodec_alloc_context3(pCodec);
	if (avcodec_parameters_to_context(pVideoCodecCtx, pCodecPar) != 0) {
		return -1;// Error copying codec context
	}
	if (avcodec_open2(pVideoCodecCtx, pCodec, NULL) < 0) {
		return -1; // Could not open codec
	}
	AVFrame *pVideoFrame = av_frame_alloc();
	if (pVideoFrame == NULL) {
		return -1;
	}
	AVPacket packet;
	int bret = -1;
	if (av_read_frame(pVideoFormatCtx, &packet) >= 0) {
		if (packet.stream_index == videoStream) {
			int ret = avcodec_send_packet(pVideoCodecCtx, &packet);
			if (ret < 0) goto end;
			if(avcodec_receive_frame(pVideoCodecCtx, pVideoFrame) == 0) {
				pVideoFrame->quality = 10;
				pVideoFrame->pts = 0;
				bret = encodejpg(save_name,pVideoFrame,pVideoCodecCtx);
			}
		}
		av_packet_unref(&packet);
	}
	end:
	avformat_network_deinit();
	return bret;
}

int encodejpg(const char *out_file,AVFrame *picture,AVCodecContext *pVideoCodecCtx) {
	AVFormatContext* pFormatCtx;
	AVOutputFormat* fmt;
	AVStream* video_st;
	AVCodecContext* pCodecCtx;
	AVCodec* pCodec;

	AVPacket pkt;
	int got_picture=0;
	int ret= -1;
	pFormatCtx = avformat_alloc_context();
	//Guess format
	fmt = av_guess_format("mjpeg", NULL, NULL);
	pFormatCtx->oformat = fmt;
        //Output URL
	if (avio_open(&pFormatCtx->pb,out_file, AVIO_FLAG_READ_WRITE) < 0){
		return -1;
	}
	video_st = avformat_new_stream(pFormatCtx, 0);
	if (video_st==NULL){
		return -1;
	}

	pCodecCtx = video_st->codec;
	pCodecCtx->codec_id = fmt->video_codec;
	pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
	pCodecCtx->pix_fmt = AV_PIX_FMT_YUVJ420P;
	pCodecCtx->time_base.num = 1;
	pCodecCtx->time_base.den = 25;

	//pCodecCtx->bit_rate = 20000;
	//pCodecCtx->bit_rate_tolerance = 4000000;
	pCodecCtx->compression_level = 10;
	pCodecCtx->width = pVideoCodecCtx->width;
	pCodecCtx->height = pVideoCodecCtx->height;
	//Output some information
	//av_dump_format(pFormatCtx, 0, out_file, 1);

	pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
	if (!pCodec){
		return -1;
	}
	if (avcodec_open2(pCodecCtx, pCodec,NULL) < 0){
		return -1;
	}
	
	avformat_write_header(pFormatCtx,NULL);

	int y_size = pCodecCtx->width * pCodecCtx->height;

	av_new_packet(&pkt,y_size*3);//enough size
	
	ret = avcodec_encode_video2(pCodecCtx, &pkt,picture, &got_picture);
	if(ret < 0){
		return -1;
	}
	if (got_picture==1){
		pkt.stream_index = video_st->index;
		ret = av_write_frame(pFormatCtx, &pkt);
	}
	av_free_packet(&pkt);
	//Write Trailer
	av_write_trailer(pFormatCtx);
	if (video_st){
		avcodec_close(video_st->codec);
		av_free(picture);
	}
	avio_close(pFormatCtx->pb);
	avformat_free_context(pFormatCtx);
	return ret;
}
}

本地的视频帧数据转成jpg,或者直接调用encodejpg方法,传入当前的视频帧。

希望能帮到各位。。。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值