2013-12-11 143 views
15

我想創建一個android應用程序,它可以找到一個視頻文件(它超過300 MB)並將其壓縮到較小的mp4文件。使用FFMPEG和JNI壓縮視頻

我已經嘗試過用this

你既然壓縮小尺寸的視頻(以下超過100 MB)

所以我試圖使用JNI來實現它本教程是一個非常有效的做到這一點。

我管理使用this

,但目前我想要做的是壓縮視頻打造的ffmpeg。我對JNI沒有很好的瞭解。但是,我嘗試使用以下link

去了解它。如果有人能指導我壓縮使用JNI它打開的文件,真正對子級很好,謝謝

+0

你說這個教程對於小尺寸視頻非常有效。那麼當您對大視頻採取同樣的措施時,是否還有任何問題? –

+0

@AndroSelva是的,其實它的設備導向 –

回答

6

假設你已經得到的字符串路徑後,視頻的步驟輸入文件,我們可以很容易地完成你的任務。我假設你已經理解了NDK的基礎知識:如何在相應的.java文件中將本地.c文件連接到native方法(讓我知道這是否是你問題的一部分)。相反,我會專注於如何在Android/JNI的上下文中使用FFmpeg。

高度概括:

#include <jni.h> 
#include <android/log.h> 
#include <string.h> 
#include "libavcodec/avcodec.h" 
#include "libavformat/avformat.h" 

#define LOG_TAG "FFmpegWrapper" 
#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 Java_com_example_yourapp_yourJavaClass_compressFile(JNIEnv *env, jobject obj, jstring jInputPath, jstring jInputFormat, jstring jOutputPath, jstring JOutputFormat){ 
    // One-time FFmpeg initialization 
    av_register_all(); 
    avformat_network_init(); 
    avcodec_register_all(); 

    const char* inputPath = (*env)->GetStringUTFChars(env, jInputPath, NULL); 
    const char* outputPath = (*env)->GetStringUTFChars(env, jOutputPath, NULL); 
    // format names are hints. See available options on your host machine via $ ffmpeg -formats 
    const char* inputFormat = (*env)->GetStringUTFChars(env, jInputFormat, NULL); 
    const char* outputFormat = (*env)->GetStringUTFChars(env, jOutputFormat, NULL); 

    AVFormatContext *outputFormatContext = avFormatContextForOutputPath(outputPath, outputFormat); 
    AVFormatContext *inputFormatContext = avFormatContextForInputPath(inputPath, inputFormat /* not necessary since file can be inspected */); 

    copyAVFormatContext(&outputFormatContext, &inputFormatContext); 
    // Modify outputFormatContext->codec parameters per your liking 
    // See http://ffmpeg.org/doxygen/trunk/structAVCodecContext.html 

    int result = openFileForWriting(outputFormatContext, outputPath); 
    if(result < 0){ 
     LOGE("openFileForWriting error: %d", result); 
    } 

    writeFileHeader(outputFormatContext); 

    // Copy input to output frame by frame 
    AVPacket *inputPacket; 
    inputPacket = av_malloc(sizeof(AVPacket)); 

    int continueRecording = 1; 
    int avReadResult = 0; 
    int writeFrameResult = 0; 
    int frameCount = 0; 
    while(continueRecording == 1){ 
     avReadResult = av_read_frame(inputFormatContext, inputPacket); 
     frameCount++; 
     if(avReadResult != 0){ 
     if (avReadResult != AVERROR_EOF) { 
      LOGE("av_read_frame error: %s", stringForAVErrorNumber(avReadResult)); 
     }else{ 
      LOGI("End of input file"); 
     } 
     continueRecording = 0; 
     } 

     AVStream *outStream = outputFormatContext->streams[inputPacket->stream_index]; 
     writeFrameResult = av_interleaved_write_frame(outputFormatContext, inputPacket); 
     if(writeFrameResult < 0){ 
      LOGE("av_interleaved_write_frame error: %s", stringForAVErrorNumber(avReadResult)); 
     } 
    } 

    // Finalize the output file 
    int writeTrailerResult = writeFileTrailer(outputFormatContext); 
    if(writeTrailerResult < 0){ 
     LOGE("av_write_trailer error: %s", stringForAVErrorNumber(writeTrailerResult)); 
    } 
    LOGI("Wrote trailer"); 
} 

對於所有auxillary功能的全部內容(那些在駝峯),見Github我的全部項目。有問題嗎?我很樂意詳細說明。

+0

我會嘗試一下,讓你知道,你可以給我你的郵件地址, –

+0

我已經從GIT下載你的示例應用程序,但它似乎只適用於Android 4.4 –

+0

作爲你說我知道「如何將原生.c文件連接到相應的.java文件中的本地方法」我想知道壓縮視頻的本地C代碼,我試圖執行ut Github項目,但它似乎可以在android 4.4上工作 –