自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

C/C++Linux、音视频、DPDK

C/C++Linux、音视频、DPDK

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

原创 音视频流媒体高级开发(FFmpeg6.0/WebRTC/RTMP/RTSP/编码解码)

开源方案简介(视频 |12分钟23秒)AppRTC服务器组成(视频 |04分钟38秒)准备工作(视频 |02分钟37秒)AppRTC必要软件安装(1)(视频 |21分钟12秒)AppRTC必要软件安装(2)(视频 |14分钟03秒)1coturncolliderapprtc(视频 |19分钟19秒)nginx代理和运行测试(视频 |11分钟08秒)解决跨域问题和总结(视频 |17分钟42秒)课程展望(视频 |09分钟10秒)

2024-02-27 15:12:46 992

原创 2023年C/C++Linux服务器开发/后台架构师知识体系整理(持续更新中)

C/C++Linux服务器开发/后台架构师知识体系1. 精进基石专栏1.1 数据结构与算法面试必聊的排序与KMP随处可见的红黑树磁盘存储链式的B树与B+树海量数据去重的Hash与布隆过滤器,bitmap图论算法,di jkstra,dfs,bfs,动态规划1.2 设计模式创建型设计模式结构型设计模式行为型设计模式1.3 工程管理手写:Makefile/cmake/configure操作:git/svn与持续集成Linux系统运行时参数命令2. 高性能网络设计专栏2.1 网络编程网络io与select,pol

2021-07-05 21:22:44 4335 5

原创 腾讯T9职级后台开发要具备哪些专业的能力及知识点?

前言首先说明这里的后台开发指的就是Linux上的C+ +编程。因为很多人对后台开发有误解,通常人们说前端后台,后台就马上联想到web后台, java、php和各种web框架横飞的既视感。web后台属于后台,但后台却不只有web后台。两者是包含关系。从网络协议的角度分析, web后台聚焦的是HTTP ,而C+ +后台更多聚焦的是TCP。web后台可以看作是一个大后台最 靠前的东西,它解析了HTTP请求,然后可能层层转发给了后面整个分布式系统的许多组件,然后调用他们的服务。公司内部服务器主机之间绝大部分

2021-01-05 18:47:35 3558 7

原创 【音视频流媒体服务端开发学习指南】音视频驱动、多媒体中间件、流媒体服务器的开发,开发过即时通讯+音视频通话的大型项目

开源方案简介AppRTC服务器组成准备工作AppRTC必要软件安装(1)AppRTC必要软件安装(2)nginx代理和运行测试解决跨域问题和总结。

2024-04-13 22:20:09 645

原创 C/C++进阶/架构师(后端/音视频/游戏/嵌入式/高性能网络/存储/基础架构/安全)开发学习路线、系统性学习教程

C++学习可以划分为几个主要阶段,每个阶段的学习目标和推荐资源都有所不同。

2024-04-12 22:13:31 632

原创 音视频开发_FFmpeg音视频编码

NAL 的主要目标是实现网络环境的抽象,它将VCL编码产生的数据包装成为一系列的 NAL units,以提供统一的接口适应不同的系统环境。网络抽象层不但使编码视频能适应各种传输协议和存储介质,而且还为错误恢复和包丢弃等网络友好特性的实现提供了可能。NAL 单元(NAL Units)H.264/AVC 的编码结果会被分割为一系列的 NAL 单元,每个 NAL 单元都有两部分组成,分别是一字节的 NAL 头和一个负载荷(Payload)。负载荷包含了编码的视频数据或者其他信息。

2024-03-27 14:44:05 783

原创 FFmpeg音视频解复用+解码

比方说,如果我们需要将一个44.1kHz的音频升采样到48kHz,我们需要相应地增加样本数量,以保证每秒钟的样本数匹配新的采样率,这种情况下就会延长整个音频的播放时间。举例来说,如果你增加了音频的采样率,每个样本表示的时间会变短,为了保持音频数据在时间上的正确展现,原有的PTS需要根据新的采样频率重新计算。例如,将一个采样率为44.1kHz的音频重采样到48kHz,如果样本数维持不变,那么每个样本表示的时间就会缩短,因此播放速率会变快,但总的播放时间不会改变。

