만들기는 6-8 개월 전에 만들었는데, 프로젝트에 쫓기면서 살다보니 이제서야 올립니다. sws_scale() 함수 및 rtsp 등의 프로토콜을 사용하는데 필요한 모든 코드가 포함되어 있습니다. 배속 재생 및 rtsp 버퍼링 등을 지원하는 플레이어를 만들면서 만들었던 것입니다. FFMPEG의 소스 및 빌드 방법은
http://ryulib.tistory.com/123 를 참고하세요. (http://goo.gl/gTyQ8 에 더 쉽고 자세한 강좌가 있으니 참고하세요)
libs.zip
jni로 한 번 래핑해서 사용하셔야 합니다.
jstring
Java_ryulib_ffmpeg_FFMpeg_getStreamInformation(JNIEnv* env, jclass clazz, jint handle)
{
FFmpegHandle *pHandle = (FFmpegHandle *) handle;
char videoInformation[512];
avcodec_string(videoInformation, sizeof(videoInformation), pHandle->pVideoCtx, 0);
char audioInformation[512];
avcodec_string(audioInformation, sizeof(audioInformation), pHandle->pAudioCtx, 0);
char result[1024 * 4];
sprintf(result,
"%s\n%s",
videoInformation, audioInformation
);
return (*env)->NewStringUTF(env, result);
}
래핑을 하시게 되면, 자신이 만든 jni로 컴파일한 so 파일과 함께 로딩해서 사용하시면 됩니다. 아래는 제가 libryumpeg.so 라는 이름으로 동적 링크 라이브러리를 만들어서 사용하는 경우의 예 입니다.
package ryulib.ffmpeg;
import android.graphics.Bitmap;
public class FFMpeg {
static {
System.loadLibrary("ffmpeg");
System.loadLibrary("ryumpeg");
}
public static final int Error_General = -1;
public static final int Error_Can_Not_Open_File = -2;
public static final int Error_Can_Not_Find_StreamInfo = -3;
public static final int Error_Can_Not_Find_VidoeStream = -4;
public static final int Error_Can_Not_Find_AudioStream = -5;
public static final int Error_Can_Not_Open_VideoCodec = -6;
public static final int Error_Can_Not_Open_AudioCodec = -7;
public static final int UnknownPacket = 0;
public static final int VideoPacket = 1;
public static final int AudioPacket = 2;
public static native String getDebugString();
// openFile(), closeFile(), start(), stop(): Main Thread에서 실행합니다.
// start(), stop(): Thread-safe 합니다.
// TODO : 파일이 없을 경우 어플리케이션이 죽음
public static native int openFile(String fileName);
public static native void closeHandle(int handle);
public static native String getStreamInformation(int handle);
// openFile() 호출 시, 내부에서 start()를 호출한 상태가 된다.
public static native void start(int handle);
public static native void stop(int handle);
public static native int readFrameToBuffer(int handle);
public static native byte[] getAudioData(int handle);
public static native int getVideoData(int handle, Bitmap bitmap);
public static native int getAudioPacketCount(int handle);
public static native int getVideoPacketCount(int handle);
// seekByTime(), rewindByTime(), forwardByTime(), readAudioPacket(): 동일한 쓰레드에서 사용되야 합니다.
public static native boolean seekByTime(int handle, int ms);
public static native boolean rewindByTime(int handle, int ms);
public static native boolean forwardByTime(int handle, int ms);
public static native int getDuration(int handle);
public static native int getPosition(int handle);
public static native int getVideoWidth(int handle);
public static native int getVideoHeight(int handle);
public static native int getSampleRate(int handle);
public static native int getChannels(int handle);
}
jni에 대해서는 아래 첨부 파일을 참고 하시기 바랍니다.
jni.pdf