记录技术 分享生活

一个不知道该写什么的人

记录技术 分享生活

函数statfstatfstatatlstat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <sys/stat.h>

int stat(const char *restrict pathname, struct stat *restrict buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *restrict pathname, struct stat *restrict buf);
int lstat(int fd, const char *restrict pathname, struct stat *restrict buf, int flag);

/* 所有4个函数的返回值:若成功,返回0;若出错,返回-1 */

sturct stat {
mode_t st_mode; /* file type & mode (permissions) */
ino_t st_ino; /* i-node number (serial number) */
dev_t st_dev; /* device number (file system) */
dev_t st_rdev; /* device number for special files */
nlink_t st_nlink; /* number of links */
uid_t st_uid; /* user ID of links */
gid_t st_gid; /* group ID of owner */
off_t st_size; /* size in bytes, for regular files */
struct timespec st_atime; /* time of last access */
struct timespec st_mtime; /* time of last modification */
struct timespec st_ctime; /* time of last file status change */
blksize_t st_blksize; /* best I/O block size */
blkcnt_t st_blocks; /* number of disk blocks allocated */
}
  • 函数stat:返回pathname命名文件有关的信息结构;
  • 函数fstat:返回在描述符fd上打开文件的有关信息;
  • 函数lstat:类似于函数stat,但当命名的文件是一个符号链接时,lstat返回该符号连接的有关信息;
  • 函数fstatat:为一个相对于当前打开目录(由fd参数指向)的路径名返回文件统计信息。

文件信息包含stat结构的st_mode成员中。可以下表中的宏文件确定文件的类型。

文件类型
S_ISREG() 普通文件
S_ISDIR() 目录文件
S_ISCHR() 字符特殊文件
S_ISBLK() 块特殊文件
S_ISFIFO() 管道或FIFO
S_ISLNK() 符号链接
S_ISSOCK() 套接字

文件类型

文件类型包括如下几类:

  1. 普通文件(regular file):包含了某种形式的数据;
  2. 目录文件(directory file):包含了其他文件的名字以及指向与这些文件有关信息的指针;
  3. 块特殊文件(block special file):该类型文件提供对设备(如磁盘)带缓冲的访问,每次访问以固定长度为单位进行;
  4. 字符特殊文件(character special file):该文件提供对设备不带缓冲的访问,每次访问长度不变。系统中的所有设备要么是字符特殊文件,要么是块特殊文件。
  5. FIFO:该文件用于进程通信,也称为命名管道(named pipe);
  6. 套接字(socket):该文件用于进程间的网络通信,也可以用在一台宿主机上进程间的非网络通信。
  7. 符号链接(symbolic link):该文件指向另一个文件。

设置用户ID和设置组ID

  • 实际用户ID和实际组ID标识我们究竟是谁。
  • 有效用户ID、有效组ID以及附属组ID决定了我们的文件访问权限。
  • 保存的设置用户ID和保存的设置组ID在执行一个程序时包含了有效用户ID和有效组ID的副本。

每个文件有一个所有者和组所有者,所有者由stat结构中的st_uid指定,组所有者则由st_gid指定。

文件访问权限

所有文件类型(目录、字符特别文件等)都有访问权限(access permisiion)。

st_mode屏蔽 含义
S_IRUSR 用户都
S_IWUSR 用户写
S_IXUSR 用户执行
S_IRGRP 组读
S_IWGRP 组写
S_IXGRP 组执行
S_IROTH 其他读
S_IWOTH 其他写
S_IXOTH 其他执行

函数accessfaccessat

1
2
3
4
#include <unistd.h>
int access(const char *pathname, int mode);
int faccessat(int fd, const char *pathname, int mode, int flag);
/* 两个函数的返回值:若成功,返回0;若出错,返回-1 */

accessfaccessat函数是按实际用户ID和实际组ID进行访问权限测试的。

mode 说明
R_OK 测试读权限
W_OK 测试写权限
X_OK 测试执行权限

函数umask

umask函数为进程设置文件模式创建屏蔽字(mask for the process),并返回之前的值。(这是少数几个没有出错返回函数中的一个。)

1
2
3
4
#include <sys/stat.h>

mode_t umask(mode_t cmask);
/* 返回值:之前的文件模式穿件屏蔽字 */

参数cmask是由上上个表列出的9个常量(S_IRUSR、S_IWUSR等)中若干个按位“或”构成的。