2024-03-25 20:50:05 967

原创 音视频开发_FFmpeg基石精讲

FFmpeg 抽象出了一套 API,隐藏了底层的复杂实现细节,提供了相对简单的接口供开发者使用。例如,不管背后具体是什么编解码器,开发者都可以通过统一的等函数来执行操作。总而言之,即使 FFmpeg 是用 C 语言编写的,它也在设计上模拟了一些 OOP 的概念,提高了代码的模块性、可读性和可维护性。然而,需要注意的是,这种模拟并不等同于真正的面向对象编程语言中的实现,如 C++,其中有对继承、多态、封装等特性的原生支持。

2024-03-22 17:40:07 998

原创 音视频开发_SDL跨平台多媒体开发库实战

SDL(Simple DirectMedia Layer)是一个非常流行和强大的跨平台开发库,它主要被用来开发视频游戏和实时多媒体应用程序。它提供了一系列的功能来处理视频、音频、键盘、鼠标、操纵杆、图形硬件加速以及聚焦3D硬件的各种功能。SDL的API通过C编程语言被设计和实现,但存在多种语言的绑定,方便不同的开发者使用不同的编程语言。在音视频开发方面,SDL提供了基础的API来进行音频播放和视频的渲染。例如,SDL_Audio接口允许你设定音频设备的参数,如采样率、音频格式和声道数,然后可以将音频数据送

2024-03-20 20:26:05 557

原创 音视频开发_快速掌握FFmpeg

解复用和复用通常是视频编解码中不可或缺的一部分,因为它们允许开发者和用户处理复杂的多媒体数据并适应各种不同的播放设备和网络状况。复用是解复用的逆过程,它涉及将独立的音频、视频和其他数据流合成为一个单一的、通常较易于传输和存储的容器格式文件。从音频文件中提取PCM(脉冲编码调制,一种未压缩的音频数据格式)和AAC(高级音频编码,一种有损压缩的音频编码标准)数据的基本步骤。在复用过程中,每个流都将按照特定的容器格式规范来封装,这包括将适当的头信息、元数据和分隔符添加到数据中。

2024-03-19 16:26:22 882

原创 音视频开发_解复用基础知识、Fmpeg开发环境搭建

解复用是指将音视频数据从容器格式中解封装出来,并进行解码操作,得到原始的音频和视频信号的过程。在音视频开发中,容器格式如MP4内部包含了音频轨、视频轨以及其他元数据,解复用过程就是将这些数据提取出来并进行解码,以便播放或者进一步处理。解析文件结构:首先需要读取MP4文件的头部信息,这包括了文件的基本结构、各个数据块的位置和大小等元数据。定位音视频数据:根据文件结构信息,找到音频轨和视频轨的位置和大小。音频解复用:将音频数据从MP4格式中提取出来,并进行解码操作,得到原始的音频信号。

2024-03-14 15:54:56 804

原创 音视频开发_视频基础知识

YUV 格式是一种描述彩色图像的格式,将颜色信息和亮度信息分开存储。Y 表示亮度(Luminance),U 和 V 表示色度(Chrominance)。在 YUV 格式中,亮度信息决定了图像的明暗,而色度信息则决定了图像的颜色。YUV 格式在视频编解码、图像处理等领域得到广泛应用。像素是图像显示和处理的基本单元,是图像中最小的可控制的点。每个像素都有自己的颜色和亮度值,通过大量的像素排列组合,可以形成完整的图像。图像分辨率。

2024-03-12 15:47:55 797

原创 音视频开发_音频基础知识

PCM是脉冲编码调制(Pulse Code Modulation)的缩写,是一种常用的数字音频编码格式。线性采样:PCM是一种线性采样编码方式,即将模拟声音信号通过固定时间间隔进行采样,并将每个采样值转换为对应的数字编码。无损编码:PCM是一种无损编码方式,即不对音频数据进行任何压缩或编码,能够完整保留原始音频信号的信息。单声道/立体声:PCM可以是单声道(Mono)或立体声(Stereo),单声道的PCM每个采样点只包含一个声道的数据,而立体声的PCM则包含左右两个声道的数据。采样率和位深度。

