android - videoview 中的 xamarin.android 视频流
问题描述
我正在使用此链接加密我的视频并将其存储在我的应用程序文件夹中。但是对于大视频来说,2GB,解密然后播放需要很长时间。所以用户必须等待 1.5-2 分钟才能解密选定的视频然后播放。
为此,我搜索了离线视频流。我发现了这个。我有同样的场景,但我不是下载,而是从画廊加密视频。我使用了不同的加密算法。
当我尝试上面的链接时,每次进入 while 循环时我的连接都会丢失。在捕获中,我得到Connection is reset
错误。我也没有在那里得到一些变量。比如, total
,readbyte
和pos
变量。有人可以解释一下吗?
我真的很想同时解密和播放视频。所以用户体验会很好。
谢谢你。
编辑 这是我的示例代码:
using Android.App;
using Android.Widget;
using Android.OS;
using Android.Support.V7.App;
using Java.IO;
using Javax.Crypto;
using Javax.Crypto.Spec;
using System;
using System.IO;
using Java.Net;
using System.Threading.Tasks;
namespace SecretCalc
{
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme",
MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
VideoView video;
Button encrypt, decrypt;
private string sKey = "0123456789abcdef";//key,
private string ivParameter = "1020304050607080";
string path = "/sdcard/Download/";
string destpath = "/sdcard/test/";
string filename = "video1.mp4";
Stream outputStream;
string date = "20180922153533.mp4"; // Already Encrypted File Name
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
video = FindViewById<VideoView>(Resource.Id.videoView);
encrypt = FindViewById<Button>(Resource.Id.btnEncrypt);
decrypt = FindViewById<Button>(Resource.Id.btnDecrypt);
encrypt.Click += Encrypt_Click;
decrypt.Click += Decrypt_ClickAsync;
}
private async void Decrypt_ClickAsync(object sender, EventArgs e)
{
video.SetVideoPath("http://0.0.0.0:9990/");
video.Prepared += Video_Prepared;
await Task.Run(() =>
{
try
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.Bind(new InetSocketAddress("0.0.0.0", 9990));
// this is a blocking call, control will be blocked until client sends the request
Socket finalAccept = serverSocket.Accept();
outputStream = finalAccept.OutputStream;
}
catch (Exception ex)
{
}
});
await Task.Run(() => DecryptThroughSocket());
}
private void Video_Prepared(object sender, EventArgs e)
{
video.Start();
}
private bool DecryptThroughSocket()
{
try
{
byte[] raw = System.Text.Encoding.Default.GetBytes(sKey);
byte[] iv = System.Text.Encoding.Default.GetBytes(ivParameter);
int count = 0, pos = 0, total = 0, readbyte;
byte[] data = new byte[1024 * 1024];
readbyte = data.Length;
long lenghtOfFile = new Java.IO.File(Path.Combine(path, date)).Length();
FileInputStream inputStream = new FileInputStream(Path.Combine(destpath, date));
while ((count = inputStream.Read(data, 0, readbyte)) != -1)
{
if (count < readbyte)
{
if ((lenghtOfFile - total) > readbyte)
{
while (true)
{
int seccount = inputStream.Read(data, pos, (readbyte - pos));
pos = pos + seccount;
if (pos == readbyte)
{
break;
}
}
}
}
// encrypt data read before writing to output stream
byte[] decryptedData = decryptFun(raw, iv, data);
outputStream.Write(decryptedData,0,decryptedData.Length);
}
}
catch (Exception ex)
{
return false;
}
return true;
}
private void Encrypt_Click(object sender, EventArgs e)
{
try
{
FileInputStream inputStream = new FileInputStream(System.IO.Path.Combine(path, filename));
date = DateTime.Now.ToString("yyyyMMddHHmmss") + ".mp4";
DirectoryInfo dir = new DirectoryInfo(destpath);
if (!dir.Exists)
{
Directory.CreateDirectory(destpath);
}
FileOutputStream outputStream = new FileOutputStream(System.IO.Path.Combine(destpath, date));
byte[] raw = System.Text.Encoding.Default.GetBytes(sKey);
byte[] iv = System.Text.Encoding.Default.GetBytes(ivParameter);
int count = 0, pos = 0, total = 0, readbyte;
byte[] data = new byte[1024 * 1024];
readbyte = data.Length;
long lenghtOfFile = new Java.IO.File(Path.Combine(path, filename)).Length();
while ((count = inputStream.Read(data, 0, readbyte)) != -1)
{
if (count < readbyte)
{
if ((lenghtOfFile - total) > readbyte)
{
while (true)
{
int seccount = inputStream.Read(data, pos, (readbyte - pos));
pos = pos + seccount;
if (pos == readbyte)
{
break;
}
}
}
}
total += count;
// encrypt data read before writing to output stream
byte[] encryptedData = encryptFun(raw, iv, data);
outputStream.Write(encryptedData);
}
}
catch (Exception ex)
{
}
}
public static byte[] encryptFun(byte[] key, byte[] iv, byte[] clear)
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.GetInstance("AES/CTR/NoPadding");
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.Init(CipherMode.EncryptMode, skeySpec, ivspec);
byte[] encrypted = cipher.DoFinal(clear);
return encrypted;
}
public static byte[] decryptFun(byte[] key, byte[] iv, byte[] encrypted)
{
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.GetInstance("AES/CTR/NoPadding");
IvParameterSpec ivspec = new IvParameterSpec(iv);
cipher.Init(CipherMode.DecryptMode, skeySpec, ivspec);
byte[] decrypted = cipher.DoFinal(encrypted);
return decrypted;
}
}
}
解决方案
推荐阅读
- c# - UWP - 语言变更
- php - Laravel Forge 上的 Laravel Nova 错误 403 页面
- java - 我如何返回答案?
- java - 为什么我们不能将@ColumnTransformer 应用于@Id(主键)字段?
- virtual-machine - 如果我在 Oracle Virtualbox 上部署我的网络功能意味着我遵循 NFV 标准
- javascript - 仅为混合图表中的特定图表类型启用数据标签
- sql - Allen Browne 的 ConcatRelated() 错误 3061:参数太少
- twitter-bootstrap-3 - 如何将引导程序从版本 4 降级到 3?
- r - Pheatmap:在完整矩阵上进行层次聚类,但只显示行的子集
- django-rest-framework - 在 Django Rest Framework 中覆盖 list() 是一个好习惯吗?