屏蔽位 含义
0400 用户读
0200 用户写
0100 用户执行
0040 组读
0020 组写
0010 组执行
0004 其他读
0002 其他写
0001 其他执行

函数chmodfchmodfchmodat

1
2
3
4
5
6
#include <sys/stat.h>

int chomd(const char *pathname, mode_t mode);
int fchome(int fd, mode_t mode);
int fchomdat(int fd, const char *pathname, mode_t mode, int flag);
/* 3个函数返回值:若成功,返回0;若出错,返回-1 */

chmod函数在指定的文件上进行操作,而fchmod函数则对已打开的文件进行操作。
fchomdat函数与chmod函数在下面两种情况下是相同的:一种是pathname参数为绝对路径,另一种是fd参数取值为AT_FDCWDpathname参数为相对路径。否则,fchmodat计算相对于打开目录(由fd参数指向)的pathname。flag参数可以用于改变fchmodat的行为,当设置了AT_SYMLIN_NOFOLLOW标志时,fchmodat并不会跟随符号链接。

mode 说明
S_ISUID 执行时设置用户ID
S_ISGID 执行时设置组ID
S_ISVTX 保存正文(粘着位)
S_IRWXU 用户(所有者)读、写和执行
S_IRUSR 用户(所有者)读
S_IWUSR 用户(所有者)写
S_IXUSR 用户(所有者)执行
S_IRWXG 组读、写和执行
S_IRGRP 组读
S_IWGRP 组写
S_IXGRP 组执行
S_IRWXO 其他读、写和执行
S_IROTH 其他读
S_IWOTH 其他写
S_IXOTH 其他执行

粘着位(sticky bit)

S_ISVTX位被称为粘着位:如果一个可执行的程序文件的这一位被设置了,那么当程序第一次被执行,在其终止时,程序正文的一个副本仍被保存在交换区。
后来的UNIX版本称为它为保存正文位(saved-text bit),因此也就有了常量S_ISVTX

函数chownfchownfchownatlchown

下面几个chown函数可用于更改文件的用户ID和组ID。如果两个参数ownergroup中的任意一个是-1,则对应的ID不变。

1
2
3
4
5
6
7
8
9
#include <unistd.h>

int chown(const char *pathname, uid_t owner, git_t group);
int fchown(int fd, uid_t owner, gid_t group);
int fchownat(int fd, const char *pathname, uid_t owner, gid_t group, int flag);
int lchown(const char *pathname, uid_t owner, gid_t group);
/*
* 4个函数的返回值:若辰宫,返回0;若出错,返回-1
*/

文件长度

stat结构成员st_size表示以字节为单位的单位长度。只对普通文件、目录文件和符号连接有效。

文件中的空洞

空洞是由所设置的偏移量超过文件端尾,并写入了某些数据后造成的。

文件截断

1
2
3
4
5
6
7
#include <unistd.h>

int truncate(const char *pathname, off_t length);
int ftruncate(int fd, off_t length);
/*
* 两个函数的返回值:若成功,返回0;若失败,返回-1
*/

如果该文件以前的长度大于length,则超过length以外的数据就不能再访问。如果以前的长度小于length,文件长度将增加,在以前的文件尾端和新的文件尾端之间的数据将读作0。

文件系统

函数linklinkatunlinkunlinkatremove

1
2
3
4
5
#include <unistd.h>

int link(const char *existingpath, const char *newpath);
int linkat(int efd, const char *existingpath, int nfd, const char *newpath, int flag);
/* 两个函数的返回值:若成功,返回0;若出错,返回-1 */

这两个函数创建一个新目录项newpath,它引用现有文件existingpath。如果newpath已存在,则返回出错。
对于linkat函数,现有文件是通过efdexistingpath指定,新的路径名是通过nfdnewpath指定的。

1
2
3
4
5
#include <unistd.h>

int unlink(const char *pathname);
int unlinkat(int fd, const char *pathname, int flag);
/* 两个函数的返回值:若成功,返回0;若出错,返回-1 */

这两个函数删除目录项,并将由pathname所引用的链接数减1。

1
2
3
4
#include <stdio.h>

int remove(const char *pathname);
/* 返回值:若成功,返回0;若失败,返回-1 */

函数renamerenameat

1
2
3
4
#include <stdio.h>