2024-03-09 22:16:25 956

原创 音视频开发基本概念

I帧、P帧和B帧:这些是视频编码中的三种关键帧类型。容器格式,有时也称为文件格式,是一种可以包含多种类型数据的格式,例如视频、音频、元数据(如标题、作者信息)、同步信息等。画面质量不仅受分辨率的影响,还与编码器的压缩效率、传输过程中的数据丢失、播放设备的显示性能等因素有关。而在视频编码中,码率一般根据分辨率、帧率和压缩格式来确定,如H.264编码的视频常见的码率范围为几百Kbps到几十Mbps。帧时长的长度通常以毫秒为单位来表示,在音视频编解码过程中,帧时长的设置会影响到视频的流畅度和音频的延迟。

2024-03-08 22:15:48 906

原创 【Linux 内核源码分析】内存管理——伙伴分配器

在Linux操作系统中,内存分配通常由内核中的内存管理模块完成。:这是内核中最基本的分配器,用于分配物理内存。伙伴系统将内存块组织成不同大小的伙伴,以便有效地分配和回收内存。它适用于分配较大的内存块。:slab分配器是一个对象缓存,用于高效地分配和回收小块内存。它将内存组织成缓存,每个缓存包含相同大小的对象。slab分配器特别适合为内核对象分配内存,如进程描述符、文件描述符等。:vmalloc是一个用于虚拟内存分配的分配器。它主要用于分配大块内存,并且不要求物理连续性,而是提供虚拟连续的内存区域。

2024-02-23 19:52:41 923

原创 【Linux 内核源码分析】内存管理——Slab 分配器

Slab 分配器在Linux内核中,伙伴分配器是一种内存管理方式,以页为单位进行内存的管理和分配。但是在内核中,经常会面临结构体内存分配问题,而这些结构体的大小通常是小于一页的。如果使用伙伴分配器来分配这些小内存,将造成很大的内存浪费。因此,为了解决这个问题,Sun公司的Jeff Bonwick在Solaris 2.4中设计并实现了一种新的内存分配器——slab分配器。与伙伴分配器不同的是,slab 分配器以字节为单位来分配内存,并基于伙伴分配器的大内存进一步细分成小内存进行分配。也就是说,slab 分

2024-02-21 22:18:32 969

原创 【Linux 内核源码分析】物理内存组织结构

多处理器系统两种体系结构:非一致内存访问(Non-Uniform Memory Access,NUMA):这种体系结构下,内存被划分成多个内存节点,每个节点由不同的处理器访问。访问一个内存节点所需的时间取决于处理器和内存节点之间的距离,因此处理器与内存节点之间的距离会影响内存访问速度。

2024-02-20 16:54:39 874

原创 【Linux 内核源码分析】内存映射(mmap)机制原理

内存映射(mmap)是 Linux 内核的一个重要机制,它为程序提供了一种将文件内容直接映射到进程虚拟地址空间的方式。同时内存映射也是虚拟内存管理和文件 IO 的重要组成部分。在 Linux 中,虚拟内存管理是基于内存映射来实现的。在调用 mmap 函数时,会创建一个结构体,该结构体代表了一段连续的虚拟地址空间,它们会相应地映射到一个后备文件或者一个匿名文件的虚拟页。一个结构体映射到一组连续的页表项,这些页表项指向物理内存中的一页。这样就把一个文件和物理内存页相映射起来。当进程试图访问映射到。

2024-02-19 17:57:20 1046

原创 【Linux 内核源码分析】虚拟内存地址空间

在现代操作系统中,每个进程被分配了独享的虚拟内存地址空间。这个地址空间可以视为一维线性空间,由多个连续的内存页组成。初始时,操作系统会将整个虚拟地址空间分成几个不同的区域,每个区域用于特定的目的。在32位模式下,虚拟地址空间通常被限制在4GB范围内。而在64位模式下,则能够支持更大的地址空间范围。

2024-02-19 14:15:00 971

原创 【Linux 内核源码分析】多核调度分析

