diff options
author | Michael Niedermayer <michaelni@gmx.at> | 2012-10-09 13:06:04 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2012-10-09 13:06:04 +0200 |
commit | ef9fe5bedd1993700818a0ba1c195cd6f6668afe (patch) | |
tree | 3c70bf61e4bae16375575e3e6e8dac55fc1ba148 /libavformat | |
parent | 238e904df3988ea0253ba08c8b2883e4740565b6 (diff) | |
parent | a75b9a1804769169456306f570b6716d977ebdc5 (diff) | |
download | ffmpeg-ef9fe5bedd1993700818a0ba1c195cd6f6668afe.tar.gz |
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.c | 2 | ||||
-rw-r--r-- | libavformat/oggparseskeleton.c | 4 | ||||
-rw-r--r-- | libavformat/rtpdec.c | 7 | ||||
-rw-r--r-- | libavformat/rtpdec_vp8.c | 117 | ||||
-rw-r--r-- | libavformat/rtpenc.c | 23 | ||||
-rw-r--r-- | libavformat/rtpenc_vp8.c | 6 | ||||
-rw-r--r-- | libavformat/sdp.c | 4 |
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; |