int rename(const char *oldname, const char *newname);
int renameat(int oldfd, const char *oldname, int newfd, const char *newname);
  1. 如果oldname指的是一个文件而不是目录,那么为该文件或符号连接重命名。
  2. 如果oldname指的是一个空目录,那么为该目录重命名。
  3. 如果oldnamenewname引用符号连接,则处理的是符号链接本身,而不是它引用的文件。
  4. 不能对...重命名。
  5. 作为一个特例,如果oldnamenewname引用同意文件,则函数不做任何更改而成功返回。

符号链接

符号链接是对一个文件的间接指针。符号链接以及它指向何种对象并无任何文件系统限制,任何用户都可以创建指向目录的符号连接。

创建和读取符号连接

1
2
3
4
5
#include <unistd.h>

int symlink(const char *actualpath, const char *sympath);
int symlinat(const char *acutalpath, int fd, const char *symptah);
/* 两个函数的返回值:若成功,返回0;若出错,返回-1 */
1
2
3
4
5
#include <unistd.h>

ssize_t readlink(const char *actualpath, const char *symptah);
sszie_t readlinkat(int fd, const char* restrict pathname, char *restrict buf, size_t bufsize);
/* 两个函数的返回值:若成功,返回读取的字节数;若出错,返回-1 */

文件时间

字段 说明 例子 ls(1)选项
st_atim 文件数据的最后访问时间 read -u
st_mtim 文件数据的最后修改时间 write 默认
st_ctim i节点状态的最后更改时间 chomd、chown -c

函数futimensutimensatutimes

1
2
3
4
5
#include <sys/stat.h>

int futimens(int fd, const struct timespec times[2]);
int utimensat(int fd, const char *path, const struct timespec times[2], int flag);
/* 两个函数返回值:若成功,返回0;若出错,返回-1 */

函数mkdirmkdiratrmdir

两个函数创建一个新目录。

1
2
3
4
5
#include <sys/stat.h>

int mkdir(const char *pathname, mode_t mode);
int mkdir(int fd, const char *pathname, mode_t mode);
/* 两个函数返回值:若成功,返回0;若出错,返回-1 */

rmdir函数可以创建一个空目录。

1
2
3
4
#include <unistd.h>

int rmdir(const char *pathname);
/* 返回值:若成功,返回0;若失败,返回-1 */

读目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <dirent.h>

DIR *opendir(const char *pathname);
DIR *fdopendir(int fd);
/* 两个函数返回值:若成功,返回指针;若出错,返回NULL */

struct dirent *readdir(DIR *dp);
/* 返回值:若成功,返回指针;若在目录尾或出错,返回NULL */

void rewinddir(DIR *dp);
int closeddir(DIR *dp);
/* 返回值:若成功,返回0;若失败,返回-1 */

long telldir(DIR *dp);
/* 返回值:与dp关联的相关位置 */

void seekdir(DIR *dp, long loc);

函数chdirfchdirgetcwd

1
2
3
4
5
#include <unistd.h>

int chdir(const char *pathname);
int fchdir(int fd);

进程调用chdirfchdir函数更改当前工作目录。

1
2
3
#include <unistd.h>

char *getcwd(char *buf, size_t size);

逐层上移,直到遇到根,得到当前工作目录完整的绝对路径。
必须像此函数传递两个函数,一个是缓冲区地址buf(要有足够的长度容纳绝对路径再加上一个终止null字节),另一个是缓冲区的长度size(以字节为单位)。

文件描述符

所有打开的文件都通过文件描述符(一个非负整数)引用。

维基百科上对于文件描述符的解释是这样的:

文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。

当读、写一个文件时,使用opencreat返回的文件描述符标识该文件,将其作为参数传给readwrite

在POSIX.1的应用程序中,文件描述符0与进程的标准输入关联(STDIN_FILENO)、文件描述符1与进程的标准输出关联(STDOUT_FILENO)、文件描述符2与进程的标准错误关联(STDERR_FILENO),且已经确定化。
文件描述符的变化范围是0~OPEN_MAX-1

函数openopenat