SMP(Symmetric Multiprocessing,对称多处理)是一种常见的多核处理器架构。它将多个处理器集成到一个计算机系统中,并通过共享系统总线和内存子系统来实现处理器之间的通信。首先,SMP架构将一组处理器集中在同一个计算机上。这些处理器可以是物理上独立的芯片,也可以是在同一芯片上集成的多个核心。无论是物理上独立的处理器还是集成在同一芯片上的核心,它们都可以同时工作,处理不同的任务。在SMP架构中,各处理器是对等的,也就是说它们具有相同的权限和地位。

2024-01-27 17:50:37 1108

原创 【Linux 内核源码分析】堆内存管理

与静态分配的栈不同,堆的内存分配不是自动的,需要显式地通过内存分配函数(如malloc、new等)来申请内存空间,并在不使用时通过释放函数(如free、delete等)来释放已分配的内存。在 glibc 中,堆是由多个内存块组成的链表,每个内存块都有一个 heap_info 结构体来描述它所在的堆。堆内存是连续的内存区域:在大多数操作系统中,包括 Linux,堆内存是通过动态内存分配来管理的。堆内存的生长方向是自下而上:在传统的内存布局中,堆内存的生长方向是从低地址向高地址增长。其中一个常用的系统调用是。

2024-01-20 22:09:02 1148 1

原创 【Linux 内核源码分析】内存屏障

smp_store_mb()和smp_load_acquire()分别是带屏障的存储和加载函数,用于确保存储和加载操作的顺序和一致性。内存屏障的作用是强制对内存的访问顺序进行排序,保证多线程或多核处理器下的内存访问的一致性和可见性。在这种模型下,程序无法依赖于全局的、确定性的操作执行顺序。这些序列关系的正确性和顺序一致性是通过硬件层面的内存屏障指令、缓存一致性协议和处理器乱序执行的机制来实现的。Linux内核提供了多种内存屏障,包括通用的内存屏障、数据依赖屏障、写屏障、读屏障、释放操作和获取操作等。

2024-01-19 21:38:16 1027

原创 【Linux 内核源码分析】RCU机制

RCU的核心思想是在更新操作时,不立即删除旧版本的数据,而是等待所有正在使用旧版本数据的读者完成后再删除。当一个线程或进程进入临界区时,它会尝试获取互斥锁,如果锁是可用的,则表示资源未被占用,线程或进程可以获取锁并进入临界区;宽限期的长度通常是预先确定的,并与系统的需求和特性相关。此外,为了保证有序的更新,编写者必须使用某种同步机制,如锁定,来确保在进行写操作时其他写操作不会干扰更新的顺序。这是因为在RCU中,读操作是无锁的,但写操作需要确保数据结构的一致性和正确性,因此需要使用同步机制来避免竞争条件。

2024-01-15 20:00:57 990

原创 【Linux 内核源码分析】进程调度 -CFS 调度器

在CFS(Completely Fair Scheduler)调度器中,任务的权重值由其nice值决定,通过对比不同任务的权重值,CFS会分配合理的CPU时间片给每个任务。这种方式实现了一种类似于多态的效果,即不同的任务可以使用不同的调度算法,而调度器的函数指针则根据具体的调度器类型来指向对应的函数。通过这种方式,Linux 内核可以根据任务的调度器类型来调用相应的调度函数,实现了灵活的调度策略,并且能够方便地扩展和切换不同的调度器。高优先级的任务会获得更多的虚拟运行时间,在排序和选择调度时更容易被选中。

2024-01-13 20:08:54 953

原创 【Linux 内核源码分析笔记】系统调用

在Linux内核中,系统调用是用户空间程序与内核之间的接口,它允许用户空间程序请求内核执行特权操作或访问受保护的内核资源。系统调用提供了一种安全可控的方式,使用户程序能够利用内核功能而不直接访问底层硬件。

2024-01-10 16:15:12 956

原创 【Linux 内核源码分析】关于Linux内核源码目录结构

需要注意的是,Linux 内核的初始化代码不仅限于 init 目录,还分布在其他各个目录中。在 Linux 内核源码中,由于主要关注于内核本身的开发,usr 目录下的工具和库文件可能相对有限,不同的 Linux 发行版或用户空间环境可能会有自己独特的目录结构和文件组织方式。在 Linux 内核源码中,tools 目录是一个非常重要的目录,它包含了许多用于开发、调试和分析内核的工具。在 Linux 内核源码中,include 目录包含了大量的头文件,这些头文件定义了内核中使用的结构体、函数原型、常量等。

