Changing video filter in a single work-thread

dev
xufuji456 4 years ago
parent ff1562d8bb
commit 43ede7ab4b
  1. 88
      app/src/main/cpp/video_filter.c
  2. 4
      app/src/main/java/com/frank/ffmpeg/VideoPlayer.java
  3. 40
      app/src/main/java/com/frank/ffmpeg/activity/FilterActivity.kt

@ -19,36 +19,22 @@
#define TAG "VideoFilter" #define TAG "VideoFilter"
AVFilterContext *buffersink_ctx; AVFilterContext *buffersink_ctx;
AVFilterContext *buffersrc_ctx; AVFilterContext *buffersrc_ctx;
AVFilterGraph *filter_graph; AVFilterGraph *filter_graph;
int video_stream_index = -1;
AVFormatContext *pFormatCtx; AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx; AVCodecContext *pCodecCtx;
ANativeWindow_Buffer windowBuffer; ANativeWindow_Buffer windowBuffer;
ANativeWindow *nativeWindow; ANativeWindow *nativeWindow;
int again;
int release;
uint8_t *buffer;
AVFrame *pFrame; AVFrame *pFrame;
AVFrame *pFrameRGBA; AVFrame *pFrameRGBA;
AVFrame *filter_frame; AVFrame *filter_frame;
uint8_t *buffer;
struct SwsContext *sws_ctx; struct SwsContext *sws_ctx;
int video_stream_index = -1;
int is_playing;
int again;
int release;
#define MAX_AUDIO_FRAME_SIZE 48000 * 4 #define MAX_AUDIO_FRAME_SIZE 48000 * 4
jmethodID audio_track_write_mid; jmethodID audio_track_write_mid;
@ -61,22 +47,18 @@ int audio_stream_index = -1;
int got_frame; int got_frame;
AVCodecContext *audioCodecCtx; AVCodecContext *audioCodecCtx;
jboolean playAudio = JNI_TRUE; jboolean playAudio = JNI_TRUE;
int pos;
//const char *filter_descr = "lutyuv='u=128:v=128'";//black white
//const char *filter_descr = "hue='h=60:s=-3'";//hue char* filters[] = {"lutyuv='u=128:v=128'",
//const char *filter_descr = "vflip";//up or down "hue='h=60:s=-3'",
//const char *filter_descr = "hflip";//left or right "edgedetect=low=0.1:high=0.4",
//const char *filter_descr = "rotate=90";//rotate "drawgrid=w=iw/3:h=ih/3:t=2:c=white@0.5",
//const char *filter_descr = "colorbalance=bs=0.3";//balance "colorbalance=bs=0.3",
//const char *filter_descr = "drawbox=x=100:y=100:w=100:h=100:color=pink@0.5'";//rectangle "drawbox=x=100:y=100:w=100:h=100:color=red@0.5'",
//const char *filter_descr = "drawgrid=w=iw/3:h=ih/3:t=2:c=white@0.5";//grid "hflip",
//const char *filter_descr = "edgedetect=low=0.1:high=0.4";//edge detection "gblur=sigma=2:steps=1:planes=1:sigmaV=1",
//const char *filter_descr = "lutrgb='r=0:g=0'";//lut "rotate=180*PI/180",
//const char *filter_descr = "noise=alls=20:allf=t+u";//add noise "unsharp"};
//const char *filter_descr = "vignette='PI/4+random(1)*PI/50':eval=frame";//flash
//const char *filter_descr = "gblur=sigma=0.5:steps=1:planes=1:sigmaV=1";//Gauss blur
//const char *filter_descr = "drawtext=fontfile='arial.ttf':fontcolor=green:fontsize=30:text='Hello world'";//draw text
//const char *filter_descr = "movie=my_logo.png[wm];[in][wm]overlay=5:5[out]";//add watermark
//init filter //init filter
int init_filters(const char *filters_descr) { int init_filters(const char *filters_descr) {
@ -298,14 +280,11 @@ int play_audio(JNIEnv *env, AVPacket *packet, AVFrame *frame) {
return 0; return 0;
} }
VIDEO_PLAYER_FUNC(jint, filter, jstring filePath, jobject surface, jstring filterDescr) { VIDEO_PLAYER_FUNC(jint, filter, jstring filePath, jobject surface, jint position) {
int ret; int ret;
pos = position;
const char *file_name = (*env)->GetStringUTFChars(env, filePath, JNI_FALSE); const char *file_name = (*env)->GetStringUTFChars(env, filePath, JNI_FALSE);
const char *filter_descr = (*env)->GetStringUTFChars(env, filterDescr, JNI_FALSE);
//open input file
if (!is_playing) {
LOGI(TAG, "open_input...");
if ((ret = open_input(env, file_name, surface)) < 0) { if ((ret = open_input(env, file_name, surface)) < 0) {
LOGE(TAG, "Couldn't allocate video frame."); LOGE(TAG, "Couldn't allocate video frame.");
goto end; goto end;
@ -324,22 +303,25 @@ VIDEO_PLAYER_FUNC(jint, filter, jstring filePath, jobject surface, jstring filte
goto end; goto end;
} }
}
//init filter //init filter
if ((ret = init_filters(filter_descr)) < 0) { if ((ret = init_filters(filters[pos])) < 0) {
LOGE(TAG, "init_filter error, ret=%d\n", ret); LOGE(TAG, "init_filter error, ret=%d\n", ret);
goto end; goto end;
} }
is_playing = 1;
int frameFinished; int frameFinished;
AVPacket packet; AVPacket packet;
while (av_read_frame(pFormatCtx, &packet) >= 0 && !release) { while (av_read_frame(pFormatCtx, &packet) >= 0 && !release) {
//switch filter //switch filter
if (again) { if (again) {
goto again; again = 0;
avfilter_graph_free(&filter_graph);
if ((ret = init_filters(filters[pos])) < 0) {
LOGE(TAG, "init_filter error, ret=%d\n", ret);
goto end;
}
LOGE(TAG, "play again,filter_descr=_=%s", filters[pos]);
} }
//is video stream or not //is video stream or not
if (packet.stream_index == video_stream_index) { if (packet.stream_index == video_stream_index) {
@ -385,14 +367,11 @@ VIDEO_PLAYER_FUNC(jint, filter, jstring filePath, jobject surface, jstring filte
} }
av_packet_unref(&packet); av_packet_unref(&packet);
} }
end: end:
is_playing = 0;
av_free(buffer); av_free(buffer);
av_free(out_buffer); av_free(out_buffer);
sws_freeContext(sws_ctx); sws_freeContext(sws_ctx);
swr_free(&audio_swr_ctx); swr_free(&audio_swr_ctx);
avfilter_free(buffersrc_ctx);
avfilter_free(buffersink_ctx);
avfilter_graph_free(&filter_graph); avfilter_graph_free(&filter_graph);
avcodec_free_context(&pCodecCtx); avcodec_free_context(&pCodecCtx);
avcodec_free_context(&audioCodecCtx); avcodec_free_context(&audioCodecCtx);
@ -401,20 +380,17 @@ VIDEO_PLAYER_FUNC(jint, filter, jstring filePath, jobject surface, jstring filte
av_free(filter_frame); av_free(filter_frame);
av_free(pFrame); av_free(pFrame);
free(audio_track); // free(audio_track);
free(&windowBuffer); // free(&windowBuffer);
ANativeWindow_release(nativeWindow); ANativeWindow_release(nativeWindow);
(*env)->ReleaseStringUTFChars(env, filePath, file_name); (*env)->ReleaseStringUTFChars(env, filePath, file_name);
(*env)->ReleaseStringUTFChars(env, filterDescr, filter_descr);
LOGE(TAG, "do release..."); LOGE(TAG, "do release...");
again:
again = 0;
LOGE(TAG, "play again...");
return ret; return ret;
} }
VIDEO_PLAYER_FUNC(void, again) { VIDEO_PLAYER_FUNC(void, again, jint position) {
again = 1; again = 1;
pos = position;
} }
VIDEO_PLAYER_FUNC(void, release) { VIDEO_PLAYER_FUNC(void, release) {

@ -18,9 +18,9 @@ public class VideoPlayer {
public native void setPlayRate(float playRate); public native void setPlayRate(float playRate);
public native int filter(String filePath, Object surface, String filterType); public native int filter(String filePath, Object surface, int position);
public native void again(); public native void again(int position);
public native void release(); public native void release();

@ -38,20 +38,25 @@ class FilterActivity : BaseActivity(), SurfaceHolder.Callback {
private var surfaceView: SurfaceView? = null private var surfaceView: SurfaceView? = null
private var surfaceHolder: SurfaceHolder? = null private var surfaceHolder: SurfaceHolder? = null
private var surfaceCreated: Boolean = false private var surfaceCreated: Boolean = false
//is playing or not
private var isPlaying: Boolean = false
//the array of filter
private val filters = arrayOf("lutyuv='u=128:v=128'", "hue='h=60:s=-3'", "edgedetect=low=0.1:high=0.4",
"drawgrid=w=iw/3:h=ih/3:t=2:c=white@0.5", "colorbalance=bs=0.3", "drawbox=x=100:y=100:w=100:h=100:color=red@0.5'", "hflip",
//adjust the coefficient of sigma to control the blur
"gblur=sigma=2:steps=1:planes=1:sigmaV=1", "rotate=180*PI/180", "unsharp")
//vflip is up and down, hflip is left and right //vflip is up and down, hflip is left and right
private val txtArray = arrayOf(FFmpegApplication.getInstance().getString(R.string.filter_sketch), FFmpegApplication.getInstance().getString(R.string.filter_distinct), FFmpegApplication.getInstance().getString(R.string.filter_edge), FFmpegApplication.getInstance().getString(R.string.filter_division), FFmpegApplication.getInstance().getString(R.string.filter_equalize), FFmpegApplication.getInstance().getString(R.string.filter_rectangle), FFmpegApplication.getInstance().getString(R.string.filter_flip), FFmpegApplication.getInstance().getString(R.string.filter_blur), FFmpegApplication.getInstance().getString(R.string.filter_rotate), FFmpegApplication.getInstance().getString(R.string.filter_sharpening)) private val txtArray = arrayOf(
FFmpegApplication.getInstance().getString(R.string.filter_sketch),
FFmpegApplication.getInstance().getString(R.string.filter_distinct),
FFmpegApplication.getInstance().getString(R.string.filter_edge),
FFmpegApplication.getInstance().getString(R.string.filter_division),
FFmpegApplication.getInstance().getString(R.string.filter_equalize),
FFmpegApplication.getInstance().getString(R.string.filter_rectangle),
FFmpegApplication.getInstance().getString(R.string.filter_flip),
FFmpegApplication.getInstance().getString(R.string.filter_blur),
FFmpegApplication.getInstance().getString(R.string.filter_rotate),
FFmpegApplication.getInstance().getString(R.string.filter_sharpening))
private var horizontalAdapter: HorizontalAdapter? = null private var horizontalAdapter: HorizontalAdapter? = null
private var recyclerView: RecyclerView? = null private var recyclerView: RecyclerView? = null
private var playAudio = true private var playAudio = true
private var btnSound: ToggleButton? = null private var btnSound: ToggleButton? = null
private var btnSelect: Button? = null private var btnSelect: Button? = null
private var filterThread: Thread? = null
@SuppressLint("HandlerLeak") @SuppressLint("HandlerLeak")
private val mHandler = object : Handler() { private val mHandler = object : Handler() {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
@ -133,13 +138,14 @@ class FilterActivity : BaseActivity(), SurfaceHolder.Callback {
* @param position position in the array of filters * @param position position in the array of filters
*/ */
private fun doFilterPlay(position: Int) { private fun doFilterPlay(position: Int) {
Thread(Runnable { if (filterThread == null) {
if (isPlaying) { filterThread = Thread(Runnable {
videoPlayer!!.again() videoPlayer!!.filter(videoPath, surfaceHolder!!.surface, position)
})
filterThread!!.start()
} else {
videoPlayer!!.again(position)
} }
isPlaying = true
videoPlayer!!.filter(videoPath, surfaceHolder!!.surface, filters[position])
}).start()
} }
private fun setPlayAudio() { private fun setPlayAudio() {
@ -163,11 +169,15 @@ class FilterActivity : BaseActivity(), SurfaceHolder.Callback {
override fun surfaceDestroyed(holder: SurfaceHolder) { override fun surfaceDestroyed(holder: SurfaceHolder) {
surfaceCreated = false surfaceCreated = false
if (filterThread != null) {
videoPlayer?.release()
filterThread?.interrupt()
filterThread = null
}
} }
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
isPlaying = false
videoPlayer = null videoPlayer = null
horizontalAdapter = null horizontalAdapter = null
} }

Loading…
Cancel
Save