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

Android音视频硬解码播放H264

  最近在学习ing,加油 硬件和软件编解码器
  在介绍之前,我们需要知道什么是硬编解码器和软编解码器?
  1.软编解码器 :使用软件本身或使用CPU的方式对原始视频进行编解码。
  优点:兼容性好。.
  缺点:CPU占用率高,app内存占用较高,可能是因为CPU发热导致降频、卡顿、无法流畅录制、播放视频等。
  2.硬编解码器 :使用非CPU编码,如显卡GPU、专用DSP芯片、厂商芯片等。一般编解码算法是固定的,所以采用芯片处理。
  优点:非常快速高效,CPU占用率低,即使长时间录制高清视频,手机也不会发热。
  缺点:但是兼容性不好,经常出现画面不够精细的问题(但是看不出来)。 MediaCodec 硬编解码器
  一般安卓直播采集终端/短视频编辑软件默认使用硬编解码,如果手机不支持软编解码。硬编解码器为王。
  在 Android MediaCodec  类中使用的是编码和解码。MediaCodec  它是什么??MediaCodec  是 Android 音视频编解码类,它通过访问底层codec  来实现编解码的功能,比如需要把摄像头的视频 yuv 数据编码为h264/h265  ,pcm  编码为aac  ,h264/h265  解码等待yuv  ,aac  解码pcm  等待。MediaCodec  是 Android 4.1 API16 引入了,在 Android 5.0 API21 中加入了异步模式。
  MediaCodec Call是系统注册的编解码器,硬件厂商在系统中注册自己的硬编解码器,称为硬编解码器,如果硬件厂商注册软件编解码器,就是软件编解码器。通常不同的硬件制造商是不同的。然后 MediaCodec 负责调用。 获取手机支持的编解码器
  不同的手机支持的编解码器不同,如何获取手机支持的编解码器?如下:     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)     private fun getSupportCodec() {         val list = MediaCodecList(MediaCodecList.REGULAR_CODECS)         val codecs = list.codecInfos         Log.d(TAG, "Decoders:")         for (codec in codecs) {             if (!codec.isEncoder) Log.d(TAG, codec.name)         }         Log.d(TAG, "Encoders:")         for (codec in codecs) {             if (codec.isEncoder) Log.d(TAG, codec.name)         }     }
  输出 2020-12-25 19:16:00.914 13115-13115/com.bj.gxz.h264decoderdemo D/H264: Decoders: 2020-12-25 19:16:00.914 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.aac.decoder 2020-12-25 19:16:00.914 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.amrnb.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.amrwb.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.flac.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.g711.alaw.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.g711.mlaw.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.gsm.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.mp3.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.opus.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.raw.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.vorbis.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.hisi.video.decoder.avc 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.h264.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.h263.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.hisi.video.decoder.hevc 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.hevc.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.hisi.video.decoder.mpeg2 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.hisi.video.decoder.mpeg4 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.mpeg4.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.hisi.video.decoder.vp8 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.vp8.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.vp9.decoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: Encoders: 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.aac.encoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.amrnb.encoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.amrwb.encoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.flac.encoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.hisi.video.encoder.avc 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.h264.encoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.h263.encoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.hisi.video.encoder.hevc 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.mpeg4.encoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.vp8.encoder 2020-12-25 19:16:00.915 13115-13115/com.bj.gxz.h264decoderdemo D/H264: OMX.google.vp9.encoder
  看一下命名,软解码器通常都是 OMX.google  以开头的,就像上面那个一样OMX.google.h264.decoder  。硬解码器是基于OMX.[hardware_vendor]  一开始的,像上面那个应该是海思芯片OMX.hisi.video.decoder.avc   。hisi  当然也有一些不遵守这个规则的,系统会认为它是软解码器。编码器的名称是相同的。来自Android系统的源码可以判断规则,
  源码地址:http ://androidos.net.cn/android/6.0.1_r16/xref/frameworks/av/media/libstagefright/OMXCodec.cpp static bool IsSoftwareCodec(const char *componentName) {     if (!strncmp("OMX.google.", componentName, 11)) {         return true;     }      if (!strncmp("OMX.", componentName, 4)) {         return false;     }      return true; } MediaCodec 处理数据的类型
  MediaCodec 非常强大,支持的编解码数据类型有:压缩音频数据、压缩视频数据、原始音频数据和原始视频数据,并且支持不同封装格式的编解码,如前所述,如果是硬解码,当然,也需要手机厂商的支持。您可以通过设置 Surface 来获取/呈现原始视频数据。MediaCodec 关于 API 每个方法和参数都有自己的含义。你可以慢慢深入地使用它。 MediaCodec 的编解码过程
  下图是Android官方文档提供的,官方文档很详细。
  https://developer.android.google.cn/reference/android/media/MediaCodec?hl=en
  MediaCodec 处理输入数据产生输出数据,异步处理数据时,使用一组输入输出ByteBuffer。该过程通常是 将数据填充到预设的输入缓冲区(ByteBuffer)中, 输入缓冲区填满数据后,传递给 MediaCodec 的编码和解码处理。经过编码和解码后,它会在 . 然后用户可以得到编码和解码后的数据,然后将ByteBuffer释放回MediaCodec,往复循环。
  需要注意的是, Buffer 并不是我们自己对 MediaCodec 的新对象,它是 MediaCodec 为了更好地控制 Buffer 来处理,我们需要使用 MediaCodec 提供的方法来获取,然后将数据插入其中并获取数据。 媒体编解码器 APIMediaCodec 的创建createDecoderByType/createEncoderByType:根据具体的MIME类型(如"video/avc")建立codec。Decoder就是decoder,Encoder就是encoder。createByCodecName: 知道组件的确切名称(如 OMX.google.h264.decoder)时,从组件名称编解码器创建。使用 MediaCodecList 可以获取组件的名称,如上所述。 configure:配置解码器或编码器。比如可以配置解码后的数据通过surface来显示,本文下面部分是解码h264的demo配置surface来把yuv的数据渲染到surface上。 start:开始编解码,等待数据。 数据处理,开始编解码dequeueInputBuffer:返回一个有效的输入缓冲区的索引queueInputBuffer: 输入流入队列。通常是用数据填充它dequeueOutputBuffer:从输出队列中取出编码/解码数据,如果输入的数据较多,可能需要循环读取,一般在写代码的时候需要调用循环releaseOutputBuffer: 释放ByteBuffer数据返回给MediaCodecgetInputBuffers: 获取需要对数据进行编码和解码的输入流队列,返回一个 ByteBuffer ArraygetOutputBuffers: 获取编解码后的数据输出流队列,返回一个ByteBuffer数组 flush:清空输入输出队列缓冲区 stop:停止编解码 release: 发布编解码器
  从上面的api我可以看到电影MediaCodec编解码器API的生命周期,可以再看官网。 MediaCodec 的同步和异步编解码器同步方式
  官方样本 MediaCodec codec = MediaCodec.createByCodecName(name);  codec.configure(format, …);  MediaFormat outputFormat = codec.getOutputFormat(); // option B  codec.start();  for (;;) {   int inputBufferId = codec.dequeueInputBuffer(timeoutUs);   if (inputBufferId >= 0) {     ByteBuffer inputBuffer = codec.getInputBuffer(…);     // fill inputBuffer with valid data     …     codec.queueInputBuffer(inputBufferId, …);   }   int outputBufferId = codec.dequeueOutputBuffer(…);   if (outputBufferId >= 0) {     ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);     MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A     // bufferFormat is identical to outputFormat     // outputBuffer is ready to be processed or rendered.     …     codec.releaseOutputBuffer(outputBufferId, …);   } else if (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {     // Subsequent data will conform to new format.     // Can ignore if using getOutputFormat(outputBufferId)     outputFormat = codec.getOutputFormat(); // option B   }  }  codec.stop();  codec.release();
  流程如下: -  Create and configure MediaCodec object  -  Loop until it"s done :   -  If input buffer Be on it      -  Read a piece of input , Fill it in with input buffer Encoding and decoding are performed in the system    -  If the output buffer Be on it :     -  From output buffer Get the data after encoding and decoding for processing . -  After processing , The destruction  MediaCodec  object . 异步方式
  在Android 5.0,API21,引入异步模式。官方样品: 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(); -  Create and configure MediaCodec object . -  to MediaCodec Object settings callback MediaCodec.Callback -  stay onInputBufferAvailable Calling back :     -  Read a piece of input , Fill it in with input buffer Encoding and decoding are performed in the system  -  stay onOutputBufferAvailable Calling back :     -  From output buffer After encoding and decoding, the data is processed . -  After processing , The destruction  MediaCodec  object . 解码h264视频
  让我们解码视频中的一个h264(摘自tiktok的一段话。/葵h264文件).h265是一回事,只要了解h264.h265的编码方式和原理以及码流结构,都是小菜一碟。为了更好地理解 h264 的比特流数据,我们演示了一次只读取内存中的文件 byte 数据。
  我们从两个方面来处理,都可以正常播放,只是我们对h264 Stream数据有了更深入的了解。 就是我们做的h264比特流结构,一次一个的NAL单元(NALU)偷偷给MediaCodec,包括第一个SPS,PPS。 是的,我们只是截取几个 k,然后用 MediaCodec 填充它
  首先初始化MediaCodec     var bytes: ByteArray? = null     var mediaCodec: MediaCodec     init {         // demo test , To facilitate one-time access to memory          bytes = FileUtil.getBytes(path)         // video/avc Namely H264, Create decoder          mediaCodec = MediaCodec.createDecoderByType("video/avc")         val mediaFormat = MediaFormat.createVideoFormat("video/avc", width, height)         mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15)         mediaCodec.configure(mediaFormat, surface, null, 0)     }
  方式一:划分NAL单元(NALU)方式     private fun decodeSplitNalu() {         if (bytes == null) {             return         }         //  Data start subscribing          var startFrameIndex = 0         val totalSizeIndex = bytes!!.size - 1         Log.i(TAG, "totalSize=$totalSizeIndex")         val inputBuffers = mediaCodec.inputBuffers         val info = MediaCodec.BufferInfo()         while (true) {             // 1ms=1000us  subtle              val inIndex = mediaCodec.dequeueInputBuffer(10_000)             if (inIndex >= 0) {                 //  Split a frame of data                  if (totalSizeIndex == 0 || startFrameIndex >= totalSizeIndex) {                     Log.e(TAG, "startIndex >= totalSize-1 ,break")                     break                 }                 val nextFrameStartIndex: Int =                     findNextFrame(bytes!!, startFrameIndex + 1, totalSizeIndex)                 if (nextFrameStartIndex == -1) {                     Log.e(TAG, "nextFrameStartIndex==-1 break")                     break                 }                 //  Fill in the data                  val byteBuffer = inputBuffers[inIndex]                 byteBuffer.clear()                 byteBuffer.put(bytes!!, startFrameIndex, nextFrameStartIndex - startFrameIndex)                  mediaCodec.queueInputBuffer(inIndex, 0, nextFrameStartIndex - startFrameIndex, 0, 0)                  startFrameIndex = nextFrameStartIndex              }             var outIndex = mediaCodec.dequeueOutputBuffer(info, 10_000)                          while (outIndex >= 0) {                 //  Here"s a simple temporal way to keep the video alive fps, Otherwise the video will play very fast                  // demo  Of H264 File is 30fps                 try {                     sleep(33)                 } catch (e: InterruptedException) {                     e.printStackTrace()                 }                 //  Parameters 2  Render to surface On ,surface Namely mediaCodec.configure Parameters of 2                 mediaCodec.releaseOutputBuffer(outIndex, true)                 outIndex = mediaCodec.dequeueOutputBuffer(info, 0)             }         }     }
  NALU分割方法     private fun findNextFrame(bytes: ByteArray, startIndex: Int, totalSizeIndex: Int): Int {         for (i in startIndex..totalSizeIndex) {             // 00 00 00 01 H264 Start code for              if (bytes[i].toInt() == 0x00 && bytes[i + 1].toInt() == 0x00 && bytes[i + 2].toInt() == 0x00 && bytes[i + 3].toInt() == 0x01) { //                Log.e(TAG, "bytes[i+4]=0X${Integer.toHexString(bytes[i + 4].toInt())}") //                Log.e(TAG, "bytes[i+4]=${(bytes[i + 4].toInt().and(0X1F))}")                 return i                 // 00 00 01 H264 Start code for              } else if (bytes[i].toInt() == 0x00 && bytes[i + 1].toInt() == 0x00 && bytes[i + 2].toInt() == 0x01) { //                Log.e(TAG, "bytes[i+3]=0X${Integer.toHexString(bytes[i + 3].toInt())}") //                Log.e(TAG, "bytes[i+3]=${(bytes[i + 3].toInt().and(0X1F))}")                 return i             }         }         return -1     }
  方式一:固定字节数据填充     private fun findNextFrameFix(bytes: ByteArray, startIndex: Int, totalSizeIndex: Int): Int {         //  Every time, it"s better to make the data bigger , Otherwise, it"s like a weak network , Slow data flow leads to video card          val len = startIndex + 40000         return if (len > totalSizeIndex) totalSizeIndex else len     }
  说明:在实际项目中,通常是web/数据流塞进去的方式,只是给大家demo演示MediaCodec解码h264文件播放。 保存 decode h264 视频 yuv 数据为图片
  我们保存在哪里呢,前面说了,解码后一定是h264保存,解码后的数据就是yuv数据。也就是说 dequeueOutputBuffer  然后取出解码后的数据,然后使用YuvImage  Class compressToJpeg  Save as Jpeg Just图片。我们 3s 保持一个。
  本地代码:                // 3s  Save a picture                  if (System.currentTimeMillis() - saveImage > 3000) {                     saveImage = System.currentTimeMillis()                      val byteBuffer: ByteBuffer = mediaCodec.outputBuffers[outIndex]                     byteBuffer.position(info.offset)                     byteBuffer.limit(info.offset + info.size)                     val ba = ByteArray(byteBuffer.remaining())                     byteBuffer.get(ba)                      try {                         val parent =                             File(Environment.getExternalStorageDirectory().absolutePath + "/h264pic/")                         if (!parent.exists()) {                             parent.mkdirs()                             Log.d(TAG, "parent=${parent.absolutePath}")                         }                          //  take NV21 Format picture , With quality 70 Compressed into Jpeg                         val path = "${parent.absolutePath}/${System.currentTimeMillis()}-frame.jpg"                         Log.e(TAG, "path:$path")                         val fos = FileOutputStream(File(path))                         val yuvImage = YuvImage(ba, ImageFormat.NV21, width, height, null)                         yuvImage.compressToJpeg(                             Rect(0, 0, yuvImage.getWidth(), yuvImage.getHeight()),                             80, fos)                         fos.flush()                         fos.close()                     } catch (e: IOException) {                         e.printStackTrace()                     }                 }
  最后,硬解码速度很快,效率很高,播放视频需要PTS时间戳处理.demo最好的办法就是让它渲染慢一点(demo视频文件是30fps,也就是说1000ms/30= 33ms一帧yuv数据),所以在 mediaCodec.releaseOutputBuffer(outIndex, true)  休眠前(33ms)达到正常播放速度。

突发两款小米手环4遭到网站泄露前一段时间,罗哥做了一个爆料!华米青春版手表2泄露信息汇总的视频,推测华米将最迟在下一个季度发布这款产品。视频一经发布,立即引起了我的亲朋好友的围观,结果到现在也就几十观看,汗。但雷军自我毁灭式曝光小米9发布会还有什么秘密?在以前的发布会,每一样即将发布的产品都是绝密状态。偶尔厂家自己或者已经提前拿到工程机的KOL放一两张在地铁或者在咖啡厅的谍照,旋即就会引起科技媒体们的跟风转载评论,即使这些谍照跟网终于来了!小米将在28号印度首发红米Note7Pro据网友IshanAgarwal昨日在推特上放出一条爆料信息,小米将于28号在印度发布两款红米新机即为RedmiNote7和Note7Pro,并且放出了两款新机的渲染图,整体外观基本大疆运动相机OsmoAction将于本月15发布,GoPro,小蚁凉凉了?昨天大疆正式预告本月15会发布一款新产品,主题是另一面,更精彩!从网上流传的各种谍照来看,就是运动相机OsmoAction无疑了(虽然海报宣传你的另一面有给人360全景相机的感觉,特普朗叫苹果CEO为蒂姆苹果,然后库克做了这么一件事情在3月6号的白宫美国劳动力政策咨询委员会议上,总统特朗普先生和他的女儿,苹果CEO库克以及其他相关人员就科技相关的工作和教育的重要性展开讨论。一顿寒暄之后,特朗普表扬了库克所做的经世界上最小游戏本,性能最强掌上游戏机,配合RTX2080秒杀一切GPDWINMax是一台8寸掌上电脑游戏机,配置冰湖i51035G7处理器,16G运行内存3733频率,512G固态硬盘,这次试玩的游戏是地铁离去。地铁离去是2019年才出的4A大性能相当一万多苏菲,预售仅4999,强大的超级掌上电脑就问你香吗这是最新的GPDWINMax掌上游戏电脑,搭配全新第十代英特尔冰湖i5处理器,16GDDR43733高频运行内存,512G固态硬盘,8英寸1280800分辨率屏,内置WIN10正版PC掌机拥有16G内存512G固态硬盘,英特尔冰湖i5处理器,细节到位这是最新一代的PC游戏掌机,GPDWINMax,硬件配置十分强大,可以直接和笔记本电脑相比较,16G超大运行内存,512G固态硬盘,英特尔冰湖i5处理器,强大的940核显可以在默认8寸掌上电脑雷电3接口,核显和显卡坞同时测试仁王,效果让人意外GPDWINMax掌上电脑游戏机,和IpadMini差不多大的,但是却能流畅玩很多大型3A,而且是打开上手即玩,不需要复杂的设置,因为冰湖i51035G7处理器性能过于强大。这次演wireshark命令行抓包Wireshark通常用于在工作期间捕获数据包,以消除Intranet和其他复杂问题,但是经常会遇到软件崩溃,尤其是在捕获数据包数小时时,准备进行分析时,会突然崩溃。查询后,得知W电脑水冷小白科普我想给准备安装的水冷的小伙伴讲解一下,不要被无良商家骗。水冷就是为了cpu和显卡更好的散热。水冷有四种模式1水导板水冷(一般情况都是串联)2单水箱水泵串联3双水箱水泵并联4单水箱水
iphone手机怎么连接家里的电视?下面我介绍手机与电视机连接的方法,连接之后,手机上的一切操作都可以在电视机的屏幕上看。准备工作如果电视机是智能电视机,那么在电视机上安装一个名叫乐播投屏的软件,其它投屏软件(例如多有什么手机充电快又适合玩游戏的,4000预算求推荐?文小伊评科技追求快充和游戏体验,那么站在当下的手机市场上来看能够满足这个需求的手机一共有四款IQOO7,黑鲨4系列(普通版和Pro版),红魔6Pro这四款手机。因为这四款手机全部都中端手机不要乱买,这4款才是最佳选择,每一款性能口碑都超棒你们身边的人都在用什么手机?他们在选购手机的时候都看中哪些方面?在互联网数码圈很多人都是参数党,但是绝大多数消费者在选手的时候都是不太了解参数的,购买旗舰机型的时候其实没什么太多的360造车!网友手机都造不好,更何况汽车?如今在中国,宣布进入汽车领域的互联网公司越来越多了,百度与吉利汽车成立了合资企业集度汽车,阿里巴巴与上汽集团合资成立了智己汽车,华为虽然没有直接坐车,华为也参与了智能汽车领域,宣布推荐一款2k以下手机?2K以下的手机不少,但是要求屏幕细腻尺寸不大于6。4拍照还要好一点的手机确实不好找。好在不玩游戏,对性价比不是那么看重!小屏拍照手机首推vivoS系列6。4英寸的手机确实非常少,加为什么很多人会花3千元去买18年出厂的苹果手机?很高兴回答你的问题,分享一下我个人的看法吧!宁愿花两三千块钱买18年的苹果手机,我感觉有两个原因。首先最大的就是虚荣心,真的不知道从什么时候开始,感觉用个苹果手机就高人一等,或者是宁愿买iPhoneXR,也不愿意加900元买A14OLED,是什么心态?那为什么不再多加点买pro?为什么不再再多加点买promax?自己心里预期多少价位就买多少的,你觉得是什么心态?为什么不多加点钱买奔驰宝马?在多加点买保时捷?你问这种问题是什么心态贾跃亭真的回来了?下周回国,因为贾跃亭而成为一个遥遥无期的梗。但是这一次,网传贾跃亭真的要回来了突发海报,贾跃亭真回国还是乐视又炒作?今日乐视突然发布了一张邀请函的海报,表示下周的5月18日将举办乐律师男车主起诉维权特斯拉女车主广东律师男车主起诉维权特斯拉女车主她维权导致我被歧视根据引用网络消息,女车主被起诉了。起诉她的人,不是特斯拉,是特斯拉的一名男车主。这名男车主叫宋某某,是广东一名律师。宋车主在民事完美适配iPhone12磁吸充电,PYS鹏元晟MagSafe磁吸无线充电器评测苹果推出MagSafe磁吸无线充电催生了很多周边产业的发展,各大厂商纷纷推出自家的MagSafe磁吸无线充电器新品,以便可以为iPhone12用户提供更多选择。近日充电头网评测室收5。9英寸的骁龙888旗舰发布4700起售5月13日,华硕的两款骁龙888新机ZenFone8和ZenFone8Flip正式发布,两款手机除了配置是目前的顶级之外,在外观设计上也都各具特色。首先是ZenFone8,它可以称