linux otg u盘,android播放外接U盘(OTG)中的视频音频文件(使用vlc)

该博客介绍了在Android环境下,利用JNI和VLC库实现从U盘直接播放视频文件的过程。作者首先通过第三方库libaums读取U盘文件信息,然后在JNI中注册并调用自定义的文件读取方法,将U盘文件流传递给VLC进行播放。文章详细阐述了如何修改VLC源码,替换文件读取操作,使其能处理U盘文件流,避免了获取文件真实路径的复杂性。
摘要由CSDN通过智能技术生成

之前一直想写这篇文章奈何没什么时间(注:本文需要您有一定的JNI基础,C/C++基础,以及在Linux环境下编译vlc的so文件的能力),做的一个关于U盘挂载然后播放里面的视频文件(视频文件经过特定的编码处理,所以我们这边的播放器也是定制,使用的是vlc),其中一个比较蛋疼的地方就是拿到U盘中某个文件的真实路径,然后传入vlc播放,但是现在的厂商的ROM啊................虽然通过判断各种挂载信息有可能拿到真实路径,但是不怎么准确,我这里使用了一个第三方的项目来获取U盘的文件信息以及能够拿到文件流

compile 'com.github.mjdev:libaums:+'

网上也有比较多关于这个库的使用,我就不做赘述了

在U盘插入拔出的时候加个广播然后开始使用这个库读取文件的操作

private BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

public void onReceive(Context context, Intent intent) {

String action = intent.getAction();

switch (action) {

case ACTION_USB_PERMISSION://接受到自定义广播

UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) { //允许权限申请

if (usbDevice != null) { //Do something

Toast.makeText(OtgActivity.this,"用户已授权,可以进行读取操作",Toast.LENGTH_SHORT).show();

readDevice(getUsbMass(usbDevice));

} else {

Toast.makeText(OtgActivity.this,"未获取到设备信息",Toast.LENGTH_SHORT).show();

}

} else {

Toast.makeText(OtgActivity.this,"用户未授权,读取失败",Toast.LENGTH_SHORT).show();

}

break;

case UsbManager.ACTION_USB_DEVICE_ATTACHED://接收到存储设备插入广播

UsbDevice device_add = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

if (device_add != null) {

Toast.makeText(OtgActivity.this,"存储设备已插入,尝试读取",Toast.LENGTH_SHORT).show();

redDeviceList();

}

break;

case UsbManager.ACTION_USB_DEVICE_DETACHED://接收到存储设备拔出广播

UsbDevice device_remove = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);

if (device_remove != null) {

Toast.makeText(OtgActivity.this,"存储设备已拔出",Toast.LENGTH_SHORT).show();

usbFiles.clear();

adapter.notifyDataSetChanged();

cFolder = null;

}

break;

}

}

};

跑题了,跑题了,接下来是我要表达的重点...就是vlc在jni中只提供了传入流的地址和文件的地址,而我们要播放U盘中的视频只能够拿到流(当然你也可以复制到SD卡里面去播放,几个G的视频那...)的情况下有两个思路去播放@1我们将手机自己作为一个服务器,然后拿到地址传到vlc(可以用netty),第二个思路就是播放器播放的时候拿到不也是个流然后进行解封装解码来播放,按照这个思路我们可以进行如下操作...

先定义一个FileRead的文件读取类供jni调用,实际上是vlc里面播放的时候要用,这个后面会说到

public class FileRead {

public static UsbFileInputStream ins = null;

public static UsbFile usbFile = null;

public static RandomAccessFile randomFile = null;

public static void initFile(UsbFile file, int configLength) {

usbFile = file;

ins = new UsbFileInputStream(file);

}

public static int open(String spath) {

return 0;

}

public static long FileSize() {

return usbFile.getLength();

}

public static long seek(long offset) {

try {

if (ins != null) {

ins.close();

ins = new UsbFileInputStream(usbFile);

ins.skip(offset);

}

} catch (IOException e) {

e.printStackTrace();

}

return 0;

}

public static int read(byte[] buffer, long offset, int len) {

int result = 0;

try {

if (ins != null) {

result = ins.read(buffer);

if (result <= 0) result = 0;

}

} catch (IOException e) {

e.printStackTrace();

}

return result;

}

public static void close() {

try {

if (ins != null) {

ins.close();

}

} catch (IOException e) {

e.printStackTrace();

}

}

}

