H264/AVC 数据分割片和传输

数据分割片

        组成片的编码数据存放在3个独立的DP(数据分割,A、B、C)中,各自包含一个编码片的子集。分割A包含片头和片中每个宏块头数据。分割B包含帧内和SI片宏块的编码残差数据。分割C包含帧间宏块的编码残差数据。每个分割可放在独立的NAL单元并独立传输。

        由A、B和C中的数据可知A是很重要的,即A对传输误差很敏感。解码器可以按着要求仅解码A和B或者A和C,以降低在一定传输条件下的复杂度。


传输

264的编码视频序列包括一系列NAL单元,每个NAL单元包含一个RBSP。NAL的头信息(一个字节)定义了RBSP单元的类型,NAL单元的其余部分则为RBSP数据。RBSP有多种类型,如下所示:

         NAL单元的传输方式会根据不同的传输环境有一定差异。在包传输网络中,每个NAL单元以独立的包传输,在解码之前进行重新排序。在电路交换传输环境中,传输之前必须在每个NAL单元之前加上起始前缀码,使解码器能够找出NAL单元的起始位置。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用H.264/AVC压缩格式对视频流进行压缩,你可以使用FFmpeg库来实现。下面是一个基本的示例,展示了如何使用FFmpeg库对视频流进行压缩: 1. 安装FFmpeg库:首先,确保你已经安装了FFmpeg库。你可以从官方网站下载并按照说明进行安装。 2. 编写C++代码:创建一个C++源文件,并使用以下代码来实现视频流的压缩: ```cpp #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <sstream> #include <fstream> extern "C" { #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h> } int main() { AVFormatContext* inputContext = nullptr; AVFormatContext* outputContext = nullptr; AVCodecContext* codecContext = nullptr; AVStream* stream = nullptr; AVPacket packet; const char* inputFilename = "your_input_video_file"; // 输入视频文件名 const char* outputFilename = "your_output_compressed_video_file.h264"; // 输出压缩后的视频文件名 av_register_all(); // 打开输入视频文件 if (avformat_open_input(&inputContext, inputFilename, nullptr, nullptr) != 0) { std::cerr << "Failed to open input video file!" << std::endl; return -1; } // 获取输入视频流信息 if (avformat_find_stream_info(inputContext, nullptr) < 0) { std::cerr << "Failed to retrieve input video stream information!" << std::endl; return -1; } // 查找视频流 int videoStreamIndex = -1; for (unsigned int i = 0; i < inputContext->nb_streams; i++) { if (inputContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoStreamIndex = i; break; } } if (videoStreamIndex == -1) { std::cerr << "Failed to find video stream in input video file!" << std::endl; return -1; } // 获取视频流编解码器参数 AVCodecParameters* codecParameters = inputContext->streams[videoStreamIndex]->codecpar; // 查找视频流编解码器 AVCodec* codec = avcodec_find_decoder(codecParameters->codec_id); if (codec == nullptr) { std::cerr << "Failed to find video decoder codec!" << std::endl; return -1; } // 创建编解码器上下文 codecContext = avcodec_alloc_context3(codec); if (codecContext == nullptr) { std::cerr << "Failed to allocate video decoder context!" << std::endl; return -1; } // 设置编解码器上下文参数 if (avcodec_parameters_to_context(codecContext, codecParameters) < 0) { std::cerr << "Failed to copy video decoder parameters to context!" << std::endl; return -1; } // 打开视频编解码器 if (avcodec_open2(codecContext, codec, nullptr) < 0) { std::cerr << "Failed to open video decoder!" << std::endl; return -1; } // 创建输出视频文件 if (avformat_alloc_output_context2(&outputContext, nullptr, nullptr, outputFilename) < 0) { std::cerr << "Failed to allocate output video file context!" << std::endl; return -1; } // 添加视频流到输出视频文件 stream = avformat_new_stream(outputContext, codec); if (stream == nullptr) { std::cerr << "Failed to create output video stream!" << std::endl; return -1; } // 复制视频流参数 if (avcodec_parameters_copy(stream->codecpar, codecParameters) < 0) { std::cerr << "Failed to copy video stream parameters!" << std::endl; return -1; } // 打开输出视频文件 if (!(outputContext->oformat->flags & AVFMT_NOFILE)) { if (avio_open(&outputContext->pb, outputFilename, AVIO_FLAG_WRITE) < 0) { std::cerr << "Failed to open output video file!" << std::endl; return -1; } } // 写视频文件头部信息 if (avformat_write_header(outputContext, nullptr) < 0) { std::cerr << "Failed to write output video file header!" << std::endl; return -1; } // 初始化视频帧 AVFrame* frame = av_frame_alloc(); if (frame == nullptr) { std::cerr << "Failed to allocate video frame!" << std::endl; return -1; } int frameNumber = 0; // 逐帧读取输入视频文件并进行压缩 while (av_read_frame(inputContext, &packet) >= 0) { if (packet.stream_index == videoStreamIndex) { // 发送解码器数据包 if (avcodec_send_packet(codecContext, &packet) < 0) { std::cerr << "Failed to send packet to video decoder!" << std::endl; return -1; } // 接收解码器输出帧 int ret = avcodec_receive_frame(codecContext, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { av_packet_unref(&packet); continue; } else if (ret < 0) { std::cerr << "Failed to receive frame from video decoder!" << std::endl; return -1; } // 压缩帧数据 AVPacket compressedPacket; av_init_packet(&compressedPacket); compressedPacket.data = nullptr; compressedPacket.size = 0; if (avcodec_encode_video2(codecContext, &compressedPacket, frame, nullptr) < 0) { std::cerr << "Failed to encode video frame!" << std::endl; return -1; } // 写入压缩后的帧数据到输出视频文件 if (av_write_frame(outputContext, &compressedPacket) < 0) { std::cerr << "Failed to write compressed video frame!" << std::endl; return -1; } av_packet_unref(&compressedPacket); frameNumber++; } av_packet_unref(&packet); } // 写视频文件尾部信息 av_write_trailer(outputContext); // 清理资源 avcodec_free_context(&codecContext); avformat_close_input(&inputContext); avformat_free_context(outputContext); av_frame_free(&frame); return 0; } ``` 请将"your_input_video_file"替换为你想要压缩的输入视频文件的路径,将"your_output_compressed_video_file.h264"替换为你想要保存的压缩后的视频文件路径。 3. 编译和运行:使用C++编译器(如g++)编译源文件,并链接FFmpeg库。 ```bash g++ your_source_file.cpp -o compress_video `pkg-config --cflags --libs libavformat libavcodec libswscale` ``` 然后运行可执行文件: ```bash ./compress_video ``` 这样,程序将读取输入视频文件并使用H.264/AVC压缩格式对视频流进行压缩,并将压缩后的视频保存到输出文件中。 请注意,上述代码仅提供了基本的功能实现,你可能需要根据具体需求进行更复杂的视频处理或参数设置。此外,确保你有适当的权限来读取输入视频文件并保存输出视频文件。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值