注:写了一系列的结构体的分析的文章,在这里列一个列表:

FFMPEG结构体分析:AVFrame
FFMPEG结构体分析:AVFormatContext
FFMPEG结构体分析:AVCodecContext
FFMPEG结构体分析:AVIOContext
FFMPEG结构体分析:AVCodec
FFMPEG结构体分析:AVStream
FFMPEG结构体分析:AVPacket

FFMPEG有几个最重要的结构体,包含了解协议,解封装,解码操作,此前已经进行过分析:

FFMPEG中最关键的结构体之间的关系

在此不再详述,其中AVFrame是包含码流参数较多的结构体。本文将会详细分析一下该结构体里主要变量的含义和作用。

首先看一下结构体的定义(位于avcodec.h):

  1. /*
  2. *雷霄骅
  3. *leixiaohua1020@126.com
  4. *中国传媒大学/数字电视技术
  5. */
  6. /**
  7. * Audio Video Frame.
  8. * New fields can be added to the end of AVFRAME with minor version
  9. * bumps. Similarly fields that are marked as to be only accessed by
  10. * av_opt_ptr() can be reordered. This allows 2 forks to add fields
  11. * without breaking compatibility with each other.
  12. * Removal, reordering and changes in the remaining cases require
  13. * a major version bump.
  14. * sizeof(AVFrame) must not be used outside libavcodec.
  15. */
  16. typedef struct AVFrame {
  17. #define AV_NUM_DATA_POINTERS 8
  18. /**图像数据
  19. * pointer to the picture/channel planes.
  20. * This might be different from the first allocated byte
  21. * - encoding: Set by user
  22. * - decoding: set by AVCodecContext.get_buffer()
  23. */
  24. uint8_t *data[AV_NUM_DATA_POINTERS];
  25. /**
  26. * Size, in bytes, of the data for each picture/channel plane.
  27. *
  28. * For audio, only linesize[0] may be set. For planar audio, each channel
  29. * plane must be the same size.
  30. *
  31. * - encoding: Set by user
  32. * - decoding: set by AVCodecContext.get_buffer()
  33. */
  34. int linesize[AV_NUM_DATA_POINTERS];
  35. /**
  36. * pointers to the data planes/channels.
  37. *
  38. * For video, this should simply point to data[].
  39. *
  40. * For planar audio, each channel has a separate data pointer, and
  41. * linesize[0] contains the size of each channel buffer.
  42. * For packed audio, there is just one data pointer, and linesize[0]
  43. * contains the total size of the buffer for all channels.
  44. *
  45. * Note: Both data and extended_data will always be set by get_buffer(),
  46. * but for planar audio with more channels that can fit in data,
  47. * extended_data must be used by the decoder in order to access all
  48. * channels.
  49. *
  50. * encoding: unused
  51. * decoding: set by AVCodecContext.get_buffer()
  52. */
  53. uint8_t **extended_data;
  54. /**宽高
  55. * width and height of the video frame
  56. * - encoding: unused
  57. * - decoding: Read by user.
  58. */
  59. int width, height;
  60. /**
  61. * number of audio samples (per channel) described by this frame
  62. * - encoding: Set by user
  63. * - decoding: Set by libavcodec
  64. */
  65. int nb_samples;
  66. /**
  67. * format of the frame, -1 if unknown or unset
  68. * Values correspond to enum AVPixelFormat for video frames,
  69. * enum AVSampleFormat for audio)
  70. * - encoding: unused
  71. * - decoding: Read by user.
  72. */
  73. int format;
  74. /**是否是关键帧
  75. * 1 -> keyframe, 0-> not
  76. * - encoding: Set by libavcodec.
  77. * - decoding: Set by libavcodec.
  78. */
  79. int key_frame;
  80. /**帧类型(I,B,P)
  81. * Picture type of the frame, see ?_TYPE below.
  82. * - encoding: Set by libavcodec. for coded_picture (and set by user for input).
  83. * - decoding: Set by libavcodec.
  84. */
  85. enum AVPictureType pict_type;
  86. /**
  87. * pointer to the first allocated byte of the picture. Can be used in get_buffer/release_buffer.
  88. * This isn't used by libavcodec unless the default get/release_buffer() is used.
  89. * - encoding:
  90. * - decoding:
  91. */
  92. uint8_t *base[AV_NUM_DATA_POINTERS];
  93. /**
  94. * sample aspect ratio for the video frame, 0/1 if unknown/unspecified
  95. * - encoding: unused
  96. * - decoding: Read by user.
  97. */
  98. AVRational sample_aspect_ratio;
  99. /**
  100. * presentation timestamp in time_base units (time when frame should be shown to user)
  101. * If AV_NOPTS_VALUE then frame_rate = 1/time_base will be assumed.
  102. * - encoding: MUST be set by user.
  103. * - decoding: Set by libavcodec.
  104. */
  105. int64_t pts;
  106. /**
  107. * reordered pts from the last AVPacket that has been input into the decoder
  108. * - encoding: unused
  109. * - decoding: Read by user.
  110. */
  111. int64_t pkt_pts;
  112. /**
  113. * dts from the last AVPacket that has been input into the decoder
  114. * - encoding: unused
  115. * - decoding: Read by user.
  116. */
  117. int64_t pkt_dts;
  118. /**
  119. * picture number in bitstream order
  120. * - encoding: set by
  121. * - decoding: Set by libavcodec.
  122. */
  123. int coded_picture_number;
  124. /**
  125. * picture number in display order
  126. * - encoding: set by
  127. * - decoding: Set by libavcodec.
  128. */
  129. int display_picture_number;
  130. /**
  131. * quality (between 1 (good) and FF_LAMBDA_MAX (bad))
  132. * - encoding: Set by libavcodec. for coded_picture (and set by user for input).
  133. * - decoding: Set by libavcodec.
  134. */
  135. int quality;
  136. /**
  137. * is this picture used as reference
  138. * The values for this are the same as the MpegEncContext.picture_structure
  139. * variable, that is 1->top field, 2->bottom field, 3->frame/both fields.
  140. * Set to 4 for delayed, non-reference frames.
  141. * - encoding: unused
  142. * - decoding: Set by libavcodec. (before get_buffer() call)).
  143. */
  144. int reference;
  145. /**QP表
  146. * QP table
  147. * - encoding: unused
  148. * - decoding: Set by libavcodec.
  149. */
  150. int8_t *qscale_table;
  151. /**
  152. * QP store stride
  153. * - encoding: unused
  154. * - decoding: Set by libavcodec.
  155. */
  156. int qstride;
  157. /**
  158. *
  159. */
  160. int qscale_type;
  161. /**跳过宏块表
  162. * mbskip_table[mb]>=1 if MB didn't change
  163. * stride= mb_width = (width+15)>>4
  164. * - encoding: unused
  165. * - decoding: Set by libavcodec.
  166. */
  167. uint8_t *mbskip_table;
  168. /**运动矢量表
  169. * motion vector table
  170. * @code
  171. * example:
  172. * int mv_sample_log2= 4 - motion_subsample_log2;
  173. * int mb_width= (width+15)>>4;
  174. * int mv_stride= (mb_width << mv_sample_log2) + 1;
  175. * motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y];
  176. * @endcode
  177. * - encoding: Set by user.
  178. * - decoding: Set by libavcodec.
  179. */
  180. int16_t (*motion_val[2])[2];
  181. /**宏块类型表
  182. * macroblock type table
  183. * mb_type_base + mb_width + 2
  184. * - encoding: Set by user.
  185. * - decoding: Set by libavcodec.
  186. */
  187. uint32_t *mb_type;
  188. /**DCT系数
  189. * DCT coefficients
  190. * - encoding: unused
  191. * - decoding: Set by libavcodec.
  192. */
  193. short *dct_coeff;
  194. /**参考帧列表
  195. * motion reference frame index
  196. * the order in which these are stored can depend on the codec.
  197. * - encoding: Set by user.
  198. * - decoding: Set by libavcodec.
  199. */
  200. int8_t *ref_index[2];
  201. /**
  202. * for some private data of the user
  203. * - encoding: unused
  204. * - decoding: Set by user.
  205. */
  206. void *opaque;
  207. /**
  208. * error
  209. * - encoding: Set by libavcodec. if flags&CODEC_FLAG_PSNR.
  210. * - decoding: unused
  211. */
  212. uint64_t error[AV_NUM_DATA_POINTERS];
  213. /**
  214. * type of the buffer (to keep track of who has to deallocate data[*])
  215. * - encoding: Set by the one who allocates it.
  216. * - decoding: Set by the one who allocates it.
  217. * Note: User allocated (direct rendering) & internal buffers cannot coexist currently.
  218. */
  219. int type;
  220. /**
  221. * When decoding, this signals how much the picture must be delayed.
  222. * extra_delay = repeat_pict / (2*fps)
  223. * - encoding: unused
  224. * - decoding: Set by libavcodec.
  225. */
  226. int repeat_pict;
  227. /**
  228. * The content of the picture is interlaced.
  229. * - encoding: Set by user.
  230. * - decoding: Set by libavcodec. (default 0)
  231. */
  232. int interlaced_frame;
  233. /**
  234. * If the content is interlaced, is top field displayed first.
  235. * - encoding: Set by user.
  236. * - decoding: Set by libavcodec.
  237. */
  238. int top_field_first;
  239. /**
  240. * Tell user application that palette has changed from previous frame.
  241. * - encoding: ??? (no palette-enabled encoder yet)
  242. * - decoding: Set by libavcodec. (default 0).
  243. */
  244. int palette_has_changed;
  245. /**
  246. * codec suggestion on buffer type if != 0
  247. * - encoding: unused
  248. * - decoding: Set by libavcodec. (before get_buffer() call)).
  249. */
  250. int buffer_hints;
  251. /**
  252. * Pan scan.
  253. * - encoding: Set by user.
  254. * - decoding: Set by libavcodec.
  255. */
  256. AVPanScan *pan_scan;
  257. /**
  258. * reordered opaque 64bit (generally an integer or a double precision float
  259. * PTS but can be anything).
  260. * The user sets AVCodecContext.reordered_opaque to represent the input at
  261. * that time,
  262. * the decoder reorders values as needed and sets AVFrame.reordered_opaque
  263. * to exactly one of the values provided by the user through AVCodecContext.reordered_opaque
  264. * @deprecated in favor of pkt_pts
  265. * - encoding: unused
  266. * - decoding: Read by user.
  267. */
  268. int64_t reordered_opaque;
  269. /**
  270. * hardware accelerator private data (FFmpeg-allocated)
  271. * - encoding: unused
  272. * - decoding: Set by libavcodec
  273. */
  274. void *hwaccel_picture_private;
  275. /**
  276. * the AVCodecContext which ff_thread_get_buffer() was last called on
  277. * - encoding: Set by libavcodec.
  278. * - decoding: Set by libavcodec.
  279. */
  280. struct AVCodecContext *owner;
  281. /**
  282. * used by multithreading to store frame-specific info
  283. * - encoding: Set by libavcodec.
  284. * - decoding: Set by libavcodec.
  285. */
  286. void *thread_opaque;
  287. /**
  288. * log2 of the size of the block which a single vector in motion_val represents:
  289. * (4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2)
  290. * - encoding: unused
  291. * - decoding: Set by libavcodec.
  292. */
  293. uint8_t motion_subsample_log2;
  294. /**(音频)采样率
  295. * Sample rate of the audio data.
  296. *
  297. * - encoding: unused
  298. * - decoding: read by user
  299. */
  300. int sample_rate;
  301. /**
  302. * Channel layout of the audio data.
  303. *
  304. * - encoding: unused
  305. * - decoding: read by user.
  306. */
  307. uint64_t channel_layout;
  308. /**
  309. * frame timestamp estimated using various heuristics, in stream time base
  310. * Code outside libavcodec should access this field using:
  311. * av_frame_get_best_effort_timestamp(frame)
  312. * - encoding: unused
  313. * - decoding: set by libavcodec, read by user.
  314. */
  315. int64_t best_effort_timestamp;
  316. /**
  317. * reordered pos from the last AVPacket that has been input into the decoder
  318. * Code outside libavcodec should access this field using:
  319. * av_frame_get_pkt_pos(frame)
  320. * - encoding: unused
  321. * - decoding: Read by user.
  322. */
  323. int64_t pkt_pos;
  324. /**
  325. * duration of the corresponding packet, expressed in
  326. * AVStream->time_base units, 0 if unknown.
  327. * Code outside libavcodec should access this field using:
  328. * av_frame_get_pkt_duration(frame)
  329. * - encoding: unused
  330. * - decoding: Read by user.
  331. */
  332. int64_t pkt_duration;
  333. /**
  334. * metadata.
  335. * Code outside libavcodec should access this field using:
  336. * av_frame_get_metadata(frame)
  337. * - encoding: Set by user.
  338. * - decoding: Set by libavcodec.
  339. */
  340. AVDictionary *metadata;
  341. /**
  342. * decode error flags of the frame, set to a combination of
  343. * FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there
  344. * were errors during the decoding.
  345. * Code outside libavcodec should access this field using:
  346. * av_frame_get_decode_error_flags(frame)
  347. * - encoding: unused
  348. * - decoding: set by libavcodec, read by user.
  349. */
  350. int decode_error_flags;
  351. #define FF_DECODE_ERROR_INVALID_BITSTREAM   1
  352. #define FF_DECODE_ERROR_MISSING_REFERENCE   2
  353. /**
  354. * number of audio channels, only used for audio.
  355. * Code outside libavcodec should access this field using:
  356. * av_frame_get_channels(frame)
  357. * - encoding: unused
  358. * - decoding: Read by user.
  359. */
  360. int64_t channels;
  361. } AVFrame;

