The simplest example of Mobile End Based on FFmpeg: Android Video Decoder and ffmpegandroid
This document records an FFmpeg-Based Video Decoder for Android. The C language source code of this video decoder comes from the simplest Video Player Based on FFMPEG + SDL. The related concepts are no longer repeated.
Directory structure of the source code project. Java source code is located in the src directory, while C code is located in the jni directory.
The Java code of the Android program is located in src \ com \ leixiao00001020 \ sffmpegandroiddecoder \ MainActivity. java, as shown below.
/*** The Simplest FFmpeg-based video Decoder-Android * Simplest FFmpeg Android Decoder ** Lei Xiaohua * leixiaohua1020@126.com * China Media University/Digital TV technology * Communication University china/Digital TV Technology * http://blog.csdn.net/leixiaohua1020 ** this program is the most simple Video Decoder Based on FFmpeg Android platform. It decodes the input video data into YUV pixel data. ** This software is the simplest decoder based on FFmpeg in Android. it can decode video stream * to raw YUV data. **/package com. leixiao000010366sffmpegandroiddecoder; import android. OS. bundle; import android. OS. environment; import android. app. activity; import android. text. editable; import android. util. log; import android. view. menu; import android. view. view; import android. view. view. onClickListener; import android. widget. button; import android. widget. editText; import android. widget. textView; public class MainActivity extends Activity {@ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); Button startButton = (Button) this. findViewById (R. id. button_start); final EditText urlEdittext_input = (EditText) this. findViewById (R. id. input_url); final EditText urlEdittext_output = (EditText) this. findViewById (R. id. output_url); startButton. setOnClickListener (new OnClickListener () {public void onClick (View arg0) {String folderurl = Environment. getExternalStorageDirectory (). getPath (); String urltext_input = urlEdittext_input.getText (). toString (); String inputurl = folderurl + "/" + urltext_input; String urltext_output = urlEdittext_output.getText (). toString (); String outputurl = folderurl + "/" + urltext_output; Log. I ("inputurl", inputurl); Log. I ("outputurl", outputurl); decode (inputurl, outputurl) ;}}) ;}@ Override public boolean onCreateOptionsMenu (Menu menu) {// Inflate the menu; this adds items to the action bar if it is present. getMenuInflater (). inflate (R. menu. main, menu); return true;} // JNI public native int decode (String inputurl, String outputurl); static {System. loadLibrary ("avutil-54"); System. loadLibrary ("swresample-1"); System. loadLibrary ("avcodec-56"); System. loadLibrary ("avformat-56"); System. loadLibrary ("swscale-3"); System. loadLibrary ("postproc-53"); System. loadLibrary ("avfilter-5"); System. loadLibrary ("avdevice-56"); System. loadLibrary ("sffdecoder ");}}
The C language source code is located in jni/simplest_ffmpeg_decoder.c, as shown below.
/*** The Simplest FFmpeg-based video Decoder-Android * Simplest FFmpeg Android Decoder ** Lei Xiaohua * leixiaohua1020@126.com * China Media University/Digital TV technology * Communication University china/Digital TV Technology * http://blog.csdn.net/leixiaohua1020 ** this program is the most simple Video Decoder Based on FFmpeg Android platform. It decodes the input video data into YUV pixel data. ** This software is the simplest decoder based on FFmpeg in Android. it can decode video stream * to raw YUV data. **/# include <stdio. h> # include <time. h> # include "libavcodec/avcodec. h "# include" libavformat/avformat. h "# include" libswscale/swscale. h "# include" libavutil/log. h "# ifdef ANDROID # include <jni. h> # include <android/log. h> # define LOGE (format ,...) _ android_log_print (ANDROID_LOG_ERROR, "(> _ <) ", Format, ##__ VA_ARGS _) # define LOGI (format ,...) _ android_log_print (ANDROID_LOG_INFO, "(= _ =)", format, ##__ VA_ARGS _) # else # define LOGE (format ,...) printf ("(>_<)" format "\ n", ##__ VA_ARGS _) # define LOGI (format ,...) printf ("(^_^)" format "\ n", ##__ VA_ARGS _) # endif // Output FFmpeg's av_log () void custom_log (void * ptr, int level, const char * fmt, va_list vl) {FILE * fp = fopen ("/storage/emulated/0/ Av_log.txt "," a + "); if (fp) {vfprintf (fp, fmt, vl); fflush (fp); fclose (fp );}} JNIEXPORT jint JNICALL encode (optional * env, jobject obj, jstring values, jstring values) {AVFormatContext * pFormatCtx; inti, videoindex; AVCodecContext * pCodecCtx; AVCodec * pCodec; AVFrame * pFrame, * pFrameYUV; uint8_t * out_buffer; AVPacket * packet; int y_size; int ret, got_pic Ture; struct SwsContext * img_convert_ctx; FILE * fp_yuv; int frame_cnt; clock_t time_start, time_finish; double time_duration = 0.0; char input_str [500] = {0 }; char output_str [500] = {0}; char info [1000] = {0}; sprintf (input_str, "% s", (* env)-> GetStringUTFChars (env, input_jstr, NULL); sprintf (output_str, "% s", (* env)-> GetStringUTFChars (env, output_jstr, NULL); // FFmpeg av_log () callback av_log_set_callback (custom_log ); Av_register_all (); avformat_network_init (); pFormatCtx = avformat_alloc_context (); if (avformat_open_input (& pFormatCtx, input_str, NULL, NULL )! = 0) {LOGE ("Couldn't open input stream. \ n "); return-1;} if (avformat_find_stream_info (pFormatCtx, NULL) <0) {LOGE (" Couldn't find stream information. \ n "); return-1 ;}videoindex =-1; for (I = 0; I <pFormatCtx-> nb_streams; I ++) if (pFormatCtx-> streams [I]-> codec-> codec_type = AVMEDIA_TYPE_VIDEO) {videoindex = I; break;} if (videoindex =-1) {LOGE ("Couldn't find a video stream. \ n "); return-1;} pCodecCtx = pFormatCtx-> streams [vide Oindex]-> codec; pCodec = avcodec_find_decoder (pCodecCtx-> codec_id); if (pCodec = NULL) {LOGE ("Couldn't find Codec. \ n "); return-1;} if (avcodec_open2 (pCodecCtx, pCodec, NULL) <0) {LOGE (" Couldn't open codec. \ n "); return-1;} pFrame = av_frame_alloc (); pFrameYUV = av_frame_alloc (); out_buffer = (uint8_t *) av_malloc (bytes, pCodecCtx-> width, pCodecCtx-> height); avpicture_fill (AVPicture *) pFrame YUV, out_buffer, bytes, pCodecCtx-> width, pCodecCtx-> height); packet = (AVPacket *) av_malloc (sizeof (AVPacket); img_convert_ctx = sws_getContext (pCodecCtx-> width, pCodecCtx-> height, pCodecCtx-> pix_fmt, pCodecCtx-> width, pCodecCtx-> height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL); sprintf (info, "[Input] % s \ n", input_str); sprintf (info, "% s [Output] % s \ n", info, output_str); sprintf (info, "% S [Format] % s \ n", info, pFormatCtx-> iformat-> name); sprintf (info, "% s [Codec] % s \ n ", info, pCodecCtx-> codec-> name); sprintf (info, "% s [Resolution] % dx % d \ n", info, pCodecCtx-> width, pCodecCtx-> height); fp_yuv = fopen (output_str, "wb +"); if (fp_yuv = NULL) {printf ("Cannot open output file. \ n "); return-1;} frame_cnt = 0; time_start = clock (); while (av_read_frame (pFormatCtx, packet)> = 0) {if (packet-> stream_index = videoi Ndex) {ret = avcodec_decode_video2 (pCodecCtx, pFrame, & got_picture, packet); if (ret <0) {LOGE ("Decode Error. \ n "); return-1;} if (got_picture) {sws_scale (img_convert_ctx, (const uint8_t * const *) pFrame-> data, pFrame-> linesize, 0, pCodecCtx-> height, pFrameYUV-> data, pFrameYUV-> linesize); y_size = pCodecCtx-> width * pCodecCtx-> height; fwrite (pFrameYUV-> data [0], 1, y_size, fp_yuv); // Y fwrite (pFrameYUV-> data [1], 1, y _ Size/4, fp_yuv); // Ufwrite (pFrameYUV-> data [2], 1, y_size/4, fp_yuv ); // V // Output infochar pictype_str [10] = {0}; switch (pFrame-> pict_type) {case AV_PICTURE_TYPE_ I: sprintf (pictype_str, "I"); break; case when: sprintf (pictype_str, "P"); break; case AV_PICTURE_TYPE_ B: sprintf (pictype_str, "B"); break; default: sprintf (pictype_str, "Other "); break;} LOGI ("Frame Index: % 5d. type: % s ", frame_cnt, pictype_str); fram E_cnt ++ ;}} av_free_packet (packet) ;}// flush decoder // FIX: Flush Frames remained in Codecwhile (1) {ret = avcodec_decode_video2 (pCodecCtx, pFrame, & got_picture, packet); if (ret <0) break; if (! Got_picture) break; sws_scale (img_convert_ctx, (const uint8_t * const *) pFrame-> data, pFrame-> linesize, 0, pCodecCtx-> height, pFrameYUV-> data, pFrameYUV-> linesize); int y_size = pCodecCtx-> width * pCodecCtx-> height; fwrite (pFrameYUV-> data [0], 1, y_size, fp_yuv ); // Y fwrite (pFrameYUV-> data [1], 1, y_size/4, fp_yuv); // Ufwrite (pFrameYUV-> data [2], 1, y_size/4, fp_yuv); // V // Output infochar pictype_str [10] = {0}; switch (pFrame-> pict_type) {case AV_PICTURE_TYPE_ I: sprintf (pictype_str, "I "); break; case AV_PICTURE_TYPE_P: sprintf (pictype_str, "P"); break; case AV_PICTURE_TYPE_ B: sprintf (pictype_str, "B"); break; default: sprintf (pictype_str, "Other"); break;} LOGI ("Frame Index: % 5d. type: % s ", frame_cnt, pictype_str); frame_cnt ++;} time_finish = clock (); time_duration = (double) (time_finish-time_start); sprintf (info, "% s [Time] % fms \ n", info, time_duration); sprintf (info, "% s [Count] % d \ n", info, frame_cnt ); sws_freeContext (img_convert_ctx); fclose (fp_yuv); av_frame_free (& pFrameYUV); av_frame_free (& pFrame); avcodec_close (pCodecCtx); convert (& pFormatCtx); return 0 ;}
The Android. mk file is located in jni/Android. mk, as shown below.
# Android. mk for FFmpeg # Lei Xiaohua # leixiaohua1020@126.com # http://blog.csdn.net/leixiaohua1020# LOCAL_PATH: = $ (call my-dir) # FFmpeg libraryinclude $ (CLEAR_VARS) LOCAL_MODULE: = avcodecLOCAL_SRC_FILES: = libavcodec-56.soinclude $ (PREBUILT_SHARED_LIBRARY) include $ (CLEAR_VARS) LOCAL_MODULE: = modules: = libavdevice-56.soinclude $ (PREBUILT_SHARED_LIBRARY) include $ (CLEAR_VARS) LOCAL_MODULE: = modules: = libavfilter-5.soinclude $ (PREBUILT_SHARED_LIBRARY) include $ (CLEAR_VARS) LOCAL_MODULE: = avformatLOCAL_SRC_FILES: = libavformat-56.soinclude $ (modules) include $ (CLEAR_VARS) LOCAL_MODULE: = modules: = libavutil-54.soinclude $ (PREBUILT_SHARED_LIBRARY) include $ (CLEAR_VARS) LOCAL_MODULE: = postprocLOCAL_SRC_FILES: = libpostproc-53.soinclude $ (PREBUILT_SHARED_LIBRARY) include $ (CLEAR_VARS) LOCAL_MODULE: = modules: = libswresample-1.soinclude $ (PREBUILT_SHARED_LIBRARY) include $ (CLEAR_VARS) LOCAL_MODULE: = modules: = libswscale-3.soinclude $ (PREBUILT_SHARED_LIBRARY) # Programinclude $ (CLEAR_VARS) LOCAL_MODULE: = partition + = $ (LOCAL_PATH)/includeLOCAL_LDLIBS: =-llog-lzLOCAL_SHARED_LIBRARIES: = avcodec avdevice avfilter avformat avutil postproc swresample swscaleinclude $ (BUILD_SHARED_LIBRARY)
Shows the running result of the App running on the mobile phone.
Note that you need to copy the video file waiting for decoding to the corresponding directory on the memory card. For example, copy sintel.mp4 to the root directory of the memory card.
Click the "Start" button to decode the video file in the root directory of the storage card to the YUV file (you need to wait for a while to complete the decoding ). Note that the size of the decoded YUV file is huge and may occupy a large amount of memory space.
Download
Simplest ffmpeg mobile
Project Homepage
Github: https://github.com/leixiaohua1020/simplest_ffmpeg_mobile
Open source China: https://git.oschina.net/leixiaohua1020/simplest_ffmpeg_mobile
CSDN project: http://download.csdn.net/detail/leixiaohua1020/8924391
This solution contains various examples of using FFmpeg to process multimedia on mobile terminals:
[Android]
Simplest_android_player: Android-Based Video Player
Simplest_ffmpeg_android_helloworld: The FFmpeg-based HelloWorld program in Android
Simplest_ffmpeg_android_decoder: the simplest FFmpeg-based video decoder on Android
Simplest_ffmpeg_android_decoder_onelib: the simplest FFmpeg-Based Video Decoder for Android-single library
Simplest_ffmpeg_android_streamer: the simplest FFmpeg-based streamer on Android
Simplest_ffmpeg_android_transcoder: The FFmpeg command line tool transplanted on the Android platform
Simplest_sdl_android_helloworld: the simplest program to port SDL to Android.
[IOS]
Simplest_ios_player: A Video Player Based on the IOS Interface
Simplest_ffmpeg_ios_helloworld: The FFmpeg-based HelloWorld program in IOS
Simplest_ffmpeg_ios_decoder: the simplest FFmpeg-based video decoder on IOS
Simplest_ffmpeg_ios_streamer: the simplest FFmpeg-based streamer on IOS
Simplest_ffmpeg_ios_transcoder: The ffmpeg. c command line tool transplanted on the IOS platform
Simplest_sdl_ios_helloworld: the simplest program to port SDL to IOS.
Copyright Disclaimer: This article is an original article by the blogger and cannot be reproduced without the permission of the blogger.