国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Flutter 使用Texture實(shí)現(xiàn)Android渲染視頻

這篇具有很好參考價(jià)值的文章主要介紹了Flutter 使用Texture實(shí)現(xiàn)Android渲染視頻。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

Flutter視頻渲染系列

第一章 Android使用Texture渲染視頻(本章)
第二章 Windows使用Texture渲染視頻
第三章 Linux使用Texture渲染視頻
第四章 全平臺(tái)FFI+CustomPainter渲染視頻
第五章 Windows使用Native窗口渲染視頻
第六章 桌面端使用texture_rgba_renderer渲染視頻



前言

flutter渲染視頻的方法有多種,比如texture、platformview、ffi,其中texture是通過flutter自己提供的一個(gè)texture對(duì)象與dart界面關(guān)聯(lián)后進(jìn)行渲染,很容易搜索到android和ios的相關(guān)資料,但是大部分資料不夠詳細(xì),尤其是jni渲染部分基本都略過了,對(duì)于使用flutter但不熟悉安卓的情況下,是比較難搞清楚通過texure拿到surface之后該怎么渲染。所以本文將說明整體的渲染流程。


一、如何實(shí)現(xiàn)?

1、定義Texture控件

在界面中定義一個(gè)Texture

Container(
  width: 640,
  height: 360,
  child: Texture(
  textureId: textureId,
))

2、創(chuàng)建Texture對(duì)象

java

TextureRegistry.SurfaceTextureEntry entry =flutterEngine.getRenderer().createSurfaceTexture();

3、關(guān)聯(lián)TextureId

dart

  int textureId = -1;
  if (textureId < 0) {
  //調(diào)用本地方法獲取textureId 
  methodChannel.invokeMethod('startPreview',<String,dynamic>{'path':'test.mov'}).then((value) {
  textureId = value;
  setState(() {
  print('textureId ==== $textureId');
  });
  });
  }

java

 //methodchannel的startPreview方法實(shí)現(xiàn),此處略
TextureRegistry.SurfaceTextureEntry entry =flutterEngine.getRenderer().createSurfaceTexture();
result.success(entry.id());

4、寫入rgba

java

TextureRegistry.SurfaceTextureEntry entry = flutterEngine.getRenderer().createSurfaceTexture();
SurfaceTexture surfaceTexture = entry.surfaceTexture();
Surface surface = new Surface(surfaceTexture);
String path = call.argument("path");
//調(diào)用jni并傳入surface
native_start_play(path,surface);

jni c++

ANativeWindow *a_native_window = ANativeWindow_fromSurface(env,surface);
ANativeWindow_setBuffersGeometry(a_native_window,width,height,WINDOW_FORMAT_RGBA_8888);
ANativeWindow_Buffer a_native_window_buffer;   
ANativeWindow_lock(a_native_window,&a_native_window_buffer,0);
uint8_t *first_window = static_cast<uint8_t *>(a_native_window_buffer.bits);
//rgba數(shù)據(jù)
uint8_t *src_data = data[0];
int dst_stride = a_native_window_buffer.stride * 4;
//ffmpeg的linesize
int src_line_size = linesize[0];
for(int i = 0; i < a_native_window_buffer.height;i++){
    memcpy(first_window+i*dst_stride,src_data+i*src_line_size,dst_stride);
}
ANativeWindow_unlockAndPost(a_native_window);

其中jni方法定義:

extern "C" JNIEXPORT void JNICALL Java_com_example_ffplay_1plugin_FfplayPlugin_native_1start_1play( JNIEnv *env, jobject /* this*/,  jstring path,jobject surface) ;

二、示例

1.使用ffmpeg解碼播放