AVFrame结构体一般用于存储原始数据(即非压缩数据,例如对视频来说是YUV,RGB,对音频来说是PCM),此外还包含了一些相关的信息。比如说,解码的时候存储了宏块类型表,QP表,运动矢量表等数据。编码的时候也存储了相关的数据。因此在使用FFMPEG进行码流分析的时候,AVFrame是一个很重要的结构体。

下面看几个主要变量的作用(在这里考虑解码的情况):

uint8_t *data[AV_NUM_DATA_POINTERS]:解码后原始数据(对视频来说是YUV,RGB,对音频来说是PCM)

int linesize[AV_NUM_DATA_POINTERS]:data中“一行”数据的大小。注意:未必等于图像的宽,一般大于图像的宽。

int width, height:视频帧宽和高(1920x1080,1280x720...)

int nb_samples:音频的一个AVFrame中可能包含多个音频帧,在此标记包含了几个

int format:解码后原始数据类型(YUV420,YUV422,RGB24...)

int key_frame:是否是关键帧

enum AVPictureType pict_type:帧类型(I,B,P...)

AVRational sample_aspect_ratio:宽高比(16:9,4:3...)

int64_t pts:显示时间戳

int coded_picture_number:编码帧序号

int display_picture_number:显示帧序号

int8_t *qscale_table:QP表