2024-01-05 15:41:55 1057

原创 【Linux 内核源码分析】GPIO子系统软件框架

Linux内核的GPIO子系统是用于管理和控制通用输入输出(GPIO)引脚的软件框架。它提供了一套统一的接口和机制,使开发者能够方便地对GPIO进行配置、读写和中断处理。主要组件:GPIO框架:提供了一套API和数据结构,用于在驱动程序中注册和操作GPIO引脚。这包括GPIO的请求、释放、配置以及读写等功能。GPIO控制器驱动:每个具体的硬件平台都需要编写相应的GPIO控制器驱动程序,负责与硬件进行交互,并向上层提供统一的接口。它们通过设备树描述文件来与硬件平台进行绑定。

2024-01-02 22:05:57 826

原创 【Linux 内核源码分析】Linux内核通知链机制

Linux内核通知链(notifier chain)是一种机制,用于实现内核中的事件通知和处理。它提供了一种灵活的方式,让不同的模块可以注册自己感兴趣的事件,并在事件发生时接收到通知。通知链由一个或多个注册在其中的回调函数组成,每个回调函数都有一个优先级。当事件发生时,内核会按照优先级顺序调用相应的回调函数进行处理。开发者可以使用notifier_chain_register()函数向通知链中注册回调函数,使用notifier_call_chain()函数触发对通知链中所有回调函数的调用。

2024-01-02 21:54:54 943

转载 【Linux 内核源码分析】I2C子系统分析 整体框架介绍

内核版本:v4.14。

2023-12-15 22:04:20 86

转载 (Linux内核源码分析)Linux 内核无线子系统

一般 WiFi 驱动包含如下三个部分:配置、发送回调、接收回调。再以 USB WiFi 适配器为例,当内核探测到设备被插入时,会调用 probe 函数。这可能发生在注册配置好的 ieee80211_ops 时。首先, ieee80211_alloc_hw 分配一个 ieee80211_hw 结构体,代表着相应 WiFi 设备。另外,如下的数据结构也会被分配:wiphy 结构:主要用来描述 WiFi 硬件参数(如, MAC 地址、接口模式与组合、支持的波特率以及其他一些硬件功能)。

2023-12-12 22:34:49 164

原创 自下而上-存储全栈(TiDB/RockDB/SPDK/fuse/ceph/NVMe/ext4)存储技术专家成长路线

数字化时代的到来带来了大规模数据的产生,各行各业都面临着数据爆炸的挑战。随着云计算、物联网、人工智能等新兴技术的发展,对存储技术的需求也越来越多样化。不同应用场景对存储的容量、性能、可靠性和成本等方面都有不同的要求。具备存储技术知识和技能的人才更具有竞争力。

2023-12-08 16:55:15 431

原创 Linux C/C++高级全栈开发(后端/游戏/嵌入式/高性能网络/存储/基础架构)

Linux C/C++高级全栈开发是一个涉及到多个领域的综合性技术要求,需要对Linux系统、C/C++编程语言以及各种相关的技术进行深入的理解和应用。下面是一些涵盖的主要技术领域和技能要点:Linux系统基础:熟悉Linux操作系统的原理和常用命令,包括文件系统、进程管理、网络配置等。C/C++编程语言:具备扎实的C/C++编程语言基础,了解常用的编程范式、数据结构和算法,并能熟练运用C/C++进行系统级开发。

2023-11-30 22:15:11 446 1

转载 Linux 内存碎片防治

Linux kernel组织管理物理内存的方式是buddy system(伙伴系统),而物理内存碎片正式buddy system的弱点之一,为了预防以及解决碎片问题,kernel采取了一些实用技术,这里将对这些技术进行总结归纳。

2023-11-28 22:11:35 69

转载 内存模型与memory orde

