• 音视频的Buffer处理


    最近在做安卓下UVC的一个案子。正好之前搞过ST方案的开机广告,这个也是我少数最后没搞成功的项目。当时也有点客观原因,当时ST要退出机顶盒市场,所以一切的支持都停了,当时啃他家播放器几十万行的代码,而且几乎没有文档,真的是非常痛苦。后面虽然功能是搞出来了,但是不稳定,持续几次后就会crash。

    还记得当时最后到底层ST是用的滑动窗口缓存,双指针,一个写指针和一个读指针,当时我做了一个管道往缓存中注数据。估计还是没有完全吃透,某些细节处理有问题。正好现在又做到类似项目,所以简单总结总结相关要点。主要就是共享内存,滑动窗口,双缓冲,环形缓冲这些内容。

    下面是一个简单的具有读写指针的循环缓冲区。

    1. #include <iostream>
    2. #include <vector>
    3. #include <stdexcept>
    4. template<typename T>
    5. class MediaQueue {
    6. public:
    7. explicit MediaQueue(size_t size)
    8. : buffer(size), readPtr(0), writePtr(0), count(0), maxSize(size) {}
    9. // 添加一个元素到队列中
    10. void enqueue(const T& item) {
    11. if (isFull()) {
    12. throw std::overflow_error("Queue is full");
    13. }
    14. buffer[writePtr] = item;
    15. writePtr = (writePtr + 1) % maxSize;
    16. ++count;
    17. }
    18. // 从队列中读取一个元素
    19. T dequeue() {
    20. if (isEmpty()) {
    21. throw std::underflow_error("Queue is empty");
    22. }
    23. T item = buffer[readPtr];
    24. readPtr = (readPtr + 1) % maxSize;
    25. --count;
    26. return item;
    27. }
    28. // 检查队列是否为空
    29. bool isEmpty() const {
    30. return count == 0;
    31. }
    32. // 检查队列是否已满
    33. bool isFull() const {
    34. return count == maxSize;
    35. }
    36. // 获取队列中的元素数量
    37. size_t size() const {
    38. return count;
    39. }
    40. // 获取队列的最大容量
    41. size_t capacity() const {
    42. return maxSize;
    43. }
    44. private:
    45. std::vector<T> buffer;
    46. size_t readPtr;
    47. size_t writePtr;
    48. size_t count;
    49. size_t maxSize;
    50. };

    还有一种叫做乒乓buffer

    就是两个buffer,一个读一个写,写完之后交换。

    1. #include <iostream>
    2. #include <vector>
    3. #include <thread>
    4. #include <mutex>
    5. #include <condition_variable>
    6. #include <cstring> // For memcpy
    7. #include <chrono> // For sleep
    8. class PingPongBuffer {
    9. public:
    10. PingPongBuffer(size_t bufferSize)
    11. : bufferSize(bufferSize), readBufferIndex(0), writeBufferIndex(1), buffers(2, std::vector<char>(bufferSize)) {}
    12. // 写入数据到当前写缓冲区
    13. void write(const char* data, size_t size) {
    14. std::unique_lock<std::mutex> lock(mutex);
    15. while (writeBufferFull) {
    16. condVar.wait(lock);
    17. }
    18. if (size > bufferSize) {
    19. throw std::overflow_error("Data size exceeds buffer capacity");
    20. }
    21. std::memcpy(buffers[writeBufferIndex].data(), data, size);
    22. writeBufferFull = true;
    23. readBufferEmpty = false;
    24. swapBuffers();
    25. condVar.notify_all();
    26. }
    27. // 从当前读缓冲区读取数据
    28. void read(char* data, size_t size) {
    29. std::unique_lock<std::mutex> lock(mutex);
    30. while (readBufferEmpty) {
    31. condVar.wait(lock);
    32. }
    33. if (size > bufferSize) {
    34. throw std::underflow_error("Data size exceeds buffer capacity");
    35. }
    36. std::memcpy(data, buffers[readBufferIndex].data(), size);
    37. readBufferEmpty = true;
    38. writeBufferFull = false;
    39. condVar.notify_all();
    40. }
    41. private:
    42. void swapBuffers() {
    43. std::swap(readBufferIndex, writeBufferIndex);
    44. }
    45. size_t bufferSize;
    46. int readBufferIndex;
    47. int writeBufferIndex;
    48. std::vector<std::vector<char>> buffers;
    49. bool readBufferEmpty = true;
    50. bool writeBufferFull = false;
    51. std::mutex mutex;
    52. std::condition_variable condVar;
    53. };
    54. void producer(PingPongBuffer& buffer) {
    55. const char* messages[] = {"Message 1", "Message 2", "Message 3"};
    56. for (const char* message : messages) {
    57. std::this_thread::sleep_for(std::chrono::seconds(1)); // Simulate work
    58. buffer.write(message, std::strlen(message) + 1);
    59. std::cout << "Produced: " << message << std::endl;
    60. }
    61. }
    62. void consumer(PingPongBuffer& buffer) {
    63. char data[1024];
    64. for (int i = 0; i < 3; ++i) {
    65. buffer.read(data, 1024);
    66. std::cout << "Consumed: " << data << std::endl;
    67. }
    68. }
    69. int main() {
    70. size_t bufferSize = 1024;
    71. PingPongBuffer buffer(bufferSize);
    72. std::thread producerThread(producer, std::ref(buffer));
    73. std::thread consumerThread(consumer, std::ref(buffer));
    74. producerThread.join();
    75. consumerThread.join();
    76. return 0;
    77. }

    空了有时间看看V4L2和ffmpeg这方面的内容再更新一下吧。。。

  • 相关阅读:
    【无标题】
    I-o-C 一篇概览
    Pycharm 配置python项目本地运行环境
    返回二叉树中两个节点的最低公共祖先
    Ubuntu18.04遇到的nodejs的坑记录
    [Spring MVC 8]高并发实战小Demo
    Unity学习笔记---材质纹理&天空盒
    21 移动网络的前世今生
    网络层解析——IP协议、地址管理、路由选择
    ros2与windows入门教程-控制小乌龟
  • 原文地址:https://blog.csdn.net/fanged/article/details/139831572