范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Android硬编解码MediaCodec解析从猪肉餐馆的故事讲起(三)

  上篇回顾
  前面两篇文章Android硬编解码MediaCodec解析——从猪肉餐馆的故事讲起(一)和Android硬编解码MediaCodec解析——从猪肉餐馆的故事讲起(二)——已经从猪肉餐馆的故事带各位比较详细地阐述了Android平台硬解码工具MediaCodec的工作流程和具体的代码,但是前两篇文章的分析是基于静态的, 但是MediaCodec具体的解码流程是怎么样的,我们并不知道。那么今天就让代码"动起来",通过log和辅助代码去更加深入掌握MediaCodec的解码流程 。
  如果还没看过前面两篇博文,还是建议看一下,因为本文和前两篇是有很大关联的。
  代码运行log分析
  首先点击第一个item:
  进入到这个界面:
  看下此时的Log:
  log打印位置在com.android.grafika.PlayMovieActivity,主要看下"SurfaceTexture ready (984x1384)"这一行: @Override public void onSurfaceTextureAvailable(SurfaceTexture st, int width, int height) {     // There"s a short delay between the start of the activity and the initialization     // of the SurfaceTexture that backs the TextureView.  We don"t want to try to     // send a video stream to the TextureView before it has initialized, so we disable     // the "play" button until this callback fires.     Log.d(TAG, "SurfaceTexture ready (" + width + "x" + height + ")");     mSurfaceTextureReady = true;     updateControls(); }
  还记得Android硬编解码工具MediaCodec解析——从猪肉餐馆的故事讲起(二)画的整体流程图么:
  onSurfaceTextureAvailable这个回调方法就是告诉我们,TextureView的SurfaceTexture已经初始化好了,可以开始渲染了。此时才会将播放按钮置为可点击。log"SurfaceTexture ready (984x1384)" 中的"(984x1384)"即为TextureView的尺寸。
  C++学习资料免费获取方法:关注音视频开发T哥  ,+「链接」 即可免费获取2023年最新 C++音视频开发进阶独家学习资料!
  此时,轻轻点击播放按钮,于是视频开始动起来了,可谓是穿梭时间旳画面的钟,从反方向开始移动~:
  首先输出了这条log:
  D/fuyao-Grafika: Extractor selected track 0 (video/avc): {track-id=1, level=32, mime=video/avc, profile=1, language=``` , color-standard=4, display-width=320, csd-1=java.nio.HeapByteBuffer[pos=0 lim=8 cap=8], color-transfer=3, durationUs=2033333, display-height=240, width=320, color-range=2, max-input-size=383, frame-rate=16, height=240, csd-0=java.nio.HeapByteBuffer[pos=0 lim=38 cap=38]}
  它是在MediaExtractor选中媒体轨道的时候打印的,打印出具体当前视频轨道格式相关信息: /**  * Selects the video track, if any.  *  * @return the track index, or -1 if no video track is found.  */ private static int selectTrack(MediaExtractor extractor) {     // Select the first video track we find, ignore the rest.     //当前媒体文件共有多少个轨道(视频轨道、音频轨道、字幕轨道等等)     int numTracks = extractor.getTrackCount();     for (int i = 0; i < numTracks; i++) {         //第i个轨道的MediaFormat         MediaFormat format = extractor.getTrackFormat(i);         //format对应的mime类型         String mime = format.getString(MediaFormat.KEY_MIME);         //找到视频轨道的index         if (mime.startsWith("video/")) {             if (VERBOSE) {             //注意这行的log打印                 Log.d(TAG, "Extractor selected track " + i + " (" + mime + "): " + format);             }             return i;         }     }      return -1; }
  稍微解释下log中的几个关键参数:
  1.log中的level和profile指的是画质级别,以下解释引用于# H264编码profile & level控制
  H.264有四种画质级别,分别是baseline, extended, main, high: 1、Baseline Profile:基本画质。支持I/P 帧,只支持无交错(Progressive)和CAVLC; 2、Extended profile:进阶画质。支持I/P/B/SP/SI 帧,只支持无交错(Progressive)和CAVLC;(用的少) 3、Main profile:主流画质。提供I/P/B 帧,支持无交错(Progressive)和交错(Interlaced), 也支持CAVLC 和CABAC 的支持; 4、High profile:高级画质。在main Profile 的基础上增加了8x8内部预测、自定义量化、 无损视频编码和更多的YUV 格式; H.264 Baseline profile、Extended profile和Main profile都是针对8位样本数据、4:2:0格式(YUV)的视频序列。在相同配置情况下,High profile(HP)可以比Main profile(MP)降低10%的码率。 根据应用领域的不同,Baseline profile多应用于实时通信领域,Main profile多应用于流媒体领域,High profile则多应用于广电和存储领域。
  2.mime为video/avc,这个上篇文章已经讲过,video/avc即为H264。
  3.color-standard:指的是视频的颜色格式, /**  * An optional key describing the color primaries, white point and  * luminance factors for video content.  *  * The associated value is an integer: 0 if unspecified, or one of the  * COLOR_STANDARD_ values.  */ public static final String KEY_COLOR_STANDARD = "color-standard";  /** BT.709 color chromacity coordinates with KR = 0.2126, KB = 0.0722. */ public static final int COLOR_STANDARD_BT709 = 1;  /** BT.601 625 color chromacity coordinates with KR = 0.299, KB = 0.114. */ public static final int COLOR_STANDARD_BT601_PAL = 2;  /** BT.601 525 color chromacity coordinates with KR = 0.299, KB = 0.114. */ public static final int COLOR_STANDARD_BT601_NTSC = 4;  /** BT.2020 color chromacity coordinates with KR = 0.2627, KB = 0.0593. */ public static final int COLOR_STANDARD_BT2020 = 6;
  还记得# 音视频开发基础知识之YUV颜色编码 里面说过,RGB到YUV有不同的转化标准: 目前一般解码后的视频格式为yuv,但是一般显卡渲染的格式是RGB,所以需要把yuv转化为RGB。
  这里涉及到  Color Range 这个概念。Color Range 分为两种,一种是 Full Range,一种是 Limited Range 。 Full Range 的 R、G、B 取值范围都是 0 255。而 Limited Range 的 R、G、B 取值范围是 16 235。
  而 对于每种Color Range来说,还有不同的转换标准,常见的标准主要是 BT601 和 BT709 (BT601 是标清的标准,而 BT709 是高清的标准)。
  这里该视频的color-standard为4,即转换标准为BT.601 525。
  4.color-range: 上面引用部分已经提及,当前color-range为2,看下谷歌文档的常量值说明: /** Limited range. Y component values range from 16 to 235 for 8-bit content.  *  Cr, Cy values range from 16 to 240 for 8-bit content.  *  This is the default for video content. */ public static final int COLOR_RANGE_LIMITED = 2;  /** Full range. Y, Cr and Cb component values range from 0 to 255 for 8-bit content. */ public static final int COLOR_RANGE_FULL = 1;
  所以当前视频的color-range为Limited range。
  其他参数因为数量太多,大家也大部分可以看明白,就不一一解释了。
  看接下来的log:
  第一行是这里打印的: //拿到可用的ByteBuffer的index int inputBufIndex = decoder.dequeueInputBuffer(TIMEOUT_USEC); //根据index得到对应的输入ByteBuffer ByteBuffer inputBuf = decoderInputBuffers[inputBufIndex]; Log.d(TAG, "decoderInputBuffers inputBuf:" + inputBuf + ",inputBufIndex:" + inputBufIndex);
  打印的是inputBuffer的情况,上一篇已经讲过,这里就如同生猪肉采购员询问厨师有没有空篮子,厨师在TIMEOUT_USEC微秒时间内告诉了采购员篮子的编号,然后采购员根据编号找到对应的空篮子。
  根据log可以看出:
  decoderInputBuffers inputBuf:java.nio.DirectByteBuffer[pos=0 lim=6291456 cap=6291456],inputBufIndex:2
  这个空Buffer大小为6291456字节(pos表示当前操作指针指向的位置,lim表示当前可读或者可写的最大数量,cap表示其容量),inputBufIndex为2,即该Buffer在MediaCodec的输入Buffer数组的位置是2。
  submitted frame 0 to dec, size=339
  这个log的frame 0表示MediaExtractor的readSampleData读取出来的第几块数据,在这里就是第几帧,size=339表示该帧大小为339字节,当然这是压缩的数据大小。
  下面一条log输出端取数据的,即顾客询问厨师猪肉炒好了没有:
  D/fuyao-Grafika: dequeueOutputBuffer decoderBufferIndex:-1,mBufferInfo:android.media.MediaCodec$BufferInfo@fcbc6e2
  D/fuyao-Grafika: no output from decoder available
  这条log来源: int outputBufferIndex = decoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC); Log.d(TAG, "dequeueOutputBuffer decoderBufferIndex:" + outputBufferIndex + ",mBufferInfo:" + mBufferInfo);
  decoderBufferIndex为-1,则等于MediaCodec.INFO_TRY_AGAIN_LATER,即当前输出端还没有数据,即厨师告诉顾客,猪肉还没做好。
  如果看过之前我写的解析H264视频编码原理——从孙艺珍的电影说起(一)和 解析H264视频编码原理——从孙艺珍的电影说起(二),就知道视频编码是一个非常复杂的过程,涉及大量的数学算法,所以解码也不会简单,基本不会刚放一帧数据到input端,output端就立马拿到解码后的数据。
  从后面的log可以看到,经过很多次在input端放入数据,又尝试在output端取出数据的循环之后,终于在第一次在input端放入数据的77ms秒之后,在output端拿到了数据:
  startup lag是官方demo已经有的统计从第一次在input端放入数据到第一次从output端拿到数据的时间长。
  接下来就是取到具体数据的log:
  decoderBufferIndex为0,即取到的解码数据所在的buffer在output端buffer数组第0个。
  ecoderOutputBuffers.length:8是我专门把output数组数量打印出来: ByteBuffer[] decoderOutputBuffers = decoder.getOutputBuffers(); Log.d(TAG, "ecoderOutputBuffers.length:" + decoderOutputBuffers.length);
  可见output端buffer数组大小为8个(经过实践发现,该数值并不是固定的)。
  outputBuffer:java.nio.DirectByteBuffer[pos=0 lim=115200 cap=115200]表示该buffer的可用数据和容量都为115200。后面解码出来的数据也是这个大小,因为解码之后的数据就是一帧画面的yuv数据,因为画面的分辨率固定,yuv格式也是固定,所以大小自然也是一样的。
  而在output拿到数据之前的上一次取数据的log需要注意下:
  D/fuyao-Grafika:dequeueOutputBuffer decoderBufferIndex:-2,mBufferInfo:android.media.MediaCodec$BufferInfo@9bec00c
  D/fuyao-Grafika: decoder output format changed: {crop-right=319, color-format=21, slice-height=240, image-data=java.nio.HeapByteBuffer[pos=0 lim=104 cap=104], mime=video/raw, stride=320, color-standard=4, color-transfer=3, crop-bottom=239, crop-left=0, width=320, color-range=2, crop-top=0, height=240}
  decoderBufferIndex为2,即MediaCodec.INFO_OUTPUT_FORMAT_CHANGED。在拿到数据之后,会现有一个通知输出数据格式变化的通知,我们可以在这里拿到输出数据的格式。
  1.crop-left=0,crop-right=319,crop-top=0,crop-bottom=239表示的是真正的视频区域的4个顶点在整个视频帧的坐标位置。
  有读者可能会问,视频不是充满一帧么?其实不是的,看下官网的解读 developer.android.google.cn/reference/a… : The  MediaFormat#KEY_WIDTH   and  MediaFormat#KEY_HEIGHT   keys specify the size of the video frames;  however, for most encondings the video (picture) only occupies a portion of the video frame . This is represented by the "crop rectangle".
  You need to use the following keys to get the crop rectangle of raw output images from the output format. If these keys are not present, the video occupies the entire video frame.The crop rectangle is understood in the context of the output frame  before  applying any rotation.
  具体key的意义:
  Format Key
  Type
  Description
  MediaFormat#KEY_CROP_LEFT
  Integer
  The left-coordinate (x) of the crop rectangle
  MediaFormat#KEY_CROP_TOP
  Integer
  The top-coordinate (y) of the crop rectangle
  MediaFormat#KEY_CROP_RIGHT
  Integer
  The right-coordinate (x)  MINUS 1  of the crop rectangle
  MediaFormat#KEY_CROP_BOTTOM
  Integer
  The bottom-coordinate (y)   MINUS 1   of the crop rectangle
  官网又给了一段通过这4个值计算视频有效区域的代码:  MediaFormat format = decoder.getOutputFormat(…);  int width = format.getInteger(MediaFormat.KEY_WIDTH);  if (format.containsKey(MediaFormat.KEY_CROP_LEFT)         && format.containsKey(MediaFormat.KEY_CROP_RIGHT)) {     width = format.getInteger(MediaFormat.KEY_CROP_RIGHT) + 1                 - format.getInteger(MediaFormat.KEY_CROP_LEFT);  }  int height = format.getInteger(MediaFormat.KEY_HEIGHT);  if (format.containsKey(MediaFormat.KEY_CROP_TOP)         && format.containsKey(MediaFormat.KEY_CROP_BOTTOM)) {     height = format.getInteger(MediaFormat.KEY_CROP_BOTTOM) + 1                  - format.getInteger(MediaFormat.KEY_CROP_TOP);  }
  2.color-format:颜色编码格式 。21即为COLOR_FormatYUV420SemiPlanar,也常叫做叫作NV21。关于yuv具体格式在音视频开发基础知识之YUV颜色编码 已有叙述,不过文章并没有具体讲NV21,NV21的于半平面格式(semi planner),y独立放一个数组,uv放一个数组,先V后U交错存放(图来自: 浅析 YUV 颜色空间)
  比如一个4*4的画面,分布如下图所示: Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y V U V U V U V U
  3.slice-height:指的是帧的高度,即有多少行 ,不过这个行数可能是内存对齐过的,有时候为了提高读取速度,视频帧高度会填充到2的次幂数值。
  4. stride:跨距,是图像存储的时候有的一个概念。它指的是图像存储时内存中每行像素所占用的空间。  同样的,这个也是经过内存对齐的,所以是大于等于原视频的每行像素个数。很多视频花屏问题的根源就是忽略了stride这个属性。
  其他参数上面已讲过,就不赘述。
  拿到输出的解码数据就通过releaseOutputBuffer渲染到Surface: //将输出buffer数组的第outputBufferIndex个buffer绘制到surface。doRender为true绘制到配置的surface decoder.releaseOutputBuffer(outputBufferIndex, doRender);
  我们看到log的output最后一帧数据是:
  output EOS
  当调用: int outputBufferIndex = decoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
  得到的mBufferInfo.flags为MediaCodec.BUFFER_FLAG_END_OF_STREAM(intput端在视频最后一帧的时候传入)的时候,说明该帧已经是视频最后一帧了,此时就跳出解码的大循环,准备释放资源:  finally {     // release everything we grabbed     if (decoder != null) {         //Call stop() to return the codec to the Uninitialized state, whereupon it may be configured again.         decoder.stop();         decoder.release();         decoder = null;     }     if (extractor != null) {         extractor.release();         extractor = null;     } }
  还记得Android硬编解码利器MediaCodec解析——从猪肉餐馆的故事讲起(一) 提及过得MediaCodec的状态机么:
  先调用了stop方法,就进入了Uninitialized状态,即猪肉餐馆要收拾桌椅了,收拾完桌椅之后,再调用release就释放资源,即猪肉餐馆关门了。 将解码输出数据保存下来
  接下来来做一件有趣的事情,就是将每次输出的解码数据保存为图片。
  创建一个方法接收输出的一帧数据,然后通过系统提供的YuvImage可以将yuv数据转化为jpeg数据,然后通过BitmapFactory.decodeByteArray将jpeg数据转化为Bitmap,再保存到本地文件夹中。 private void outputFrameAsPic(byte[] ba, int i) {     Log.d(TAG, "outputBuffer i:" + i);     YuvImage yuvImage = new YuvImage(ba, ImageFormat.NV21, mVideoWidth, mVideoHeight, null);     ByteArrayOutputStream baos = new ByteArrayOutputStream();     //将yuv转化为jpeg     yuvImage.compressToJpeg(new Rect(0, 0, mVideoWidth, mVideoHeight), 100, baos);     byte[] jdata = baos.toByteArray();//rgb     Bitmap bmp = BitmapFactory.decodeByteArray(jdata, 0, jdata.length);     if (bmp != null) {         try {             File parent = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/moviePlayer/");             if (!parent.exists()){                 parent.mkdirs();             }              File myCaptureFile = new File(parent.getAbsolutePath(),String.format("img%s.png", i));             if (!myCaptureFile.exists()){                 myCaptureFile.createNewFile();             }             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(myCaptureFile));             bmp.compress(Bitmap.CompressFormat.JPEG, 80, bos);             Log.d(TAG, "bmp.compress myCaptureFile:" + myCaptureFile.getAbsolutePath());             bos.flush();             bos.close();         } catch (Exception e) {             e.printStackTrace();             Log.d(TAG, "outputFrameAsPic Exception:" + e);         }     } }
  然后在每次获得output端Buffer的地方调用该方法: ByteBuffer outputBuffer = decoderOutputBuffers[outputBufferIndex]; Log.d(TAG, "outputBuffer:" + outputBuffer);  outputBuffer.position(mBufferInfo.offset); outputBuffer.limit(mBufferInfo.offset + mBufferInfo.size);  byte[] ba = new byte[outputBuffer.remaining()]; //byteBuffer数据放入ba outputBuffer.get(ba); //输出的一帧保存为本地的一张图片 outputFrameAsPic(ba, decodeFrameIndex);
  再运行下程序,得到以下图片:
  可见每一帧都成功截图并保存到本地~~ 同步与异步模式
  最后说下,MediaCodec编解码是分为同步和异步模式的(Android 5.0开始支持异步状态),同步就是比如生猪肉采购员和顾客必须 在Android硬编解码工具MediaCodec解析——从猪肉餐馆的故事讲起(二)的关于MediaCodec的解码流程代码,是属于同步,所谓的同步,是相对于异步而言的。同步和异步最大的不同, 个人认为就是前者是要求我们主动去咨询MeidaCodec有没有可用的Buffer可以用,后者是MeidaCodec来通知我们已经有有了可用的buffer 。就像原来是猪肉采购员主动询问厨师有没有空篮子可以用,现在变为厨师发个微信告诉采购员现在有空篮子可以用。
  对于异步来说,MediaCodec的工作状态和同步有一点不同:
  异步的情况下从Configured会直接进入Running状态,然后等待MediaCodec的回调通知再处理数据即可,以下为官方给的代码模板: MediaCodec codec = MediaCodec.createByCodecName(name);  MediaFormat mOutputFormat; // member variable  codec.setCallback(new MediaCodec.Callback() {   @Override   void onInputBufferAvailable(MediaCodec mc, int inputBufferId) {     ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);     // fill inputBuffer with valid data     …     codec.queueInputBuffer(inputBufferId, …);   }     @Override   void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, …) {     ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);     MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A     // bufferFormat is equivalent to mOutputFormat     // outputBuffer is ready to be processed or rendered.     …     codec.releaseOutputBuffer(outputBufferId, …);   }     @Override   void onOutputFormatChanged(MediaCodec mc, MediaFormat format) {     // Subsequent data will conform to new format.     // Can ignore if using getOutputFormat(outputBufferId)     mOutputFormat = format; // option B   }     @Override   void onError(…) {     …   }  });  codec.configure(format, …);  mOutputFormat = codec.getOutputFormat(); // option B  codec.start();  // wait for processing to complete  codec.stop();  codec.release();总结
  本文在上一文章分析代码的基础上运行了代码,通过分析log分析解码流程的细节,让各位对解码流程有更清晰的认识。并将解码出来的每帧截图保存到本地,验证了视频解码的output端每次获取的数据确实是表示一帧的数据。
  最后讲了一下MediaCodec编解码异步模式相关。
  美好的时光总是过得很快,不知不觉已经用了三篇博文讲MediaCodec了, 我已经迫不及待地想进入下一个系列了——OpenGL系列。
  因为解码成功后,就是渲染到屏幕了,而当前Android平台最主流的渲染工具,就是OpenGL了。
  作者:半岛铁盒里的猫 链接:https://juejin.cn/post/7113767096512675870 来源:稀土掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  在开发的路上你不是一个人,欢迎加入 C++音视频开发交流群大家庭正在跳转讨论交流
  #程序员# #C++# #音视频开发#

冰雪产业制冰产业链分析一冬奥会促进我国冰雪产业发展,制冰系统产业有望受益1冬奥会促进冰雪产业发展北京冬奥会将于2022年2月4日举行,2022年冬季奥运会的申办成功,为中国冰雪行业带来重大机遇。2021新赛季更新确认,两款法师神装上线,段位继承不改,王者玩家笑了爱生活,爱游戏,大家好,我是阿呆。期待大家的关注,我会在这里分享更多有趣的最新资讯。前言相信大家应该都知道,在王者荣耀新赛季到来之前,官方会提前在王者荣耀抢先服上更新,而最近官方已格斗游戏搓波花样最多的角色,最可恶的是从开局一直搓到结束当年你见过的最恶心的飞行道具是什么呢?豪血寺一族3马克斯的飞鱼攻击应该可以排得上号吧!释放一堆类似蝌蚪带有牙齿的爬行动物,不断撕咬对手。这一幕要是出现在电影中的话,估计就是一个限制原神中出现一个毅力帝,玩家怒攒6。7万原石,只为2。4版本等他复刻哈罗大家好,我是盟盟,本期和大家聊聊原神的话题。众所周知,原神2。4版本即将来袭,2。4版本和2。3版本有点不一样,2。4版本直接上线就是双UP,不仅有新角色申鹤,还会有甘雨和魈等天龙怀旧八卦做生活玩家还是打架玩家最好?尝试转变后真香每个游戏中的玩家应该都可以被划分为打架派和生活派,打架派热爱和人pk对决,简单来说就是喜欢干架,而生活玩家一般来说不喜欢打架,刷刷副本搬砖就完事,那么这两种玩家谁更香呢?曾经在经典阴阳师SP金鱼姬技能调整过于离谱加强幅度过于BUG已经超神了阴阳师这次体验服对式神技能和强度方面的调整,如果你把注意力都集中在了荒总身上,那真的是太年轻了,这次SP金鱼姬的加强可以说非常的突然和意想不到,虽然说这式神确实是这些日子比较遇冷,原神新角色,遭遇外服疯狂吐槽原神的2。4版本预热活动以及全球直播活动开启,新版本的两个角色再次成为游戏圈的热门话题。在有关新角色申鹤的服装风波以后,另一以京剧元素为主的新角色云堇也登上了热搜。在YouTube来看看原神里我最喜欢的角色排行榜(2)上次说完了五星角色今天就来说说我在原神里最喜欢的四星角色吧!一烟绯喜欢烟绯,就是喜欢,真爱!我做翠石砌玉壶的任务时第一次见到烟绯,看她第一眼,我就懵了啊这,这也太漂亮了吧!如此美丽不出意外,以色列将出卖中方!以媒同意向美国通报对华贸易情况自特朗普发动贸易战以来,美国就开始在全球范围内逼迫他国在中美之间二选一。而拜登则继承了特朗普的这一政策,继续逼迫各国在中美之间站队。作为美国最忠实的盟友,以色列曾试图在中美之间的博原神老玩家退游一个月,官方会送一份大礼?500原石四星武器哈罗大家好,我是盟盟,本期和大家聊聊原神的话题。众所周知,每款游戏都有独特的退游机制,比如王者荣耀,如果你一段时间没有上线,官方就会给你送出回归礼物,有可能是皮肤有可能是英雄,再比LOL无限乱斗即将回归!国服预计21号上线,全随机英雄模式前言众所周知,无限火力乱斗作为一直被LOL玩家誉为最有趣游戏模式,每次开启都受到了许多玩家的热情反响。而在2022年春节即将到来之际,有关无限火力乱斗即将回归的消息又来了,一起来了
浪琴这几个新款,还没上市就火了在腕表天地的表友群里,每天都有海量信息。虽然有时也聊点八卦,但大多数时间还是在聊表。前不久,有位表友在群里发了浪琴(Longines)名匠系列190周年纪念腕表的图片,马上得到了很不塞耳朵的蓝牙耳机,骨传导TypeC充电,降至仅49元常见的耳机分为入耳式耳机和半入耳式耳机,前者很塞耳朵,所以有不少用户接受不了,半入耳式耳机佩戴起来会舒适不少,但还不是最舒适的状态。市面上还有一种相对非常少见的完全不塞耳朵的耳机,积家大师GrandeTradition三问万年历银色表盘上手评测说到三问报时,没有人比瑞士人更擅长。而对于瑞士人来说,很少有制造商能像积家一样在制作三问报时方面知识渊博能力强。我们仔细看看积家大师级大传统重复分钟Perptuelle。Jaege从十二篇古典诗词中发掘出的自信满满的男女宝宝名字在学校和生活中,阳光自信的孩子总是能够吸引到别人的目光,让别人很轻易便喜爱上他们,我们都相信这世界上每一位父母,都希望自己的孩子能够充满阳光积极乐观自信,与人相处时敢于发表自己的观案例1岁男童吃饭噎死,家属向幼儿园索要巨额赔偿,玉溪法院判了入学难还体现在幼儿园入学难这一点上,许多外地人口涌入而当地正规幼儿园的容纳量有限,导致很多外来人员的孩子无处可去,也由此滋生了很多的黑幼儿园,这些幼儿园虽然满足了不少外来人员托管孩幼儿园老师指出孩子在校乖,回家难带的4个原因,不都是坏事今年刚入园的宝宝已经开学有一阵子了,你家宝宝还好吗?顺便问一句,你还好吗?最近一些妈妈发现一个奇怪现象,有些宝宝在学校很听话很乖,一回到家就放飞自我,很难带。同样的一个孩子,为什么数字美金要来了?数字美金与人民币的碰撞,会擦出什么样的火花呢拜登总统在他最近的加密货币监管指南中表达了对美元数字美元的兴趣。美国中央银行数字货币(CBDC)的发展没有官方确认。然而,白宫的负责任地开发数字资产的综合框架概述了美国CBDC的潜求助同事的孩子很明显是唐氏儿,我该不该提醒她这个问题?唐氏儿唐氏综合征,先天愚型儿,是由于人类第21条染色体多了一条,才造成了染色体病,在怀孕期间可以通过检查,提前了解是否为唐氏儿,据说,产妇年轻越大,胎儿患病几率越高!求助我该不该提孩子长个儿盲目补,当心吃出性早熟大河健康报记者吴文可现在,孩子的身高越来越被家长们重视,为了孩子能长高个儿,家长们也都是操碎了心使尽了浑身解数。有的家长天天给孩子喝牛奶骨头汤,以为这样补钙就能长高有的家长盲目购买秋天冬瓜这样做,孩子超爱吃,滑嫩鲜香,开胃下饭,补营养润秋燥秋天气候干燥,适合多吃一些补水润燥,清淡营养的食材,像冬瓜就是很不错的选择,这个季节的冬瓜品质新鲜,价格便宜,简单烹饪就十分可口,所以最近去买菜,我总少不了要买上一大块冬瓜,清炒红成功的人正诱因大于负诱因01洛克定律感受成就感更能促使人进步,挫败感只能打消积极性。达到目标最好的结果是执行,也就是你为目标努力地去做了。行动和目标之间有几个维度需要平衡。人没有目标的表现缺失目标,人便没有了方向。会像无希望在不远处等你人有冲天之志,非运不能自通。有船无风,难以启航。生活本来就全靠运气。时来天地皆同力,每个人都有属于自己的好运时期,希望就在不远处等着我。老甄絮语所谓天时地利人和,说的是人生占尽了所20条短句子摘抄1如果你真的想实现梦想,最快捷的方式便是竭尽所能地过好今天。2不曾拥有某样东西,那所谓的缺失就无从谈起。你太淡了。原谅我,你只是在我的生命里太淡了尘曲七堇年3人的低头有两种可能,一九九重阳节图片配图唯美高清带字,重阳节祝福语朋友圈文案短句子人共菊花醉重阳,年年岁岁皆平安,做好年轻的大人,陪伴年长的孩子。一朵花里见天地,三餐烟火父母情。重阳节,愿父母怡乐,福寿绵长。九九相逢是重阳,秋高气爽菊花香。九九相随是重阳,天长地红极一时的维密时装秀,缘何轰然倒塌维密秀时尚表演无论是当年的超级火爆,还是如今跌落神坛后,依旧余热未消。它都是娱乐大众茶余饭后的谈资,在网络和自媒体蔚然成风的当下,即使节目停办了,过往的辉煌也不可磨灭,不会被遗忘。心灵的远方人只有经历自己的渺小,才能到达高尚。卡夫卡箴言你的意志是自由的。这就是说当它想要穿越沙漠时,它是自由的,因为它可以选择穿越的道路,所以它是自由的,由于它可以选择走路的方式,所以它是助力长三角区域一体化海太长江隧道开工按照规划,海太长江隧道连接苏州太仓市常熟市和南通市海门区,计划工期为6年,预计2028年建成。图为海太长江隧道效果图。作为中国经济发展最活跃开放程度最高创新能力最强的区域之一,长三广州增城露营的世外桃源这次去广州增城,在增城市附近有一大片桃树,很多橘子都是黑色的,却没有人去采摘。他很想知道,他曾经在广东的一个老友那里听说过,在广东有很多的熟果,都是用来酿酒的,对健康有好处,市面上世外桃源般的老姆登村很多人去过怒江州的记忆之城知子罗,却不知道在距知子罗只有5公里的地方藏着一个仿如世外桃源般的美丽村庄老姆登。老姆登是怒族语的音译,意思是人喜欢来的地方。位于怒江州福贡县匹河乡的老姆原神3。0主线地图分析做完黄金梦乡了,探索了一部分沙漠。赤王陵真的太大了,没有独立小地图已经非常影响游戏体验了。稍微往周围探索一会儿,就找不到自己位置了。建议大家一起在问卷里填反馈,要求增加独立小地图或拉不动弓抱不动女主肾功能退化,内娱男星体虚的秘密藏不住了有没有发现一个很奇怪的现象,娱乐圈的女演员一个比一个内卷,然而大多数男演员根本不为所动,反而在普信男的道路上越走越远。甚至在很多公开场合,男演员因为自己体虚而抱不动女演员就不断嘲讽高秀敏因病离世17年后,男方回到原配身边,其中的原因令人动容高秀敏被称为赵丽蓉之后最成功的小品演员。凭借着和赵本山合作的卖拐卖轮椅等春晚小品红遍大江南北,成为了家喻户晓的小品明星。2005年8月18日,高秀敏因突发心脏病不幸离世。葬礼上,何