uint8_t *mbskip_table:跳过宏块表

int16_t (*motion_val[2])[2]:运动矢量表

uint32_t *mb_type:宏块类型表

short *dct_coeff:DCT系数,这个没有提取过

int8_t *ref_index[2]:运动估计参考帧列表(貌似H.264这种比较新的标准才会涉及到多参考帧)

int interlaced_frame:是否是隔行扫描

uint8_t motion_subsample_log2:一个宏块中的运动矢量采样个数,取log的

其他的变量不再一一列举,源代码中都有详细的说明。在这里重点分析一下几个需要一定的理解的变量:

1.data[]

对于packed格式的数据(例如RGB24),会存到data[0]里面。

对于planar格式的数据(例如YUV420P),则会分开成data[0],data[1],data[2]...(YUV420P中data[0]存Y,data[1]存U,data[2]存V)

具体参见:FFMPEG 实现 YUV,RGB各种图像原始数据之间的转换(swscale)

2.pict_type

包含以下类型:

  1. enum AVPictureType {
  2. AV_PICTURE_TYPE_NONE = 0, ///< Undefined
  3. AV_PICTURE_TYPE_I,     ///< Intra
  4. AV_PICTURE_TYPE_P,     ///< Predicted
  5. AV_PICTURE_TYPE_B,     ///< Bi-dir predicted
  6. AV_PICTURE_TYPE_S,     ///< S(GMC)-VOP MPEG4
  7. AV_PICTURE_TYPE_SI,    ///< Switching Intra
  8. AV_PICTURE_TYPE_SP,    ///< Switching Predicted
  9. AV_PICTURE_TYPE_BI,    ///< BI type
  10. };