我是直接用的vlc自带的lib库,所以加的jni代码也是在原基础上加的,我这里偷懒直接把我们注册方法写入到他原有的方法里面了,懒得去一个一个写注册了.一步一步来

第一我们要注册声明我们类文件实际上这里也是用的反射获取的

void initClassHelper(JNIEnv *env, const char *path, jobject *objptr) {

jclass cls = (*env)->FindClass(env,path);

if(!cls) {

LOGE("initClassHelper: failed to get %s class reference", path);

return;

}

jmethodID constr = (*env)->GetMethodID(env,cls, "", "()V");

if(!constr) {

LOGE("initClassHelper: failed to get %s constructor", path);

return;

}

jobject obj = (*env)->NewObject(env,cls, constr);

if(!obj) {

LOGE("initClassHelper: failed to create a %s object", path);

return;

}

(*objptr) = (*env)->NewGlobalRef(env,obj);

}

第二步就是我们vlc里面要调用的方法我这里定义为了

libvlc_set_file_callback(vlc_f_open, vlc_f_read, vlc_f_seek, vlc_f_close, vlc_f_length);//这个方法是我们vlc要调用的

第三步就是vlc中各个方法的具体对应调用我们的java方法了

int64_t* vlc_f_open(int64_t *fsize,const char* spath){

JNIEnv* env = jni_get_env("open");

jclass cls = (*env)->GetObjectClass(env,gInterfaceObject);

if (cls != 0)

{

jmethodID mid = (*env)->GetStaticMethodID(env, cls, "open", "(Ljava/lang/String;)I");

if (mid != 0)

{

int result = (*env)->CallStaticIntMethod(env, cls, mid,(*env)->NewStringUTF(env,spath));

(*env)->DeleteLocalRef(env,cls);

return result;

}

}

return 0;

}

int64_t vlc_f_length(){

JNIEnv* env = jni_get_env("length");

jclass cls = (*env)->GetObjectClass(env,gInterfaceObject);

if (cls != 0)

{

jmethodID mid = (*env)->GetStaticMethodID(env, cls, "FileSize", "()J");

if (mid != 0)

{

jlong result = (*env)->CallStaticLongMethod(env, cls, mid);

(*env)->DeleteLocalRef(env,cls);

return result;

}

}

return 0;

}

int vlc_f_read(char* buffer, int64_t offset, int size){

JNIEnv* env = jni_get_env("read");

jclass cls = (*env)->GetObjectClass(env,gInterfaceObject);

if (cls != 0)

{

jmethodID mid = (*env)->GetStaticMethodID(env, cls, "read", "([BJI)I");

if (mid != 0)

{

jbyteArray arr = (*env)->NewByteArray(env,size);

jint result = (*env)->CallStaticIntMethod(env, cls, mid, arr,offset,size);

(*env)->GetByteArrayRegion(env,arr,0,result,buffer);

(*env)->DeleteLocalRef(env,arr);

(*env)->DeleteLocalRef(env,cls);

return result;

}

}

return 0;

}

int vlc_f_seek(int64_t offset){

JNIEnv* env = jni_get_env("offset");

jclass cls = (*env)->GetObjectClass(env,gInterfaceObject);

if (cls != 0)

{

jmethodID mid = (*env)->GetStaticMethodID(env, cls, "seek", "(J)J");

if (mid != 0)

{

jint result = (*env)->CallStaticLongMethod(env, cls, mid,offset);

(*env)->DeleteLocalRef(env,cls);

return result;

}

}

return 0;

}

