关键帧切割视频

3 篇文章 0 订阅
#include <jni.h>
#include <android/log.h>
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/avutil.h"
#include "libavutil/rational.h"
#include "libavutil/mathematics.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/mem.h"
#include "libavutil/fifo.h"
#include "libavdevice/avdevice.h"

#define LO
#define ERRCODE(a) (-10000-a)
static int rv;
static int split(const char* filepath,const char* outpath,int begin/*seconds*/,int end/*seconds*/);

#define TAG    "myhello-jni-test" // 这个是自定义的LOG的标识
#define LOGD(...)  {__android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__) // 定义LOGD类型

JNIEXPORT void JNICALL Java_com_yiche_lecargemproj_VideoEditActivity_setModify (JNIEnv *env, jobject thiz,jint a,jint b, jstring origin,jstring end)
{
   //剪辑视频
	int ret;
	const char* strin;
	const char* strout;

        strin = (*env)->GetStringUTFChars(env,origin,NULL);
	if(strin == NULL) {
		return; /* OutOfMemoryError already thrown */
	}

        strout = (*env)->GetStringUTFChars(env,end,NULL);
	if(strout == NULL) {
		return; /* OutOfMemoryError already thrown */
	}
        //LOGD("outfile = %s",strout);

	ret = split(strin,strout,(int)a,(int)b);
        //LOGD("return value = %d",ret);
        rv = (ret == 0)?1:0;
	
        (*env)->ReleaseStringUTFChars(env,origin, strin);
        (*env)->ReleaseStringUTFChars(env,end, strout);
}

JNIEXPORT jint JNICALL Java_com_yiche_lecargemproj_VideoEditActivity_getResult(JNIEnv *env, jobject thiz)
{
   //视频编辑完成后返回状态,1:成功,0:失败

        return (jint)rv;
}