3.sample_aspect_ratio

宽高比是一个分数,FFMPEG中用AVRational表达分数:

  1. /**
  2. * rational number numerator/denominator
  3. */
  4. typedef struct AVRational{
  5. int num; ///< numerator
  6. int den; ///< denominator
  7. } AVRational;

4.qscale_table

QP表指向一块内存,里面存储的是每个宏块的QP值。宏块的标号是从左往右,一行一行的来的。每个宏块对应1个QP。

qscale_table[0]就是第1行第1列宏块的QP值;qscale_table[1]就是第1行第2列宏块的QP值;qscale_table[2]就是第1行第3列宏块的QP值。以此类推...

宏块的个数用下式计算:

注:宏块大小是16x16的。

每行宏块数:

  1. int mb_stride = pCodecCtx->width/16+1

宏块的总数:

  1. int mb_sum = ((pCodecCtx->height+15)>>4)*(pCodecCtx->width/16+1)

5.motion_subsample_log2

1个运动矢量所能代表的画面大小(用宽或者高表示,单位是像素),注意,这里取了log2。

代码注释中给出以下数据:

4->16x16, 3->8x8, 2-> 4x4, 1-> 2x2

即1个运动矢量代表16x16的画面的时候,该值取4;1个运动矢量代表8x8的画面的时候,该值取3...以此类推

