FFmpeg源代码简单分析-通用-结构体分析-AVIOContext

参考链接

  • FFMPEG结构体分析:AVIOContext_雷霄骅的博客-CSDN博客_aviocontext

AVIOContext

  • AVIOContext是FFMPEG管理输入输出数据的结构体
  • 结构体的定义位于位于avio.h

关键的变量如下所示

  • unsigned char *buffer:缓存开始位置
  • int buffer_size:缓存大小(默认32768)
  • unsigned char *buf_ptr:当前指针读取到的位置
  • unsigned char *buf_end:缓存结束的位置
  • void *opaque:URLContext结构体 
  • 在解码的情况下,buffer用于存储ffmpeg读入的数据。
  • 例如打开一个视频文件的时候,先把数据从硬盘读入buffer,然后在送给解码器用于解码。
    /*** A callback that is used instead of write_packet.*/int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,enum AVIODataMarkerType type, int64_t time);
  • 其中opaque指向了URLContext。不是很理解这句话的含义
  • 涉及到write_data_type的一共仅有三处
    • 第一部分:函数的定义
    • 第二部分:if判断
    • 第三部分:函数的调用 

 

  • 注意,这个结构体并不在FFMPEG提供的头文件中,而是在FFMPEG的源代码中。修正:目前在url.h文件中

  • URLContext结构体中还有一个结构体URLProtocol
  • 注:每种协议(rtp,rtmp,file等)对应一个URLProtocol
typedef struct URLProtocol {const char *name;int     (*url_open)( URLContext *h, const char *url, int flags);/*** This callback is to be used by protocols which open further nested* protocols. options are then to be passed to ffurl_open_whitelist()* or ffurl_connect() for those nested protocols.*/int     (*url_open2)(URLContext *h, const char *url, int flags, AVDictionary **options);int     (*url_accept)(URLContext *s, URLContext **c);int     (*url_handshake)(URLContext *c);/*** Read data from the protocol.* If data is immediately available (even less than size), EOF is* reached or an error occurs (including EINTR), return immediately.* Otherwise:* In non-blocking mode, return AVERROR(EAGAIN) immediately.* In blocking mode, wait for data/EOF/error with a short timeout (0.1s),* and return AVERROR(EAGAIN) on timeout.* Checking interrupt_callback, looping on EINTR and EAGAIN and until* enough data has been read is left to the calling function; see* retry_transfer_wrapper in avio.c.*/int     (*url_read)( URLContext *h, unsigned char *buf, int size);int     (*url_write)(URLContext *h, const unsigned char *buf, int size);int64_t (*url_seek)( URLContext *h, int64_t pos, int whence);int     (*url_close)(URLContext *h);int (*url_read_pause)(URLContext *h, int pause);int64_t (*url_read_seek)(URLContext *h, int stream_index,int64_t timestamp, int flags);int (*url_get_file_handle)(URLContext *h);int (*url_get_multi_file_handle)(URLContext *h, int **handles,int *numhandles);int (*url_get_short_seek)(URLContext *h);int (*url_shutdown)(URLContext *h, int flags);const AVClass *priv_data_class;int priv_data_size;int flags;int (*url_check)(URLContext *h, int mask);int (*url_open_dir)(URLContext *h);int (*url_read_dir)(URLContext *h, AVIODirEntry **next);int (*url_close_dir)(URLContext *h);int (*url_delete)(URLContext *h);int (*url_move)(URLContext *h_src, URLContext *h_dst);const char *default_whitelist;
} URLProtocol;
  • 在这个结构体中,除了一些回调函数接口之外,有一个变量const char *name,该变量存储了协议的名称。
  • 每一种输入协议都对应这样一个结构体。

文件协议  数据结构ff_file_protocol

  • 位于file.c
  • 函数指针 指向具体的执行函数
  • 等号右边的函数是完成具体读写功能的函数。可以看一下file协议的几个函数(其实就是读文件,写文件这样的操作)