main.dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
MethodChannel methodChannel = MethodChannel('ffplay_plugin');
void main() {
  runApp(MyApp());
}
class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  int textureId = -1;
  Future<void> _createTexture() async {
  print('textureId = $textureId');
  //調(diào)用本地方法播放視頻
  if (textureId < 0) {
  methodChannel.invokeMethod('startPreview',<String,dynamic>{'path':'https://sf1-hscdn-tos.pstatp.com/obj/media-fe/xgplayer_doc_video/flv/xgplayer-demo-360p.flv'}).then((value) {
  textureId = value;
  setState(() {
  print('textureId ==== $textureId');
  });
  });
  }
  }
  @override
  Widget build(BuildContext context) {
  return Scaffold(
  appBar: AppBar(
  title: Text(widget.title),
  ),
  //控件布局
  body: Center(
  child: Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
  if (textureId > -1)
  ClipRect (
  child: Container(
  width: 640,
  height: 360,
  child: Texture(
  textureId: textureId,
  )),
  ),
  ],
  ),
  ),
  floatingActionButton: FloatingActionButton(
  onPressed: _createTexture,
  tooltip: 'createTexture',
  child: Icon(Icons.add),
  ),
  );
  }
}

定義一個(gè)插件我這里是fflay_plugin。
fflayplugin.java

if (call.method.equals("startPreview")) {
      //創(chuàng)建texture
      TextureRegistry.SurfaceTextureEntry entry =flutterEngine.getRenderer().createSurfaceTexture();
      SurfaceTexture surfaceTexture = entry.surfaceTexture();
      Surface surface = new Surface(surfaceTexture);
      //獲取參數(shù)
      String path = call.argument("path");
      //調(diào)用jni開始渲染
      native_start_play(path,surface);
      //返回textureId
      result.success(entry.id());
    }
public native void native_start_play(String path, Surface surface);

native-lib.cpp

extern "C" JNIEXPORT void
JNICALL
Java_com_example_ffplay_1plugin_FfplayPlugin_native_1start_1play(
        JNIEnv *env,
        jobject /* this */,  jstring path,jobject surface) {
    //獲取用于繪制的NativeWindow
    ANativeWindow *a_native_window = ANativeWindow_fromSurface(env,surface);
    //轉(zhuǎn)換視頻路徑字符串為C中可用的
    const char *video_path = env->GetStringUTFChars(path,0);
    //初始化播放器,Play中封裝了ffmpeg
    Play *play=new Play;
    //播放回調(diào)
    play->Display=[=](unsigned char* data[8], int linesize[8], int width, int height, AVPixelFormat format)
        {
        //設(shè)置NativeWindow繪制的緩沖區(qū)
        ANativeWindow_setBuffersGeometry(a_native_window,width,height,WINDOW_FORMAT_RGBA_8888);
        //繪制時(shí),用于接收的緩沖區(qū)
        ANativeWindow_Buffer a_native_window_buffer;
        //加鎖然后進(jìn)行渲染
        ANativeWindow_lock(a_native_window,&a_native_window_buffer,0);
        uint8_t *first_window = static_cast<uint8_t *>(a_native_window_buffer.bits);
        uint8_t *src_data = data[0];
        //拿到每行有多少個(gè)RGBA字節(jié)
        int dst_stride = a_native_window_buffer.stride * 4;
        int src_line_size = linesize[0];
        //循環(huán)遍歷所得到的緩沖區(qū)數(shù)據(jù)
        for(int i = 0; i < a_native_window_buffer.height;i++){
            //內(nèi)存拷貝進(jìn)行渲染
            memcpy(first_window+i*dst_stride,src_data+i*src_line_size,dst_stride);
        }
        //繪制完解鎖
        ANativeWindow_unlockAndPost(a_native_window);
};
    //開始播放
    play->Start(video_path,AV_PIX_FMT_RGBA);
    env->ReleaseStringUTFChars(path,video_path);
}

效果預(yù)覽
android TV橫屏
Flutter 使用Texture實(shí)現(xiàn)Android渲染視頻


三、完整代碼

