|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
/*
|
|
|
|
|
* RTP Theora Protocol |
|
|
|
|
* Xiph RTP Protocols |
|
|
|
|
* Copyright (c) 2010 Josh Allmann |
|
|
|
|
* |
|
|
|
|
* This file is part of FFmpeg. |
|
|
|
@ -20,8 +20,8 @@ |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @file libavformat/rtpdec_theora.c |
|
|
|
|
* @brief Theora / RTP Code |
|
|
|
|
* @file libavformat/rtpdec_xiph.c |
|
|
|
|
* @brief Xiph / RTP Code |
|
|
|
|
* @author Josh Allmann <joshua.allmann@gmail.com> |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
@ -35,7 +35,7 @@ |
|
|
|
|
#include "rtpdec_xiph.h" |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* RTP/Theora specific private data. |
|
|
|
|
* RTP/Xiph specific private data. |
|
|
|
|
*/ |
|
|
|
|
struct PayloadContext { |
|
|
|
|
unsigned ident; ///< 24-bit stream configuration identifier
|
|
|
|
@ -43,7 +43,7 @@ struct PayloadContext { |
|
|
|
|
ByteIOContext* fragment; ///< buffer for split payloads
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static PayloadContext *theora_new_context(void) |
|
|
|
|
static PayloadContext *xiph_new_context(void) |
|
|
|
|
{ |
|
|
|
|
return av_mallocz(sizeof(PayloadContext)); |
|
|
|
|
} |
|
|
|
@ -58,13 +58,13 @@ static inline void free_fragment_if_needed(PayloadContext * data) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void theora_free_context(PayloadContext * data) |
|
|
|
|
static void xiph_free_context(PayloadContext * data) |
|
|
|
|
{ |
|
|
|
|
free_fragment_if_needed(data); |
|
|
|
|
av_free(data); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int theora_handle_packet(AVFormatContext * ctx, |
|
|
|
|
static int xiph_handle_packet(AVFormatContext * ctx, |
|
|
|
|
PayloadContext * data, |
|
|
|
|
AVStream * st, |
|
|
|
|
AVPacket * pkt, |
|
|
|
@ -79,7 +79,7 @@ static int theora_handle_packet(AVFormatContext * ctx, |
|
|
|
|
return AVERROR_INVALIDDATA; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// read theora rtp headers
|
|
|
|
|
// read xiph rtp headers
|
|
|
|
|
ident = AV_RB24(buf); |
|
|
|
|
fragmented = buf[3] >> 6; |
|
|
|
|
tdt = (buf[3] >> 4) & 3; |
|
|
|
@ -95,13 +95,13 @@ static int theora_handle_packet(AVFormatContext * ctx, |
|
|
|
|
|
|
|
|
|
if (ident != data->ident) { |
|
|
|
|
av_log(ctx, AV_LOG_ERROR, |
|
|
|
|
"Unimplemented Theora SDP configuration change detected\n"); |
|
|
|
|
"Unimplemented Xiph SDP configuration change detected\n"); |
|
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (tdt) { |
|
|
|
|
av_log(ctx, AV_LOG_ERROR, |
|
|
|
|
"Unimplemented RTP Theora packet settings (%d,%d,%d)\n", |
|
|
|
|
"Unimplemented RTP Xiph packet settings (%d,%d,%d)\n", |
|
|
|
|
fragmented, tdt, num_pkts); |
|
|
|
|
return AVERROR_PATCHWELCOME; |
|
|
|
|
} |
|
|
|
@ -149,7 +149,7 @@ static int theora_handle_packet(AVFormatContext * ctx, |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
} else if (fragmented == 1) { |
|
|
|
|
// start of theora data fragment
|
|
|
|
|
// start of xiph data fragment
|
|
|
|
|
int res; |
|
|
|
|
|
|
|
|
|
// end packet has been lost somewhere, so drop buffered data
|
|
|
|
@ -175,9 +175,9 @@ static int theora_handle_packet(AVFormatContext * ctx, |
|
|
|
|
put_buffer(data->fragment, buf, pkt_len); |
|
|
|
|
|
|
|
|
|
if (fragmented == 3) { |
|
|
|
|
// end of theora data packet
|
|
|
|
|
uint8_t* theora_data; |
|
|
|
|
int frame_size = url_close_dyn_buf(data->fragment, &theora_data); |
|
|
|
|
// end of xiph data packet
|
|
|
|
|
uint8_t* xiph_data; |
|
|
|
|
int frame_size = url_close_dyn_buf(data->fragment, &xiph_data); |
|
|
|
|
|
|
|
|
|
if (frame_size < 0) { |
|
|
|
|
av_log(ctx, AV_LOG_ERROR, |
|
|
|
@ -190,10 +190,10 @@ static int theora_handle_packet(AVFormatContext * ctx, |
|
|
|
|
return AVERROR_NOMEM; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
memcpy(pkt->data, theora_data, frame_size); |
|
|
|
|
memcpy(pkt->data, xiph_data, frame_size); |
|
|
|
|
pkt->stream_index = st->index; |
|
|
|
|
|
|
|
|
|
av_free(theora_data); |
|
|
|
|
av_free(xiph_data); |
|
|
|
|
data->fragment = NULL; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
@ -226,7 +226,7 @@ static int get_base128(const uint8_t ** buf, const uint8_t * buf_end) |
|
|
|
|
static unsigned int |
|
|
|
|
parse_packed_headers(const uint8_t * packed_headers, |
|
|
|
|
const uint8_t * packed_headers_end, |
|
|
|
|
AVCodecContext * codec, PayloadContext * theora_data) |
|
|
|
|
AVCodecContext * codec, PayloadContext * xiph_data) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
unsigned num_packed, num_headers, length, length1, length2, extradata_alloc; |
|
|
|
@ -240,7 +240,7 @@ parse_packed_headers(const uint8_t * packed_headers, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
num_packed = bytestream_get_be32(&packed_headers); |
|
|
|
|
theora_data->ident = bytestream_get_be24(&packed_headers); |
|
|
|
|
xiph_data->ident = bytestream_get_be24(&packed_headers); |
|
|
|
|
length = bytestream_get_be16(&packed_headers); |
|
|
|
|
num_headers = get_base128(&packed_headers, packed_headers_end); |
|
|
|
|
length1 = get_base128(&packed_headers, packed_headers_end); |
|
|
|
@ -284,8 +284,8 @@ parse_packed_headers(const uint8_t * packed_headers, |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int theora_parse_fmtp_pair(AVCodecContext * codec, |
|
|
|
|
PayloadContext *theora_data, |
|
|
|
|
static int xiph_parse_fmtp_pair(AVCodecContext * codec, |
|
|
|
|
PayloadContext *xiph_data, |
|
|
|
|
char *attr, char *value) |
|
|
|
|
{ |
|
|
|
|
int result = 0; |
|
|
|
@ -325,7 +325,7 @@ static int theora_parse_fmtp_pair(AVCodecContext * codec, |
|
|
|
|
|
|
|
|
|
result = parse_packed_headers |
|
|
|
|
(decoded_packet, decoded_packet + packet_size, codec, |
|
|
|
|
theora_data); |
|
|
|
|
xiph_data); |
|
|
|
|
} else { |
|
|
|
|
av_log(codec, AV_LOG_ERROR, |
|
|
|
|
"Out of memory while decoding SDP configuration.\n"); |
|
|
|
@ -340,7 +340,7 @@ static int theora_parse_fmtp_pair(AVCodecContext * codec, |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int theora_parse_sdp_line(AVFormatContext *s, int st_index, |
|
|
|
|
static int xiph_parse_sdp_line(AVFormatContext *s, int st_index, |
|
|
|
|
PayloadContext *data, const char *line) |
|
|
|
|
{ |
|
|
|
|
const char *p; |
|
|
|
@ -366,7 +366,7 @@ static int theora_parse_sdp_line(AVFormatContext *s, int st_index, |
|
|
|
|
while (ff_rtsp_next_attr_and_value(&p, |
|
|
|
|
attr, attr_size, |
|
|
|
|
value, value_size)) { |
|
|
|
|
res = theora_parse_fmtp_pair(codec, data, attr, value); |
|
|
|
|
res = xiph_parse_fmtp_pair(codec, data, attr, value); |
|
|
|
|
if (res < 0 && res != AVERROR_PATCHWELCOME) |
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
@ -380,8 +380,8 @@ RTPDynamicProtocolHandler ff_theora_dynamic_handler = { |
|
|
|
|
.enc_name = "theora", |
|
|
|
|
.codec_type = AVMEDIA_TYPE_VIDEO, |
|
|
|
|
.codec_id = CODEC_ID_THEORA, |
|
|
|
|
.parse_sdp_a_line = theora_parse_sdp_line, |
|
|
|
|
.open = theora_new_context, |
|
|
|
|
.close = theora_free_context, |
|
|
|
|
.parse_packet = theora_handle_packet |
|
|
|
|
.parse_sdp_a_line = xiph_parse_sdp_line, |
|
|
|
|
.open = xiph_new_context, |
|
|
|
|
.close = xiph_free_context, |
|
|
|
|
.parse_packet = xiph_handle_packet |
|
|
|
|
}; |
|
|
|
|