利用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方法,传入当前的视频帧。
希望能帮到各位。。。