int vlc_f_close(){

JNIEnv* env = jni_get_env("close");

jclass cls = (*env)->GetObjectClass(env,gInterfaceObject);

if (cls != 0)

{

jmethodID mid = (*env)->GetStaticMethodID(env, cls, "close", "()V");

if (mid != 0)

{

(*env)->CallStaticVoidMethod(env, cls, mid);

(*env)->DeleteLocalRef(env,cls);

return 0;

}

}

return 0;

}

这里的参数类型转换一定要细心,比较容易搞混.

其中获取JNIEnv这个结构体的方法有个坑我把方法贴出来

JNIEnv *jni_get_env(const char *name)

{

JNIEnv *env;

env = pthread_getspecific(jni_env_key);

if (env == NULL) {

if ((*myVm)->GetEnv(myVm, (void **)&env, VLC_JNI_VERSION) != JNI_OK)

{

JavaVMAttachArgs args;

jint result;

args.version = VLC_JNI_VERSION;

args.name = name;

args.group = NULL;

if ((*myVm)->AttachCurrentThread(myVm, &env, &args) != JNI_OK)

return NULL;

if (pthread_setspecific(jni_env_key, env) != 0)

{

(*myVm)->DetachCurrentThread(myVm);

return NULL;

}

}

}

return env;

}

刚开始自己少了一个DetachCurrentThread函数,这个函数的具体作用就是在结束的时候取消我们线程和虚拟机的绑定,在我自己测的几部手机都是没有问题的,但是在乐视的某些手机会直接崩溃...这个问题应该是和手机的cpu有关..不过还是必须要加上的

接下来我们就要修改vlc中的代码了,我都是按照vlc他的各个模块的代码来加的代码..不得不说vlc的代码真的具有艺术性,超高度解耦.

在vlc/lib这个目录下全部都是与jni打交道的.c文件 我是在media.c当中加入

void libvlc_set_file_callback(f_open fo, f_read fr, f_seek fs, f_close fc, f_length fl){

vlc_set_file_callback( fo, fr, fs, fc, fl);

}

至于里面头文件的申明和引用就不用多说了,最后一步就是重点了,如何修改vlc自带的文件的读取方法,我们可以在vlc/modules/access的目录下找到file.c文件 这个文件就是vlc播放时控制流的读取,我们可以先看下当中的部分方法

/*****************************************************************************

* FileOpen: open the file

*****************************************************************************/

int FileOpen( vlc_object_t *p_this )

{

stream_t *p_access = (stream_t*)p_this;

/* Open file */

int fd = -1;

//

if (p_access->file_open)

{

uint64_t i_size = 0;

int result = p_access->file_open(&i_size,p_access->psz_location);

if( result > 0 )

{

access_sys_t *p_sys = vlc_obj_malloc(p_this, sizeof (*p_sys));

char* file_path = p_access->psz_location;

if (unlikely(p_sys == NULL))

goto error;

p_access->pf_read = Read;

p_access->pf_block = NULL;

p_access->pf_control = FileControl;

p_access->p_sys = p_sys;

p_sys->fd = DEFAULT_HANDLE;

p_access->pf_seek = FileSeek;

p_sys->b_pace_control = true;

/* Demuxers will need the beginning of the file for probing. */

posix_fadvise (fd, 0, 4096, POSIX_FADV_WILLNEED);

/* In most cases, we only read the file once. */

posix_fadvise (fd, 0, 0, POSIX_FADV_NOREUSE);

return VLC_SUCCESS;

}

}

if (!strcasecmp (p_access->psz_name, "fd"))

{

char *end;

int oldfd = strtol (p_access->psz_location, &end, 10);

if (*end == '\0')

fd = vlc_dup (oldfd);

else if (*end == '/' && end > p_access->psz_location)

{

char *name = vlc_uri_decode_duplicate (end - 1);

if (name != NULL)

{

name[0] = '.';

fd = vlc_openat (oldfd, name, O_RDONLY | O_NONBLOCK);

free (name);

}

}

}

else

{

if (unlikely(p_access->psz_filepath == NULL))

return VLC_EGENERIC;

fd = vlc_open (p_access->psz_filepath, O_RDONLY | O_NONBLOCK);

}

if (fd == -1)

{

msg_Err (p_access, "cannot open file %s (%s)",

p_access->psz_filepath ? p_access->psz_filepath

: p_access->psz_location,

vlc_strerror_c(errno));

return VLC_EGENERIC;

}

struct stat st;

if (fstat (fd, &st))

{

msg_Err (p_access, "read error: %s", vlc_strerror_c(errno));

goto error;

}

#if O_NONBLOCK

/* Force blocking mode back */

fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) & ~O_NONBLOCK);

