自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

说码解字

分享关于计算机理论和技术的研究,欢迎探讨。

  • 博客(29)
  • 资源 (2)
  • 收藏
  • 关注

原创 Kotlin 协程

它在概念上类似于线程,因为它需要运行一个代码块,该代码块与其他代码并发运行。它可以在一个线程中暂停执行,并在另一个线程中恢复执行。在实际应用中,会启动大量协程。根据操作系统、JDK 版本及其设置,要么会抛出内存不足错误,要么会缓慢启动线程,以确保并发运行的线程数量不会过多。修饰符的新函数,这是一个暂停函数,暂停函数可以像普通函数一样在协程内部使用,但它们的额外特性是,它们可以反过来使用其他暂停函数(如。通常用在应用程序的最顶层,但在实际代码中很少见,因为线程是昂贵的资源,阻塞它们会导致效率低下。

2025-05-19 20:50:46 1028

原创 ExoPlayer 如何实现音画同步

ExoPlayer 的音画同步实现采用音频作为主时钟,通过精确计算视频帧与音频位置的时间差来决定视频帧的处理方式。此外,还有其他一些特性如跳过静音、速度调整等,但这些是音频处理的功能,而不是基本的输出模式。第二种是直通模式(Passthrough Mode),对于编码音频格式(如杜比数字、DTS),编码音频直接传递给兼容的音频硬件,无需解码。还有一种模式是隧道模式(Tunnel Mode),它是一种特殊的播放方式,它使用AV同步标头来确保音视频同步。第一种是PCM模式(普通播放模式)。

2025-05-13 16:55:33 565

原创 如何读懂《纯粹理性批判》

最后给出一些具体的学习建议。《纯》是对理性主义和经验主义的综合与批判,因此必须了解这两大流派的核心观点,尤其是休谟对因果性的怀疑,这是康德写作的直接触发点。之前的哲学家作品包括休谟《人类理解研究》(尤其是关于因果性和怀疑主义的部分),笛卡尔的《第一哲学沉思集》(了解理性主义的基本立场),洛克的《人类理解论》(经验主义的起点)。康德的入门作品包括《未来形而上学导论》(这是康德对《纯粹理性批判》的简化版,语言更通俗,适合初学者),《实践理性批判》和《道德形而上学基础》(可以帮助理解康德哲学的整体框架)。

2025-05-11 21:05:54 404

原创 如何从播放器构造角度研究 Media3 源码

构建一个播放器,通常需要加载媒体源、解码、渲染、播放控制这几个关键环节。Media3 通过构建一个 ExoPlayer 实例来协调这些环节。Jetpack Media3 是 Android 提供的现代化媒体播放库。Media3 的模块化设计和扩展能力。管理播放器的生命周期和组件:通过入口类。)负责抽象不同类型的数据。解码和渲染:Media3 中通过。负责从不同渠道获取数据。播放控制与状态管理:核心类是。

2025-05-08 22:57:56 638

原创 Media3 中 Window 的时间相关属性详解

类中,与时间相关的属性描述了媒体播放窗口(window)在时间维度上的关键信息。这些属性帮助开发者理解媒体的播放范围、起始点、持续时间以及与设备时间或直播流的同步关系。)表示时间未设置,常用于直播或未完全加载的媒体。AndroidX Media3 的。(相对于 Unix 纪元,如。(相对于窗口内部,如。

2025-05-07 20:47:20 520

原创 如何系统学习音视频

学习音视频技术涉及多个领域,包括音频处理、视频处理、编码解码、流媒体传输等。

2025-04-29 22:19:46 1393

原创 ExoPlayer 中的 Timeline、Period 和 Window

表示窗口内的一个逻辑分段,通常对应媒体内容的子部分(如 DASH 的一个 Period 或 HLS 的一个片段组)。表示时间轴上的一个逻辑时间窗口,通常对应一个连续的播放内容段。每个窗口有自己的时间范围(开始时间、持续时间)和元数据(如是否动态、是否可寻址)。),新窗口或周期会随时间添加,旧周期可能被移除(滑动窗口)。可以是静态的(如点播视频,固定时长)或动态的(如直播流,窗口随时间滑动)。定期更新,反映新的窗口或周期(例如,HLS 播放列表刷新)。定义窗口内的细粒度分段(如流的一个片段)。

2025-04-28 22:30:49 864

原创 C++ RAII

它通过将资源的生命周期绑定到对象的生命周期,利用 C++ 的自动对象管理机制(主要是栈对象的构造和析构),确保资源在使用完毕后被正确释放,避免资源泄漏。禁用异常的场景包括极小型系统(内存不足,如 2K),硬实时系统(无法保证异常处理时间),遗留代码(指针使用复杂,缺乏所有权策略),异常实现效率低(慢、内存占用大或动态链接库支持差),管理决策(需挑战传统观念)。通常用于确保资源在代码块结束时释放,但 RAII 通过将资源管理封装在对象中,析构函数自动释放资源实现相同的目标,且更简洁。)需明确定义拷贝语义。

