# # # introduction

In the last article we compiled and exported the dynamic library files required by the Android project. And then we’re going to use this library to decode the video.

### Video decoding

#### create Android Studio project

When creating an Android Studio project, remember to bring C++Support.

Then write the CMake script:

The minimum VERSION # configure CMake cmake_minimum_required (VERSION 3.4.1 track) # configuration project path # set (path_project/home/wuhuannan/AndroidPrj/FFmpeg) Set (path_project D: / AndroidStudio/FFmpeg) # configuration header file contains the path include_directories (${path_project} / app/SRC/main/CPP/include) Add_library (ffmpeg-lib SHARED SRC /main/ CPP /ffmpeg.c) add_library(avutil SHARED IMPORTED) Set_target_properties (Avutil PROPERTIES IMPORTED_LOCATION) set_target_properties(avutil PROPERTIES IMPORTED_LOCATION ${path_project}/app/libs/${ANDROID_ABI}/libavutil-54.so ) add_library( swresample SHARED IMPORTED ) set_target_properties( swresample PROPERTIES IMPORTED_LOCATION ${path_project}/app/libs/${ANDROID_ABI}/libswresample-1.so ) add_library( avcodec SHARED IMPORTED ) set_target_properties( avcodec PROPERTIES IMPORTED_LOCATION ${path_project}/app/libs/${ANDROID_ABI}/libavcodec-56.so ) add_library( avformat SHARED IMPORTED ) set_target_properties( avformat PROPERTIES IMPORTED_LOCATION ${path_project}/app/libs/${ANDROID_ABI}/libavformat-56.so ) add_library( swscale SHARED IMPORTED ) set_target_properties( swscale PROPERTIES IMPORTED_LOCATION ${path_project}/app/libs/${ANDROID_ABI}/libswscale-3.so ) add_library( postproc SHARED IMPORTED ) set_target_properties( postproc PROPERTIES IMPORTED_LOCATION ${path_project}/app/libs/${ANDROID_ABI}/libpostproc-53.so ) add_library( avfilter SHARED IMPORTED ) set_target_properties( avfilter PROPERTIES IMPORTED_LOCATION ${path_project}/app/libs/${ANDROID_ABI}/libavfilter-5.so ) add_library( avdevice SHARED IMPORTED ) set_target_properties( avdevice PROPERTIES IMPORTED_LOCATION ${path_project}/app/libs/${ANDROID_ABI}/libavdevice-56. So Target_link_libraries (ffmpeg-lib ${log-lib} avutil swresAMPLE AVCOdec avFormat swScale postproc) # link the library to your own target_link_libraries(ffmpeg-lib ${log-lib} avutil swresample AVCodec AvFormat swScale postproc avfilter avdevice )Copy the code

The main job is to load several dynamic libraries from our last article and link to our own library.

#### 2. Write Java methods for testing

package com.nan.ffmpeg.utils; public class VideoUtils { 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("ffmpeg-lib"); } public native static void decode(String input, String outpTU); }Copy the code

###### here it should be noted that FFmpeg’s dynamic library is dependent, loading time needs to follow a certain order, load the most basic library first.

#### 3. JNI implementation

The FFmpeg video decoding process is as follows:

The file path of the relevant sample program in FFmpeg:

Ffmpeg - 2.6.9 \ doc \ examplesCopy the code

This is how we program.

