summaryrefslogtreecommitdiff
path: root/libavformat
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2012-10-09 13:06:04 +0200
committerMichael Niedermayer <michaelni@gmx.at>2012-10-09 13:06:04 +0200
commitef9fe5bedd1993700818a0ba1c195cd6f6668afe (patch)
tree3c70bf61e4bae16375575e3e6e8dac55fc1ba148 /libavformat
parent238e904df3988ea0253ba08c8b2883e4740565b6 (diff)
parenta75b9a1804769169456306f570b6716d977ebdc5 (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: mingw/cygwin: Stop adding -fno-common to gcc CFLAGS Restructure av_log_missing_feature message rtp: Support packetization/depacketization of opus file: Set the return value type for lseek to int64_t. ppc: fix Altivec build with old compilers build: add LTO support for PGI compiler build: add -Mdse to PGI optimisation flags rtpenc_vp8: Update the packetizer to the latest spec version rtpdec_vp8: Make the depacketizer implement the latest spec draft doc: allow building with old texi2html versions avutil: skip old_pix_fmts.h since it is just a list Conflicts: libavcodec/aacdec.c libavcodec/h264.c libavcodec/ppc/fmtconvert_altivec.c libavcodec/utils.c libavformat/file.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-rw-r--r--libavformat/file.c2
-rw-r--r--libavformat/oggparseskeleton.c4
-rw-r--r--libavformat/rtpdec.c7
-rw-r--r--libavformat/rtpdec_vp8.c117
-rw-r--r--libavformat/rtpenc.c23
-rw-r--r--libavformat/rtpenc_vp8.c6
-rw-r--r--libavformat/sdp.c4
7 files changed, 101 insertions, 62 deletions
diff --git a/libavformat/file.c b/libavformat/file.c
index 8c41a3c372..209957b9d3 100644
--- a/libavformat/file.c
+++ b/libavformat/file.c
@@ -135,7 +135,7 @@ static int file_open(URLContext *h, const char *filename, int flags)
static int64_t file_seek(URLContext *h, int64_t pos, int whence)
{
FileContext *c = h->priv_data;
- off_t ret;
+ int64_t ret;
if (whence == AVSEEK_SIZE) {
struct stat st;
diff --git a/libavformat/oggparseskeleton.c b/libavformat/oggparseskeleton.c
index 4b02c838f2..d819e0efb1 100644
--- a/libavformat/oggparseskeleton.c
+++ b/libavformat/oggparseskeleton.c
@@ -75,8 +75,8 @@ static int skeleton_header(AVFormatContext *s, int idx)
target_idx = ogg_find_stream(ogg, AV_RL32(buf+12));
start_granule = AV_RL64(buf+36);
if (os->start_granule != OGG_NOGRANULE_VALUE) {
- av_log_missing_feature(s, "multiple fisbone for the "
- "same stream\n", 0);
+ av_log_missing_feature(s,
+ "multiple fisbone for the same stream", 0);
return 1;
}
if (target_idx >= 0 && start_granule != OGG_NOGRANULE_VALUE) {
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index e044435332..a90f0051c0 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -55,6 +55,12 @@ static RTPDynamicProtocolHandler speex_dynamic_handler = {
.codec_id = AV_CODEC_ID_SPEEX,
};
+static RTPDynamicProtocolHandler opus_dynamic_handler = {
+ .enc_name = "opus",
+ .codec_type = AVMEDIA_TYPE_AUDIO,
+ .codec_id = AV_CODEC_ID_OPUS,
+};
+
/* statistics functions */
static RTPDynamicProtocolHandler *RTPFirstDynamicPayloadHandler= NULL;
@@ -85,6 +91,7 @@ void av_register_rtp_dynamic_payload_handlers(void)
ff_register_dynamic_payload_handler(&ff_qcelp_dynamic_handler);
ff_register_dynamic_payload_handler(&realmedia_mp3_dynamic_handler);
ff_register_dynamic_payload_handler(&speex_dynamic_handler);
+ ff_register_dynamic_payload_handler(&opus_dynamic_handler);
ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler);
ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler);
diff --git a/libavformat/rtpdec_vp8.c b/libavformat/rtpdec_vp8.c
index e24bbb6a6f..aef5f78132 100644
--- a/libavformat/rtpdec_vp8.c
+++ b/libavformat/rtpdec_vp8.c
@@ -1,6 +1,7 @@
/*
* RTP VP8 Depacketizer
* Copyright (c) 2010 Josh Allmann
+ * Copyright (c) 2012 Martin Storsjo
*
* This file is part of FFmpeg.
*
@@ -23,7 +24,7 @@
* @file
* @brief RTP support for the VP8 payload
* @author Josh Allmann <joshua.allmann@gmail.com>
- * @see http://www.webmproject.org/code/specs/rtp/
+ * @see http://tools.ietf.org/html/draft-ietf-payload-vp8-05
*/
#include "libavcodec/bytestream.h"
@@ -33,14 +34,12 @@
struct PayloadContext {
AVIOContext *data;
uint32_t timestamp;
- int is_keyframe;
};
static void prepare_packet(AVPacket *pkt, PayloadContext *vp8, int stream)
{
av_init_packet(pkt);
pkt->stream_index = stream;
- pkt->flags = vp8->is_keyframe ? AV_PKT_FLAG_KEY : 0;
pkt->size = avio_close_dyn_buf(vp8->data, &pkt->data);
pkt->destruct = av_destruct_packet;
vp8->data = NULL;
@@ -54,70 +53,84 @@ static int vp8_handle_packet(AVFormatContext *ctx,
const uint8_t *buf,
int len, int flags)
{
- int start_packet, end_packet, has_au, ret = AVERROR(EAGAIN);
-
- if (!buf) {
- // only called when vp8_handle_packet returns 1
- if (!vp8->data) {
- av_log(ctx, AV_LOG_ERROR, "Invalid VP8 data passed\n");
+ int start_partition, end_packet;
+ int extended_bits, non_ref, part_id;
+ int pictureid_present = 0, tl0picidx_present = 0, tid_present = 0,
+ keyidx_present = 0;
+ int pictureid = -1, keyidx = -1;
+
+ if (len < 1)
+ return AVERROR_INVALIDDATA;
+
+ extended_bits = buf[0] & 0x80;
+ non_ref = buf[0] & 0x20;
+ start_partition = buf[0] & 0x10;
+ part_id = buf[0] & 0x0f;
+ end_packet = flags & RTP_FLAG_MARKER;
+ buf++;
+ len--;
+ if (extended_bits) {
+ if (len < 1)
return AVERROR_INVALIDDATA;
+ pictureid_present = buf[0] & 0x80;
+ tl0picidx_present = buf[0] & 0x40;
+ tid_present = buf[0] & 0x20;
+ keyidx_present = buf[0] & 0x10;
+ buf++;
+ len--;
+ }
+ if (pictureid_present) {
+ if (len < 1)
+ return AVERROR_INVALIDDATA;
+ if (buf[0] & 0x80) {
+ if (len < 2)
+ return AVERROR_INVALIDDATA;
+ pictureid = AV_RB16(buf) & 0x7fff;
+ buf += 2;
+ len -= 2;
+ } else {
+ pictureid = buf[0] & 0x7f;
+ buf++;
+ len--;
}
- prepare_packet(pkt, vp8, st->index);
- *timestamp = vp8->timestamp;
- return 0;
}
+ if (tl0picidx_present) {
+ // Ignoring temporal level zero index
+ buf++;
+ len--;
+ }
+ if (tid_present || keyidx_present) {
+ // Ignoring temporal layer index and layer sync bit
+ if (len < 1)
+ return AVERROR_INVALIDDATA;
+ if (keyidx_present)
+ keyidx = buf[0] & 0x1f;
+ buf++;
+ len--;
+ }
+ if (len < 1)
+ return AVERROR_INVALIDDATA;
- start_packet = *buf & 1;
- end_packet = flags & RTP_FLAG_MARKER;
- has_au = *buf & 2;
- buf++;
- len--;
-
- if (start_packet) {
+ if (start_partition && part_id == 0) {
int res;
- uint32_t ts = *timestamp;
if (vp8->data) {
- // missing end marker; return old frame anyway. untested
- prepare_packet(pkt, vp8, st->index);
- *timestamp = vp8->timestamp; // reset timestamp from old frame
-
- // if current frame fits into one rtp packet, need to hold
- // that for the next av_get_packet call
- ret = end_packet ? 1 : 0;
+ uint8_t *tmp;
+ avio_close_dyn_buf(vp8->data, &tmp);
+ av_free(tmp);
+ vp8->data = NULL;
}
if ((res = avio_open_dyn_buf(&vp8->data)) < 0)
return res;
- vp8->is_keyframe = *buf & 1;
- vp8->timestamp = ts;
+ vp8->timestamp = *timestamp;
}
- if (!vp8->data || vp8->timestamp != *timestamp && ret == AVERROR(EAGAIN)) {
+ if (!vp8->data || vp8->timestamp != *timestamp) {
av_log(ctx, AV_LOG_WARNING,
"Received no start marker; dropping frame\n");
return AVERROR(EAGAIN);
}
- // cycle through VP8AU headers if needed
- // not tested with actual VP8AUs
- while (len) {
- int au_len = len;
- if (has_au && len > 2) {
- au_len = AV_RB16(buf);
- buf += 2;
- len -= 2;
- if (buf + au_len > buf + len) {
- av_log(ctx, AV_LOG_ERROR, "Invalid VP8AU length\n");
- return AVERROR_INVALIDDATA;
- }
- }
-
- avio_write(vp8->data, buf, au_len);
- buf += au_len;
- len -= au_len;
- }
-
- if (ret != AVERROR(EAGAIN)) // did we miss a end marker?
- return ret;
+ avio_write(vp8->data, buf, len);
if (end_packet) {
prepare_packet(pkt, vp8, st->index);
@@ -129,8 +142,6 @@ static int vp8_handle_packet(AVFormatContext *ctx,
static PayloadContext *vp8_new_context(void)
{
- av_log(NULL, AV_LOG_ERROR, "RTP VP8 payload implementation is incompatible "
- "with the latest spec drafts.\n");
return av_mallocz(sizeof(PayloadContext));
}
diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
index ea678a6792..3a5bbeb398 100644
--- a/libavformat/rtpenc.c
+++ b/libavformat/rtpenc.c
@@ -77,6 +77,7 @@ static int is_supported(enum AVCodecID id)
case AV_CODEC_ID_ILBC:
case AV_CODEC_ID_MJPEG:
case AV_CODEC_ID_SPEEX:
+ case AV_CODEC_ID_OPUS:
return 1;
default:
return 0;
@@ -181,15 +182,21 @@ static int rtp_write_header(AVFormatContext *s1)
s->max_payload_size -= 6; // ident+frag+tdt/vdt+pkt_num+pkt_length
s->num_frames = 0;
goto defaultcase;
- case AV_CODEC_ID_VP8:
- av_log(s1, AV_LOG_ERROR, "RTP VP8 payload implementation is "
- "incompatible with the latest spec drafts.\n");
- break;
case AV_CODEC_ID_ADPCM_G722:
/* Due to a historical error, the clock rate for G722 in RTP is
* 8000, even if the sample rate is 16000. See RFC 3551. */
avpriv_set_pts_info(st, 32, 1, 8000);
break;
+ case AV_CODEC_ID_OPUS:
+ if (st->codec->channels > 2) {
+ av_log(s1, AV_LOG_ERROR, "Multistream opus not supported in RTP\n");
+ goto fail;
+ }
+ /* The opus RTP RFC says that all opus streams should use 48000 Hz
+ * as clock rate, since all opus sample rates can be expressed in
+ * this clock rate, and sample rate changes on the fly are supported. */
+ avpriv_set_pts_info(st, 32, 1, 48000);
+ break;
case AV_CODEC_ID_ILBC:
if (st->codec->block_align != 38 && st->codec->block_align != 50) {
av_log(s1, AV_LOG_ERROR, "Incorrect iLBC block size specified\n");
@@ -529,6 +536,14 @@ static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
case AV_CODEC_ID_MJPEG:
ff_rtp_send_jpeg(s1, pkt->data, size);
break;
+ case AV_CODEC_ID_OPUS:
+ if (size > s->max_payload_size) {
+ av_log(s1, AV_LOG_ERROR,
+ "Packet size %d too large for max RTP payload size %d\n",
+ size, s->max_payload_size);
+ return AVERROR(EINVAL);
+ }
+ /* Intentional fallthrough */
default:
/* better than nothing : send the codec raw data */
rtp_send_raw(s1, pkt->data, size);
diff --git a/libavformat/rtpenc_vp8.c b/libavformat/rtpenc_vp8.c
index e865514cef..d16e6764c9 100644
--- a/libavformat/rtpenc_vp8.c
+++ b/libavformat/rtpenc_vp8.c
@@ -22,7 +22,7 @@
#include "rtpenc.h"
/* Based on a draft spec for VP8 RTP.
- * ( http://www.webmproject.org/code/specs/rtp/ ) */
+ * ( http://tools.ietf.org/html/draft-ietf-payload-vp8-05 ) */
void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buf, int size)
{
RTPMuxContext *s = s1->priv_data;
@@ -32,7 +32,9 @@ void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buf, int size)
s->timestamp = s->cur_timestamp;
max_packet_size = s->max_payload_size - 1; // minus one for header byte
- *s->buf_ptr++ = 1; // 0b1 indicates start of frame
+ // no extended control bits, reference frame, start of partition,
+ // partition id 0
+ *s->buf_ptr++ = 0x10;
while (size > 0) {
len = FFMIN(size, max_packet_size);
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index 9a4dec4bb2..ca8c3dfdb7 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -576,6 +576,10 @@ static char *sdp_write_media_attributes(char *buff, int size, AVCodecContext *c,
av_strlcatf(buff, size, "a=rtpmap:%d speex/%d\r\n",
payload_type, c->sample_rate);
break;
+ case AV_CODEC_ID_OPUS:
+ av_strlcatf(buff, size, "a=rtpmap:%d opus/48000\r\n",
+ payload_type);
+ break;
default:
/* Nothing special to do here... */
break;