2025-04-27 17:52:09 759

原创 C++ 同步原语

同步原语(Synchronization Primitives)是操作系统和编程语言提供的基本工具,用于在多线程或并发环境中协调线程(或进程)之间的执行顺序,管理共享资源的访问,以避免数据竞争(data race)、死锁(deadlock)等问题。(C++11):RAII 封装,构造时加锁,析构时解锁,不支持手动解锁。(C++11):允许同一线程多次锁定(递归加锁),但其他线程仍被阻塞,适合需要递归调用的场景。作用:提供无锁(lock-free)的线程安全的原子操作,适合简单变量(如计数器)的并发访问。

2025-04-26 20:25:16 1084

原创 C++ Lambda 表达式

在 C++11 到 C++17 中,Lambda 表达式生成的闭包类型没有默认构造函数,且不能直接赋值(即使 Lambda 是无状态的,即不捕获任何变量)。Lambda 表达式的捕获列表是 [],表示空捕获,即不捕获任何外部变量,既不是按值捕获也不是按引用捕获。如果 Lambda 捕获变量(有状态 Lambda),则无法使用默认构造或赋值,因为它们的行为依赖捕获的变量。是全局的,不需要捕获,而 x 是 Lambda 的参数,不是外部作用域的变量。捕获列表决定了 Lambda 如何访问外部作用域的变量。

2025-04-24 21:53:18 708

原创 C++ 完美转发

完美转发(Perfect Forwarding)是 C++11 引入的一项重要特性,用于在函数模板中将参数以原始值类别(左值或右值)无损地传递给另一个函数,而不引入额外的拷贝或类型变化。如果参数是左值(lvalue),则以左值形式转发。如果参数是右值(rvalue),则以右值形式转发。完美转发的优势在于它将参数传递的责任从调用者转移到了模板函数(如 wrapper),从而避免了为每种参数类型或值类别编写多个重载版本。它的作用是将参数按原始值类别(左值或右值)传递给目标函数。(右值引用折叠为右值引用)

2025-04-23 22:15:21 193

原创 C++ 实现无锁线程安全栈

进行深拷贝也不合理,深拷贝需要遍历链表并创建新节点,但遍历过程中链表可能被其他线程修改,导致不一致,深拷贝需要复制整个链表,性能开销很大,在并发环境中难以实现,需要锁住整个链表。遍历时看到的是链表的“快照”,可能不反映最新状态,例如,线程 A 在遍历到某个节点时,线程 B 可能在头部插入一个符合条件的节点,线程 A 不会看到它。),而是通过原子操作实现线程安全,避免了锁的阻塞,提高了并发性能,但是在高竞争场景(多个线程同时压入),最终,所有线程的元素都会被正确插入,链表结构不会损坏。自动释放链表中的节点。

2025-04-22 22:16:54 791

原创 归并排序算法

在 merge 方法中,创建了两个临时数组,总临时数组大小为 $ n1 + n2 = right − left + 1$,在最顶层递归(合并整个数组时),right - left + 1 = n,因此临时数组的总大小最大为 $ O(n) $,虽然每一层递归的 merge 都会创建临时数组,但这些数组在 merge 方法结束后会被垃圾回收,且递归是分阶段执行的(先完成左子树递归,再右子树,再合并),因此不会同时存在多个大数组。总体来看,临时数组的空间占用在任何时刻不会超过 $ O(n)

2025-04-20 20:32:03 256

原创 C++ 的循环引用问题

相互引用,形成一个闭环,导致它们的引用计数无法降为0.即使这些对象不再被程序的其他部分引用,它们的内存也不会被释放,因为每个对象的。的引用计数机制依赖于计数归零来释放资源,循环引用破坏了这一机制。循环引用会导致内存泄漏,因为资源无法被析构。引用资源但不控制其生命周期(不增加引用计数)。自动变为“过期”(expired),不会阻止资源析构。引用资源但不增加引用计数,因此不会阻止资源释放。循环引用是指多个对象通过。以下示例展示了两个类。,可以打破循环引用。