1
2
3
4
5
6
7
8
9
#include <fcntl.h>
int open(const char *path, int oflag, ... /* mode_t mode */);
int openat(int fd, const char *path, int oflag, ... /* mode_t mode */);
/*
*path :文件的名称,可以包含(绝对和相对)路径
*flags:文件打开模式
*mode:用来规定对该文件的所有者,文件的用户组及系 统中其他用户的访问权限
*/
/* 两函数的返回值: 若成功,返回文件描述符; 若出错,返回-1 */
打开方式 描述
O_RDONLY 只读打开.
O_WRONLY 只写打开.
O_RDWR 读、写打开.
O_EXEC 只执行打开.
O_SEARCH 只搜索打开 (应用于目录).
O_APPEND 每次写时都追加到文件的尾端.
O_CLOEXEC 设置FD_CLOEXEC文件描述符.
O_CREAT 若此文件不存在则创建它.
O_DIRECTORY 如果path引用的不是目录,则出错.
O_EXCL 如果同时指定了O_CREAT,而文件已存在,则出错.
O_NOCTTY 如果path引用的是终端设备,则不将该设备分配作为此进程的控制终端.
O_NOFOLLOW 如果path引用的是一个符号连接,则出错.
O_NONBLOCK 如果path引用的是一个FIFO、一个块特殊文件或一个自负特殊文件,则此选项为文件的本次打开操作和后续的I/O操作设置非阻塞方式.
O_SYNC 使每次write等待物理I/O完成,包括由该write操作引起的文件属性更新所需的I/O.
O_TRUNC 如果此文件存在,而且为只写或读-写成功打开,则将其长度截断为0.
O_TTY_INIT 如果打开一个还未打开的终端设备,设置非标准termios参数值,使其符合Single UNIX Specification.
O_DSYNC 使每次write要等待物理I/O完成,但是如果该写操作并不影响读取刚写入的数据,则不需等待文件属性被更新.
O_RSYNC 使每一个一文件描述符作为参数进行的read操作等待,直至所有对文件同一部份挂起的写操作都完成.

fd参数吧openopenat函数区分开,共有3种可能性。

  1. path参数指定的是绝对路径名,在这种情况下,fd参数被忽略,openat函数就相当于open函数。
  2. path参数指定的是相对路径名,fd参数指出了相对路径名在文件系统中的开始地址。fd参数是通过打开相对路径名所在的目录来获取。
  3. path参数指定了相对路径名,fd参数具有特殊值AT_FDCWD。在这种情况下,路径名在当前工作目录中获取,openat函数在操作上与open函数类似。

函数creat

调用函数creat创建一个新的文件

1
2
3
4
#include <fcntl.h>

int creat(const char *path, mode_t mode);
/* 返回值: 若成功,返回为只写打开的文件描述符;如出错,返回-1 */

等效于:

1
open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);

函数close

调用close函数关闭一个打开文件

1
2
3
#include <unistd.h>
int close(int fd);
/* 返回值:若成功,返回0;如出错,返回-1 */

函数lseek

当前文件偏移量(current file offset):它通常是一个非负整数,用以度量从文件开始处计算的字节数。

调用lseek显式的为一个打开文件设置偏移量。

1
2
3
4
#include <unistd.h>

off_t lseek(int fd, off_t offset, int whence);
/* 返回值:若辰宫,返回新的文件偏移量;若出错,返回-1 */

对参数offset的解释与参数whence的值有关。

  • whenceSEEK_SET,则经该文件的偏移量设置为距文件开始处offset个字节。
  • whenceSEEK_CUR,则经该文件的偏移量设置为其当前量增加offsetoffset可为正或负。
  • whenceSEEK_END,则经该文件的偏移量设置为文件长度加offsetoffset可正可负。

函数read

调用read函数从打开文件中读数据。

1
2
3
4
#include <unistd.h>

ssize_t read(int fd, void *buf, size_t nbytes);
/* 返回值:读到的字节数,若已到文件尾,返回0;若出错,返回-1 */

有多种情况可使实际读到的字节数少于要求读的字节数:

  • 读到普通文件时,在读到要求字计数之前已到达了文件微端。
  • 当从终端设备读时,通常一次最多读一行。
  • 当从网络读时,网络中的缓冲机制可能造成返回值小于所要求的字节数。
  • 当从管道或FIFO读时,如若管道包含的字节少于所需的数量,那么read将只返回实际可用的字节数。
  • 当从某些面向记录的设备读时,一次最多返回一个记录。
  • 当一信号造成中断,而已经读到部分数据量时。

函数write

调用write函数向打开文件写数据。

1
2
3
4
#include <unistd.h>

ssize_t write(int fd, const void *buf, size_t nbytes);
/* 返回值:若成功,返回已写的字节数;若出错,返回-1 */

函数preadpwrite

1
2
3
4
5
6
7
#include <unistd.h>

ssize_t pread(int fd, void *buf, size_t nbytes. off_t offset);
/* 返回值:读到的字节数,若已到文件尾,返回0;若出错,返回-1 */

ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset);

