当前位置: 首页 > news >正文

全国分站seo做百度推广需要有网站吗

全国分站seo,做百度推广需要有网站吗,门户网站需要多少费用,wordpress登陆页文件系列文章目录 ExoPlayer架构详解与源码分析#xff08;1#xff09;——前言 ExoPlayer架构详解与源码分析#xff08;2#xff09;——Player ExoPlayer架构详解与源码分析#xff08;3#xff09;——Timeline ExoPlayer架构详解与源码分析#xff08;4#xff09;—…系列文章目录 ExoPlayer架构详解与源码分析1——前言 ExoPlayer架构详解与源码分析2——Player ExoPlayer架构详解与源码分析3——Timeline ExoPlayer架构详解与源码分析4——整体架构 ExoPlayer架构详解与源码分析5——MediaSource ExoPlayer架构详解与源码分析6——MediaPeriod ExoPlayer架构详解与源码分析7——SampleQueue ExoPlayer架构详解与源码分析8——Loader ExoPlayer架构详解与源码分析9——TsExtractor 文章目录 系列文章目录前言ProgressiveMediaPeriodLoaderExtractingLoadableBundledExtractorsAdapterExtractor总结 前言 ProgressiveMediaPeriod的左半部分SampleQueue已经在上篇讲完相对今天说的这部分还算简单ProgressiveMediaPeriod右半部分主要为Loader而Loader中及包含数据的获取也包含数据的解析本篇主要分析Loader的整体机构和数据解析部分结构。 ProgressiveMediaPeriod 还是先预习下上篇的整体结构本篇主要分析右半半部分的Loader 图中Loader数据的加载主要靠DataSource而解析部分主要为Executor Loader Loader本质上就是就是一个线程池初始化时就创建了一个ExecutorService启动时实例化出一个LoadTask放入线程池中执行。 private final ExecutorService downloadExecutorService;public Loader(String threadNameSuffix) {this.downloadExecutorService Util.newSingleThreadExecutor(THREAD_NAME_PREFIX threadNameSuffix);}public T extends Loadable long startLoading(T loadable, CallbackT callback, int defaultMinRetryCount) {Looper looper Assertions.checkStateNotNull(Looper.myLooper());//获取当前启动线程的looperfatalError null;long startTimeMs SystemClock.elapsedRealtime();new LoadTask(looper, loadable, callback, defaultMinRetryCount, startTimeMs).start(0);return startTimeMs;}LoadTask初始化时会传入当前线程的looper和callback通过looper将后台线程的信息传递到启动线程的callback中执行所以startLoading的线程必须要包含一个loopercallback也将在启动现场上调用。通常情况下启动线程就是内部播放线程具体参照之前将的线程模型。 //LoadTask.java Overridepublic void run() {try {boolean shouldLoad;synchronized (this) {shouldLoad !canceled;executorThread Thread.currentThread();}if (shouldLoad) {TraceUtil.beginSection(load: loadable.getClass().getSimpleName());try {loadable.load();//执行loadable} finally {TraceUtil.endSection();}}synchronized (this) {executorThread null;// Clear the interrupted flag if set, to avoid it leaking into a subsequent task.Thread.interrupted();}if (!released) {sendEmptyMessage(MSG_FINISH);//将执行结果通过handler发给启动线程looper}...}Overridepublic void handleMessage(Message msg) {if (released) {return;}if (msg.what MSG_START) {execute();return;}if (msg.what MSG_FATAL_ERROR) {throw (Error) msg.obj;}finish();long nowMs SystemClock.elapsedRealtime();long durationMs nowMs - startTimeMs;Loader.CallbackT callback Assertions.checkNotNull(this.callback);if (canceled) {callback.onLoadCanceled(loadable, nowMs, durationMs, false);return;}switch (msg.what) {case MSG_FINISH:try {callback.onLoadCompleted(loadable, nowMs, durationMs);//执行完毕在启动线程上调用callback...}}可以看到最终是调用了loadable.load方法 这个loadable定义在ProgressiveMediaPeriod的ExtractingLoadable中 ExtractingLoadable ExtractingLoadable主要包含2个东西DataSource和ProgressiveMediaExtractorDataSource负责从媒体数据源获取数据而ProgressiveMediaExtractor则负责将获取的数据解析出Format和Metadata等sample到SampleQueue中由此完成数据的加载 看下最核心的load方法。 Overridepublic void load() throws IOException {int result Extractor.RESULT_CONTINUE;while (result Extractor.RESULT_CONTINUE !loadCanceled) {//循环多次读取和sample数据try {long position positionHolder.position;//获取当前的读取位置dataSpec buildDataSpec(position);//构建dataSource的dataSpeclong length dataSource.open(dataSpec);//打开读取的流返回实际数据的长度if (length ! C.LENGTH_UNSET) {length position;//获取加载后的长度onLengthKnown();}...progressiveMediaExtractor.init(//初始化ProgressiveMediaExtractorextractorDataSource,//传入dataSource,此时的dataSource已经open可以直接通过调用dataSource的read获取数据uri,dataSource.getResponseHeaders(),position,//当前读取位置length,//流加载后的总长度extractorOutput);//传入output最终会关联输出到SampleQueue中...while (result Extractor.RESULT_CONTINUE !loadCanceled) {try {//当未open时阻塞当前执行主要作用是当上层正在决定是否要继续加载时阻塞住下一次加载//当上层决定完可以继续加载时loadCondition.open()//这里的上层决定一般由LoadControl做出后面会讲到loadCondition.block();} catch (InterruptedException e) {//如果不继续加载线程会等待直到调用Loader的cancel方法会executorThread.interrupt();结束当前线程throw new InterruptedIOException();}result progressiveMediaExtractor.read(positionHolder);//读取并解析数据到传入positionHolder用于更新下一次读取位置long currentInputPosition progressiveMediaExtractor.getCurrentInputPosition();//获取当前已经读取到的位置//如果当前进度达到必要去继续加载检查的阈值时调用上层加载检查判断是否下次加载这个阈值有个默认值为1024*1024if (currentInputPosition position continueLoadingCheckIntervalBytes) {position currentInputPosition;loadCondition.close();//阻塞下次加载handler.post(onContinueLoadingRequestedRunnable);//通过回调询问上层是否需要继续加载}}} finally {if (result Extractor.RESULT_SEEK) {//如果解析器返回RESULT_SEEKresult Extractor.RESULT_CONTINUE;//就会再次open数据源此时的Uri还是同一个但是position可能已经在解析器中重新指定} else if (progressiveMediaExtractor.getCurrentInputPosition() ! C.INDEX_UNSET) {positionHolder.position progressiveMediaExtractor.getCurrentInputPosition();}DataSourceUtil.closeQuietly(dataSource);//关闭当前流}}}这里有2个While循环第一个While循环说明同一个数据源可能会从不同的位置被打开多次当内循环中解析数据需要SEEK跳过一段数据时就会返回RESULT_SEEK这个时候跳出内循环再次执行外循环。下面会讲到什么时候需要SEEK数据另外我们注意到Loader从打开数据加载操作1M默认值数据时就会阻塞住内循环停止向SampleQueue中写入数据而是向上层讯问是否需要继续加载数据如果上层决定继续加载更多数据就会调用ProgressiveMediaPeriod continueLoading解开阻塞的锁继续加载。因为我们知道数据是加载到内存中的如果无限制的加载肯定是不行的需要有节制的加载和释放数据。 接下看下ProgressiveMediaExtractor的实现BundledExtractorsAdapter。 BundledExtractorsAdapter 这个类相当于包裹了一个Extractor最终读取工作其实是转发给Extractor初始化时确认当前流对应的Extractor Overridepublic void init(DataReader dataReader,Uri uri,MapString, ListString responseHeaders,long position,long length,ExtractorOutput output)throws IOException {//包装输入流ExtractorInput extractorInput new DefaultExtractorInput(dataReader, position, length);this.extractorInput extractorInput;if (extractor ! null) {return;}//extractorsFactory通过网络请求的返回的Content-Type和文件的后缀名获取按优先级创建一个Extractor列表Extractor[] extractors extractorsFactory.createExtractors(uri, responseHeaders);if (extractors.length 1) {this.extractor extractors[0];} else {for (Extractor extractor : extractors) {try {//通过调用extractor方法获取流的头部信息最终确定当前流是否可以用这个extractor来解析,如TS就是通过判断0x47同步位来确定的if (extractor.sniff(extractorInput)) {this.extractor extractor;break;}} catch (EOFException e) {// Do nothing.} finally {Assertions.checkState(this.extractor ! null || extractorInput.getPosition() position);extractorInput.resetPeekPosition();}}if (extractor null) {//没有支持解析的extractor报错throw new UnrecognizedInputFormatException(None of the available extractors ( Util.getCommaDelimitedSimpleClassNames(extractors) ) could read the stream.,Assertions.checkNotNull(uri));}}extractor.init(output);//初始化extractor}Overridepublic int read(PositionHolder positionHolder) throws IOException {return Assertions.checkNotNull(extractor).read(Assertions.checkNotNull(extractorInput), positionHolder);//将数据的读取解析转发给extractor}Extractor 主要将媒体数据从容器格式中解析出来支持很多容器格式每种都做了实现有很多下图只列了一部分 FileTypes类里定义了这些格式inferFileTypeFromUri可以看出他们与文件后缀之间的对应关系 public static FileTypes.Type int inferFileTypeFromUri(Uri uri) {Nullable String filename uri.getLastPathSegment();if (filename null) {return FileTypes.UNKNOWN;} else if (filename.endsWith(EXTENSION_AC3) || filename.endsWith(EXTENSION_EC3)) {return FileTypes.AC3;} else if (filename.endsWith(EXTENSION_AC4)) {return FileTypes.AC4;} else if (filename.endsWith(EXTENSION_ADTS) || filename.endsWith(EXTENSION_AAC)) {return FileTypes.ADTS;} else if (filename.endsWith(EXTENSION_AMR)) {return FileTypes.AMR;} else if (filename.endsWith(EXTENSION_FLAC)) {return FileTypes.FLAC;} else if (filename.endsWith(EXTENSION_FLV)) {return FileTypes.FLV;} else if (filename.endsWith(EXTENSION_MID)|| filename.endsWith(EXTENSION_MIDI)|| filename.endsWith(EXTENSION_SMF)) {return FileTypes.MIDI;} else if (filename.startsWith(EXTENSION_PREFIX_MK,/* toffset */ filename.length() - (EXTENSION_PREFIX_MK.length() 1))|| filename.endsWith(EXTENSION_WEBM)) {return FileTypes.MATROSKA;} else if (filename.endsWith(EXTENSION_MP3)) {return FileTypes.MP3;} else if (filename.endsWith(EXTENSION_MP4)|| filename.startsWith(EXTENSION_PREFIX_M4,/* toffset */ filename.length() - (EXTENSION_PREFIX_M4.length() 1))|| filename.startsWith(EXTENSION_PREFIX_MP4,/* toffset */ filename.length() - (EXTENSION_PREFIX_MP4.length() 1))|| filename.startsWith(EXTENSION_PREFIX_CMF,/* toffset */ filename.length() - (EXTENSION_PREFIX_CMF.length() 1))) {return FileTypes.MP4;} else if (filename.startsWith(EXTENSION_PREFIX_OG,/* toffset */ filename.length() - (EXTENSION_PREFIX_OG.length() 1))|| filename.endsWith(EXTENSION_OPUS)) {return FileTypes.OGG;} else if (filename.endsWith(EXTENSION_PS)|| filename.endsWith(EXTENSION_MPEG)|| filename.endsWith(EXTENSION_MPG)|| filename.endsWith(EXTENSION_M2P)) {return FileTypes.PS;} else if (filename.endsWith(EXTENSION_TS)|| filename.startsWith(EXTENSION_PREFIX_TS,/* toffset */ filename.length() - (EXTENSION_PREFIX_TS.length() 1))) {return FileTypes.TS;} else if (filename.endsWith(EXTENSION_WAV) || filename.endsWith(EXTENSION_WAVE)) {return FileTypes.WAV;} else if (filename.endsWith(EXTENSION_VTT) || filename.endsWith(EXTENSION_WEBVTT)) {return FileTypes.WEBVTT;} else if (filename.endsWith(EXTENSION_JPG) || filename.endsWith(EXTENSION_JPEG)) {return FileTypes.JPEG;} else if (filename.endsWith(EXTENSION_AVI)) {return FileTypes.AVI;} else {return FileTypes.UNKNOWN;}}从这些代码中可以看出EXO所支持的媒体容器格式。 下篇我们以TS容器格式为例讲解下TsExtractor了解媒体数据如何从容器格式中解析出来最终要交给Readerer渲染的。 总结 Loader主要作用就是将加载逻辑放入线程池中管理然后通过ExtractingLoadable控制数据的加载而数据主要由DataSource来获取解析部分主要为ExecutorExecutor通过持有已经open的DataSource不断从DataSource中read出数据用来解析媒体整个过程都只有一个线程即使到了数据加载部分也是在同一个线程中同步加载的在这段同步操作中还将加载的控制权交给了上层组件。下篇将会把TsExtractor作为一个典型的解析器来分析解析器的具体作用和执行过程。 版权声明 © 本文为CSDN作者山雨楼原创文章 转载请注明出处 原创不易觉得有用的话收藏转发点赞支持
http://www.hkea.cn/news/14571172/