2025-04-18 01:16:16 379

原创 补码系统计算一致性的数学推导

补码系统设计了一套机制,将数学上的有符号整数范围−2n−12n−1−1映射到无符号整数范围02n−1。映射后,映射后,所有的算术运算(加法、减法等)在无符号二进制运算下,结果等价于有符号整数的数学运算。补码的核心是设计一种“编码”,让负数、正数在二进制世界里用统一的规则运算,结果和数学一致。在这种映射规则下,对于正数和零(x≥0),直接用二进制表示,最高位为 0,即Bxx02n−1−1。对于负数(x0),负数−x(其中x0B−x。

2025-04-16 11:24:21 707

原创 补码系统设计的数学表达

补码(Two’s Complement)是计算机中表示有符号整数的标准方式,其设计目标是:统一加减法运算:让正数和负数的加法直接用硬件加法器处理,无需额外的减法逻辑。避免零的歧义:确保零只有一种表示(而不是正零和负零)。最大化表示范围:在固定位数下尽可能多地表示不同数值。基于这种设计,能简化硬件电路地实现,只需寄存器、NOT 门(取反)、加法器(加 1)、ALU(算术逻辑单元)即可实现计算。2n。

2025-04-15 21:32:22 899

原创 快速排序算法及其优化

在递归调用栈中,平均情况下,当分区平衡时,递归树的深度为 O(logn),每次递归调用在栈上存储常量级的变量(low、high、pi 等),因此栈空间为O(log n)。所以快速排序的总空间复杂度由递归栈主导,平均情况是O(log n),最坏情况是O(n)。每一层的总工作量是O(n)(所有子数组的元素总数约为 n )。总时间复杂度 = 每层工作量 O(n) × 层数 O(logn) = O(nlogn)。与平均情况类似,递归深度为 O(log n),每层工作量为 O(n),总时间为 O(n log n)。

2025-04-12 23:30:24 517

原创 C++ 的右值引用和移动语义

MyString &&other 表示右值引用,表示 other 是一个右值(临时对象或即将销毁的对象)。noexcept 表示这个函数不会抛出异常,移动构造函数通常需要时 noexcept 的,标准库(如 std::vector )在移动元素时会优先选择 noexcept 的移动构造函数,否则可能退回到拷贝。如果 s1 即将销毁(比如临时对象),这种拷贝是浪费的。如果没有定义拷贝构造函数,编译器会生成默认的拷贝构造函数,导致浅拷贝(s1 和 s2 共享 data),析构时会重复释放内存,引发崩溃。

2025-04-11 18:19:49 135

原创 Java 的动态代理

Java 的动态代理(Dynamic Proxy)是 Java 提供的一种允许在运行时动态创建代理对象的机制,用于拦截和处理对目标对象方法的调用,它基于 Java 的反射机制,被广泛运用于 AOP (面向切面编程)、框架开发(如 Spring)等领域。Prxoy.newProxyInstance 在运行时生成一个代理类,这个代理类的字节码是动态创建的,通常以 $Proxy0 这样的形式命名,代理类的每个方法都会调用 InvocationHandler.invoke。

2025-04-09 21:30:39 238

原创 Windows 配置 OpenGL 开发环境

启动Visual Studio(假设为2019版本)。创建一个新的C++空项目。在界面顶部中心,菜单栏下方有两个相邻的下拉菜单。选择x64。先在Debug模式下(然后在Release模式下)进入“项目属性”并进行以下更改。在“VC++目录”下(也可能写成“C/C++”),单击“常规”,然后在“包含目录”中添加你之前创建的include文件夹。在“链接器”下,有以下两个更改:单击“常规”,然后在“附加库目录”下添加先前创建的lib文件夹。

2024-09-05 13:54:58 1376

原创 Android 平台 OpenGL 环境搭建的两种方法及示例

static float triangleCoords[] = { // 按逆时针方向顺序// 设置颜色// 初始化顶点字节缓冲区// (每个浮点数占用4个字节)均同上。

2024-07-26 19:55:07 2140 2

原创 JNI 语法

全称Java Native Interface,主要用于在Java代码中调用非Java代码,以此绕过Java的内存管理和解决Java的性能问题。

2020-09-01 22:49:04 22169

原创 Java 局部匿名内部类是否会持有外部类的引用

5:调用Demo$DemoRunnable类的init方法(即参数为Demo的构造方法),将Demo对象作为了参数传递进来。发现生成的类只有一个构造器,参数就是Demo类型,而且保存到内部类本身的this$0字段中。4:aload_0指令将外部类Demo的this对象压栈。用javac命令生成字节码文件,根目录下生成两个文件。以下的分析方法和上面类似,这里给出简化过程。,查看反编译后的代码,根目录下生成两个文件。根目录下生成两个文件。根目录下生成两个文件。

2020-08-19 01:13:24 2053

原创 流媒体协议介绍

类似苹果公司的HTTP Live Streaming(HLS)方案,MPEG-DASH会将内容分解成一系列小型的基于HTTP的文件片段,每个片段包含很短长度的可播放内容,而内容总长度可能长达数小时(例如电影或体育赛事直播)。当媒体流正在播放时,客户端可以选择从许多不同的备用源中以不同的速率下载同样的资源,允许流媒体会话适应不同的数据速率。自适应流解决方案的标准化是为向市场提供信心,使该解决方案可以用于通用部署,抗衡类似但更专有的解决方案,如微软Smooth Streaming与Adobe的HDS。

2020-08-17 01:35:04 1839

原创 如何将 ORM 框架封装为通用的 BaseDao

最近开发的项目中需要使用到ORM框架,但是我并不想针对每一个具体业务写一个Dao,对于通用的CRUD功能,我想试着通过一个BaseDao解决问题,这里涉及到一个关键问题是:如何在编译时获取泛型的实际类型?后来通过抽象类解决了这个问题。

2020-08-13 01:46:35 960 1

原创 响应式编程在 Android 中的应用

响应式编程是一种基于异步数据流概念的编程模式。数据流就像一条河:它可以被观测,被过滤,被操作,或者为新的消费者与另外一条流合并为一条新的流。响应式编程的一个关键概念是事件。事件可以被等待,可以触发过程,也可以触发其它事件。事件是唯一的以合适的方式将我们的现实世界映射到我们的软件中:如果屋里太热了我们就打开一扇窗户。同样的,当我们更改电子表(变化的传播)中的一些数值时,我们需要更新整个表格或者我们的机器人碰到墙时会转弯(响应事件)。

2020-08-13 01:46:20 7092 1

原创 利用 AspectJ 实现 Android 端非侵入式埋点

最近在项目中遇到通过埋点对用户行为进行收集的需求,由于项目运行在局域网,而且有一些很细化的需求,比较几种技术方案之后,选择了通过AspectJ进行埋点。本文主要介绍笔者对学习和使用AspectJ的总结。AOP编程在进行用户行为统计是是一种非常可靠的解决方案,避免了直接在业务代码中进行埋点,而AOP编程的应用还不仅于此,它在性能监控,数据采集等方面也有着广泛的应用,后续将继续研究,并整理发布。AspectJ是一个很强大的用于AOP编程的库,使用AspectJ关键在于掌握它的pointcut的语法,

2020-08-13 01:46:02 5086 1

原创 集合在迭代过程中能否添加、删除或修改元素

modCount表示集合的元素被修改的次数,每次增加或删除一个元素的时候,modCount都会加一,而expectedModCount用于记录在集合遍历之前的modCount,检查这两者是否相等就是为了检查集合在迭代遍历的过程中有没有被修改,如果被修改了,就会在运行时抛出ConcurrentModificationException这个RuntimeException,以提醒开发者集合已经被修改。第一种使用for循环进行遍历时内部使用的就是集合本身的遍历方法,这里不做讨论。2.使用 foreach 遍历。

2020-08-13 01:45:47 7353 1

原创 多线程下的单例模式

用来检查实例是否被创建的代码是线程同步的,也就是说此代码块在同一时刻只能被一个线程执行,但是同步锁(locking)只有在实例没被创建的情况下才起作用。如果单例实例已经被创建了,那么任何线程都能用非同步的方式获取当前的实例,而无需经过线程锁的同步过程,避免了不必要的延迟。如果发生这种情况,第一个线程会首先使用新构造器实例化单例对象,同时第二个线程也会检查单例实例是否为空,由于第一个线程还没完成单例对象的实例化操作,所以第二个线程会发现这个实例是空的,也会开始实例化单例对象。可以通过以下两种方式来实现。

2020-07-06 20:25:25 444

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除