以上就是我们所有说到的内存模型:SC(完全一致性),TSO(完全存储一致性),PSO(部分存储一致性),RMO(完全宽松),这些都是硬件架构上的不同会带来内存可见性问题,但是除此之外,cpu在执行的时候也会乱序,编译器在编译优化的时候是会对指令做重排的,,也会产生如上的内存模型,所幸c++给我们封装了memory_order,让我们直接忽视硬件-cpu-指令这些运行细节,就只是从内存模型的角度去控制程序的运行;

2023-11-28 16:21:21 69

转载 Kafka如何保证高吞吐量

Kafka把所有的消息存放到一个文件中,当消费者需要数据的时候直接将文件发送给消费者,比如10W的消息共10M,全部发送给消费者,10M的消息在内网中传输是非常快的,假如需要1s,那么kafka的tps就是10w。而Kafka 的做法是保存Consumer在Topic分区中的位置offset,在offset之前的消息是已被“消费”的,在offset之后则为未“消费”的,并且offset是可以任意移动的,这样就消除了大部分的随机IO。压缩的好处就是减少传输的数据量,减轻对网络传输的压力。

2023-11-28 15:16:13 90

原创 Redis的五大数据类型详细用法

我们说 Redis 相对于 Memcache 等其他的缓存产品,有一个比较明显的优势就是 Redis 不仅仅支持简单的key-value类型的数据,同时还提供listsetzsethash等数据结构的存储。本篇博客我们就将介绍这些数据类型的详细使用以及顺带介绍Redis系统的相关命令用法。注意:Redis的命令不区分大小写,但是key 严格区分大小写;redis都是基于key-value形式的;redis不适合存储大数据类型,因为是单线程的,大数据会造成阻塞,浪费时间;

2023-11-27 20:22:50 41

转载 c++ web框架实现之静态反射实现

虽然代码不长,但理解起来还是有点难度的,这种方式实现简单,但有个缺点就是,静态变量的生存周期是初始化到程序结束,也就是说我们注册用到的静态类会在程序的整个周期都存在这个url和类名的映射关系,我们可以让用户写到配置文件里,这样我们来一个请求后,根据请求位置获取处理该业务的类名,然后根据类名创建对象处理业务整体流程就是:请求资源位置 -> 获取类名 -> 创建对象 -> 处理业务。

2023-11-25 21:05:26 92

原创 【FFmpeg视频解码】解码数据结构及函数总结

转载自原文地址:https://www.cnblogs.com/wangguchangqing/p/5744941.html在学习的过程主要参考的是dranger tutorial,所以跟着教程在本文的最后使用SDL2.0将解码后的数据输出到屏幕上。

2023-11-25 15:48:04 79

原创 Linux内核阻塞IO(wait_queue)和非阻塞IO(轮询poll)

等待队列头就是一个等待队列的头部,每个访问设备的进程都是一个队列项,当设备不可用的时候就要将这些进程对应的等待队列项添加到等待队列里面。0x01该宏用于定义并初始化一个名为name的等待队列。name 就是等待队列项的名字,tsk 表示这个等待队列项属于哪个任务(进程),一般设置为current,在 Linux内核中current相当于一个全局变量 , 表当前进程。因此宏DECLARE_WAITQUEUE 就是给当前正在运行的进程创建并初始化了一个等待队列项。NULLNULL。

2023-11-24 21:43:49 87

原创 【FFmpeg实战】FFmpeg的H264解码源码分析:解析器

原文地址:https://www.cnblogs.com/vczf/p/14837759.html解析器主要就是解析出NALU,以及解析一些SPS、PPS等信息,下面分析一下ff_h264_parser。

2023-11-24 21:14:52 99

死锁的检测方案教程(LinuxC/C++)

死锁的检测方案教程(LinuxC/C++)

2022-09-15

C++11 (智能指针、关键字、类型推导、新特性)

c++11 面试题总结 1. 左值引用与右值引用的区别?右值引用的意义? 2. c++11 的智能指针种类以及使用场景? 3. c++11 override,final关键字的作用? 4. c++11 类型推导 5. c++11 用过哪些新特性? (C++后台开发教程)

2022-08-20

Linux内核驱动与应用开发全套学习资料.rar

Linux内核驱动与应用开发全套学习资料

2021-07-02

C/C++Linux设计模式.mp4

C/C++Linux设计模式.mp4

2021-01-30

空空如也

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

TA关注的人

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