ffmpeg 中 rtsp相关源码解析(五)

<<ffmpeg 中 rtsp相关源码解析(四)>> 

简单介绍了rtp包是通过ff_rtsp_fetch_packet来获取的

我们更深入地问一个问题,那么对于vp8 、h264等音视频编解码标准,这些packet又是如何处理的呢?

这边就涉及一个非常重要的结构体

RTPDynamicProtocolHandler

位于rtpdec.h文件中定义如下

struct RTPDynamicProtocolHandler {
    const char *enc_name;
    enum AVMediaType codec_type;
    enum AVCodecID codec_id;
    enum AVStreamParseType need_parsing;
    int static_payload_id; /* 0 means no payload id is set. 0 is a valid
                            * payload ID (PCMU), too, but that format doesn't
                            * require any custom depacketization code. */
    int priv_data_size;

    /** Initialize dynamic protocol handler, called after the full rtpmap line is parsed, may be null */
    int (*init)(AVFormatContext *s, int st_index, PayloadContext *priv_data);
    /** Parse the a= line from the sdp field */
    int (*parse_sdp_a_line)(AVFormatContext *s, int st_index,
                            PayloadContext *priv_data, const char *line);
    /** Free any data needed by the rtp parsing for this dynamic data.
      * Don't free the protocol_data pointer itself, that is freed by the
      * caller. This is called even if the init method failed. */
    void (*close)(PayloadContext *protocol_data);
    /** Parse handler for this dynamic packet */
    DynamicPayloadPacketHandlerProc parse_packet;
    int (*need_keyframe)(PayloadContext *context);

    struct RTPDynamicProtocolHandler *next;
};

其中DynamicPayloadPacketHandlerProc parse_packet; 就是我们关注的解析包的方法

以h264协议为例,ffmpeg 在 rtpdec_h264.c中定义了ff_h264_dynamic_handler,并且在rtpdec.c 中

通过ff_register_dynamic_payload_handler(&ff_h264_dynamic_handler);注册了这个handler

RTPDynamicProtocolHandler ff_h264_dynamic_handler = {
    .enc_name         = "H264",
    .codec_type       = AVMEDIA_TYPE_VIDEO,
    .codec_id         = AV_CODEC_ID_H264,
    .need_parsing     = AVSTREAM_PARSE_FULL,
    .priv_data_size   = sizeof(PayloadContext),
    .parse_sdp_a_line = parse_h264_sdp_line,
    .close            = h264_close_context,
    .parse_packet     = h264_handle_packet,
};

 

而它的调用方式如下

如果有buffer

ff_rtsp_fetch_packet ---> ff_rtp_parse_packet  ----> rtp_parse_one_packet ---> rtp_parse_packet_internal ---> parse_packet 

如果没有buffer

ff_rtsp_fetch_packet ---> ff_rtp_parse_packet  ----> rtp_parse_one_packet  ---> parse_packet 

 

 

                                                                                                                                                 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FFmpeg是一个用于处理多媒体数据的开源库,它支持多种音视频格式的解析、转换和处理。其FFmpeg可以通过RTSP协议来解析实时流媒体数据。 使用FFmpeg解析RTSP流的基本步骤如下: 1. 初始化FFmpeg库和网络模块。 2. 打开RTSP流地址,获取AVFormatContext对象。 3. 找到音视频流的索引,获取AVStream对象。 4. 解码音视频流,获取AVPacket对象。 5. 对AVPacket进行解码,获取AVFrame对象。 6. 对AVFrame进行处理或者编码成其他格式。 具体来说,可以通过如下的代码来解析RTSP流: ```c // 初始化FFmpeg库和网络模块 av_register_all(); avformat_network_init(); // 打开RTSP流地址,获取AVFormatContext对象 AVFormatContext *pFormatCtx = avformat_alloc_context(); if (avformat_open_input(&pFormatCtx, "rtsp://xxx.xxx.xxx.xxx:xxxx/xxx", NULL, NULL) != 0) { printf("Could not open input stream.\n"); return -1; } // 找到音视频流的索引,获取AVStream对象 if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { printf("Could not find stream information.\n"); return -1; for (int i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO) { audioStream = i; } else if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; } } if (audioStream == -1 || videoStream == -1) { printf("Could not find audio or video stream.\n"); return -1; } // 解码音视频流,获取AVPacket对象 AVPacket *packet = av_packet_alloc(); AVFrame *frame = av_frame_alloc(); while (av_read_frame(pFormatCtx, packet) >= 0) { if (packet->stream_index == audioStream || packet->stream_index == videoStream) { // 对AVPacket进行解码,获取AVFrame对象 int ret = avcodec_send_packet(pCodecCtx, packet); if (ret < 0) { printf("Error sending a packet for decoding.\n"); break; } while (ret >= 0) { ret = avcodec_receive_frame(pCodecCtx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { printf("Error during decoding.\n"); break; } // 对AVFrame进行处理或者编码成其他格式 } } av_packet_unref(packet); } // 释放资源 av_frame_free(&frame); av_packet_free(&packet); avcodec_close(pCodecCtx); avformat_close_input(&pFormatCtx); ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值