-
2020-11-24 12:41:23
此文为转载 ,如需原始作者要求删除请私信我
计算机的存储系统采用Register,Cache,Memory和I/O的方式来构成存储系统,无疑是一个性能和经济性的妥协的产物。Cache和Memory机制是计算机硬件的基础内容,这里就不再啰嗦。下面重点说明Write-back,Write-through及write allocate这三种操作的区别。
一、CPU读Cache
1. Read through,即直接从内存中读取数据;
2. Read allocate,先把数据读取到Cache中,再从Cache中读数据。
二、CPU写Cache
1. 若hit命中,有两种处理方式:
Write-through: write is done synchronously both to the cache and to the backing store。Write-through(直写模式)在数据更新时,把数据同时写入Cache和后端存储。此模式的优点是操作简单;缺点是因为数据修改需要同时写入存储,数据写入速度较慢。
Write-back (also called write-behind): initially, writing is done only to the cache. The write to the backing store is postponed until the cache blocks containing the data are about to be modified/replaced by new content。Write-back(回写模式)在数据更新时只写入缓存Cache。只在数据被替换出缓存时,被修改的缓存数据才会被写到后端存储(即先把数据写到Cache中,再通过flush方式写入到内存中)。此模式的优点是数据写入速度快,因为不需要写存储;缺点是一旦更新后的数据未被写入存储时出现系统掉电的情况,数据将无法找回。
2. 若miss,有两种处理方式:
Write allocate (also called fetch on write): data at the missed-write location is loaded to cache, followed by a write-hit operation. In this approach, write misses are similar to read misses.。Write allocate:先把要写的数据载入到Cache中,写Cache,然后再通过flush方式写入到内存中; 写缺失操作与读缺失操作类似。
No-write allocate (also called write-no-allocate or write around): data at the missed-write location is not loaded to cache, and is written directly to the backing store. In this approach, only the reads are being cached。No write allocate:并不将写入位置读入缓存,直接把要写的数据写入到内存中。这种方式下,只有读操作会被缓存。
更多相关内容 -
Python serial.write方法代码示例
2020-12-09 04:37:40本文整理汇总了Python中serial.write方法的典型用法代码示例。如果您正苦于以下问题:Python serial.write方法的具体用法?Python serial.write怎么用?Python serial.write使用的例子?那么恭喜您, 这里精选的方法...本文整理汇总了Python中serial.write方法的典型用法代码示例。如果您正苦于以下问题:Python serial.write方法的具体用法?Python serial.write怎么用?Python serial.write使用的例子?那么恭喜您, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在模块serial的用法示例。
在下文中一共展示了serial.write方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Python代码示例。
示例1: __checkType__
点赞 5
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def __checkType__(self, serial):
byte = serial.read().decode("utf-8")
print(byte)
if byte == "1":
print("??? ???? ?? : " + serial.port)
serial.write(b'0')
self.threads["Sensor"] = SensorThread(serial)
return self.threads["Sensor"]
elif byte == "2" :
print("??? ???? ?? : " + serial.port)
serial.write(b'0')
self.threads["Control"] = ControlThread(serial)
return self.threads["Control"]
else :
print("? ? ?? ???? : " + serial.port)
serial.write(b'1')
return None
#?? ???
开发者ID:toy0605,项目名称:Hydroponics,代码行数:21,
示例2: write
点赞 4
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def write(self, data):
"""\
Output the given byte string over the serial port. Can block if the
connection is blocked. May raise SerialException if the connection is
closed.
"""
if not self.is_open:
raise portNotOpenError
with self._write_lock:
try:
self._socket.sendall(to_bytes(data).replace(IAC, IAC_DOUBLED))
except socket.error as e:
raise SerialException("connection failed (socket error): %s" % (e,))
return len(data)
开发者ID:sketchpunk,项目名称:android3dblendermouse,代码行数:16,
示例3: write
点赞 3
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def write(self, value):
print(value)
if(value == 0):
serial.write('0')
elif(value == 1):
serial.write('1')
elif(value == 2):
serial.write('2')
elif(value == 3):
serial.write('3')
elif(value == 4):
serial.write('4')
# Disconnects the Arduino
开发者ID:ThermoNuclearPanda,项目名称:Project_Automail,代码行数:16,
示例4: showReady
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def showReady(self):
serial.write('6')
开发者ID:ThermoNuclearPanda,项目名称:Project_Automail,代码行数:4,
示例5: _internal_raw_write
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def _internal_raw_write(self, data):
"""internal socket write with no data escaping. used to send telnet stuff."""
with self._write_lock:
self._socket.sendall(data)
开发者ID:sketchpunk,项目名称:android3dblendermouse,代码行数:6,
示例6: telnetSendOption
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def telnetSendOption(self, action, option):
"""Send DO, DONT, WILL, WONT."""
self.connection.write(to_bytes([IAC, action, option]))
开发者ID:sketchpunk,项目名称:android3dblendermouse,代码行数:5,
示例7: rfc2217SendSubnegotiation
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def rfc2217SendSubnegotiation(self, option, value=b''):
"""Subnegotiation of RFC 2217 parameters."""
value = value.replace(IAC, IAC_DOUBLED)
self.connection.write(to_bytes([IAC, SB, COM_PORT_OPTION, option] + list(value) + [IAC, SE]))
# - check modem lines, needs to be called periodically from user to
# establish polling
开发者ID:sketchpunk,项目名称:android3dblendermouse,代码行数:9,
示例8: write
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def write(self, data):
"""\
Output the given byte string over the serial port. Can block if the
connection is blocked. May raise SerialException if the connection is
closed.
"""
if not self.is_open:
raise portNotOpenError
with self._write_lock:
try:
self._socket.sendall(to_bytes(data).replace(IAC, IAC_DOUBLED))
except socket.error as e:
raise SerialException("connection failed (socket error): {}".format(e))
return len(data)
开发者ID:arpruss,项目名称:gcodeplot,代码行数:16,
示例9: telnet_send_option
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def telnet_send_option(self, action, option):
"""Send DO, DONT, WILL, WONT."""
self.connection.write(to_bytes([IAC, action, option]))
开发者ID:arpruss,项目名称:gcodeplot,代码行数:5,
示例10: rfc2217_send_subnegotiation
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def rfc2217_send_subnegotiation(self, option, value=b''):
"""Subnegotiation of RFC 2217 parameters."""
value = value.replace(IAC, IAC_DOUBLED)
self.connection.write(to_bytes([IAC, SB, COM_PORT_OPTION, option] + list(value) + [IAC, SE]))
# - check modem lines, needs to be called periodically from user to
# establish polling
开发者ID:arpruss,项目名称:gcodeplot,代码行数:9,
示例11: telnet_send_option
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def telnet_send_option(self, action, option):
"""Send DO, DONT, WILL, WONT."""
self.connection.write(IAC + action + option)
开发者ID:whaleygeek,项目名称:bitio,代码行数:5,
示例12: rfc2217_send_subnegotiation
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def rfc2217_send_subnegotiation(self, option, value=b''):
"""Subnegotiation of RFC 2217 parameters."""
value = value.replace(IAC, IAC_DOUBLED)
self.connection.write(IAC + SB + COM_PORT_OPTION + option + value + IAC + SE)
# - check modem lines, needs to be called periodically from user to
# establish polling
开发者ID:whaleygeek,项目名称:bitio,代码行数:9,
示例13: filter
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def filter(self, data):
"""\
Handle a bunch of incoming bytes. This is a generator. It will yield
all characters not of interest for Telnet/RFC 2217.
The idea is that the reader thread pushes data from the socket through
this filter:
for byte in filter(socket.recv(1024)):
# do things like CR/LF conversion/whatever
# and write data to the serial port
serial.write(byte)
(socket error handling code left as exercise for the reader)
"""
for byte in iterbytes(data):
if self.mode == M_NORMAL:
# interpret as command or as data
if byte == IAC:
self.mode = M_IAC_SEEN
else:
# store data in sub option buffer or pass it to our
# consumer depending on state
if self.suboption is not None:
self.suboption += byte
else:
yield byte
elif self.mode == M_IAC_SEEN:
if byte == IAC:
# interpret as command doubled -> insert character
# itself
if self.suboption is not None:
self.suboption += byte
else:
yield byte
self.mode = M_NORMAL
elif byte == SB:
# sub option start
self.suboption = bytearray()
self.mode = M_NORMAL
elif byte == SE:
# sub option end -> process it now
self._telnetProcessSubnegotiation(bytes(self.suboption))
self.suboption = None
self.mode = M_NORMAL
elif byte in (DO, DONT, WILL, WONT):
# negotiation
self.telnet_command = byte
self.mode = M_NEGOTIATE
else:
# other telnet commands
self._telnetProcessCommand(byte)
self.mode = M_NORMAL
elif self.mode == M_NEGOTIATE: # DO, DONT, WILL, WONT was received, option now following
self._telnetNegotiateOption(self.telnet_command, byte)
self.mode = M_NORMAL
# - incoming telnet commands and options
开发者ID:sketchpunk,项目名称:android3dblendermouse,代码行数:60,
示例14: filter
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def filter(self, data):
"""\
Handle a bunch of incoming bytes. This is a generator. It will yield
all characters not of interest for Telnet/RFC 2217.
The idea is that the reader thread pushes data from the socket through
this filter:
for byte in filter(socket.recv(1024)):
# do things like CR/LF conversion/whatever
# and write data to the serial port
serial.write(byte)
(socket error handling code left as exercise for the reader)
"""
for byte in iterbytes(data):
if self.mode == M_NORMAL:
# interpret as command or as data
if byte == IAC:
self.mode = M_IAC_SEEN
else:
# store data in sub option buffer or pass it to our
# consumer depending on state
if self.suboption is not None:
self.suboption += byte
else:
yield byte
elif self.mode == M_IAC_SEEN:
if byte == IAC:
# interpret as command doubled -> insert character
# itself
if self.suboption is not None:
self.suboption += byte
else:
yield byte
self.mode = M_NORMAL
elif byte == SB:
# sub option start
self.suboption = bytearray()
self.mode = M_NORMAL
elif byte == SE:
# sub option end -> process it now
self._telnet_process_subnegotiation(bytes(self.suboption))
self.suboption = None
self.mode = M_NORMAL
elif byte in (DO, DONT, WILL, WONT):
# negotiation
self.telnet_command = byte
self.mode = M_NEGOTIATE
else:
# other telnet commands
self._telnet_process_command(byte)
self.mode = M_NORMAL
elif self.mode == M_NEGOTIATE: # DO, DONT, WILL, WONT was received, option now following
self._telnet_negotiate_option(self.telnet_command, byte)
self.mode = M_NORMAL
# - incoming telnet commands and options
开发者ID:arpruss,项目名称:gcodeplot,代码行数:60,
示例15: run
点赞 2
# 需要导入模块: import serial [as 别名]
# 或者: from serial import write [as 别名]
def run(self):
if self.log.fan_out == True :
jsonString = json.dumps({ "Comm" : "onFan" })
self.serial.write(bytes(jsonString, encoding="utf-8"))
else :
jsonString = json.dumps({ "Comm" : "offFan" })
self.serial.write(bytes(jsonString, encoding="utf-8"))
self.serial.write(b'\n')
byte = self.serial.read().decode("utf-8")
print(byte)
if byte == "0" :
print("?? ?? ??")
else :
print("?? ?? ??")
if self.log.humidifier == True :
jsonString = json.dumps({ "Comm" : "onHumidifier" })
self.serial.write(bytes(jsonString, encoding="utf-8"))
else :
jsonString = json.dumps({ "Comm" : "offHumidifier" })
self.serial.write(bytes(jsonString, encoding="utf-8"))
self.serial.write(b'\n')
byte = self.serial.read().decode("utf-8")
print(byte)
if byte == "0" :
print("?? ?? ??")
else :
print("?? ?? ??")
if self.log.peltier == True :
jsonString = json.dumps({ "Comm" : "onPeltier" })
self.serial.write(bytes(jsonString, encoding="utf-8"))
else :
jsonString = json.dumps({ "Comm" : "offPeltier" })
self.serial.write(bytes(jsonString, encoding="utf-8"))
self.serial.write(b'\n')
byte = self.serial.read().decode("utf-8")
print(byte)
if byte == "0" :
print("?? ?? ??")
else :
print("?? ?? ??")
开发者ID:toy0605,项目名称:Hydroponics,代码行数:48,
注:本文中的serial.write方法示例整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。
-
FFmpeg源码分析:写媒体文件头avformat_write_header()
2022-02-07 23:08:56FFmpeg在libavformat模块提供mux封装视频的API,包括avformat_write_header()写文件头、av_write_frame()写音视频帧、av_write_trailer()写文件尾。本文主要介绍写文件头的方法avformat_write_header()。通过分析...FFmpeg在libavformat模块提供mux封装视频的API,包括avformat_write_header()写文件头、av_write_frame()写音视频帧、av_write_trailer()写文件尾。本文主要介绍写文件头的方法avformat_write_header()。通过分析源码,与大家一起探讨FFmpeg是如何封装视频文件的。
在libavformat/avformat.h有这三个API的描述:
* The main API functions for muxing are avformat_write_header() for writing the * file header, av_write_frame() / av_interleaved_write_frame() for writing the * packets and av_write_trailer() for finalizing the file. * When the muxing context is fully set up, the caller must call * avformat_write_header() to initialize the muxer internals and write the file * header. Any muxer private options must be passed in the options parameter to * this function.
翻译如下:
封装文件格式的主要API包括:avformat_write_header()写文件头,av_write_frame() / av_interleaved_write_frame()写音视频帧,av_write_trailer()写文件尾。当完全创建封装上下文后,必须调用avformat_write_header()来初始化封装器内部和写入文件头。任何封装器的私有选项必须通过选项参数传递到这个函数。
avformat_write_header()函数声明位于libavformat/avformat.h:
/** * Allocate the stream private data and write the stream header to * an output media file. * * @param s Media file handle, must be allocated with avformat_alloc_context(). * Its oformat field must be set to the desired output format; * Its pb field must be set to an already opened AVIOContext. * @param options An AVDictionary filled with AVFormatContext and muxer-private options. * On return this parameter will be destroyed and replaced with a dict containing * options that were not found. May be NULL. * * @return AVSTREAM_INIT_IN_WRITE_HEADER on success if the codec had not already been fully initialized in avformat_init, * AVSTREAM_INIT_IN_INIT_OUTPUT on success if the codec had already been fully initialized in avformat_init, * negative AVERROR on failure. * * @see av_opt_find, av_dict_set, avio_open, av_oformat_next, avformat_init_output. */ av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options);
函数的实现位于libavformat/mux.c,具体如下:
int avformat_write_header(AVFormatContext *s, AVDictionary **options) { int ret = 0; int already_initialized = s->internal->initialized; int streams_already_initialized = s->internal->streams_initialized; if (!already_initialized) // 初始化输出 if ((ret = avformat_init_output(s, options)) < 0) return ret; if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) // 写入marker标识 avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_HEADER); if (s->oformat->write_header) { // 写入文件头 ret = s->oformat->write_header(s); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; if (ret < 0) goto fail; flush_if_needed(s); } if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_UNKNOWN); if (!s->internal->streams_initialized) { // 初始化pts if ((ret = init_pts(s)) < 0) goto fail; } return streams_already_initialized; fail: deinit_muxer(s); return ret; }
由此可见,avformat_write_header函数主要做4件事:
- 调用avformat_init_output()来初始化输出文件;
- 调用avio_write_marker()来写入marker标识,如果存在AVIOContext;
- 调用AVOutputFormat的write_header()来写入文件头;
- 调用init_pts()来初始化时间戳;
我们来看下avformat_init_output()函数:
int avformat_init_output(AVFormatContext *s, AVDictionary **options) { int ret = 0; if ((ret = init_muxer(s, options)) < 0) return ret; s->internal->initialized = 1; s->internal->streams_initialized = ret; if (s->oformat->init && ret) { if ((ret = init_pts(s)) < 0) return ret; return AVSTREAM_INIT_IN_INIT_OUTPUT; } return AVSTREAM_INIT_IN_WRITE_HEADER; }
内部调用init_muxer()函数来初始化封装器:
static int init_muxer(AVFormatContext *s, AVDictionary **options) { ...... // 检查nb_streams是否为0 if (s->nb_streams == 0 && !(of->flags & AVFMT_NOSTREAMS)) { av_log(s, AV_LOG_ERROR, "No streams to mux were specified\n"); ret = AVERROR(EINVAL); goto fail; } for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; par = st->codecpar; // 检查timebase时间基,如果没有就设置默认时间基 if (!st->time_base.num) { if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->sample_rate) avpriv_set_pts_info(st, 64, 1, par->sample_rate); else avpriv_set_pts_info(st, 33, 1, 90000); } switch (par->codec_type) { case AVMEDIA_TYPE_AUDIO: // 检查音频采样率、block_align块对齐 if (par->sample_rate <= 0) { ret = AVERROR(EINVAL); goto fail; } if (!par->block_align) par->block_align = par->channels * av_get_bits_per_sample(par->codec_id) >> 3; break; case AVMEDIA_TYPE_VIDEO: // 检查视频宽高、宽高比 if ((par->width <= 0 || par->height <= 0) && !(of->flags & AVFMT_NODIMENSIONS)) { ret = AVERROR(EINVAL); goto fail; } if (av_cmp_q(st->sample_aspect_ratio, par->sample_aspect_ratio) && fabs(av_q2d(st->sample_aspect_ratio) - av_q2d(par->sample_aspect_ratio)) > 0.004*av_q2d(st->sample_aspect_ratio)) { if (st->sample_aspect_ratio.num != 0 && st->sample_aspect_ratio.den != 0 && par->sample_aspect_ratio.num != 0 && par->sample_aspect_ratio.den != 0) { ret = AVERROR(EINVAL); goto fail; } } break; } desc = avcodec_descriptor_get(par->codec_id); if (desc && desc->props & AV_CODEC_PROP_REORDER) st->internal->reorder = 1; st->internal->is_intra_only = ff_is_intra_only(par->codec_id); // 检查codec_tag if (of->codec_tag) { if ( par->codec_tag && par->codec_id == AV_CODEC_ID_RAWVIDEO && ( av_codec_get_tag(of->codec_tag, par->codec_id) == 0 || av_codec_get_tag(of->codec_tag, par->codec_id) == MKTAG('r', 'a', 'w', ' ')) && !validate_codec_tag(s, st)) { par->codec_tag = 0; } if (par->codec_tag) { if (!validate_codec_tag(s, st)) { const uint32_t otag = av_codec_get_tag(s->oformat->codec_tag, par->codec_id); ret = AVERROR_INVALIDDATA; goto fail; } } else par->codec_tag = av_codec_get_tag(of->codec_tag, par->codec_id); } if (par->codec_type != AVMEDIA_TYPE_ATTACHMENT) s->internal->nb_interleaved_streams++; } // 检查priv_data if (!s->priv_data && of->priv_data_size > 0) { s->priv_data = av_mallocz(of->priv_data_size); if (!s->priv_data) { ret = AVERROR(ENOMEM); goto fail; } if (of->priv_class) { *(const AVClass **)s->priv_data = of->priv_class; av_opt_set_defaults(s->priv_data); if ((ret = av_opt_set_dict2(s->priv_data, &tmp, AV_OPT_SEARCH_CHILDREN)) < 0) goto fail; } } // 设置encoder if (!(s->flags & AVFMT_FLAG_BITEXACT)) { av_dict_set(&s->metadata, "encoder", LIBAVFORMAT_IDENT, 0); } else { av_dict_set(&s->metadata, "encoder", NULL, 0); } ...... return 0; fail: av_dict_free(&tmp); return ret; }
接着看s->oformat->write_header()函数,以mp4封装格式为例,位于libavformat/movenc.c。那么mp4对应的AVOutputFormat如下:
AVOutputFormat ff_mp4_muxer = { .name = "mp4", .long_name = NULL_IF_CONFIG_SMALL("MP4 (MPEG-4 Part 14)"), .mime_type = "video/mp4", .extensions = "mp4", .priv_data_size = sizeof(MOVMuxContext), .audio_codec = AV_CODEC_ID_AAC, .video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, .init = mov_init, .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, .deinit = mov_free, .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = mp4_codec_tags_list, .check_bitstream = mov_check_bitstream, .priv_class = &mp4_muxer_class, };
此时,write_header函数指针指向mov_write_header,具体函数如下:
static int mov_write_header(AVFormatContext *s) { AVIOContext *pb = s->pb; MOVMuxContext *mov = s->priv_data; int i, ret, hint_track = 0, tmcd_track = 0, nb_tracks = s->nb_streams; if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) nb_tracks++; if (mov->flags & FF_MOV_FLAG_RTP_HINT) { hint_track = nb_tracks; for (i = 0; i < s->nb_streams; i++) if (rtp_hinting_needed(s->streams[i])) nb_tracks++; } if (mov->nb_meta_tmcd) tmcd_track = nb_tracks; for (i = 0; i < s->nb_streams; i++) { int j; AVStream *st= s->streams[i]; MOVTrack *track= &mov->tracks[i]; // 如果存在extradata就进行拷贝 if (st->codecpar->extradata_size) { if (st->codecpar->codec_id == AV_CODEC_ID_DVD_SUBTITLE) mov_create_dvd_sub_decoder_specific_info(track, st); else if (!TAG_IS_AVCI(track->tag) && st->codecpar->codec_id != AV_CODEC_ID_DNXHD) { track->vos_len = st->codecpar->extradata_size; track->vos_data = av_malloc(track->vos_len + AV_INPUT_BUFFER_PADDING_SIZE); if (!track->vos_data) { return AVERROR(ENOMEM); } memcpy(track->vos_data, st->codecpar->extradata, track->vos_len); memset(track->vos_data + track->vos_len, 0, AV_INPUT_BUFFER_PADDING_SIZE); } } if (st->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || track->par->channel_layout != AV_CH_LAYOUT_MONO) continue; for (j = 0; j < s->nb_streams; j++) { AVStream *stj= s->streams[j]; MOVTrack *trackj= &mov->tracks[j]; if (j == i) continue; if (stj->codecpar->codec_type != AVMEDIA_TYPE_AUDIO || trackj->par->channel_layout != AV_CH_LAYOUT_MONO || trackj->language != track->language || trackj->tag != track->tag) continue; track->multichannel_as_mono++; } } if (!(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { if ((ret = mov_write_identification(pb, s)) < 0) return ret; } if (mov->reserved_moov_size){ mov->reserved_header_pos = avio_tell(pb); if (mov->reserved_moov_size > 0) avio_skip(pb, mov->reserved_moov_size); } if (mov->flags & FF_MOV_FLAG_FRAGMENT) { // 设置flag为FF_MOV_FLAG_FRAG_KEYFRAME if (!(mov->flags & (FF_MOV_FLAG_FRAG_KEYFRAME | FF_MOV_FLAG_FRAG_CUSTOM | FF_MOV_FLAG_FRAG_EVERY_FRAME)) && !mov->max_fragment_duration && !mov->max_fragment_size) mov->flags |= FF_MOV_FLAG_FRAG_KEYFRAME; } else { if (mov->flags & FF_MOV_FLAG_FASTSTART) mov->reserved_header_pos = avio_tell(pb); // 写入mdat的tag mov_write_mdat_tag(pb, mov); } ff_parse_creation_time_metadata(s, &mov->time, 1); if (mov->time) mov->time += 0x7C25B080; // 1970 based -> 1904 based if (mov->chapter_track) if ((ret = mov_create_chapter_track(s, mov->chapter_track)) < 0) return ret; if (mov->flags & FF_MOV_FLAG_RTP_HINT) { for (i = 0; i < s->nb_streams; i++) { if (rtp_hinting_needed(s->streams[i])) { if ((ret = ff_mov_init_hinting(s, hint_track, i)) < 0) return ret; hint_track++; } } } if (mov->nb_meta_tmcd) { const AVDictionaryEntry *t, *global_tcr = av_dict_get( s->metadata, "timecode", NULL, 0); // 初始化tmcd的track轨道 for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; t = global_tcr; if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { AVTimecode tc; if (!t) t = av_dict_get(st->metadata, "timecode", NULL, 0); if (!t) continue; if (mov_check_timecode_track(s, &tc, i, t->value) < 0) continue; if ((ret = mov_create_timecode_track(s, tmcd_track, i, tc)) < 0) return ret; tmcd_track++; } } } avio_flush(pb); if (mov->flags & FF_MOV_FLAG_ISML) mov_write_isml_manifest(pb, mov, s); // 写入moov的tag if (mov->flags & FF_MOV_FLAG_EMPTY_MOOV && !(mov->flags & FF_MOV_FLAG_DELAY_MOOV)) { if ((ret = mov_write_moov_tag(pb, mov, s)) < 0) return ret; mov->moov_written = 1; if (mov->flags & FF_MOV_FLAG_GLOBAL_SIDX) mov->reserved_header_pos = avio_tell(pb); } return 0; }
总结一下,mov_write_header函数主要做4件事情:
- 拷贝extradata;
- 写入mdat的tag或设置fragment的flag;
- 初始化tmcd(timecode)的track轨道;
- 写入moov的tag;
至此, avformat_write_header()写文件头的函数分析完毕。
-
MongoDB 批量操作(bulkWrite)
2020-03-26 21:01:53mongodb 3.2 版中的新版本提供了db.collection.bulkWrite() 方法提供了执行批量插入、更新和删除操作的能力。 mongodb 还支持批量插入 db.collection.insertMany()。 1.1、语法 db.collection.bulkWrite( [ <...一、概述
mongodb 3.2 版中的新版本提供了db.collection.bulkWrite() 方法提供了执行批量插入、更新和删除操作的能力。
mongodb 还支持批量插入 db.collection.insertMany()。
1.1、语法
db.collection.bulkWrite( [ <operation 1>, <operation 2>, ... ], { writeConcern : <document>, ordered : <boolean> } )
参数 类型 描述 operations array bulkWrite() 写操作的数组。支持操作:insertOne、updateOne、updateMany、deleteOne、deleteMany、replaceOne writeConcern document 可选, write concern 文档,省略则使用默认的 write concern。 ordered boolean 可选,表示mongod实例有序还是无序执行操作。默认值true。 方法返回值:
- 操作基于 write concern 运行则 acknowledged 值为true,如果禁用 write concern 运行则 acknowledged 值为false。
- 每一个写操作数。
- 成功 inserted 或 upserted文档的 _id 的组数。
行为
bulkWrite() 接收一个写操作的数组然后执行它们中的每一个。默认是有序的执行。
二、写操作
insertOne
插入单个文档到集合中。
db.collection.bulkWrite( [ { insertOne : { "document" : <document> } } ] )
updateOne 及 updateMany
updateOne 更新集合中 filter 匹配的单个文档。如果匹配到多个文档 updateOne 仅更新第一个匹配到的文档。
db.collection.bulkWrite( [ { updateOne : { "filter" : <document>, "update" : <document>, "upsert" : <boolean> } } ] )
updateMany 更新集合中所有匹配到的文档。
db.collection.bulkWrite( [ { updateMany : { "filter" : <document>, "update" : <document>, "upsert" : <boolean> } } ] )
对字段的更新操作例如 $ set 、$ unset 、$rename等。
默认情况 upsert 为 false。
replaceOne
replaceOne 替换集合中 filter 匹配到的单个文档。如果匹配到多个文档 replaceOne 只会替换一个匹配到的文档。
db.collection.bulkWrite([ { replaceOne : { "filter" : <document>, "replacement" : <document>, "upsert" : <boolean> } } ] )
replacement 字段中不能包含 update 操作。
默认情况 upsert 为 false。
deleteOne 及 deleteMany
deleteOne 删除集合中 filter 匹配到的单个文档。如果匹配到多个文档 deleteOne 只会删除一个匹配到的文档。
db.collection.bulkWrite([ { deleteOne : { "filter" : <document> } } ] )
deleteMany 删除集合中 filter 匹配到的所有文档。
db.collection.bulkWrite([ { deleteMany : { "filter" : <document> } } ] )
三、_id 字段
如果文档未指定 _id 字段,则mongod会在 insert 或 upsert 文档之前添加 _id 字段并指定唯一的ObjectId。 大多数驱动程序会创建一个ObjectId并插入到 _id 字段,但如果驱动程序或应用程序没有,mongod将创建并填充 _id。
如果文档包含 _id 字段,则 _id 值在集合中必须是唯一的,以避免重复键错误。
更新或替换操作不能指定与原始文档不同的 _id 值。
四、执行操作
ordered 参数指定 bulkWrite() 是否有序执行,默认情况下是有序执行。
含有6个操作的 bulkWrite() 代码如下:
db.collection.bulkWrite( [ { insertOne : <document> }, { updateOne : <document> }, { updateMany : <document> }, { replaceOne : <document> }, { deleteOne : <document> }, { deleteMany : <document> } ] )
默认情况下 ordered : true ,每个操作将会有序的执行,从第一个insertOne 到最后一个deleteMany 顺序执行。
应用程序不依赖操作执行顺序是,可以设置 ordered 为 false ,此时mongod 会重新排序操作来提高性能。
含有6个操作无序的 bulkWrite() 代码如下:
db.collection.bulkWrite( [ { insertOne : <document> }, { updateOne : <document> }, { updateMany : <document> }, { replaceOne : <document> }, { deleteOne : <document> }, { deleteMany : <document> } ], { ordered : false } )
对于ordered:false,操作结果可能会有所不同。 例如,deleteOne或deleteMany 删除的文档可能会变多或变少,具体取决于deleteOne或deleteMany 是在insertOne,updateOne,updateMany或replaceOne操作之前或之后的运行。
每组操作最多可以有1000次操作。 如果一个组超过此限制,MongoDB会将该组划分为1000或更小的组。 例如,如果队列包含2000个操作,MongoDB将创建2个组,每个组具有1000个操作。
大小和分组机制是内部的执行细节,在将来的版本中可能会有所变化。
在分片集合上执行有序操作通常比执行无序操作慢,因为对于有序,每个操作必须等待上一个操作完成。
五、固定集合(Capped Collections)
bulkWrite() 写操作在固定集合上使用有所限制。
-
updateOne 和 updateMany 更新时增加了被修改文档的大小将会抛出 WriteError
-
replaceOne 操作替换的文档比之前的文档大会抛出 WriteError
-
deleteOne 和 deleteMany 操作在固定集合上会抛出 WriteError
六、操作处理(Error Handling)
bulkWrite() 在错误发生时会抛出 BulkWriteError 异常。
排除Write Concern错误,有序操作在发生错误后停止,及无序操作继续处理队列中的剩余写入操作。
Write Concern 错误显示在 writeConcernErrors字段中,而所有其他错误都显示在writeErrors字段中。 如果遇到错误,则显示成功写入操作的数量而不是插入的_id值。 有序操作显示遇到的单个错误,而无序操作显示数组中的每个错误。
七、实例
7.1、批量写
characters 集合包含以下文档:
{ "_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4 }, { "_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3 }, { "_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3 }
bulkWrite() 在集合上执行批量操作:
try { db.characters.bulkWrite( [ { insertOne : { "document" : { "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4 } } }, { insertOne : { "document" : { "_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3 } } }, { updateOne : { "filter" : { "char" : "Eldon" }, "update" : { $set : { "status" : "Critical Injury" } } } }, { deleteOne : { "filter" : { "char" : "Brisbane"} } }, { replaceOne : { "filter" : { "char" : "Meldane" }, "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 } } } ] ); } catch (e) { print(e); }
操作结果如下:
{ "acknowledged" : true, "deletedCount" : 1, "insertedCount" : 2, "matchedCount" : 2, "upsertedCount" : 0, "insertedIds" : { "0" : 4, "1" : 5 }, "upsertedIds" : { } }
如果 第二个 insertOne 操作的 _id 是集合中已经存在的,则会抛出以下错误:
BulkWriteError({ "writeErrors" : [ { "index" : 0, "code" : 11000, "errmsg" : "E11000 duplicate key error collection: guidebook.characters index: _id_ dup key: { : 4 }", "op" : { "_id" : 5, "char" : "Taeln" } } ], "writeConcernErrors" : [ ], "nInserted" : 1, "nUpserted" : 0, "nMatched" : 0, "nModified" : 0, "nRemoved" : 0, "upserted" : [ ] })
默认情况下 ordered 为 true, 顺序执行时遇到错误就停止执行(后续的操作不会被执行)。
7.2、无序批量写
characters 集合包含以下文档:
{ "_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4 }, { "_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3 }, { "_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3 }
bulkWrite() 在集合上执行批量操作:
try { db.characters.bulkWrite( [ { insertOne : { "document" : { "_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4 } } }, { insertOne : { "document" : { "_id" : 4, "char" : "Taeln", "class" : "fighter", "lvl" : 3 } } }, { updateOne : { "filter" : { "char" : "Eldon" }, "update" : { $set : { "status" : "Critical Injury" } } } }, { deleteOne : { "filter" : { "char" : "Brisbane"} } }, { replaceOne : { "filter" : { "char" : "Meldane" }, "replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 } } } ], { ordered : false } ); } catch (e) { print(e); }
操作结果如下:
BulkWriteError({ "writeErrors" : [ { "index" : 0, "code" : 11000, "errmsg" : "E11000 duplicate key error collection: guidebook.characters index: _id_ dup key: { : 4 }", "op" : { "_id" : 4, "char" : "Taeln" } } ], "writeConcernErrors" : [ ], "nInserted" : 1, "nUpserted" : 0, "nMatched" : 2, "nModified" : 2, "nRemoved" : 1, "upserted" : [ ] })
无序操作,尽管操作过程中出现错误,剩余的操作也不会就此终止执行。
7.3、基于 Write Concern 的批量写
enemies 集合包含以下文档:
{ "_id" : 1, "char" : "goblin", "rating" : 1, "encounter" : 0.24 }, { "_id" : 2, "char" : "hobgoblin", "rating" : 1.5, "encounter" : 0.30 }, { "_id" : 3, "char" : "ogre", "rating" : 3, "encounter" : 0.2 }, { "_id" : 4, "char" : "ogre berserker" , "rating" : 3.5, "encounter" : 0.12}
以下使用 write concern 值为 “majority” 及 timeout 为 100 毫秒来执行批量写操作:
try { db.enemies.bulkWrite( [ { updateMany : { "filter" : { "rating" : { $gte : 3} }, "update" : { $inc : { "encounter" : 0.1 } } }, }, { updateMany : { "filter" : { "rating" : { $lt : 2} }, "update" : { $inc : { "encounter" : -0.25 } } }, }, { deleteMany : { "filter" : { "encounter" { $lt : 0 } } } }, { insertOne : { "document" : { "_id" :5, "char" : "ogrekin" , "rating" : 2, "encounter" : 0.31 } } } ], { writeConcern : { w : "majority", wtimeout : 100 } } ); } catch (e) { print(e); }
如果副本集中所有必需节点确认写入操作所需的总时间大于wtimeout,则在wtimeout 时间过去时将显示以下writeConcernError。
BulkWriteError({ "writeErrors" : [ ], "writeConcernErrors" : [ { "code" : 64, "errInfo" : { "wtimeout" : true }, "errmsg" : "waiting for replication timed out" } ], "nInserted" : 1, "nUpserted" : 0, "nMatched" : 4, "nModified" : 4, "nRemoved" : 1, "upserted" : [ ] })
结果集显示执行的操作,因为writeConcernErrors错误不是任何写入操作失败的标志。
-
Datax 支持增量 oracle writeMode update
2020-06-21 10:05:43columnHolders, List<String> valueHolders, String writeMode, DataBaseType dataBaseType, boolean forceUseUpdate) { boolean isWriteModeLegal = writeMode.trim().toLowerCase().startsWith("insert") || write... -
Presto Cannot write to non-managed Hive table
2022-03-23 11:06:58Cannot write to non-managed Hive table 网上搜了一下也没发现类似的错,不过让我注意到了non-managed Hive table。 那么,什么是non-managed Hive table? 查了一下才发现,原来 Managed Table 就是 Internal ... -
再探Linux内核write系统调用操作的原子性
2017-12-23 13:52:52很多人都在问Linux系统的write调用到底是不是原子的。网上能搜出一大堆文章,基本上要么是翻译一些文献,要么就是胡扯,本文中我来结合实例来试着做一个稍微好一点的回答。 先摆出结论吧。结论包含两点,即write... -
document write( )解析
2019-04-25 16:31:21document write( )解析 转至:https://www.cnblogs.com/ziyunfei/p/5881426.html 该文主要作为学习笔记进行转载,如有侵权请联系 在传统的浏览器中,同步的 script 标签是会阻塞 HTML 解析器的,无论是内联的还是... -
fastjson报错:write javaBean error, fastjson version 1.2.76, class io.undertow.servlet.xx,已解决
2021-09-01 11:15:43小白一枚,开发项目过程中测试了下导出文件功能,发现了一个bug,控制台输出报错信息,结果是正确的,但是bug报在控制台真的不好看啊。弄了一天半,一路debug删删减减到service方法都注释掉了,...write javaBean -
iwrite复制粘贴方法
2022-04-11 21:46:14iwrite复制粘贴方法 -
Copy On Write机制了解一下
2019-05-15 17:29:50执行BGSAVE命令或者BGREWRITEAOF命令的过程中,Redis需要创建当前服务器进程的子进程,而大多数操作系统都采用写时复制(copy-on-write)来优化子进程的使用效率,所以在子进程存在期间,服务器会提高负载因子的阈值... -
linux中write函数详解
2022-03-08 09:46:371、write函数 头文件#include <unistd.h> 三个参数 函数说明:write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内。 返回值:如果顺利write()会返回实际写入的字节数(len)。当有错误发生... -
fortran中write用法
2021-05-23 00:51:07fortran中write用法 格式化输出的控制字符非常的丰富,但常用的并不多,一般说来:" I 、F、E、A、X "是最常使用的几个格式,最好把它们都记下来。 Iw[.m] 以w个字符的宽度来输出整数,至少输出m个数字。 如:write(*... -
Java Writer write()方法
2021-03-07 08:32:28Java Writer write()方法java.io.Writer.write(String str,int off,int len)写入字符串的一部分。1 语法public void write(String str,int off,int len)2 参数str:要写入的字符串。off:开始写入字符的偏移量。len... -
write.csv()函数--R语言
2021-04-12 22:50:35write.table prints its required argument x (after converting it to a data frame if it is not one nor a matrix) to a file or connection. 将X输出到文件或者链接 函数语法: write.table(x, file = "", ... -
python write( )函数
2021-01-12 08:26:38(交流学习群 467604262)在博客(python 本地数据获取 网址:http://blog.csdn.net/sxingming/article/details/51333663)中...write( )函数的参数是一个字符串,分以下2种情况:1》通过write()函数向文件中写入一行>... -
缓存模式(Cache Aside、Read Through、Write Through、Write Behind)
2020-06-25 23:43:55文章目录 概览 Cache-Aside 读操作 更新操作 1、缓存失效 2、缓存更新 Read-Through Write-Through Write-Behind 总结 参考 概览 缓存是一个有着更快的查询速度的存储技术,这里的更快是指比起从初始的数据源查询... -
fatfs文件系统详解之f_write函数分析
2020-05-31 18:36:43本篇分析f_write()函数,fatfs文件系统对应的不知道文件的读写,也对应了文件的其他的操作,也有文件夹的操作,函数分析确实是一个非常耗时耗精力的事情,此函数分析完之后,就结束函数分析。 分析假设 (1)假设一... -
fortran write格式
2020-07-17 23:14:31write(*,"(f10.1)",advance="no")A 格式化输出的控制字符非常的丰富,但常用的并不多,一般说来:" I 、F、E、A、X "是最常使用的几个格式,最好把它们都记下来。 Iw[.m]以w个字符的宽度来输出整数,至少输出m个... -
write函数过程解析 __write_nocancel
2017-07-26 11:08:19write函数过程解析 write函数作为用户向终端或者文件进行写数据的重要函数,有着重要的作用。 |------| |---------| |---------| |----------| | write |----->|sys_write|-------->|vfs_write|------->|ext... -
document中的write用法
2018-08-28 20:07:02一、document.write()运行原理 首先我们先了解一下这条语句运行的原理: document.write()是Javascript中对document.open()所开启的文档流操作的API方法。 它能够直接砸文档流中写入字符串,一旦文档流已经... -
turtle.write方法使用说明
2021-02-21 10:56:13turtle.write方法使用说明 关于turtle可参见 Python新手入门学习讲座系列文章 https://blog.csdn.net/cnds123/article/details/108676296 turtle.write()方法 在当前乌龟位置写入文本。使用格式: write(arg... -
C语言之write()函数解析:Write Failed Bad address
2019-11-23 09:20:47在ARM开发板上跑如下测试程序的时候会概率性出现“Write Failed Bad address”: /* Write test */ #include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<sys/stat.h> #... -
python中write方法是如何使用?
2020-11-29 11:36:39关于这个函数,之前小编给大家介绍过,不知道大家还有印象吗,今天再把这个函数拿来跟...语法write(data)data为要写入的数据,可以为字符串str类型,也可以是bytes类型。二、 案例1、实现一个文本文件的拷贝,使用... -
WRITE_EXTERNAL_STORAGE no longer provides write access when targeting Android 10+
2020-10-26 10:45:07Android 10+ 适配数据存取权限,WRITE_EXTERNAL_STORAGE no longer provides write access when targeting Android 10+Android 10+ 适配数据存取权限简介方法总结 Android 10+ 适配数据存取权限 你好! 这是你第一次... -
prometheus的remote write功能
2020-08-30 17:37:54prometheus配置了remote write的目标地址后,它会从WAL读取数据,然后把采样数据写入各分片的内存队列,最后发起向远程目标地址的请求。 数据流的逻辑大致如下: |--> queue (shard_1) --> remote endpoint ... -
Python中write()方法有哪些功能?
2021-01-29 04:43:34摘要:下文讲述Python中write()的方法的功能简介说明,如下所示:write()方法功能:用于向文件中写入指定字符串(如:写入一个列表)write()方法语法fileObject.write(str)--------参数说明--------fileObject:文件对象... -
curl CURLOPT_WRITEDATA CURLOPT_WRITEFUNCTION 回调函数
2019-10-15 17:46:03最近用libcurl开源库做了...1,curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, HttpPostWriteBack); HttpPostWriteBack是回调函数指针,需要自己实现原型为:unsigned int HttpPostWriteBack(void *contents, siz... -
python文件写入write()的操作
2020-12-19 17:02:32本文实例为大家分享了python文件写入write()的操作的具体代码,供大家参考,具体内容如下filename = 'pragramming.txt'with open(filename,'w') as fileobject: #使用‘w'来提醒python用写入的方式打开fileobject.... -
iWrite英语写作教学与评阅系统移动端——学生使用手册
2020-12-19 03:43:12通过微信搜索公众号:iWrite爱写作,点击“关注”。一、注册iWrite英语写作教学与评阅系统移动端首页底端显示“登录”按钮。首次关注,点击“登录”按钮,页面跳转至登录/注册界面。点击“注册账号”按钮,即可跳转...