androidffmpeg播放
『壹』 如何在Android用FFmpeg解碼圖像
創建一個VideoPicture結構體用來保存解碼出來的圖像。
LOCAL_PATH := $(call my-dir)
###########################
#
# SDL shared library
#
###########################
include $(CLEAR_VARS)
LOCAL_MODULE := SDL2
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES)
LOCAL_SRC_FILES := \
$(subst $(LOCAL_PATH)/,, \
$(wildcard $(LOCAL_PATH)/src/*.c) \
$(wildcard $(LOCAL_PATH)/src/audio/*.c) \
$(wildcard $(LOCAL_PATH)/src/audio/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/audio/mmy/*.c) \
$(LOCAL_PATH)/src/atomic/SDL_atomic.c \
$(LOCAL_PATH)/src/atomic/SDL_spinlock.c.arm \
$(wildcard $(LOCAL_PATH)/src/core/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/cpuinfo/*.c) \
$(wildcard $(LOCAL_PATH)/src/dynapi/*.c) \
$(wildcard $(LOCAL_PATH)/src/events/*.c) \
$(wildcard $(LOCAL_PATH)/src/file/*.c) \
$(wildcard $(LOCAL_PATH)/src/haptic/*.c) \
$(wildcard $(LOCAL_PATH)/src/haptic/mmy/*.c) \
$(wildcard $(LOCAL_PATH)/src/joystick/*.c) \
$(wildcard $(LOCAL_PATH)/src/joystick/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/loadso/dlopen/*.c) \
$(wildcard $(LOCAL_PATH)/src/power/*.c) \
$(wildcard $(LOCAL_PATH)/src/power/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/filesystem/mmy/*.c) \
$(wildcard $(LOCAL_PATH)/src/render/*.c) \
$(wildcard $(LOCAL_PATH)/src/render/*/*.c) \
$(wildcard $(LOCAL_PATH)/src/stdlib/*.c) \
$(wildcard $(LOCAL_PATH)/src/thread/*.c) \
$(wildcard $(LOCAL_PATH)/src/thread/pthread/*.c) \
$(wildcard $(LOCAL_PATH)/src/timer/*.c) \
$(wildcard $(LOCAL_PATH)/src/timer/unix/*.c) \
$(wildcard $(LOCAL_PATH)/src/video/*.c) \
$(wildcard $(LOCAL_PATH)/src/video/android/*.c) \
$(wildcard $(LOCAL_PATH)/src/test/*.c))
LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES
LOCAL_LDLIBS := -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
include $(BUILD_SHARED_LIBRARY)
###########################
#
# SDL static library
#
###########################
#LOCAL_MODULE := SDL2_static
#LOCAL_MODULE_FILENAME := libSDL2
#LOCAL_SRC_FILES += $(LOCAL_PATH)/src/main/android/SDL_android_main.c
#LOCAL_LDLIBS :=
#LOCAL_EXPORT_LDLIBS := -Wl,--undefined=java_org_libsdl_app_SDLActivity_nativeInit -ldl -lGLESv1_CM -lGLESv2 -llog -landroid
#include $(BUILD_STATIC_LIBRARY)
二、參考[原]如何在Android用FFmpeg解碼圖像, 在工程中新建一個ffmpeg文件夾,將與ffmpeg相關的頭文件include進來。ffmpeg文件夾下的Android.mk內容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := /path/to/build/ffmpeg/libffmpeg.so
include $(PREBUILT_SHARED_LIBRARY)
三、新建player文件夾,用來編寫解碼與顯示文件。player.c文件內容:
/*
* SDL_Lesson.c
*
* Created on: Aug 12, 2014
* Author: clarck
*/
#include <jni.h>
#include <android/native_window_jni.h>
#include "SDL.h"
#include "SDL_thread.h"
#include "SDL_events.h"
#include "../include/logger.h"
#include "../ffmpeg/include/libavcodec/avcodec.h"
#include "../ffmpeg/include/libavformat/avformat.h"
#include "../ffmpeg/include/libavutil/pixfmt.h"
#include "../ffmpeg/include/libswscale/swscale.h"
int main(int argc, char *argv[]) {
char *file_path = argv[1];
LOGI("file_path:%s", file_path);
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
AVFrame *pFrame, *pFrameYUV;
AVPacket *packet;
uint8_t *out_buffer;
SDL_Texture *bmp = NULL;
SDL_Window *screen = NULL;
SDL_Rect rect;
SDL_Event event;
static struct SwsContext *img_convert_ctx;
int videoStream, i, numBytes;
int ret, got_picture;
av_register_all();
pFormatCtx = avformat_alloc_context();
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
LOGE("Could not initialize SDL - %s. \n", SDL_GetError());
exit(1);
}
if (avformat_open_input(&pFormatCtx, file_path, NULL, NULL) != 0) {
LOGE("can't open the file. \n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
LOGE("Could't find stream infomation.\n");
return -1;
}
videoStream = 1;
for (i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
}
}
LOGI("videoStream:%d", videoStream);
if (videoStream == -1) {
LOGE("Didn't find a video stream.\n");
return -1;
}
pCodecCtx = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);
if (pCodec == NULL) {
LOGE("Codec not found.\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
LOGE("Could not open codec.\n");
return -1;
}
pFrame = av_frame_alloc();
pFrameYUV = av_frame_alloc();
//---------------------------init sdl---------------------------//
screen = SDL_CreateWindow("My Player Window", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, pCodecCtx->width, pCodecCtx->height,
SDL_WINDOW_FULLSCREEN | SDL_WINDOW_OPENGL);
SDL_Renderer *renderer = SDL_CreateRenderer(screen, -1, 0);
bmp = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12,
SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height);
//-------------------------------------------------------------//
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
numBytes = avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx->width,
pCodecCtx->height);
out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) pFrameYUV, out_buffer, AV_PIX_FMT_YUV420P,
pCodecCtx->width, pCodecCtx->height);
rect.x = 0;
rect.y = 0;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
int y_size = pCodecCtx->width * pCodecCtx->height;
packet = (AVPacket *) malloc(sizeof(AVPacket));
av_new_packet(packet, y_size);
av_mp_format(pFormatCtx, 0, file_path, 0);
while (av_read_frame(pFormatCtx, packet) >= 0) {
if (packet->stream_index == videoStream) {
ret = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,
packet);
if (ret < 0) {
LOGE("decode error.\n");
return -1;
}
LOGI("got_picture:%d", got_picture);
if (got_picture) {
sws_scale(img_convert_ctx,
(uint8_t const * const *) pFrame->data,
pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data,
pFrameYUV->linesize);
////iPitch 計算yuv一行數據占的位元組數
SDL_UpdateTexture(bmp, &rect, pFrameYUV->data[0], pFrameYUV->linesize[0]);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, bmp, &rect, &rect);
SDL_RenderPresent(renderer);
}
SDL_Delay(50);
}
av_free_packet(packet);
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
SDL_Quit();
exit(0);
break;
default:
break;
}
『貳』 如何在Android用FFmpeg+SDL2.0解碼顯示圖像
關於如何在Android上用FFmpeg+SDL2.0解碼顯示圖像參考[原]如何在Android用FFmpeg+SDL2.0解碼顯示圖像 ,關於如何在Android使用FFmpeg+SDL2.0解碼聲音參考[原]如何在Android用FFmpeg+SDL2.0解碼聲音。但是該文章有一個問題,就是解碼出來的聲音有很大的噪音,基本無法聽清,這是由於對於聲音的處理有問題。故本文參考ffmpeg-sdl音頻播放分析聲音解碼的處理,解碼出來的聲音就正常了。
博主的開發環境:Ubuntu 14.04 64位,Eclipse+CDT+ADT+NDK。
在文章開始之前假定你已經知道如何使用NDK編譯FFmpeg,以及知道如何移植SDL2.0到Android平台上來並且知道如何解碼顯示圖像和聲音了。
我們初步了解如何解碼視頻圖像和視頻聲音。但是這些都是初步簡單的解碼出來而已,我們的主要功能是處理非常多:它是通過事件循環中運行,讀取數據包,並在視頻解碼。所以,我們要做的就是拆分這些功能:我們將有一個線程,該線程將負責數據包進行解碼;這些數據包將被添加到該隊列中,並通過相應的音頻和視頻解碼線程讀取。
音頻線:我們在[原]如何在Android用FFmpeg+SDL2.0解碼聲音這篇文章裡面有了一個初步的音頻線模型,在本文我們繼續去完善這個;
視頻線:頻線會相對比較麻煩一些,因為我們要自己顯示自己的視頻畫面。我們將實際實現的代碼添加到主循環。我們的想法是對視頻進行解碼,保存生成到一個隊列中,然後創建一個自定義刷新事件(FF_REFRESH_EVENT),我們添加它到事件系統中,那麼當我們的事件循環看到這種情況,它會顯示在隊列的下一幀中,這樣一邊解碼一邊顯示。
工程中的目錄結構和[原]如何在Android用FFmpeg+SDL2.0解碼聲音 一樣,只是在其基礎上繼續添加功能。
一、創建一個VideoPicture結構體用來保存解碼出來的圖像。
二、添加數據隊列的初始化、添加以及讀取的函數。
三、audio_decode_frame():解碼音頻
四、audio_callback(): 回調函數,向SDL緩沖區填充數據
五、創建視頻刷新相關的函數:
schele_refresh():它主要的作用是告訴系統指定的毫秒數後推FF_REFRESH_EVENT。當我們看到它在事件隊列時,將依次調用視頻刷新功能。
六、添加視頻顯示函數:
因為我們的屏幕可以是任意大小(我們設定我們為640×480,並有一些方法來設置它,所以它是由用戶調整大小),我們需要動態地計算出我們有多大的矩形。因此,首先我們需要弄清楚我們的電影的顯示比例,這僅僅是寬度除以身高。某些編解碼器將有一個奇怪的樣本縱橫比,這就是一個像素,或樣品的寬度/高度。因為在我們的編解碼器的上下文中的高度和寬度值以像素為單位測量,實際的寬高比等於寬高比數倍的樣品長寬比。一些編解碼器將顯示0-5的寬高比,這表示每個像素僅僅是大小1x1的。然後,我們擴展了電影,以適應在我們的屏幕上。
七、分配顯示輸出內存空間:
使用隊列中,我們有兩個指針 - 寫入索引和閱讀索引。我們還跟蹤實際的照片有多少是在緩沖區中。要寫入隊列中,我們將首先等待我們的緩沖清除,所以我們足夠的空間來存儲我們VideoPicture。然後我們檢查,看看是否已經分配了覆蓋在我們的寫作索引。如果沒有,我們就必須分配一定的空間。如果窗口的大小發生了變化, 我們也要重新分配緩沖區。
八、解碼線程,將解碼器,建立音頻線,保存重要信息到數據結構中。
九、編寫Main函數用來調用解碼線程。
『叄』 android 中使用ffmpeg,將視頻加入字幕,用ass文件,在PC上可以,但在Android上一直不行
理論上來講:任何視頻格式都是支持外掛字幕的 迅雷看看也是支持外掛字幕的 沒顯示字幕的可能性有兩個: 1、播放器不支持外掛字幕(顯然應該不是播放器的問題,有可能你關閉了外掛字幕功能,你可以試著重新安裝迅雷看看) 2、視頻文件名跟字幕文件名不同(在同一個文件夾下要播放器自動載入外掛字幕,首先必須保證視頻跟字幕在同一個文件夾內,然後要保證文件名稱一樣,這里說的文件名稱不包括後綴名 舉個例子: 視頻文件名為:ZXCV.mp4 ,,這里我們可以看到這個視頻是一個名稱為:ZXCV的MP4格式的視頻文件,ZXCV為為視頻名稱,「.mp4」則為文件的後綴名,即為文件種類 要保證外掛字幕文件順利的自動載入,那麼它的文件名就必須為:「ZXCV.ass」) 明白?
『肆』 如何在Android用FFmpeg+SDL2.0之同步音頻
一、創建一個VideoPicture結構體用來保存解碼出來的圖像。
二、添加數據隊列的初始化、添加以及讀取的函數。
三、audio_decode_frame():解碼音頻
四、audio_callback(): 回調函數,向SDL緩沖區填充數據
五、創建視頻刷新相關的函數:
schele_refresh():它主要的作用是告訴系統指定的毫秒數後推FF_REFRESH_EVENT。當我們看到它在事件隊列時,將依次調用視頻刷新功能。
六、添加視頻顯示函數:
因為我們的屏幕可以是任意大小(我們設定我們為640×480,並有一些方法來設置它,所以它是由用戶調整大小),我們需要動態地計算出我們有多大的矩形。因此,首先我們需要弄清楚我們的電影的顯示比例,這僅僅是寬度除以身高。某些編解碼器將有一個奇怪的樣本縱橫比,這就是一個像素,或樣品的寬度/高度。因為在我們的編解碼器的上下文中的高度和寬度值以像素為單位測量,實際的寬高比等於寬高比數倍的樣品長寬比。一些編解碼器將顯示0-5的寬高比,這表示每個像素僅僅是大小1x1的。然後,我們擴展了電影,以適應在我們的屏幕上。
七、分配顯示輸出內存空間:
使用隊列中,我們有兩個指針 - 寫入索引和閱讀索引。我們還跟蹤實際的照片有多少是在緩沖區中。要寫入隊列中,我們將首先等待我們的緩沖清除,所以我們足夠的空間來存儲我們VideoPicture。然後我們檢查,看看是否已經分配了覆蓋在我們的寫作索引。如果沒有,我們就必須分配一定的空間。如果窗口的大小發生了變化, 我們也要重新分配緩沖區。
八、解碼線程,將解碼器,建立音頻線,保存重要信息到數據結構中。
九、編寫Main函數用來調用解碼線程。
『伍』 哪位高人知道FFmpeg在android平台下如何應用
這個可以看c與java的傳遞數據那一方面的內容,你可以在java端寫一個native方法,傳入轉碼命令,在jni寫代碼接收命令,分析命令
『陸』 android ffmpeg 是啥意思
FFmpeg是一套可以用來記錄、轉換數字音頻、視頻,並能將其轉化為流的開源計算機程序。
用來開發音視頻的~!
『柒』 android-ffmpeg-x264 怎麼用
Android內置的編解碼器實在太少,於是我們需要FFmpeg。Android提供了NDK,為我們使用FFmpeg這種C語言代碼提供了方便。
不過為了用NDK編譯FFmpeg,還真的花費了不少時間,也得到了很多人的幫助,最應該謝謝havlenapetr。我覺得我現在這些方法算是比較簡潔的了--
下面就盡量詳細的說一下我是怎麼在項目中使用FFmpeg的,但是基於我混亂的表達能力,有不明白的就問我。
你得了解JNI和Android NDK的基本用法,若覺得我的文章還不錯,可以看之前寫的JNI簡單入門和Android NDK入門
首先創建一個標準的Android項目vPlayer
android create project -n vPlayer -t 8 -p vPlayer -k me.abitno.vplayer -a PlayerView
然後在vPlayer目錄里
mkdir jni && cd jni
wget http://ffmpeg.org/releases/ffmpeg-0.6.tar.bz2
tar xf ffmpeg-0.6.tar.bz2 && mv ffmpeg-0.6 ffmpeg && cd ffmpeg
在ffmpeg下新建一個config.sh,內容如下,注意把PREBUILT和PLATFORM設置正確。另外裡面有些參數你也可以自行調整,我主要是為了配置一個播放器而這樣設置的。
#!/bin/bash
PREBUILT=/home/abitno/Android/android-ndk-r4/build/prebuilt/linux-x86/arm-eabi-4.4.0
PLATFORM=/home/abitno/Android/android-ndk-r4/build/platforms/android-8/arch-arm
./configure --target-os=linux \
--arch=arm \
--enable-version3 \
--enable-gpl \
--enable-nonfree \
--disable-stripping \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffserver \
--disable-ffprobe \
--disable-encoders \
--disable-muxers \
--disable-devices \
--disable-protocols \
--enable-protocol=file \
--enable-avfilter \
--disable-network \
--disable-mpegaudio-hp \
--disable-avdevice \
--enable-cross-compile \
--cc=$PREBUILT/bin/arm-eabi-gcc \
--cross-prefix=$PREBUILT/bin/arm-eabi- \
--nm=$PREBUILT/bin/arm-eabi-nm \
--extra-cflags="-fPIC -DANDROID" \
--disable-asm \
--enable-neon \
--enable-armv5te \
--extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"
運行config.sh開始configure
chmod +x config.sh
./config.sh
configure完成後,編輯剛剛生成的config.h,找到這句
#define restrict restrict
Android的GCC不支持restrict關鍵字,於是修改成下面這樣
#define restrict
編輯libavutil/libm.h,把其中的static方法都刪除。
『捌』 怎麼利用ffmpeg實現android播放器
下面把具體編譯步驟描述如下,假定NDK安裝在~/android-ndk-r7:
1. 首先從FFmpeg官網下載最新的release版本源碼ffmpeg-0.11.tar.gz解壓縮到Android源碼樹的ffmpeg/下。
2 准備一個編譯腳本build_android.sh並放在ffmpeg/下面,這個腳本也是Rockplayer提供的,需做一些修改,其內容附在後面。我目前用的也會附在後面。
3 在ffmpeg目錄下運行./build_android.sh開始編譯FFmpeg,編譯好的libffmpeg.so會放在文件夾android裡面,一共有3個版本分別對應3種ARM體系結構,包括armv7-a、armv7-a-vfp、armv6_vfp,根據所運行的硬體平台選取其中一個版本。為了編譯使用FFmpeg的程序時可以方便地找到libffmpeg.so,可將它復制到$OUT/system/lib/和$OUT/obj/lib/,當然這一步也可以加在build_android.sh中做。
4. 接下來就是編譯可執行文件ffmpeg了,這個工具可以在命令行下完成FFmpeg提供的幾乎所有功能包括編碼、解碼、轉碼等,也是用來調試和驗證很有用的工具。其實上述編譯完後在$ANDROID_BUILD_TOP/external/ffmpeg/下也會生成ffmpeg,但是在設備上無法運行。為了編出能在設備上運行的ffmpeg,可以寫一個簡單的Android.mk,
『玖』 如何在Android用FFmpeg+SDL2.0解碼聲音
一、創建一個VideoPicture結構體用來保存解碼出來的圖像;
二、添加數據隊列的初始化、添加以及讀取的函數;
三、audio_decode_frame():解碼音頻;
四、audio_callback(): 回調函數,向SDL緩沖區填充數據;
五、創建視頻刷新相關的函數;
六、添加視頻顯示函數;
七、分配顯示輸出內存空間;
八、解碼線程,將解碼器,建立音頻線,保存重要信息到數據結構中;
九、編寫Main函數用來調用解碼線程。
知識點延伸:
FFmpeg是一個開源免費跨平台的視頻和音頻流方案,屬於自由軟體,採用LGPL或GPL許可證(依據你選擇的組件)。它提供了錄制、轉換以及流化音視頻的完整解決方案。它包含了非常先進的音頻/視頻編解碼庫libavcodec,為了保證高可移植性和編解碼質量,libavcodec里很多codec都是從頭開發的。FFmpeg在Linux平台下開發,但它同樣也可以在其它操作系統環境中編譯運行。
SDL2.0(Simple DirectMedia Layer)是一套開放源代碼的跨平台多媒體開發庫,使用C語言寫成。SDL多用於開發游戲、模擬器、媒體播放器等多媒體應用領域。SDL內置了調用OpenGL的函數。SDL提供了數種控制圖像、聲音、輸出入的函數,讓開發者只要用相同或是相似的代碼就可以開發出跨多個平台(Linux、Windows、Mac OS X等)的應用軟體。