const URLProtocol ff_file_protocol = {.name                = "file",.url_open            = file_open,.url_read            = file_read,.url_write           = file_write,.url_seek            = file_seek,.url_close           = file_close,.url_get_file_handle = file_get_handle,.url_check           = file_check,.url_delete          = file_delete,.url_move            = file_move,.priv_data_size      = sizeof(FileContext),.priv_data_class     = &file_class,.url_open_dir        = file_open_dir,.url_read_dir        = file_read_dir,.url_close_dir       = file_close_dir,.default_whitelist   = "file,crypto,data"
};
static int file_read(URLContext *h, unsigned char *buf, int size)
{FileContext *c = h->priv_data;int ret;size = FFMIN(size, c->blocksize);ret = read(c->fd, buf, size);if (ret == 0 && c->follow)return AVERROR(EAGAIN);if (ret == 0)return AVERROR_EOF;return (ret == -1) ? AVERROR(errno) : ret;
}static int file_write(URLContext *h, const unsigned char *buf, int size)
{FileContext *c = h->priv_data;int ret;size = FFMIN(size, c->blocksize);ret = write(c->fd, buf, size);return (ret == -1) ? AVERROR(errno) : ret;
}static int file_get_handle(URLContext *h)
{FileContext *c = h->priv_data;return c->fd;
}static int file_check(URLContext *h, int mask)
{int ret = 0;const char *filename = h->filename;av_strstart(filename, "file:", &filename);{
#if HAVE_ACCESS && defined(R_OK)if (access(filename, F_OK) < 0)return AVERROR(errno);if (mask&AVIO_FLAG_READ)if (access(filename, R_OK) >= 0)ret |= AVIO_FLAG_READ;if (mask&AVIO_FLAG_WRITE)if (access(filename, W_OK) >= 0)ret |= AVIO_FLAG_WRITE;
#elsestruct stat st;ret = stat(filename, &st);if (ret < 0)return AVERROR(errno);ret |= st.st_mode&S_IRUSR ? mask&AVIO_FLAG_READ  : 0;ret |= st.st_mode&S_IWUSR ? mask&AVIO_FLAG_WRITE : 0;
#endif}return ret;
}#if CONFIG_FILE_PROTOCOLstatic int file_delete(URLContext *h)
{
#if HAVE_UNISTD_Hint ret;const char *filename = h->filename;av_strstart(filename, "file:", &filename);ret = rmdir(filename);if (ret < 0 && (errno == ENOTDIR
#   ifdef _WIN32|| errno == EINVAL
#   endif))ret = unlink(filename);if (ret < 0)return AVERROR(errno);return ret;
#elsereturn AVERROR(ENOSYS);
#endif /* HAVE_UNISTD_H */
}static int file_move(URLContext *h_src, URLContext *h_dst)
{const char *filename_src = h_src->filename;const char *filename_dst = h_dst->filename;av_strstart(filename_src, "file:", &filename_src);av_strstart(filename_dst, "file:", &filename_dst);if (rename(filename_src, filename_dst) < 0)return AVERROR(errno);return 0;
}static int file_open(URLContext *h, const char *filename, int flags)
{FileContext *c = h->priv_data;int access;int fd;struct stat st;av_strstart(filename, "file:", &filename);if (flags & AVIO_FLAG_WRITE && flags & AVIO_FLAG_READ) {access = O_CREAT | O_RDWR;if (c->trunc)access |= O_TRUNC;} else if (flags & AVIO_FLAG_WRITE) {access = O_CREAT | O_WRONLY;if (c->trunc)access |= O_TRUNC;} else {access = O_RDONLY;}
#ifdef O_BINARYaccess |= O_BINARY;
#endiffd = avpriv_open(filename, access, 0666);if (fd == -1)return AVERROR(errno);c->fd = fd;h->is_streamed = !fstat(fd, &st) && S_ISFIFO(st.st_mode);/* Buffer writes more than the default 32k to improve throughput especially* with networked file systems */if (!h->is_streamed && flags & AVIO_FLAG_WRITE)h->min_packet_size = h->max_packet_size = 262144;if (c->seekable >= 0)h->is_streamed = !c->seekable;return 0;
}/* XXX: use llseek */
static int64_t file_seek(URLContext *h, int64_t pos, int whence)
{FileContext *c = h->priv_data;int64_t ret;if (whence == AVSEEK_SIZE) {struct stat st;ret = fstat(c->fd, &st);return ret < 0 ? AVERROR(errno) : (S_ISFIFO(st.st_mode) ? 0 : st.st_size);}ret = lseek(c->fd, pos, whence);return ret < 0 ? AVERROR(errno) : ret;
}static int file_close(URLContext *h)
{FileContext *c = h->priv_data;int ret = close(c->fd);return (ret == -1) ? AVERROR(errno) : 0;
}static int file_open_dir(URLContext *h)
{
#if HAVE_LSTATFileContext *c = h->priv_data;c->dir = opendir(h->filename);if (!c->dir)return AVERROR(errno);return 0;
#elsereturn AVERROR(ENOSYS);
#endif /* HAVE_LSTAT */
}static int file_read_dir(URLContext *h, AVIODirEntry **next)
{
#if HAVE_LSTATFileContext *c = h->priv_data;struct dirent *dir;char *fullpath = NULL;*next = ff_alloc_dir_entry();if (!*next)return AVERROR(ENOMEM);do {errno = 0;dir = readdir(c->dir);if (!dir) {av_freep(next);return AVERROR(errno);}} while (!strcmp(dir->d_name, ".") || !strcmp(dir->d_name, ".."));fullpath = av_append_path_component(h->filename, dir->d_name);if (fullpath) {struct stat st;if (!lstat(fullpath, &st)) {if (S_ISDIR(st.st_mode))(*next)->type = AVIO_ENTRY_DIRECTORY;else if (S_ISFIFO(st.st_mode))(*next)->type = AVIO_ENTRY_NAMED_PIPE;else if (S_ISCHR(st.st_mode))(*next)->type = AVIO_ENTRY_CHARACTER_DEVICE;else if (S_ISBLK(st.st_mode))(*next)->type = AVIO_ENTRY_BLOCK_DEVICE;else if (S_ISLNK(st.st_mode))(*next)->type = AVIO_ENTRY_SYMBOLIC_LINK;else if (S_ISSOCK(st.st_mode))(*next)->type = AVIO_ENTRY_SOCKET;else if (S_ISREG(st.st_mode))(*next)->type = AVIO_ENTRY_FILE;else(*next)->type = AVIO_ENTRY_UNKNOWN;(*next)->group_id = st.st_gid;(*next)->user_id = st.st_uid;(*next)->size = st.st_size;(*next)->filemode = st.st_mode & 0777;(*next)->modification_timestamp = INT64_C(1000000) * st.st_mtime;(*next)->access_timestamp =  INT64_C(1000000) * st.st_atime;(*next)->status_change_timestamp = INT64_C(1000000) * st.st_ctime;}av_free(fullpath);}(*next)->name = av_strdup(dir->d_name);return 0;
#elsereturn AVERROR(ENOSYS);
#endif /* HAVE_LSTAT */
}static int file_close_dir(URLContext *h)
{
#if HAVE_LSTATFileContext *c = h->priv_data;closedir(c->dir);return 0;
#elsereturn AVERROR(ENOSYS);
#endif /* HAVE_LSTAT */
}

 

 

libRTMP

  • 位于librtmp.c
RTMP_CLASS(rtmp)
const URLProtocol ff_librtmp_protocol = {.name                = "rtmp",.url_open            = rtmp_open,.url_read            = rtmp_read,.url_write           = rtmp_write,.url_close           = rtmp_close,.url_read_pause      = rtmp_read_pause,.url_read_seek       = rtmp_read_seek,.url_get_file_handle = rtmp_get_file_handle,.priv_data_size      = sizeof(LibRTMPContext),.priv_data_class     = &librtmp_class,.flags               = URL_PROTOCOL_FLAG_NETWORK,
};RTMP_CLASS(rtmpt)
const URLProtocol ff_librtmpt_protocol = {.name                = "rtmpt",.url_open            = rtmp_open,.url_read            = rtmp_read,.url_write           = rtmp_write,.url_close           = rtmp_close,.url_read_pause      = rtmp_read_pause,.url_read_seek       = rtmp_read_seek,.url_get_file_handle = rtmp_get_file_handle,.priv_data_size      = sizeof(LibRTMPContext),.priv_data_class     = &librtmpt_class,.flags               = URL_PROTOCOL_FLAG_NETWORK,
};RTMP_CLASS(rtmpe)
const URLProtocol ff_librtmpe_protocol = {.name                = "rtmpe",.url_open            = rtmp_open,.url_read            = rtmp_read,.url_write           = rtmp_write,.url_close           = rtmp_close,.url_read_pause      = rtmp_read_pause,.url_read_seek       = rtmp_read_seek,.url_get_file_handle = rtmp_get_file_handle,.priv_data_size      = sizeof(LibRTMPContext),.priv_data_class     = &librtmpe_class,.flags               = URL_PROTOCOL_FLAG_NETWORK,
};RTMP_CLASS(rtmpte)
const URLProtocol ff_librtmpte_protocol = {.name                = "rtmpte",.url_open            = rtmp_open,.url_read            = rtmp_read,.url_write           = rtmp_write,.url_close           = rtmp_close,.url_read_pause      = rtmp_read_pause,.url_read_seek       = rtmp_read_seek,.url_get_file_handle = rtmp_get_file_handle,.priv_data_size      = sizeof(LibRTMPContext),.priv_data_class     = &librtmpte_class,.flags               = URL_PROTOCOL_FLAG_NETWORK,
};RTMP_CLASS(rtmps)
const URLProtocol ff_librtmps_protocol = {.name                = "rtmps",.url_open            = rtmp_open,.url_read            = rtmp_read,.url_write           = rtmp_write,.url_close           = rtmp_close,.url_read_pause      = rtmp_read_pause,.url_read_seek       = rtmp_read_seek,.url_get_file_handle = rtmp_get_file_handle,.priv_data_size      = sizeof(LibRTMPContext),.priv_data_class     = &librtmps_class,.flags               = URL_PROTOCOL_FLAG_NETWORK,
};

 

 udp协议

  • 位于udp.c
const URLProtocol ff_udp_protocol = {.name                = "udp",.url_open            = udp_open,.url_read            = udp_read,.url_write           = udp_write,.url_close           = udp_close,.url_get_file_handle = udp_get_file_handle,.priv_data_size      = sizeof(UDPContext),.priv_data_class     = &udp_class,.flags               = URL_PROTOCOL_FLAG_NETWORK,
};const URLProtocol ff_udplite_protocol = {.name                = "udplite",.url_open            = udplite_open,.url_read            = udp_read,.url_write           = udp_write,.url_close           = udp_close,.url_get_file_handle = udp_get_file_handle,.priv_data_size      = sizeof(UDPContext),.priv_data_class     = &udplite_context_class,.flags               = URL_PROTOCOL_FLAG_NETWORK,
};

 

 

代码

/*** Bytestream IO Context. //字节流 IO 上下文* New public fields can be added with minor version bumps. //新的公共字段可以添加小版本颠簸* Removal, reordering and changes to existing public fields require * a major version bump. 移除、重新排序和更改现有公共字段需要一个主要版本的凹凸* sizeof(AVIOContext) must not be used outside libav*. //sizeof(AVIOContext) 不得在 libav* 之外使用** @note None of the function pointers in AVIOContext should be called*       directly, they should only be set by the client application*       when implementing custom I/O. Normally these are set to the*       function pointers specified in avio_alloc_context()* AVIOContext 中的任何函数指针都不应直接调用,它们只能由客户端应用程序* 在实现自定义 I/O 时设置。 通常这些设置为 avio_alloc_context() 中指定的函数指针*/
typedef struct AVIOContext {/*** A class for private options. //一个私人选项类** If this AVIOContext is created by avio_open2(), av_class is set and* passes the options down to protocols.* 如果此 AVIOContext 由 avio_open2() 创建,则设置 av_class 并将选项传递给协议** If this AVIOContext is manually allocated, then av_class may be set by* the caller.* 如果这个 AVIOContext 是手动分配的,那么 av_class 可能由调用者设置* * warning -- this field can be NULL, be sure to not pass this AVIOContext * to any av_opt_* functions in that case.* 警告——该字段可以为 NULL,在这种情况下,请确保不要将此 AVIOContext 传递给任何 av_opt_* 函数*/const AVClass *av_class;/** The following shows the relationship between buffer, buf_ptr,* buf_ptr_max, buf_end, buf_size, and pos, when reading and when writing* (since AVIOContext is used for both):************************************************************************************                                   READING************************************************************************************                            |              buffer_size              |*                            |---------------------------------------|*                            |                                       |**                         buffer          buf_ptr       buf_end*                            +---------------+-----------------------+*                            |/ / / / / / / /|/ / / / / / /|         |*  read buffer:              |/ / consumed / | to be read /|         |*                            |/ / / / / / / /|/ / / / / / /|         |*                            +---------------+-----------------------+**                                                         pos*              +-------------------------------------------+-----------------+*  input file: |                                           |                 |*              +-------------------------------------------+-----------------+*************************************************************************************                                   WRITING************************************************************************************                             |          buffer_size                 |*                             |--------------------------------------|*                             |                                      |**                                                buf_ptr_max*                          buffer                 (buf_ptr)       buf_end*                             +-----------------------+--------------+*                             |/ / / / / / / / / / / /|              |*  write buffer:              | / / to be flushed / / |              |*                             |/ / / / / / / / / / / /|              |*                             +-----------------------+--------------+*                               buf_ptr can be in this*                               due to a backward seek**                            pos*               +-------------+----------------------------------------------+*  output file: |             |                                              |*               +-------------+----------------------------------------------+**/unsigned char *buffer;  /**< Start of the buffer. */int buffer_size;        /**< Maximum buffer size */unsigned char *buf_ptr; /**< Current position in the buffer */unsigned char *buf_end; /**< End of the data, may be less thanbuffer+buffer_size if the read function returnedless data than requested, e.g. for streams whereno more data has been received yet. */void *opaque;           /**< A private pointer, passed to the read/write/seek/...functions. */int (*read_packet)(void *opaque, uint8_t *buf, int buf_size);int (*write_packet)(void *opaque, uint8_t *buf, int buf_size);int64_t (*seek)(void *opaque, int64_t offset, int whence);int64_t pos;            /**< position in the file of the current buffer */int eof_reached;        /**< true if was unable to read due to error or eof */int error;              /**< contains the error code or 0 if no error happened */int write_flag;         /**< true if open for writing */int max_packet_size;int min_packet_size;    /**< Try to buffer at least this amount of databefore flushing it. */unsigned long checksum;unsigned char *checksum_ptr;unsigned long (*update_checksum)(unsigned long checksum, const uint8_t *buf, unsigned int size);/*** Pause or resume playback for network streaming protocols - e.g. MMS.*/int (*read_pause)(void *opaque, int pause);/*** Seek to a given timestamp in stream with the specified stream_index.* Needed for some network streaming protocols which don't support seeking* to byte position.*/int64_t (*read_seek)(void *opaque, int stream_index,int64_t timestamp, int flags);/*** A combination of AVIO_SEEKABLE_ flags or 0 when the stream is not seekable.*/int seekable;/*** avio_read and avio_write should if possible be satisfied directly* instead of going through a buffer, and avio_seek will always* call the underlying seek function directly.*/int direct;/*** ',' separated list of allowed protocols.*/const char *protocol_whitelist;/*** ',' separated list of disallowed protocols.*/const char *protocol_blacklist;/*** A callback that is used instead of write_packet.*/int (*write_data_type)(void *opaque, uint8_t *buf, int buf_size,enum AVIODataMarkerType type, int64_t time);/*** If set, don't call write_data_type separately for AVIO_DATA_MARKER_BOUNDARY_POINT,* but ignore them and treat them as AVIO_DATA_MARKER_UNKNOWN (to avoid needlessly* small chunks of data returned from the callback).*/int ignore_boundary_point;#if FF_API_AVIOCONTEXT_WRITTEN/*** @deprecated field utilized privately by libavformat. For a public*             statistic of how many bytes were written out, see*             AVIOContext::bytes_written.*/attribute_deprecatedint64_t written;
#endif/*** Maximum reached position before a backward seek in the write buffer,* used keeping track of already written data for a later flush.*/unsigned char *buf_ptr_max;/*** Read-only statistic of bytes read for this AVIOContext.*/int64_t bytes_read;/*** Read-only statistic of bytes written for this AVIOContext.*/int64_t bytes_written;
} AVIOContext;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/445993.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初闻动态规划

前言 本文以一道常见的算法面试题开篇&#xff0c;引入动态规划的基础概念&#xff0c; 介绍其思考过程。 正文 一、常见的一道算法面试题——上台阶 有一个楼梯总共n个台阶&#xff0c;只能往上走&#xff0c;每次只能上1个、2个台阶&#xff0c;总共有多少种走法。 解决…

FFmpeg源代码简单分析-通用-结构体分析-AVCodec

参考链接 FFMPEG结构体分析&#xff1a;AVCodec_雷霄骅的博客-CSDN博客_avcodec AVCodec AVCodec是存储编解码器信息的结构体结构体的定义位于avcodec.h文件中最主要的几个变量 const char *name&#xff1a;编解码器的名字&#xff0c;比较短const char *long_name&#xff…

SLF4J简介与使用(整合log4j)

SLF4J简介与使用(整合log4j) 一、概念 SLF4J的全称是Simple Logging Facade for Java&#xff0c;即简单日志门面。SLF4J并不是具体的日志框架&#xff0c;而是作为一个简单门面服务于各类日志框架&#xff0c;如java.util.logging, logback和log4j。 SLF4J提供了统一的记录…

multism中ui和uo应该怎么表示_王者荣耀:梦泪直播时谈到体验服大改动,表示装备的改动很关键...

王者荣耀的主播梦泪&#xff0c;大家都很熟了&#xff0c;也是一个很强的主播&#xff0c;他对于王者荣耀的理解&#xff0c;还是非常深刻的&#xff0c;而最近王者荣耀的体验服&#xff0c;进行了大改动&#xff0c;也是改变了很多的东西。对此&#xff0c;网友们也是非常的在…

怎么关闭或者卸载ivanti_电脑软件卸载不了怎么办,教您解决电脑软件无法卸载方法技巧...

我们在使用电脑的过程中&#xff0c;肯定会安装各种软件&#xff0c;但是一些软件在使用完之后就不会再使用了&#xff0c;但又无法卸载。下面由小编分享一下电脑安装的软件无法卸载解决方法&#xff0c;如果你在某卸载软件的时候出现无法卸载的情况&#xff0c;不妨通过以下方…

解决Github图片加载失败

问题描述 浏览自己Github某仓库的README.md内时&#xff0c;发现文档的图片始终加载不出&#xff0c;打开浏览器后台&#xff0c;冒出一片红&#xff0c;Failed to load resource: net::ERR_CONNECTION_RESET&#xff0c;如下图所示&#xff1a; 问题分析 可能造成这问题的原…

FFmpeg源代码简单分析-通用-结构体分析-关键结构体之间的关系

参考链接 FFMPEG中最关键的结构体之间的关系_雷霄骅的博客-CSDN博客_ffmpeg 结构体关系 最关键的结构体可以分成以下几类&#xff1a; 解协议&#xff08;http,rtsp,rtmp,mms&#xff09; AVIOContext&#xff0c;URLProtocol&#xff0c;URLContext主要存储视音频使用的协…

用Python下载文件

前提条件 需要事先安装requests模块&#xff1a; pip install requests 放码过来 import requestsurl XXX #文件下载来源URL filename #下载到本地后新文件名 r requests.get(url) with open(filename, "wb") as code:code.write(r.content)实战演习 从目标…

FFmpeg源代码简单分析-通用-常见结构体的初始化和销毁(AVFormatContext,AVFrame等)

参考链接 FFmpeg源代码简单分析&#xff1a;常见结构体的初始化和销毁&#xff08;AVFormatContext&#xff0c;AVFrame等&#xff09;_雷霄骅的博客-CSDN博客 结构体 AVFormatContext&#xff1a;统领全局的基本结构体。主要用于处理封装格式&#xff08;FLV/MKV/RMVB等&…

FFmpeg源代码简单分析-通用-avio_open2()

参考链接 FFmpeg源代码简单分析&#xff1a;avio_open2()_雷霄骅的博客-CSDN博客_avio_open avio_open2() 该函数用于打开FFmpeg的输入输出文件avio_open2()的声明位于libavformat\avio.h文件中&#xff0c;如下所示。 /*** Create and initialize a AVIOContext for accessi…

用Tomcat构建一个简单图片服务器

前提条件 Tomcat 7.0.90 方法一&#xff1a;修改配置文件 在TOMCAT_HOME/conf/server.xml配置文件内的<Host>内添加一子标签&#xff1a; <Context docBase"C:\exambase\" path"/img"/>方法二&#xff1a;添加Servlet 新建一应用&#xf…

FFmpeg源代码简单分析-通用-av_find_decoder()和av_find_encoder()

参考链接 FFmpeg源代码简单分析&#xff1a;av_find_decoder()和av_find_encoder()_雷霄骅的博客-CSDN博客_avcodec_find_encoder avcodec_find_encoder avcodec_find_encoder()用于查找FFmpeg的编码器avcodec_find_encoder()的声明位于libavcodec\codec.h 版本差异avcode…

post方法就反回了一个string字符串前台怎么接_Golang Web入门(2):如何实现一个RESTful风格的路由...

摘要在上一篇文章中&#xff0c;我们聊了聊在Golang中怎么实现一个Http服务器。但是在最后我们可以发现&#xff0c;固然DefaultServeMux可以做路由分发的功能&#xff0c;但是他的功能同样是不完善的。由DefaultServeMux做路由分发&#xff0c;是不能实现RESTful风格的API的&a…

FFmpeg源代码简单分析-通用-avcodec_open2()

参考链接 FFmpeg源代码简单分析&#xff1a;avcodec_open2()_雷霄骅的博客-CSDN博客 avcodec_open2() 该函数用于初始化一个音视频编解码器的AVCodecContextavcodec_open2()的声明位于libavcodec\avcodec.h&#xff0c;如下所示。 /*** Initialize the AVCodecContext to use…

统计MySQL中某数据库硬盘占用量大小

放码过来 select TABLE_NAME, concat(truncate(data_length/1024/1024,2), MB) as data_size, concat(truncate(index_length/1024/1024,2), MB) as index_size from information_schema.tables where TABLE_SCHEMA your_db_name order by data_length desc;运行结果 参考…

FFmpeg源代码简单分析-解码-打开媒体的函数avformat_open_input

参考链接 图解FFMPEG打开媒体的函数avformat_open_input_雷霄骅的博客-CSDN博客_avformat_open_input 使用FFmpeg源代码简单分析&#xff1a;avformat_open_input()_雷霄骅的博客-CSDN博客_avformat_open_input() avformat_open_input FFmpeg打开媒体的的过程开始于avformat_…

redis session java获取attribute_面试题:给我说说你能想到几种分布式session实现?...

作者&#xff1a;yanglbme 来源&#xff1a;https://github.com/doocs/advanced-java/blob/master/docs/distributed-system/distributed-session.md# 面试官心理分析面试官问了你一堆 dubbo 是怎么玩儿的&#xff0c;你会玩儿 dubbo 就可以把单块系统弄成分布式系统&#xff0…

FFmpeg源代码简单分析-解码-avformat_find_stream_info()

参考链接 FFmpeg源代码简单分析&#xff1a;avformat_find_stream_info()_雷霄骅的博客-CSDN博客_avformat_find_stream_info avformat_find_stream_info() ​该函数可以读取一部分视音频数据并且获得一些相关的信息avformat_find_stream_info()的声明位于libavformat\avform…

Tail Recursion尾递归

什么是尾递归 Tail Recursion /teɪl rɪˈkɜːrʒn/ In traditional recursion, the typical model is that you perform your recursive calls first, and then you take the return value of the recursive call and calculate the result. In this manner, you don’t g…

FFmpeg源代码简单分析-解码-av_read_frame()

参考链接 ffmpeg 源代码简单分析 &#xff1a; av_read_frame()_雷霄骅的博客-CSDN博客_ffmpeg frame av_read_frame() ffmpeg中的av_read_frame()的作用是读取码流中的音频若干帧或者视频一帧。例如&#xff0c;解码视频的时候&#xff0c;每解码一个视频帧&#xff0c;需要…