调用pread相当于调用lseek后调用read,但是pread又与这种顺序调用有下列重要区别。

  • 调用pread时,无法中断其定位和都读操作。
  • 不更新当前文件偏移量。
    调用pwrite相当于调用lseek后调用write,但也与它们有类似的区别。

原子操作(atomic operation);指的是由多步组成一个一个操作。如果该操作原子地执行,则要么执行所有步骤,要么一步也不执行,不可能只执行所有步骤的一个子集。

函数dupdup2

复制一个现有的文件描述符

1
2
3
4
5
#include <unistd.h>

int dup(int fd);
int dup2(int fd, int fd2);
/* 两函数的返回值:若成功,返回新的文件描述符;如出错,返回-1 */

函数syncfsyncfdatasync

内核通常先将数据复制到缓冲区中,然后排入队列,晚些时候写入磁盘。这种方法被称为延迟写(delayed write).

1
2
3
4
5
6
7
#include <unitstd.h>

int fsync(int fd);
int fdatasync(int fd);
/* 返回值:若成功,返回0;若出错,返回-1 */

void sync(void);

sync只是将所有修改过的块缓冲区排入写队列,然后就返回,它并不等待实际写磁盘操作结束。
fsync函数只对由文件描述符fd指定的一个文件起作用,并且等待写磁盘操作结束才返回。
fdatasync函数类似于fsync,但它只影响文件的数据部分。

函数fcntl

改变已经打开文件的属性。

1
2
3
4
#include <fcntl.h>

int fcntl(int fd, int cmd, ... /* int arg */);
/* 返回值:若成功,则依赖cmd,若出错,返回-1 */

fcntl函数有以下5种功能。

  1. 复制一个已有的描述符 (cmd=F_DUPFDF_DUPFD_CLOEXEC)。
  2. 获取/设置文件描述符标志 (cmd=F_GETFDF_SETFD)。
  3. 获取/设置文件状态标志 (cmd=F_GETFLF_SETFL)。
  4. 获取/设置异步I/O所有权 (cmd=F_GETOWNF_SETOWN)。
  5. 获取/设置记录锁 (cmd=F_GETLKF_SETLKW)。

|cmd|功能
|
|——|:—————————————————-|
|F_DUPFD|复制文件描述符fd。|
|F_DUPFD_CLOEXEC|复制文件描述符,设置与新描述符关联的FD_CLOEXEC文件描述符标志的值,返回新文件描述符。|
|F_GETFD|对应于fd的文件描述符标志作为函数值返回。|
|F_SETFD|对于fd设置文件描述符标志。|
|F_GETFL|对应于fd的文件状态标志作为函数值返回。|
|F_SETFL|将文件状态标志设置为第3个参数的值。可以更改的几个标志是:O_APPENDO_NONBLOCKO_SYNCO_DSYNCO_RSYNCO_FSYNC、和O_ASYNC。|
|F_GETOWN|获取当前接收SIGIOSIGURG信号进程ID或进程组ID。|
|F_SETOWN|设置接收SIGIOSIGURG信号的进程ID或进程组ID。|

函数ioctl

1
2
3
4
5
6
#include <unistd.h> /* System V */

#include <sys/ioctl.h> /* BSD and Linux */

int ioctl(int fd, int request, ...);
/* 返回值:若出错,返回-1;若成功,返回其他值 */

/dev/fd

较新的系统都提供名为/dev/fd的目录,其目录项是名为0、1、2等的文件。打开文件/dev/fdn等效于复制描述符n(假设描述符n是打开的).

下载源代码

我们在学习APUE这本书的时候,总会见到书上的源代码总会引用apue.h这个头文件,这个并不是Linux系统自带的。所以,我们要自己编译。
我们在http://www.apuebook.com/src.3e.tar.gz下载源代码后,解压。

1
tar -zxvf src.3e.tar.gz

然后编译

1
sudo make

但是在编译过程中,会出现错误,错误部分的log是这样的。

1
2
3
4
5
6
7
8
9
gcc -ansi -I../include -Wall -DLINUX -D_GNU_SOURCE  badexit2.c -o badexit2  -L../lib -lapue -pthread -lrt -lbsd
/usr/bin/ld: cannot find -lbsd
collect2: ld returned 1 exit status
Makefile:31: recipe for target 'badexit2' failed
make[1]: *** [badexit2] Error 1
make[1]: Leaving directory '/home/pi/apue.3e/threads'
Makefile:6: recipe for target 'all' failed