H > #include <jni.h> #include <string.h> #include <android/log.h #include "libswscale/swscale.h" #define LOGI(FORMAT,...) __android_log_print(ANDROID_LOG_INFO,"wuhuannan",FORMAT,##__VA_ARGS__); #define LOGE(FORMAT, ...) __android_log_print(ANDROID_LOG_ERROR,"wuhuannan",FORMAT,##__VA_ARGS__); JNIEXPORT void JNICALL Java_com_nan_ffmpeg_utils_VideoUtils_decode(JNIEnv *env, jclass type, Jstring input_, jString outpTU_) {const char *input = (*env)->GetStringUTFChars(env, input_, 0); const char *outptu = (*env)->GetStringUTFChars(env, outptu_, 0); //1. Register all components, such as initializing some global variables, initializing network, etc. Av_register_all (); //avcodec_register_all(); AVFormatContext *pFormatCtx = avformat_alloc_context(); If (avformat_open_INPUT (&pFormatCtx, INPUT, NULL, NULL)! = 0) {LOGE("%s", "can't open input video file "); return; } // the second parameter is a dictionary, which indicates what information you need to obtain. If (avformat_find_stream_info(pFormatCtx, NULL) < 0) {LOGE("%s", "can't get video file info "); return; Int v_stream_idx = -1;} // Get the index position of the video stream // iterate over all types of streams (audio stream, video stream, subtitle stream) int i = 0; //number of streams for (; i < pFormatCtx->nb_streams; If (pFormatCtx->streams[I]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {v_stream_idx = I; break; }} the if (v_stream_idx = = 1) {LOGE (" % s ", "can't find the video stream \ n"); return; AVCodecContext *pCodecCtx = streamctx ->streams[v_stream_idx]->codec; AVCodec *pCodec = avcodec_find_decoder(pCodecCtx->codec_id); If (pCodec == NULL) {LOGE("%s", "can't find the decoder, or the video is encrypted \n"); return; } //5. If (avCodec_open2 (pCodecCtx, pCodec, NULL) < 0) {LOGE("%s", "decoder cannot open \n"); return; PFormatCtx ->iformat->name);} // Output video information LOGI(" video file format: %s", pFormatCtx->iformat->name); LOGI(" Video duration: % LLD ", (pFormatCtx->duration) / 1000000); LOGI(" %d,%d", pCodecCtx->width, pCodecCtx->height); LOGI(" decoder name: %s", pCodec->name); AVPacket *packet = (AVPacket *) av_malloc(sizeof(AVPacket)); av_malloc(sizeof(AVPacket)); // Memory allocation AVFrame *pFrame = av_frame_alloc(); //YUV420 AVFrame *pFrameYUV = av_frame_alloc(); Uint8_t *out_buffer = (uint8_t *) av_malloc avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height)); Avpicture_fill ((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height); // Parameters used for transcoding (scaling), width before scaling, width after scaling, Struct SwsContext *sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL); int got_picture, ret; FILE *fp_yuv = fopen(outptu, "wb+"); int frame_count = 0; While (av_read_frame(pFormatCtx, Packet) >= 0) {if (packet->stream_index == v_stream_idx) {//7. Decode a frame of video compression data, get video pixel data RET = AVCODEC_decode_videO2 (pCodecCtx, pFrame, & GOt_picture, packet); If (ret < 0) {LOGE("%s", "decoded error "); return; If (got_picture) {//AVFrame is converted to pixel format YUV420, Width height //2 6 input and output data //3 7 Input and output screen data row size AVFrame conversion is a row of conversion //4 input data column to transcode position from 0 //5 input screen height sws_scale(SWs_ctx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize); // Output to YUV file //AVFrame pixel frame write file //data decoded image pixel data (audio sampling data) //Y brightness UV chroma (compressed) people are more sensitive to brightness //U V number is 1/4 of Y int y_size = pCodecCtx->width * pCodecCtx->height; fwrite(pFrameYUV->data[0], 1, y_size, fp_yuv); fwrite(pFrameYUV->data[1], 1, y_size / 4, fp_yuv); fwrite(pFrameYUV->data[2], 1, y_size / 4, fp_yuv); frame_count++; LOGI(" decode frame % D ", frame_count); } // Free av_free_packet(packet); } fclose(fp_yuv); av_frame_free(&pFrame); avcodec_close(pCodecCtx); avformat_free_context(pFormatCtx); (*env)->ReleaseStringUTFChars(env, input_, input); (*env)->ReleaseStringUTFChars(env, outptu_, outptu); }Copy the code

#### 4. Test in the Activity

@Override public void onClick(View v) { String inputVideo = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + "input.mp4"; String outputVideo = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separatorChar + "output_1280x720_yuv420p.yuv"; switch (v.getId()) { case R.id.btn_decode: VideoUtils.decode(inputVideo, outputVideo); break; }}Copy the code

Relevant source: https://github.com/huannan/FFmpeg

If you feel that my words are helpful to you, welcome to pay attention to my public number:

My group welcomes everyone to come in and discuss all kinds of technical and non-technical topics. If you are interested, please add my wechat huannan88 and I will take you into our group.