深入理解nginx mp4流媒体模块[上]
深入理解nginx mp4流媒体模块[中]
深入理解nginx mp4流媒体模块[下]
深入理解nginx mp4流媒体模块[下下]
以下对ngx_http_mp4_file_t的结构定义进行说明:
typedef struct {
ngx_file_t file; # mp4文件对象
u_char *buffer; # 用于mp4分析的缓冲区
u_char *buffer_start; # buffer空闲的起始位置
u_char *buffer_pos; # buffer中可用于分析的起始位置
u_char *buffer_end; # buffer中可用于分析的结束位置
size_t buffer_size; # mp4分析缓冲区buffer的大小
off_t offset; # buffer_start对应的mp4文件读取的偏移量
off_t end; # 当前mp4文件的文件大小
off_t content_length; # 最终发送给客户端响应的内容长度
ngx_uint_t start; # 请求的起始偏移时间
ngx_uint_t length; # 请求的视频时长
uint32_t timescale; # mp4文件中设置的时间scale值
ngx_http_request_t *request; # 对应当前的http request对象
ngx_array_t trak; # mp4包含的track列表,引用traks,最多2个
ngx_http_mp4_trak_t traks[2]; # mp4包含的track列表
size_t ftyp_size; # ftyp atom的大小
size_t moov_size; # moov atom的大小
ngx_chain_t *out;
ngx_chain_t ftyp_atom; # 链接了ftyp_atom_buf的缓冲区链
ngx_chain_t moov_atom; # 链接了moov_atom_buf的缓冲区链
ngx_chain_t mvhd_atom; # 链接了mvhd_atom_buf的缓冲区链
ngx_chain_t mdat_atom; # 链接了mdat_atom_buf的缓冲区链
ngx_chain_t mdat_data; # 链接了mdat_data_buf的缓冲区链
ngx_buf_t ftyp_atom_buf; # ftyp atom的缓冲区
ngx_buf_t moov_atom_buf; # moov atom的缓冲区
ngx_buf_t mvhd_atom_buf; # mvhd atom的缓冲区
ngx_buf_t mdat_atom_buf; # mdat atom的缓冲区
ngx_buf_t mdat_data_buf; # mdat atom的缓冲区
u_char moov_atom_header[8];
u_char mdat_atom_header[16];
} ngx_http_mp4_file_t;
3.2.4 MP4文件的发送
其实现源码如下,源码里面进行了详细的备注说明:
log->action = "sending mp4 to client";
/* 如果需要,开启directio */
if (clcf->directio <= of.size) {
/*
* DIRECTIO is set on transfer only
* to allow kernel to cache "moov" atom
*/
if (ngx_directio_on(of.fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
ngx_directio_on_n " \"%s\" failed", path.data);
}
of.is_directio = 1;
if (mp4) {
mp4->file.directio = 1;
}
}
/* 设置响应状态和相关响应头信息,然后将响应头发送给用户 */
r->headers_out.status = NGX_HTTP_OK;
r->headers_out.last_modified_time = of.mtime;
if (ngx_http_set_etag(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (ngx_http_set_content_type(r) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
if (mp4 == NULL) {
b = ngx_calloc_buf(r->pool);
if (b == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
if (b->file == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
rc = ngx_http_send_header(r);
if (rc == NGX_ERROR || rc