make: *** [all] Error 1

修复

出现这个错误是因为,我们缺少一个库。

1
sudo apt-get inatall libbsd-dev

安装完成后,重新进行编译.

1
cp ./include/apue.h ./lib/error.c /usr/include

然后,在/usr/include/apue.hifdefendif中间添加#include "error.c",就可以在编写的程序中,愉快的使用apue.h了。

新年快乐~

在新的一年里,希望我能入门C++,哈哈哈哈哈哈哈哈哈哈哈哈

VLC的官方网站,VLC的源代码是用C语言实现的。我们这里用C#的封装——nVLC。
nVLC

开始

在运行本程序之前,请先安装VLC,或者拷贝libvlc.dlllibvlccode.dllplugins目录到你的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
using System;
using System.Windows.Forms;
using Declarations;
using Declarations.Enums;
using Declarations.Media;
using Declarations.Players;
using Implementation;

namespace nVLC_Demo_MemoryInputOutput
{
public partial class Form1 : Form
{
IMediaPlayerFactory m_factory;
IVideoPlayer m_sourcePlayer;
IVideoPlayer m_renderPlayer;
IMemoryInputMedia m_inputMedia;
const long MicroSecondsInSecomd = 1000 * 1000;
long MicroSecondsBetweenFrame;
long frameCounter;
FrameData data = new FrameData() { DTS = -1 };
const int DefaultFps = 24;
Timer timer = new Timer();

public Form1()
{
InitializeComponent();
timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 1000;
}

void timer_Tick(object sender, EventArgs e)
{
this.Text = m_inputMedia.PendingFramesCount.ToString();
}

protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

m_factory = new MediaPlayerFactory(true);
m_sourcePlayer = m_factory.CreatePlayer<IVideoPlayer>();
m_sourcePlayer.Events.PlayerPlaying += new EventHandler(Events_PlayerPlaying);
m_sourcePlayer.Mute = true;
m_renderPlayer = m_factory.CreatePlayer<IVideoPlayer>();
m_renderPlayer.WindowHandle = panel1.Handle;
m_inputMedia = m_factory.CreateMedia<IMemoryInputMedia>(MediaStrings.IMEM);
SetupOutput(m_sourcePlayer.CustomRendererEx);
}

void Events_PlayerPlaying(object sender, EventArgs e)
{
MicroSecondsBetweenFrame = (long)(MicroSecondsInSecomd / (m_sourcePlayer.FPS != 0 ? m_sourcePlayer.FPS : DefaultFps));
}

private void SetupOutput(IMemoryRendererEx iMemoryRenderer)
{
iMemoryRenderer.SetFormatSetupCallback(OnSetupCallback);
iMemoryRenderer.SetExceptionHandler(OnErrorCallback);
iMemoryRenderer.SetCallback(OnNewFrameCallback);
}

private BitmapFormat OnSetupCallback(BitmapFormat format)
{
SetupInput(format);
return new BitmapFormat(format.Width, format.Height, ChromaType.RV24);
}

private void OnErrorCallback(Exception error)
{
MessageBox.Show(error.Message);
}

private void OnNewFrameCallback(PlanarFrame frame)
{
data.Data = frame.Planes[0];
data.DataSize = frame.Lenghts[0];
data.PTS = frameCounter++ * MicroSecondsBetweenFrame;
m_inputMedia.AddFrame(data);

if (/*m_inputMedia.PendingFramesCount == 10 && */!m_renderPlayer.IsPlaying)
{
m_renderPlayer.Play();
}
}

private void SetupInput(BitmapFormat format)
{
var streamInfo = new StreamInfo();
streamInfo.Category = StreamCategory.Video;
streamInfo.Codec = VideoCodecs.BGR24;
streamInfo.Width = format.Width;
streamInfo.Height = format.Height;
streamInfo.Size = format.ImageSize;

m_inputMedia.Initialize(streamInfo);
m_inputMedia.SetExceptionHandler(OnErrorCallback);
m_renderPlayer.Open(m_inputMedia);
}

private void OpenSourceMedia(string path)
{
//IMediaFromFile media = m_factory.CreateMedia<IMediaFromFile>(path);
IMedia media = m_factory.CreateMedia<IMedia>(path);
m_sourcePlayer.Open(media);
m_sourcePlayer.Play();
timer.Start();

}

private void button1_Click(object sender, EventArgs e)
{
OpenSourceMedia("http://192.168.2.108:8090");
}
}
}
0%