6.motion_val

运动矢量表存储了一帧视频中的所有运动矢量。

该值的存储方式比较特别:

  1. int16_t (*motion_val[2])[2];

为了弄清楚该值究竟是怎么存的,花了我好一阵子功夫...

注释中给了一段代码:

  1. int mv_sample_log2= 4 - motion_subsample_log2;
  2. int mb_width= (width+15)>>4;
  3. int mv_stride= (mb_width << mv_sample_log2) + 1;
  4. motion_val[direction][x + y*mv_stride][0->mv_x, 1->mv_y];

大概知道了该数据的结构:

1.首先分为两个列表L0和L1

2.每个列表(L0或L1)存储了一系列的MV(每个MV对应一个画面,大小由motion_subsample_log2决定)

3.每个MV分为横坐标和纵坐标(x,y)

注意,在FFMPEG中MV和MB在存储的结构上是没有什么关联的,第1个MV是屏幕上左上角画面的MV(画面的大小取决于motion_subsample_log2),第2个MV是屏幕上第1行第2列的画面的MV,以此类推。因此在一个宏块(16x16)的运动矢量很有可能如下图所示(line代表一行运动矢量的个数):

  1. //例如8x8划分的运动矢量与宏块的关系:
  2. //-------------------------
  3. //|          |            |
  4. //|mv[x]     |mv[x+1]     |
  5. //-------------------------
  6. //|          |            |
  7. //|mv[x+line]|mv[x+line+1]|
  8. //-------------------------

7.mb_type

宏块类型表存储了一帧视频中的所有宏块的类型。其存储方式和QP表差不多。只不过其是uint32类型的,而QP表是uint8类型的。每个宏块对应一个宏块类型变量。