#endif

/* Directories can be opened and read from, but only readdir() knows

* how to parse the data. The directory plugin will do it. */

if (S_ISDIR (st.st_mode))

{

#ifdef HAVE_FDOPENDIR

DIR *p_dir = fdopendir(fd);

if (!p_dir) {

msg_Err (p_access, "fdopendir error: %s", vlc_strerror_c(errno));

goto error;

}

return DirInit (p_access, p_dir);

#else

msg_Dbg (p_access, "ignoring directory");

goto error;

#endif

}

access_sys_t *p_sys = vlc_obj_malloc(p_this, sizeof (*p_sys));

if (unlikely(p_sys == NULL))

goto error;

p_access->pf_read = Read;

p_access->pf_block = NULL;

p_access->pf_control = FileControl;

p_access->p_sys = p_sys;

p_sys->fd = fd;

if (S_ISREG (st.st_mode) || S_ISBLK (st.st_mode))

{

p_access->pf_seek = FileSeek;

p_sys->b_pace_control = true;

/* Demuxers will need the beginning of the file for probing. */

posix_fadvise (fd, 0, 4096, POSIX_FADV_WILLNEED);

/* In most cases, we only read the file once. */

posix_fadvise (fd, 0, 0, POSIX_FADV_NOREUSE);

#ifdef F_NOCACHE

fcntl (fd, F_NOCACHE, 0);

#endif

#ifdef F_RDAHEAD

if (IsRemote(fd, p_access->psz_filepath))

fcntl (fd, F_RDAHEAD, 0);

else

fcntl (fd, F_RDAHEAD, 1);

#endif

}

else

{

p_access->pf_seek = NoSeek;

p_sys->b_pace_control = strcasecmp (p_access->psz_name, "stream");

}

return VLC_SUCCESS;

error:

vlc_close (fd);

return VLC_EGENERIC;

}

/*****************************************************************************

* FileClose: close the target

*****************************************************************************/

void FileClose (vlc_object_t * p_this)

{

stream_t *p_access = (stream_t*)p_this;

if (p_access->pf_read == NULL)

{

DirClose (p_this);

return;

}

access_sys_t *p_sys = p_access->p_sys;

if (p_access->file_close && (DEFAULT_HANDLE == p_sys->fd))

{

p_access->file_close();

}

else

{

vlc_close (p_sys->fd);

}

}

static ssize_t Read (stream_t *p_access, void *p_buffer, size_t i_len)

{

access_sys_t *p_sys = p_access->p_sys;

int fd = p_sys->fd;

//ssize_t val = vlc_read_i11e (fd, p_buffer, i_len);

ssize_t val = 0/**/;

if (p_access->file_read && (DEFAULT_HANDLE == p_sys->fd))

{

val = p_access->file_read(p_buffer, 0, i_len);

}

else

{

vlc_read_i11e (fd, p_buffer, i_len);

}

if (val < 0)

{

switch (errno)

{

case EINTR:

case EAGAIN:

return -1;

}

msg_Err (p_access, "read error: %s", vlc_strerror_c(errno));

val = 0;

}

return val;

}

