2013-12-11 17 views
15

Chcę utworzyć aplikację na Androida, która może zlokalizować plik wideo (powyżej 300 MB) i skompresować go do pliku mp4 o mniejszym rozmiarze.Kompresja wideo za pomocą FFMPEG i JNI

Już próbowałem zrobić to z this

Ten poradnik jest bardzo skuteczne, ponieważ jesteś po kompresji mały Rozmiar wideo (poniżej niż 100 MB)

więc starałem się wdrożyć go przy użyciu JNI.

udało mi się zbudować ffmpeg za pomocą this

Ale obecnie to, co chcę zrobić, to do kompresji wideo. Nie mam bardzo dobrej wiedzy na temat JNI. Ale starałam się go zrozumieć za pomocą poniższej link

Jeśli ktoś może kierować mi kroki do kompresji video po otwartym pliku to przy użyciu JNI że whould naprawdę wielkie dzięki

+0

Mówisz, że samouczek jest bardzo skuteczny w przypadku filmów o małym rozmiarze. Czy istnieje jakiś problem, gdy postępujesz tak samo w przypadku dużych filmów? –

+0

@AndroSelva tak, właściwie zorientowany na urządzenie –

Odpowiedz

6

Zakładając, że masz ścieżkę String plik wejściowy, możemy dość łatwo wykonać twoje zadanie. Zakładam, że rozumiesz podstawy NDK: Jak podłączyć natywny plik .c do metod native w odpowiednim pliku .java (Daj mi znać, jeśli to część twojego pytania). Zamiast tego skupię się na tym, jak używać FFmpeg w kontekście Androida/JNI.

wysokiego szczebla Przegląd:

#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"); 
} 

Dla pełnej treści wszystkich funkcji AUXILLARY (te w CamelCase), patrz mój pełny projekt na Github. Masz pytania? Cieszę się, że mogę to rozwinąć.

+0

Spróbuję i daję znać, możesz wysłać mi adres url, –

+0

Pobrałem Twoją przykładową aplikację z GIT, ale wygląda na to, że działa tylko dla Androida 4.4 –

+0

jak ty powiedziałem, że wiem "Jak podłączyć natywny plik .c do natywnych metod w odpowiednim pliku .java" chcę znać natywny kod c do kompresji wideo, próbowałem wykonać projekt ut Github, ale wydaje się, że działa na Androidzie 4.4 –

Powiązane problemy