宏块类型如下定义所示:

  1. //The following defines may change, don't expect compatibility if you use them.
  2. #define MB_TYPE_INTRA4x4   0x0001
  3. #define MB_TYPE_INTRA16x16 0x0002 //FIXME H.264-specific
  4. #define MB_TYPE_INTRA_PCM  0x0004 //FIXME H.264-specific
  5. #define MB_TYPE_16x16      0x0008
  6. #define MB_TYPE_16x8       0x0010
  7. #define MB_TYPE_8x16       0x0020
  8. #define MB_TYPE_8x8        0x0040
  9. #define MB_TYPE_INTERLACED 0x0080
  10. #define MB_TYPE_DIRECT2    0x0100 //FIXME
  11. #define MB_TYPE_ACPRED     0x0200
  12. #define MB_TYPE_GMC        0x0400
  13. #define MB_TYPE_SKIP       0x0800
  14. #define MB_TYPE_P0L0       0x1000
  15. #define MB_TYPE_P1L0       0x2000
  16. #define MB_TYPE_P0L1       0x4000
  17. #define MB_TYPE_P1L1       0x8000
  18. #define MB_TYPE_L0         (MB_TYPE_P0L0 | MB_TYPE_P1L0)
  19. #define MB_TYPE_L1         (MB_TYPE_P0L1 | MB_TYPE_P1L1)
  20. #define MB_TYPE_L0L1       (MB_TYPE_L0   | MB_TYPE_L1)
  21. #define MB_TYPE_QUANT      0x00010000
  22. #define MB_TYPE_CBP        0x00020000
  23. //Note bits 24-31 are reserved for codec specific use (h264 ref0, mpeg1 0mv, ...)

一个宏块如果包含上述定义中的一种或两种类型,则其对应的宏块变量的对应位会被置1。
注:一个宏块可以包含好几种类型,但是有些类型是不能重复包含的,比如说一个宏块不可能既是16x16又是8x8。

8.ref_index

运动估计参考帧列表存储了一帧视频中所有宏块的参考帧索引。这个列表其实在比较早的压缩编码标准中是没有什么用的。只有像H.264这样的编码标准才有多参考帧的概念。但是这个字段目前我还没有研究透。只是知道每个宏块包含有4个该值,该值反映的是参考帧的索引。以后有机会再进行细研究吧。

在这里展示一下自己做的码流分析软件的运行结果。将上文介绍的几个列表图像化显示了出来(在这里是使用MFC的绘图函数画出来的)

视频帧:

QP参数提取的结果:

美化过的(加上了颜色):

宏块类型参数提取的结果:

美化过的(加上了颜色,更清晰一些,s代表skip宏块):

运动矢量参数提取的结果(在这里是List0):

运动估计参考帧参数提取的结果:

转自:http://blog.csdn.net/leixiaohua1020/article/details/14214577