/*****************************************************************************

* Seek: seek to a specific location in a file

*****************************************************************************/

static int FileSeek (stream_t *p_access, uint64_t i_pos)

{

access_sys_t *sys = p_access->p_sys;

if (p_access->file_seek && (DEFAULT_HANDLE == sys->fd))

{

p_access->file_seek(i_pos);

}

else

{

if (lseek(sys->fd, i_pos, SEEK_SET) == (off_t)-1)

return VLC_EGENERIC;

}

return VLC_SUCCESS;

}

static int FileControl( stream_t *p_access, int i_query, va_list args )

{

access_sys_t *p_sys = p_access->p_sys;

bool *pb_bool;

int64_t *pi_64;

switch( i_query )

{

case STREAM_CAN_SEEK:

case STREAM_CAN_FASTSEEK:

pb_bool = va_arg( args, bool * );

*pb_bool = (p_access->pf_seek != NoSeek);

break;

case STREAM_CAN_PAUSE:

case STREAM_CAN_CONTROL_PACE:

pb_bool = va_arg( args, bool * );

*pb_bool = p_sys->b_pace_control;

break;

case STREAM_GET_SIZE:

{ uint64_t i_size = 0;

if(p_access->file_length && (DEFAULT_HANDLE == p_sys->fd))

{

i_size = p_access->file_length();

}

else

{

struct stat st;

fstat (p_sys->fd, &st);

i_size = st.st_size;

}

*va_arg( args, uint64_t * ) = i_size;

break;

}

case STREAM_GET_PTS_DELAY:

pi_64 = va_arg( args, int64_t * );

if (IsRemote (p_sys->fd, p_access->psz_filepath))

*pi_64 = var_InheritInteger (p_access, "network-caching");

else

*pi_64 = var_InheritInteger (p_access, "file-caching");

*pi_64 *= 1000;

break;

case STREAM_SET_PAUSE_STATE:

/* Nothing to do */

break;

default:

return VLC_EGENERIC;

}

return VLC_SUCCESS;

都有对文件的open,seek,read,close的操作,这个时候我们只需要将vlc播放的时候需要open,seek,read,close的操作,传入我们自己定义的方法

int FileOpen( vlc_object_t *p_this )

{

access_t *p_access = (access_t*)p_this;

/* Open file */

int fd = -1;

//cyxhlhaaaaaaaaaa

if (p_access->file_open)

{

uint64_t i_size = 0;

p_access->file_open(&i_size);

access_sys_t *p_sys = malloc(sizeof(*p_sys));

if (unlikely(p_sys == NULL))

goto error;

access_InitFields(p_access);

p_access->pf_block = NULL;

p_access->pf_control = FileControl;

p_access->p_sys = p_sys;

p_sys->fd = 6;

p_access->pf_read = FileRead;

p_access->pf_seek = FileSeek;

p_sys->b_pace_control = true;

p_sys->size = i_size;

/* Demuxers will need the beginning of the file for probing. */

posix_fadvise(fd, 0, 4096, POSIX_FADV_WILLNEED);

/* In most cases, we only read the file once. */

posix_fadvise(fd, 0, 0, POSIX_FADV_NOREUSE);

return VLC_SUCCESS;

}

if (!strcasecmp (p_access->psz_access, "fd"))

{

char *end;

int oldfd = strtol (p_access->psz_location, &end, 10);

if (*end == '\0')

fd = vlc_dup (oldfd);

else if (*end == '/' && end > p_access->psz_location)

{

char *name = decode_URI_duplicate (end - 1);

if (name != NULL)

{

name[0] = '.';

fd = vlc_openat (oldfd, name, O_RDONLY | O_NONBLOCK);

free (name);

}

}

}

else

{

const char *path = p_access->psz_filepath;

if (unlikely(path == NULL))

return VLC_EGENERIC;

msg_Dbg (p_access, "opening file `%s'", path);

fd = vlc_open (path, O_RDONLY | O_NONBLOCK);

if (fd == -1)

{

msg_Err (p_access, "cannot open file %s (%s)", path,

vlc_strerror_c(errno));

dialog_Fatal (p_access, _("File reading failed"),

_("VLC could not open the file \"%s\" (%s)."), path,

vlc_strerror(errno));

}

}

if (fd == -1)

return VLC_EGENERIC;

struct stat st;

if (fstat (fd, &st))

{

msg_Err (p_access, "read error: %s", vlc_strerror_c(errno));

goto error;

}

#if O_NONBLOCK

int flags = fcntl (fd, F_GETFL);

if (S_ISFIFO (st.st_mode) || S_ISSOCK (st.st_mode))

/* Force non-blocking mode where applicable (fd://) */

flags |= O_NONBLOCK;

else

/* Force blocking mode when not useful or not specified */

flags &= ~O_NONBLOCK;

fcntl (fd, F_SETFL, flags);

#endif

/* Directories can be opened and read from, but only readdir() knows

* how to parse the data. The directory plugin will do it. */

if (S_ISDIR (st.st_mode))

{

#ifdef HAVE_FDOPENDIR

DIR *handle = fdopendir (fd);

if (handle == NULL)

goto error; /* Uh? */

return DirInit (p_access, handle);

#else

msg_Dbg (p_access, "ignoring directory");

goto error;

#endif

}

access_sys_t *p_sys = malloc (sizeof (*p_sys));

if (unlikely(p_sys == NULL))

goto error;

access_InitFields (p_access);

p_access->pf_block = NULL;

p_access->pf_control = FileControl;

p_access->p_sys = p_sys;

p_sys->fd = fd;

if (S_ISREG (st.st_mode) || S_ISBLK (st.st_mode))

{

p_access->pf_read = FileRead;

p_access->pf_seek = FileSeek;

p_sys->b_pace_control = true;

p_sys->size = st.st_size;

/* Demuxers will need the beginning of the file for probing. */

posix_fadvise (fd, 0, 4096, POSIX_FADV_WILLNEED);

/* In most cases, we only read the file once. */

posix_fadvise (fd, 0, 0, POSIX_FADV_NOREUSE);

#ifdef F_NOCACHE

fcntl (fd, F_NOCACHE, 0);

#endif

#ifdef F_RDAHEAD

if (IsRemote(fd, p_access->psz_filepath))

fcntl (fd, F_RDAHEAD, 0);

else

fcntl (fd, F_RDAHEAD, 1);

#endif

}

else

{

p_access->pf_read = StreamRead;

p_access->pf_seek = NoSeek;

p_sys->b_pace_control = strcasecmp (p_access->psz_access, "stream");

p_sys->size = 0;

}

return VLC_SUCCESS;

error:

close (fd);

return VLC_EGENERIC;

}

/*****************************************************************************

* FileClose: close the target

*****************************************************************************/

void FileClose (vlc_object_t * p_this)

{

access_t *p_access = (access_t*)p_this;

if (p_access->pf_read == NULL)

{

DirClose (p_this);

return;

}

access_sys_t *p_sys = p_access->p_sys;

//cyxhlhaaaaaaaaaa

if (p_access->file_close)

{

p_access->file_close();

}

//close (p_sys->fd);

free (p_sys);

}

#include

/**

* Reads from a regular file.

*/

static ssize_t FileRead (access_t *p_access, uint8_t *p_buffer, size_t i_len)

{

access_sys_t *p_sys = p_access->p_sys;

int fd = p_sys->fd;

//cyxhlhaaaaaaaaaa

ssize_t val = 0/*read (fd, p_buffer, i_len)*/;

if (p_access->file_read)

{

val = p_access->file_read(p_buffer, p_access->info.i_pos, i_len);

}

if (val < 0)

{

switch (errno)

{

case EINTR:

case EAGAIN:

return -1;

}

msg_Err (p_access, "read error: %s", vlc_strerror_c(errno));

dialog_Fatal (p_access, _("File reading failed"),

_("VLC could not read the file (%s)."),

vlc_strerror(errno));

val = 0;

}

p_access->info.i_pos += val;

p_access->info.b_eof = !val;

if (p_access->info.i_pos >= p_sys->size)

{

//cyxhlhaaaaaaaaaa

uint64_t i_size = p_access->file_length();

if (i_size > 0)

p_sys->size = i_size;

//struct stat st;

//if (fstat (fd, &st) == 0)

//p_sys->size = st.st_size;

}

return val;

}

/*****************************************************************************

* Seek: seek to a specific location in a file

*****************************************************************************/

static int FileSeek (access_t *p_access, uint64_t i_pos)

{

p_access->info.i_pos = i_pos;

p_access->info.b_eof = false;

//cy

if (p_access->file_seek)

{

p_access->file_seek(i_pos);

}

//lseek (p_access->p_sys->fd, i_pos, SEEK_SET);

return VLC_SUCCESS;

}

/**

* Reads from a non-seekable file.

*/

static ssize_t StreamRead (access_t *p_access, uint8_t *p_buffer, size_t i_len)

{

access_sys_t *p_sys = p_access->p_sys;

int fd = p_sys->fd;

#if !defined (_WIN32) && !defined (__OS2__)

ssize_t val = net_Read (p_access, fd, NULL, p_buffer, i_len, false);

#else

ssize_t val = read (fd, p_buffer, i_len);

#endif

if (val < 0)

{

switch (errno)

{

case EINTR:

case EAGAIN:

return -1;

}

msg_Err (p_access, "read error: %s", vlc_strerror_c(errno));

val = 0;

}

p_access->info.i_pos += val;

p_access->info.b_eof = !val;

return val;

}

static int NoSeek (access_t *p_access, uint64_t i_pos)

{

/* assert(0); ?? */

(void) p_access; (void) i_pos;

return VLC_EGENERIC;

}

/*****************************************************************************

* Control:

*****************************************************************************/

static int FileControl( access_t *p_access, int i_query, va_list args )

{

access_sys_t *p_sys = p_access->p_sys;

bool *pb_bool;

int64_t *pi_64;

switch( i_query )

{

case ACCESS_CAN_SEEK:

case ACCESS_CAN_FASTSEEK:

pb_bool = (bool*)va_arg( args, bool* );

*pb_bool = (p_access->pf_seek != NoSeek);

break;

case ACCESS_CAN_PAUSE:

case ACCESS_CAN_CONTROL_PACE:

pb_bool = (bool*)va_arg( args, bool* );

*pb_bool = p_sys->b_pace_control;

break;

case ACCESS_GET_SIZE:

{

//cyxhlhaaaaaaaaaa

//struct stat st;

//if (fstat (p_sys->fd, &st) == 0)

//p_sys->size = st.st_size;

uint64_t i_size = p_access->file_length();

if (i_size > 0)

p_sys->size = i_size;

*va_arg( args, uint64_t * ) = p_sys->size;

break;

}

case ACCESS_GET_PTS_DELAY:

pi_64 = (int64_t*)va_arg( args, int64_t * );

if (IsRemote (p_sys->fd, p_access->psz_filepath))

*pi_64 = var_InheritInteger (p_access, "network-caching");

else

*pi_64 = var_InheritInteger (p_access, "file-caching");

*pi_64 *= 1000;

break;

case ACCESS_SET_PAUSE_STATE:

/* Nothing to do */

break;

default:

return VLC_EGENERIC;

}

return VLC_SUCCESS;

}

里面修改的地方我已经做了注释了,也没什么好说明的,这篇文章主要给大家提供一个解决的思路,遇到的这种需求的人应该比较少,不过也是对技术的提升

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值