相关文章:

  • 做板材外贸一般用哪个网站网站代码开发方式
  • 北京网站建设公司大全网站设计有哪些创新点
  • 广东省网站备案要多久网站托管公司如何选择
  • 网站制作程序下载网站链接收费怎么做的
  • 南宁市网站开发公司电话oa软件开发公司
  • 建设一个普通网站需要多少钱网络营销和直播营销的区别
  • 网上支付网站怎摸做惠东东莞网站建设
  • 网站建设 竞赛 方案wordpress不能启动怎么解决方法
  • 网站制作论文网站开发项目挣钱吗
  • 美橙云建站网页特效模板
  • 域控制网站访问php c2c网站开发的 书
  • 推荐常州网站推广什么建网站免费
  • 昆明做网站建设技巧公司负面口碑营销案例
  • 济宁北湖建设集团网站网站的专业
  • 中资源 网站域名解析国外做动运服装的网站
  • 什么网站可以做私房菜外卖网站设计优缺点分析
  • 上饶市网站建设ftp制作网站
  • 免费素材网站图库wordpress 微博页面
  • wordpress中文站cn免费h5模板
  • 创意网站建设设计公司十大外包公司
  • 北京国都建设集团网站企业建站都有什么网站
  • 百度seo整站优化wordpress后台白屏
  • 青海做网站找谁百度域名是什么意思
  • 西安h5响应式网站WordPress禁用f12
  • 网站建设阐述录播教育系统网站建设费用
  • 金融公司网站建设模板网站增加权重
  • 网站建设功能报价单黄岛因特网站建设公司
  • 自贡网站制作对建设工程施工合同实施过程中
  • 做网站装什么服务器wordpress社区模版
  • html网页设计代码购物网站免费高清图片素材网站有哪些