[转载] FFMPEG结构体分析:AVFrame的更多相关文章

  1. FFMPEG结构体分析:AVFrame

    注:写了一系列的结构体的分析的文章,在这里列一个列表: FFMPEG结构体分析:AVFrameFFMPEG结构体分析:AVFormatContextFFMPEG结构体分析:AVCodecContext ...

  2. FFMPEG结构体分析:AVPacket

    注:写了一系列的结构体的分析的文章,在这里列一个列表: FFMPEG结构体分析:AVFrame FFMPEG结构体分析:AVFormatContext FFMPEG结构体分析:AVCodecConte ...

  3. FFMPEG结构体分析:AVStream

    注:写了一系列的结构体的分析的文章,在这里列一个列表: FFMPEG结构体分析:AVFrame FFMPEG结构体分析:AVFormatContext FFMPEG结构体分析:AVCodecConte ...

  4. FFMPEG结构体分析:AVCodec

    注:写了一系列的结构体的分析的文章,在这里列一个列表: FFMPEG结构体分析:AVFrame FFMPEG结构体分析:AVFormatContext FFMPEG结构体分析:AVCodecConte ...

  5. FFMPEG结构体分析:AVIOContext

    注:写了一系列的结构体的分析的文章,在这里列一个列表: FFMPEG结构体分析:AVFrame FFMPEG结构体分析:AVFormatContext FFMPEG结构体分析:AVCodecConte ...

  6. FFMPEG结构体分析:AVCodecContext

    注:写了一系列的结构体的分析的文章,在这里列一个列表: FFMPEG结构体分析:AVFrame FFMPEG结构体分析:AVFormatContext FFMPEG结构体分析:AVCodecConte ...

  7. FFMPEG结构体分析:AVFormatContext

    注:写了一系列的结构体的分析的文章,在这里列一个列表: FFMPEG结构体分析:AVFrameFFMPEG结构体分析:AVFormatContextFFMPEG结构体分析:AVCodecContext ...

  8. FFMPEG结构体分析:AVCodecContext(转)

    注:写了一系列的结构体的分析的文章,在这里列一个列表: FFMPEG结构体分析:AVFrameFFMPEG结构体分析:AVFormatContextFFMPEG结构体分析:AVCodecContext ...

  9. FFMPEG结构体分析:AVFrame(解码后的数据)

    https://blog.csdn.net/jxcr1984/article/details/52766524 本文转自: http://blog.csdn.net/leixiaohua1020/ar ...

随机推荐

  1. cf100989b

    http://codeforces.com/gym/100989/my B. LCS (B) time limit per test 0.25 seconds memory limit per tes ...

  2. iOS 多线程安全 与可变数组

    完全来自于iOS 多线程安全与可变字典 的学习 基本相同,举一反三 直接上样例代码 是我参照网上,根据当前业务需求改的. 其实好多人在这里喜欢用类别处理.我个人觉得用类别 极其容易和普通方法混淆,所以 ...

  3. Xcode 解决日志打印不全问题

    Xcode 出了8.0后,代码运行日志过长时会出现打印不全的问题. 这可能是Xcode优化的一项,不过这也给开发带来的不必要的麻烦.下面的宏定义可以解决这一问题. #ifdef DEBUG #defi ...

  4. maven项目,去除jar包中的不想要的依赖关系

    解释:就是说项目中要用到某一个a.jar包,通过maven引入了之后,也自动的导入了该jar包所依赖的包,这里就会存在一个问题,如果a.jar包依赖b.jar这个项目的1.0版本,可是我的项目中已经有 ...

  5. hadoop2.7.x运行wordcount程序卡住在INFO mapreduce.Job: Running job:job _1469603958907_0002

    一.抛出问题 Hadoop集群(全分布式)配置好后,运行wordcount程序测试,发现每次运行都会卡住在Running job处,然后程序就呈现出卡死的状态. wordcount运行命令:[hado ...

  6. Web安全学习笔记之HTTP协议

    HTTP是一个应用层协议,主要用于Web开发,通常由HTTP客户端发起一个请求,创建一个到服务器指定端口(默认是80端口)的TCP连接.HTTP服务器则在那个端口监听客户端的请求.一旦收到请求,服务器 ...

  7. JavaScript右下角信息提示插件Notyf

    在线演示 本地下载

  8. 用“倍增法”求最近公共祖先(LCA)

    1.最近公共祖先:对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.的祖先且x的深度尽可能大. 2.朴素算法:记录下每个节点的父亲,使节点u,v一步一步地向上找 ...

  9. sql server 数据库复制实现数据同步常见问题(不定期更新)

    sql server2008数据库复制实现数据同步常见问题 在原作者基础上追加 sql server2008数据库复制实现数据同步常见问题 23.发布 'xx' 的并发快照不可用,因为该快照尚未完全生 ...

  10. ELK分布式日志收集搭建和使用

    大型系统分布式日志采集系统ELK全框架 SpringBootSecurity1.传统系统日志收集的问题2.Logstash操作工作原理3.分布式日志收集ELK原理4.Elasticsearch+Log ...