https://download.csdn.net/download/u013113678/87094784
包含完整代碼的flutter項(xiàng)目,版本3.0.4、3.3.8都成功運(yùn)行,目錄說明如下。
Flutter 使用Texture實(shí)現(xiàn)Android渲染視頻


總結(jié)

以上就是今天要講的內(nèi)容,flutter在安卓上渲染視頻還是相對(duì)容易實(shí)現(xiàn)的。因?yàn)橘Y料比較多,但是只搜索fluter相關(guān)的資料只能了解調(diào)texture的用法,無法搞清楚texture到ffmpeg的串連,我們需要單獨(dú)去了解安卓調(diào)用ffmpeg渲染才能找到的它們之間的關(guān)聯(lián)??偟膩碚f,實(shí)現(xiàn)相對(duì)容易效果也能接受。文章來源地址http://www.zghlxwxcb.cn/news/detail-402245.html

到了這里,關(guān)于Flutter 使用Texture實(shí)現(xiàn)Android渲染視頻的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Flutter視頻播放器在iOS端和Android端都能實(shí)現(xiàn)全屏播放

    Flutter視頻播放器在iOS端和Android端都能實(shí)現(xiàn)全屏播放

    Flutter開發(fā)過程中,對(duì)于視頻播放的三方組件有很多,在Android端適配都挺好,但是在適配iPhone手機(jī)的時(shí)候,如果設(shè)置了 UIInterfaceOrientationLandscapeLeft 和 UIInterfaceOrientationLandscapeRight 都為false的情況下,無法做到全屏播放,因?yàn)镕Lutter的 SystemChrome.setPreferredOrientations 方法不適配iOS端

    2024年02月05日
    瀏覽(38)
  • 【unity shader】水體渲染基礎(chǔ)-基于texture distortion的流體流動(dòng)材質(zhì)

    【unity shader】水體渲染基礎(chǔ)-基于texture distortion的流體流動(dòng)材質(zhì)

    當(dāng)液體靜止時(shí),它在視覺上與固體沒有太大區(qū)別。 但大多數(shù)時(shí)候,我們的性能不一定支持去實(shí)現(xiàn)特別復(fù)雜的水物理模擬, 需要的只是在常規(guī)的靜態(tài)材料的表面上讓其運(yùn)動(dòng)起來。我們可以對(duì)網(wǎng)格的 UV 坐標(biāo)實(shí)現(xiàn)動(dòng)態(tài)變化,從而讓表面的紋理效果實(shí)現(xiàn)變形的動(dòng)態(tài)變化。 1.1. uv實(shí)時(shí)

    2024年02月03日
    瀏覽(28)
  • Android視頻融合特效播放與渲染

    Android視頻融合特效播放與渲染

    一個(gè)有趣且很有創(chuàng)意的視頻特效項(xiàng)目。 https://github.com/duqian291902259/AlphaPlayerPlus 前言 直播產(chǎn)品,需要更多炫酷的禮物特效,比如飛機(jī)特效,跑車特效,生日蛋糕融特效等,融合了直播流畫面的特效。所以在字節(jié)開源的alphaPlayer庫和特效VAP庫的基礎(chǔ)上進(jìn)行改造,實(shí)現(xiàn)融合特效渲染

    2023年04月13日
    瀏覽(26)
  • Flutter 使用 Key 強(qiáng)制重新渲染小部件

    Key 在 Flutter 中是一個(gè)抽象類,它有兩個(gè)主要的子類:LocalKey 和 GlobalKey。LocalKey 只在當(dāng)前小部件樹中唯一,而 GlobalKey 在整個(gè)應(yīng)用程序中是全局唯一的。 Key 的主要作用是標(biāo)識(shí)小部件。當(dāng) Flutter 進(jìn)行小部件樹的重建時(shí),它會(huì)根據(jù) Key 來判斷哪些小部件需要重新創(chuàng)建,哪些小部件

    2024年02月09日
    瀏覽(17)
  • android開發(fā)教程視頻孫老師,flutter中文網(wǎng)

    1.網(wǎng)絡(luò) 2.Java 基礎(chǔ)容器同步設(shè)計(jì)模式 3.Java 虛擬機(jī)內(nèi)存結(jié)構(gòu)GC類加載四種引用動(dòng)態(tài)代理 4.Android 基礎(chǔ)性能優(yōu)化Framwork 5.Android 模塊化熱修復(fù)熱更新打包混淆壓縮 6.音視頻FFmpeg播放器 網(wǎng)絡(luò)協(xié)議模型 應(yīng)用層 :負(fù)責(zé)處理特定的應(yīng)用程序細(xì)節(jié) HTTP、FTP、DNS 傳輸層 :為兩臺(tái)主機(jī)提供端到端

    2024年03月15日
    瀏覽(20)
  • Android 循環(huán)錄像,保留加鎖視頻,flutter框架

    Android 循環(huán)錄像,保留加鎖視頻,flutter框架

    return 0; } } /** 獲取所有的視頻信息 @return */ public List getAllDriveVideo() { List driveVideoList = new ArrayList(); String selectQuery = \\\"SELECT * FROM \\\" + VIDEO_TABLE_NAME; SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(selectQuery, null); // looping through all rows and adding to list if (cursor.moveToFirst()) { do

    2024年04月13日
    瀏覽(19)
  • Android 使用FFmpeg3.3.9基于命令實(shí)現(xiàn)視頻壓縮

    Android 使用FFmpeg3.3.9基于命令實(shí)現(xiàn)視頻壓縮

    前言 首先利用linux平臺(tái)編譯ffmpeg的so庫,具體詳情請(qǐng)查看文章:Android NDK(ndk-r16b)交叉編譯FFmpeg(3.3.9)_jszlittlecat_720的博客-CSDN博客 ? ?點(diǎn)擊Create JNI function for compressVideo 自動(dòng)打開native-lib.cpp并創(chuàng)建完成Java_com_suoer_ndk_ffmpegtestapplication_VideoCompress_compressVideo 方法 ?在此方法下實(shí)現(xiàn)壓縮

    2024年02月02日
    瀏覽(28)
  • Android - 使用GSY實(shí)現(xiàn)視頻播放和畫中畫懸浮窗

    Android - 使用GSY實(shí)現(xiàn)視頻播放和畫中畫懸浮窗

    0. 現(xiàn)完成功能: 懸浮窗區(qū)分橫屏豎屏兩種尺寸 懸浮窗可以在頁面上隨意拖動(dòng) 在播放視頻時(shí)按返回鍵/Home鍵/離開當(dāng)前頁時(shí)觸發(fā)開啟 懸浮窗顯示在退到后臺(tái)/在應(yīng)用內(nèi)/桌面 帶播放進(jìn)度開啟懸浮窗,帶播放進(jìn)度回到應(yīng)用內(nèi)頁面 權(quán)限:每次開啟前判斷有無權(quán)限,沒權(quán)限并且請(qǐng)求過

    2023年04月11日
    瀏覽(24)
  • libVLC 提取視頻幀使用OpenGL渲染

    libVLC 提取視頻幀使用OpenGL渲染

    在上一節(jié)中,我們講解了如何使用QWidget渲染每一幀視頻數(shù)據(jù)。 由于我們不停的生成的是QImage對(duì)象,因此對(duì) CPU 負(fù)荷較高。其實(shí)在繪制這塊我們可以使用 OpenGL去繪制,利用 GPU 減輕 CPU 計(jì)算負(fù)荷,本節(jié)講解使用OpenGL來繪制每一幀視頻數(shù)據(jù)。 libVLC 提取視頻幀使用QWidget渲染-CSDN博

    2024年04月10日
    瀏覽(29)
  • Linux平臺(tái)下基于OpenGL實(shí)現(xiàn)YUV視頻渲染

    源碼詳見https://github.com/samxfb/linux-opengl-render

    2024年01月21日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包