This source file includes following definitions.
- h261_close_context
- h261_handle_packet
#include "libavcodec/get_bits.h"
#include "avformat.h"
#include "avio_internal.h"
#include "rtpdec_formats.h"
#define RTP_H261_PAYLOAD_HEADER_SIZE 4
struct PayloadContext {
AVIOContext *buf;
uint8_t endbyte;
int endbyte_bits;
uint32_t timestamp;
};
static av_cold void h261_close_context(PayloadContext *pl_ctx)
{
if (!pl_ctx)
return;
ffio_free_dyn_buf(&pl_ctx->buf);
}
static int h261_handle_packet(AVFormatContext *ctx, PayloadContext *rtp_h261_ctx,
AVStream *st, AVPacket *pkt, uint32_t *timestamp,
const uint8_t *buf, int len, uint16_t seq,
int flags)
{
int sbit, ebit, gobn, mbap, quant;
int res;
if (rtp_h261_ctx->buf && rtp_h261_ctx->timestamp != *timestamp) {
ffio_free_dyn_buf(&rtp_h261_ctx->buf);
rtp_h261_ctx->endbyte_bits = 0;
}
if (len < RTP_H261_PAYLOAD_HEADER_SIZE + 1) {
av_log(ctx, AV_LOG_ERROR, "Too short RTP/H.261 packet, got %d bytes\n", len);
return AVERROR_INVALIDDATA;
}
sbit = (buf[0] >> 5) & 0x07;
ebit = (buf[0] >> 2) & 0x07;
gobn = (buf[1] >> 4) & 0x0f;
mbap = ((buf[1] << 1) & 0x1e) | ((buf[2] >> 7) & 0x01);
quant = (buf[2] >> 2) & 0x1f;
buf += RTP_H261_PAYLOAD_HEADER_SIZE;
len -= RTP_H261_PAYLOAD_HEADER_SIZE;
if (!rtp_h261_ctx->buf) {
if (!gobn && !sbit && !mbap && !quant) {
res = avio_open_dyn_buf(&rtp_h261_ctx->buf);
if (res < 0)
return res;
rtp_h261_ctx->timestamp = *timestamp;
} else {
return AVERROR(EAGAIN);
}
}
if (rtp_h261_ctx->endbyte_bits || sbit) {
if (rtp_h261_ctx->endbyte_bits == sbit) {
rtp_h261_ctx->endbyte |= buf[0] & (0xff >> sbit);
rtp_h261_ctx->endbyte_bits = 0;
buf++;
len--;
avio_w8(rtp_h261_ctx->buf, rtp_h261_ctx->endbyte);
} else {
GetBitContext gb;
init_get_bits(&gb, buf, len*8 - ebit);
skip_bits(&gb, sbit);
if (rtp_h261_ctx->endbyte_bits) {
rtp_h261_ctx->endbyte |= get_bits(&gb, 8 - rtp_h261_ctx->endbyte_bits);
avio_w8(rtp_h261_ctx->buf, rtp_h261_ctx->endbyte);
}
while (get_bits_left(&gb) >= 8)
avio_w8(rtp_h261_ctx->buf, get_bits(&gb, 8));
rtp_h261_ctx->endbyte_bits = get_bits_left(&gb);
if (rtp_h261_ctx->endbyte_bits)
rtp_h261_ctx->endbyte = get_bits(&gb, rtp_h261_ctx->endbyte_bits) <<
(8 - rtp_h261_ctx->endbyte_bits);
ebit = 0;
len = 0;
}
}
if (ebit) {
if (len > 0)
avio_write(rtp_h261_ctx->buf, buf, len - 1);
rtp_h261_ctx->endbyte_bits = 8 - ebit;
rtp_h261_ctx->endbyte = buf[len - 1] & (0xff << ebit);
} else {
avio_write(rtp_h261_ctx->buf, buf, len);
}
if (!(flags & RTP_FLAG_MARKER))
return AVERROR(EAGAIN);
if (rtp_h261_ctx->endbyte_bits)
avio_w8(rtp_h261_ctx->buf, rtp_h261_ctx->endbyte);
rtp_h261_ctx->endbyte_bits = 0;
res = ff_rtp_finalize_packet(pkt, &rtp_h261_ctx->buf, st->index);
if (res < 0)
return res;
return 0;
}
const RTPDynamicProtocolHandler ff_h261_dynamic_handler = {
.enc_name = "H261",
.codec_type = AVMEDIA_TYPE_VIDEO,
.codec_id = AV_CODEC_ID_H261,
.need_parsing = AVSTREAM_PARSE_FULL,
.priv_data_size = sizeof(PayloadContext),
.close = h261_close_context,
.parse_packet = h261_handle_packet,
.static_payload_id = 31,
};