int split(const char* filepath,const char* outpath,int begin/*seconds*/,int end/*seconds*/)
{
    AVFormatContext* ifmtctx = NULL;
    AVCodecContext* vcdcctx = NULL;
    AVCodecContext* acdcctx = NULL;
    AVCodec* vcdc = NULL;
    AVCodec* acdc = NULL;
    AVFrame* afrm = NULL;
    AVFrame* vfrm = NULL;
    AVPacket pkt;
    AVFormatContext* ofmtctx = NULL;
    AVOutputFormat* ofmt = NULL;
    AVIOContext* ioctx = NULL;
    AVStream* ovStm = NULL;
    AVStream* oaStm = NULL;
    int width;
    int height;
    int fin;
    int vndx;
    int andx;
    int frmrate;
    int start_frmnum;
    int end_frmnum;
    int frm_counter;
    int bsave;
    int rt = 0;


    av_register_all();
    avcodec_register_all();
    //LOGD("infile = %s,outfile = %s,begin = %d,end = %d",filepath,outpath,begin,end);
    //LOGD("avcodec_version = %d",avcodec_version());
    ifmtctx = avformat_alloc_context();
    if(rt = avformat_open_input(&ifmtctx,filepath,NULL,NULL) != 0)
    {
        //LOGD("Couldn't open file : %d(%s)",  rt , buf);
        return rt;
    }
    //LOGD("avformat_open_input");

    if(avformat_find_stream_info(ifmtctx,NULL) < 0)
    {
        return ERRCODE(2);
    }
    //LOGD("avformat_find_stream_info");

    vndx = -1;
    andx = -1;
    int i = 0;
    for(i = 0 ; i < ifmtctx->nb_streams ; i++)
    {
        if(ifmtctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO
            && vndx == -1)
        {
            vndx = i;
        }

        if(ifmtctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO
            && andx == -1)
        {
            andx = i;
        }
    }

    if(vndx != -1)
    {
        vcdcctx = ifmtctx->streams[vndx]->codec;

        vcdc = avcodec_find_decoder(vcdcctx->codec_id);
        if(vcdc == NULL)
        {
            return ERRCODE(3);
        }

        if(avcodec_open2(vcdcctx,vcdc,NULL) != 0)
        {
            return ERRCODE(4);
        }

        vfrm = av_frame_alloc();

        width = vcdcctx->width;
        height = vcdcctx->height;
     }


    if(andx != -1)
    {
        acdcctx = ifmtctx->streams[andx]->codec;

        acdc = avcodec_find_decoder(acdcctx->codec_id);
        if(acdc == NULL)
        {
            return ERRCODE(5);
        }

        if(avcodec_open2(acdcctx,acdc,NULL) != 0)
        {
            return ERRCODE(6);
        }

        afrm = av_frame_alloc();
    }

    frmrate = vcdcctx->framerate.num / vcdcctx->framerate.den;
    start_frmnum = frmrate*begin;
    end_frmnum = frmrate*end;
    frm_counter = 0;
    bsave = -1;
    ofmtctx = avformat_alloc_context();
    ofmt = av_guess_format("mp4",NULL,NULL);
    ofmtctx->oformat = ofmt;



    //add video stream
    ovStm = avformat_new_stream(ofmtctx,0);
    oaStm = avformat_new_stream(ofmtctx,0);
    avcodec_copy_context(ovStm->codec,vcdcctx);
    avcodec_copy_context(oaStm->codec,acdcctx);
/*ovStm->codec->codec_id = vcdcctx->codec_id;
    ovStm->codec->codec_type = vcdcctx->codec_type;
    ovStm->codec->bit_rate = vcdcctx->bit_rate;
    ovStm->codec->time_base = vcdcctx->time_base;
    ovStm->codec->ticks_per_frame = vcdcctx->ticks_per_frame;
    ovStm->codec->pix_fmt = vcdcctx->pix_fmt;
    ovStm->codec->width = vcdcctx->width;
    ovStm->codec->height = vcdcctx->height;
    ovStm->codec->has_b_frames = vcdcctx->has_b_frames;
    oaStm->codec->channel_layout = av_get_default_channel_layout(1);
    oaStm->codec->channels = acdcctx->channels;
    oaStm->codec->bit_rate = acdcctx->bit_rate;
    oaStm->codec->sample_rate = acdcctx->sample_rate;
    oaStm->codec->sample_fmt = acdcctx->sample_fmt;*/
    ovStm->codec->codec_tag = 0;
    oaStm->codec->codec_tag = 0;
    if (ofmtctx->oformat->flags & AVFMT_GLOBALHEADER)
    {
           ovStm->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
           oaStm->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
    }

    if(avio_open2(&ofmtctx->pb,outpath,AVIO_FLAG_WRITE,NULL,NULL) < 0)
    {
        return ERRCODE(7);
    }
    //LOGD("avio_open2");

    avformat_write_header(ofmtctx,NULL);
    //LOGD("avformat_write_header");
    av_init_packet(&pkt);
    pkt.data = NULL;
    pkt.size = 0;

    while(av_read_frame(ifmtctx,&pkt) >= 0)
    {
        if(pkt.stream_index == vndx)
        {
            if((frm_counter >= start_frmnum) && (pkt.flags & AV_PKT_FLAG_KEY) && (bsave == -1))
            {
                bsave = 1;
            }

            if(frm_counter > end_frmnum)
            {
                bsave = 2;
                goto quit;
            }

            frm_counter++;
        }

        if(bsave == 1)
        {
            AVStream *in_stream = ifmtctx->streams[pkt.stream_index];
            AVStream *out_stream = ofmtctx->streams[pkt.stream_index];
            pkt.pts = av_rescale_q_rnd(pkt.pts , in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF );
            pkt.dts = av_rescale_q_rnd(pkt.dts , in_stream->time_base, out_stream->time_base, AV_ROUND_NEAR_INF );
            pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
            pkt.pos = -1;
            av_write_frame(ofmtctx,&pkt);
            //LOGD("av_write_frame,frame num = %d",frm_counter);
        }

        av_free_packet(&pkt);
    }

quit:
    av_write_trailer(ofmtctx);
    //LOGD("av_write_trailer");

    av_free(vfrm);
    av_free(afrm);
    avcodec_close(vcdcctx);
    avcodec_close(acdcctx);
    avformat_close_input(&ifmtctx);

    return 0;
}
安卓makefile:
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)


include $(CLEAR_VARS)
PATH_TO_FFMPEG_SOURCE:=$(LOCAL_PATH)/ffmpeg
LOCAL_C_INCLUDES += /home/a/android-ndk-r9/sources/ffmpeg-2.6.2/include/
LOCAL_SHARED_LIBRARIES := libavformat libavcodec libavutil libswscale libswresample libc libz
LOCAL_LDLIBS :=-llog 
LOCAL_MODULE    := video
LOCAL_SRC_FILES := video.c


include $(BUILD_SHARED_LIBRARY)
$(call import-module,ffmpeg-2.6.2/android/arm)


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值