diff options
author | Andras Becsi <andras.becsi@digia.com> | 2013-12-11 21:33:03 +0100 |
---|---|---|
committer | Andras Becsi <andras.becsi@digia.com> | 2013-12-13 12:34:07 +0100 |
commit | f2a33ff9cbc6d19943f1c7fbddd1f23d23975577 (patch) | |
tree | 0586a32aa390ade8557dfd6b4897f43a07449578 /chromium/third_party/ffmpeg/libavformat | |
parent | 5362912cdb5eea702b68ebe23702468d17c3017a (diff) | |
download | qtwebengine-chromium-f2a33ff9cbc6d19943f1c7fbddd1f23d23975577.tar.gz |
Update Chromium to branch 1650 (31.0.1650.63)
Change-Id: I57d8c832eaec1eb2364e0a8e7352a6dd354db99f
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'chromium/third_party/ffmpeg/libavformat')
206 files changed, 9760 insertions, 4925 deletions
diff --git a/chromium/third_party/ffmpeg/libavformat/4xm.c b/chromium/third_party/ffmpeg/libavformat/4xm.c index 1e142f550f2..3714297dae3 100644 --- a/chromium/third_party/ffmpeg/libavformat/4xm.c +++ b/chromium/third_party/ffmpeg/libavformat/4xm.c @@ -57,7 +57,7 @@ #define GET_LIST_HEADER() \ fourcc_tag = avio_rl32(pb); \ - size = avio_rl32(pb); \ + size = avio_rl32(pb); \ if (fourcc_tag != LIST_TAG) \ return AVERROR_INVALIDDATA; \ fourcc_tag = avio_rl32(pb); @@ -72,8 +72,6 @@ typedef struct AudioTrack { } AudioTrack; typedef struct FourxmDemuxContext { - int width; - int height; int video_stream_index; int track_count; AudioTrack *tracks; @@ -91,6 +89,107 @@ static int fourxm_probe(AVProbeData *p) return AVPROBE_SCORE_MAX; } +static int parse_vtrk(AVFormatContext *s, + FourxmDemuxContext *fourxm, uint8_t *buf, int size, + int left) +{ + AVStream *st; + /* check that there is enough data */ + if (size != vtrk_SIZE || left < size + 8) { + return AVERROR_INVALIDDATA; + } + + /* allocate a new AVStream */ + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + avpriv_set_pts_info(st, 60, 1, fourxm->fps); + + fourxm->video_stream_index = st->index; + + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = AV_CODEC_ID_4XM; + st->codec->extradata_size = 4; + st->codec->extradata = av_malloc(4); + AV_WL32(st->codec->extradata, AV_RL32(buf + 16)); + st->codec->width = AV_RL32(buf + 36); + st->codec->height = AV_RL32(buf + 40); + + return 0; +} + + +static int parse_strk(AVFormatContext *s, + FourxmDemuxContext *fourxm, uint8_t *buf, int size, + int left) +{ + AVStream *st; + int track; + /* check that there is enough data */ + if (size != strk_SIZE || left < size + 8) + return AVERROR_INVALIDDATA; + + track = AV_RL32(buf + 8); + if ((unsigned)track >= UINT_MAX / sizeof(AudioTrack) - 1) { + av_log(s, AV_LOG_ERROR, "current_track too large\n"); + return AVERROR_INVALIDDATA; + } + if (track + 1 > fourxm->track_count) { + if (av_reallocp_array(&fourxm->tracks, track + 1, sizeof(AudioTrack))) + return AVERROR(ENOMEM); + memset(&fourxm->tracks[fourxm->track_count], 0, + sizeof(AudioTrack) * (track + 1 - fourxm->track_count)); + fourxm->track_count = track + 1; + } + fourxm->tracks[track].adpcm = AV_RL32(buf + 12); + fourxm->tracks[track].channels = AV_RL32(buf + 36); + fourxm->tracks[track].sample_rate = AV_RL32(buf + 40); + fourxm->tracks[track].bits = AV_RL32(buf + 44); + fourxm->tracks[track].audio_pts = 0; + + if (fourxm->tracks[track].channels <= 0 || + fourxm->tracks[track].sample_rate <= 0 || + fourxm->tracks[track].bits < 0) { + av_log(s, AV_LOG_ERROR, "audio header invalid\n"); + return AVERROR_INVALIDDATA; + } + if (!fourxm->tracks[track].adpcm && fourxm->tracks[track].bits<8) { + av_log(s, AV_LOG_ERROR, "bits unspecified for non ADPCM\n"); + return AVERROR_INVALIDDATA; + } + + /* allocate a new AVStream */ + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->id = track; + avpriv_set_pts_info(st, 60, 1, fourxm->tracks[track].sample_rate); + + fourxm->tracks[track].stream_index = st->index; + + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_tag = 0; + st->codec->channels = fourxm->tracks[track].channels; + st->codec->sample_rate = fourxm->tracks[track].sample_rate; + st->codec->bits_per_coded_sample = fourxm->tracks[track].bits; + st->codec->bit_rate = st->codec->channels * + st->codec->sample_rate * + st->codec->bits_per_coded_sample; + st->codec->block_align = st->codec->channels * + st->codec->bits_per_coded_sample; + + if (fourxm->tracks[track].adpcm){ + st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM; + } else if (st->codec->bits_per_coded_sample == 8) { + st->codec->codec_id = AV_CODEC_ID_PCM_U8; + } else + st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; + + return 0; +} + static int fourxm_read_header(AVFormatContext *s) { AVIOContext *pb = s->pb; @@ -100,11 +199,10 @@ static int fourxm_read_header(AVFormatContext *s) FourxmDemuxContext *fourxm = s->priv_data; unsigned char *header; int i, ret; - AVStream *st; fourxm->track_count = 0; - fourxm->tracks = NULL; - fourxm->fps = 1.0; + fourxm->tracks = NULL; + fourxm->fps = 1.0; /* skip the first 3 32-bit numbers */ avio_skip(pb, 12); @@ -119,7 +217,7 @@ static int fourxm_read_header(AVFormatContext *s) header = av_malloc(header_size); if (!header) return AVERROR(ENOMEM); - if (avio_read(pb, header, header_size) != header_size){ + if (avio_read(pb, header, header_size) != header_size) { av_free(header); return AVERROR(EIO); } @@ -127,123 +225,38 @@ static int fourxm_read_header(AVFormatContext *s) /* take the lazy approach and search for any and all vtrk and strk chunks */ for (i = 0; i < header_size - 8; i++) { fourcc_tag = AV_RL32(&header[i]); - size = AV_RL32(&header[i + 4]); + size = AV_RL32(&header[i + 4]); if (size > header_size - i - 8 && (fourcc_tag == vtrk_TAG || fourcc_tag == strk_TAG)) { av_log(s, AV_LOG_ERROR, "chunk larger than array %d>%d\n", size, header_size - i - 8); return AVERROR_INVALIDDATA; } if (fourcc_tag == std__TAG) { - if (header_size < i + 16) { + if (header_size - i < 16) { av_log(s, AV_LOG_ERROR, "std TAG truncated\n"); - return AVERROR_INVALIDDATA; + ret = AVERROR_INVALIDDATA; + goto fail; } fourxm->fps = av_int2float(AV_RL32(&header[i + 12])); } else if (fourcc_tag == vtrk_TAG) { - /* check that there is enough data */ - if (size != vtrk_SIZE) { - ret= AVERROR_INVALIDDATA; + if ((ret = parse_vtrk(s, fourxm, header + i, size, + header_size - i)) < 0) goto fail; - } - fourxm->width = AV_RL32(&header[i + 36]); - fourxm->height = AV_RL32(&header[i + 40]); - - /* allocate a new AVStream */ - st = avformat_new_stream(s, NULL); - if (!st){ - ret= AVERROR(ENOMEM); - goto fail; - } - avpriv_set_pts_info(st, 60, 1, fourxm->fps); - - fourxm->video_stream_index = st->index; - - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_4XM; - st->codec->extradata_size = 4; - st->codec->extradata = av_malloc(4); - AV_WL32(st->codec->extradata, AV_RL32(&header[i + 16])); - st->codec->width = fourxm->width; - st->codec->height = fourxm->height; i += 8 + size; } else if (fourcc_tag == strk_TAG) { - int current_track; - /* check that there is enough data */ - if (size != strk_SIZE) { - ret= AVERROR_INVALIDDATA; - goto fail; - } - current_track = AV_RL32(&header[i + 8]); - if((unsigned)current_track >= UINT_MAX / sizeof(AudioTrack) - 1){ - av_log(s, AV_LOG_ERROR, "current_track too large\n"); - ret = AVERROR_INVALIDDATA; - goto fail; - } - if (current_track + 1 > fourxm->track_count) { - fourxm->tracks = av_realloc_f(fourxm->tracks, - sizeof(AudioTrack), - current_track + 1); - if (!fourxm->tracks) { - ret = AVERROR(ENOMEM); - goto fail; - } - memset(&fourxm->tracks[fourxm->track_count], 0, - sizeof(AudioTrack) * (current_track + 1 - fourxm->track_count)); - fourxm->track_count = current_track + 1; - } - fourxm->tracks[current_track].adpcm = AV_RL32(&header[i + 12]); - fourxm->tracks[current_track].channels = AV_RL32(&header[i + 36]); - fourxm->tracks[current_track].sample_rate = AV_RL32(&header[i + 40]); - fourxm->tracks[current_track].bits = AV_RL32(&header[i + 44]); - fourxm->tracks[current_track].audio_pts = 0; - if( fourxm->tracks[current_track].channels <= 0 - || fourxm->tracks[current_track].sample_rate <= 0 - || fourxm->tracks[current_track].bits < 0){ - av_log(s, AV_LOG_ERROR, "audio header invalid\n"); - ret = AVERROR_INVALIDDATA; - goto fail; - } - if(!fourxm->tracks[current_track].adpcm && fourxm->tracks[current_track].bits<8){ - av_log(s, AV_LOG_ERROR, "bits unspecified for non ADPCM\n"); - ret = AVERROR_INVALIDDATA; + if ((ret = parse_strk(s, fourxm, header + i, size, + header_size - i)) < 0) goto fail; - } - i += 8 + size; - /* allocate a new AVStream */ - st = avformat_new_stream(s, NULL); - if (!st){ - ret= AVERROR(ENOMEM); - goto fail; - } - - st->id = current_track; - avpriv_set_pts_info(st, 60, 1, fourxm->tracks[current_track].sample_rate); - - fourxm->tracks[current_track].stream_index = st->index; - - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = 0; - st->codec->channels = fourxm->tracks[current_track].channels; - st->codec->sample_rate = fourxm->tracks[current_track].sample_rate; - st->codec->bits_per_coded_sample = fourxm->tracks[current_track].bits; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * - st->codec->bits_per_coded_sample; - st->codec->block_align = st->codec->channels * st->codec->bits_per_coded_sample; - if (fourxm->tracks[current_track].adpcm){ - st->codec->codec_id = AV_CODEC_ID_ADPCM_4XM; - }else if (st->codec->bits_per_coded_sample == 8){ - st->codec->codec_id = AV_CODEC_ID_PCM_U8; - }else - st->codec->codec_id = AV_CODEC_ID_PCM_S16LE; + i += 8 + size; } } /* skip over the LIST-MOVI chunk (which is where the stream should be */ GET_LIST_HEADER(); - if (fourcc_tag != MOVI_TAG){ - ret= AVERROR_INVALIDDATA; + if (fourcc_tag != MOVI_TAG) { + ret = AVERROR_INVALIDDATA; goto fail; } @@ -262,7 +275,7 @@ static int fourxm_read_packet(AVFormatContext *s, AVPacket *pkt) { FourxmDemuxContext *fourxm = s->priv_data; - AVIOContext *pb = s->pb; + AVIOContext *pb = s->pb; unsigned int fourcc_tag; unsigned int size; int ret = 0; @@ -272,18 +285,16 @@ static int fourxm_read_packet(AVFormatContext *s, int audio_frame_count; while (!packet_read) { - if ((ret = avio_read(s->pb, header, 8)) < 0) return ret; fourcc_tag = AV_RL32(&header[0]); - size = AV_RL32(&header[4]); + size = AV_RL32(&header[4]); if (url_feof(pb)) return AVERROR(EIO); switch (fourcc_tag) { - case LIST_TAG: /* this is a good time to bump the video pts */ - fourxm->video_pts ++; + fourxm->video_pts++; /* skip the LIST-* tag and move on to the next fourcc */ avio_rl32(pb); @@ -300,45 +311,43 @@ static int fourxm_read_packet(AVFormatContext *s, if (size + 8 < size || av_new_packet(pkt, size + 8)) return AVERROR(EIO); pkt->stream_index = fourxm->video_stream_index; - pkt->pts = fourxm->video_pts; - pkt->pos = avio_tell(s->pb); + pkt->pts = fourxm->video_pts; + pkt->pos = avio_tell(s->pb); memcpy(pkt->data, header, 8); ret = avio_read(s->pb, &pkt->data[8], size); - if (ret < 0){ + if (ret < 0) { av_free_packet(pkt); - }else + } else packet_read = 1; break; case snd__TAG: track_number = avio_rl32(pb); avio_skip(pb, 4); - size-=8; + size -= 8; - if (track_number < fourxm->track_count && fourxm->tracks[track_number].channels>0) { - ret= av_get_packet(s->pb, pkt, size); - if(ret<0) + if (track_number < fourxm->track_count && + fourxm->tracks[track_number].channels > 0) { + ret = av_get_packet(s->pb, pkt, size); + if (ret < 0) return AVERROR(EIO); pkt->stream_index = fourxm->tracks[track_number].stream_index; - pkt->pts = fourxm->tracks[track_number].audio_pts; + pkt->pts = fourxm->tracks[track_number].audio_pts; packet_read = 1; /* pts accounting */ audio_frame_count = size; if (fourxm->tracks[track_number].adpcm) - audio_frame_count -= - 2 * (fourxm->tracks[track_number].channels); - audio_frame_count /= - fourxm->tracks[track_number].channels; - if (fourxm->tracks[track_number].adpcm){ + audio_frame_count -= 2 * (fourxm->tracks[track_number].channels); + audio_frame_count /= fourxm->tracks[track_number].channels; + if (fourxm->tracks[track_number].adpcm) { audio_frame_count *= 2; - }else + } else audio_frame_count /= - (fourxm->tracks[track_number].bits / 8); + (fourxm->tracks[track_number].bits / 8); fourxm->tracks[track_number].audio_pts += audio_frame_count; - } else { avio_skip(pb, size); } diff --git a/chromium/third_party/ffmpeg/libavformat/Makefile b/chromium/third_party/ffmpeg/libavformat/Makefile index 470e7f34e84..35d49f73024 100644 --- a/chromium/third_party/ffmpeg/libavformat/Makefile +++ b/chromium/third_party/ffmpeg/libavformat/Makefile @@ -11,6 +11,7 @@ OBJS = allformats.o \ avio.o \ aviobuf.o \ cutils.o \ + format.o \ id3v1.o \ id3v2.o \ metadata.o \ @@ -20,9 +21,14 @@ OBJS = allformats.o \ riff.o \ sdp.o \ seek.o \ + url.o \ utils.o \ +OBJS-$(HAVE_MSVCRT) += file_open.o + OBJS-$(CONFIG_NETWORK) += network.o +OBJS-$(CONFIG_RIFFDEC) += riffdec.o +OBJS-$(CONFIG_RIFFENC) += riffenc.o OBJS-$(CONFIG_RTPDEC) += rdt.o \ rtp.o \ rtpdec.o \ @@ -50,11 +56,12 @@ OBJS-$(CONFIG_SHARED) += log2_tab.o # muxers/demuxers OBJS-$(CONFIG_A64_MUXER) += a64.o rawenc.o -OBJS-$(CONFIG_AAC_DEMUXER) += aacdec.o rawdec.o +OBJS-$(CONFIG_AAC_DEMUXER) += aacdec.o apetag.o img2.o rawdec.o OBJS-$(CONFIG_AC3_DEMUXER) += ac3dec.o rawdec.o OBJS-$(CONFIG_AC3_MUXER) += rawenc.o OBJS-$(CONFIG_ACT_DEMUXER) += act.o OBJS-$(CONFIG_ADF_DEMUXER) += bintext.o sauce.o +OBJS-$(CONFIG_ADP_DEMUXER) += adp.o OBJS-$(CONFIG_ADX_DEMUXER) += adxdec.o OBJS-$(CONFIG_ADX_MUXER) += rawenc.o OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o @@ -91,6 +98,7 @@ OBJS-$(CONFIG_BINTEXT_DEMUXER) += bintext.o sauce.o OBJS-$(CONFIG_BIT_DEMUXER) += bit.o OBJS-$(CONFIG_BIT_MUXER) += bit.o OBJS-$(CONFIG_BMV_DEMUXER) += bmv.o +OBJS-$(CONFIG_BOA_DEMUXER) += boadec.o OBJS-$(CONFIG_BRSTM_DEMUXER) += brstm.o OBJS-$(CONFIG_C93_DEMUXER) += c93.o vocdec.o voc.o OBJS-$(CONFIG_CAF_DEMUXER) += cafdec.o caf.o mov.o mov_chan.o \ @@ -102,6 +110,8 @@ OBJS-$(CONFIG_CDG_DEMUXER) += cdg.o OBJS-$(CONFIG_CDXL_DEMUXER) += cdxl.o OBJS-$(CONFIG_CONCAT_DEMUXER) += concatdec.o OBJS-$(CONFIG_CRC_MUXER) += crcenc.o +OBJS-$(CONFIG_DATA_DEMUXER) += rawdec.o +OBJS-$(CONFIG_DATA_MUXER) += rawdec.o OBJS-$(CONFIG_DAUD_DEMUXER) += daud.o OBJS-$(CONFIG_DAUD_MUXER) += daud.o OBJS-$(CONFIG_DFA_DEMUXER) += dfa.o @@ -128,6 +138,7 @@ OBJS-$(CONFIG_FFMETADATA_MUXER) += ffmetaenc.o OBJS-$(CONFIG_FILMSTRIP_DEMUXER) += filmstripdec.o OBJS-$(CONFIG_FILMSTRIP_MUXER) += filmstripenc.o OBJS-$(CONFIG_FLAC_DEMUXER) += flacdec.o rawdec.o \ + flacdec_picture.o \ oggparsevorbis.o \ vorbiscomment.o OBJS-$(CONFIG_FLAC_MUXER) += flacenc.o flacenc_header.o \ @@ -156,7 +167,7 @@ OBJS-$(CONFIG_H263_MUXER) += rawenc.o OBJS-$(CONFIG_H264_DEMUXER) += h264dec.o rawdec.o OBJS-$(CONFIG_H264_MUXER) += rawenc.o OBJS-$(CONFIG_HLS_DEMUXER) += hls.o -OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o mpegtsenc.o +OBJS-$(CONFIG_HLS_MUXER) += hlsenc.o OBJS-$(CONFIG_ICO_DEMUXER) += icodec.o OBJS-$(CONFIG_ICO_MUXER) += icoenc.o OBJS-$(CONFIG_IDCIN_DEMUXER) += idcin.o @@ -191,7 +202,7 @@ OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ isom.o rmsipr.o OBJS-$(CONFIG_MATROSKA_MUXER) += matroskaenc.o matroska.o \ isom.o avc.o \ - flacenc_header.o avlanguage.o + flacenc_header.o avlanguage.o wv.o OBJS-$(CONFIG_MD5_MUXER) += md5enc.o OBJS-$(CONFIG_MGSTS_DEMUXER) += mgsts.o OBJS-$(CONFIG_MICRODVD_DEMUXER) += microdvddec.o subtitles.o @@ -249,7 +260,8 @@ OBJS-$(CONFIG_OGG_DEMUXER) += oggdec.o \ oggparsespeex.o \ oggparsetheora.o \ oggparsevorbis.o \ - vorbiscomment.o + vorbiscomment.o \ + flacdec_picture.o OBJS-$(CONFIG_OGG_MUXER) += oggenc.o \ vorbiscomment.o OBJS-$(CONFIG_OMA_DEMUXER) += omadec.o pcm.o oma.o @@ -304,11 +316,13 @@ OBJS-$(CONFIG_R3D_DEMUXER) += r3d.o OBJS-$(CONFIG_RAWVIDEO_DEMUXER) += rawvideodec.o OBJS-$(CONFIG_RAWVIDEO_MUXER) += rawenc.o OBJS-$(CONFIG_REALTEXT_DEMUXER) += realtextdec.o subtitles.o +OBJS-$(CONFIG_REDSPARK_DEMUXER) += redspark.o OBJS-$(CONFIG_RL2_DEMUXER) += rl2.o OBJS-$(CONFIG_RM_DEMUXER) += rmdec.o rm.o rmsipr.o OBJS-$(CONFIG_RM_MUXER) += rmenc.o rm.o OBJS-$(CONFIG_ROQ_DEMUXER) += idroqdec.o OBJS-$(CONFIG_ROQ_MUXER) += idroqenc.o rawenc.o +OBJS-$(CONFIG_RSD_DEMUXER) += rsd.o OBJS-$(CONFIG_RSO_DEMUXER) += rsodec.o rso.o pcm.o OBJS-$(CONFIG_RSO_MUXER) += rsoenc.o rso.o OBJS-$(CONFIG_RPL_DEMUXER) += rpl.o @@ -364,10 +378,11 @@ OBJS-$(CONFIG_MKVTIMESTAMP_V2_MUXER) += mkvtimestamp_v2.o OBJS-$(CONFIG_TMV_DEMUXER) += tmv.o OBJS-$(CONFIG_TRUEHD_DEMUXER) += rawdec.o OBJS-$(CONFIG_TRUEHD_MUXER) += rawenc.o -OBJS-$(CONFIG_TTA_DEMUXER) += tta.o +OBJS-$(CONFIG_TTA_DEMUXER) += tta.o apetag.o img2.o OBJS-$(CONFIG_TTY_DEMUXER) += tty.o sauce.o OBJS-$(CONFIG_TXD_DEMUXER) += txd.o OBJS-$(CONFIG_VC1_DEMUXER) += rawdec.o +OBJS-$(CONFIG_VC1_MUXER) += rawenc.o OBJS-$(CONFIG_VC1T_DEMUXER) += vc1test.o OBJS-$(CONFIG_VC1T_MUXER) += vc1testenc.o OBJS-$(CONFIG_VIVO_DEMUXER) += vivo.o @@ -384,15 +399,16 @@ OBJS-$(CONFIG_WAV_MUXER) += wavenc.o OBJS-$(CONFIG_WC3_DEMUXER) += wc3movie.o OBJS-$(CONFIG_WEBM_MUXER) += matroskaenc.o matroska.o \ isom.o avc.o \ - flacenc_header.o avlanguage.o + flacenc_header.o avlanguage.o wv.o OBJS-$(CONFIG_WEBVTT_DEMUXER) += webvttdec.o subtitles.o +OBJS-$(CONFIG_WEBVTT_MUXER) += webvttenc.o OBJS-$(CONFIG_WSAUD_DEMUXER) += westwood_aud.o OBJS-$(CONFIG_WSVQA_DEMUXER) += westwood_vqa.o OBJS-$(CONFIG_WTV_DEMUXER) += wtvdec.o wtv.o asfdec.o asf.o asfcrypt.o \ avlanguage.o mpegts.o isom.o OBJS-$(CONFIG_WTV_MUXER) += wtvenc.o wtv.o asf.o asfenc.o -OBJS-$(CONFIG_WV_DEMUXER) += wv.o apetag.o img2.o -OBJS-$(CONFIG_WV_MUXER) += wvenc.o apetagenc.o +OBJS-$(CONFIG_WV_DEMUXER) += wvdec.o wv.o apetag.o img2.o +OBJS-$(CONFIG_WV_MUXER) += wvenc.o wv.o apetag.o img2.o OBJS-$(CONFIG_XA_DEMUXER) += xa.o OBJS-$(CONFIG_XBIN_DEMUXER) += bintext.o sauce.o OBJS-$(CONFIG_XMV_DEMUXER) += xmv.o @@ -402,6 +418,7 @@ OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg.o OBJS-$(CONFIG_YUV4MPEGPIPE_DEMUXER) += yuv4mpeg.o # external libraries +OBJS-$(CONFIG_LIBGME_DEMUXER) += libgme.o OBJS-$(CONFIG_LIBMODPLUG_DEMUXER) += libmodplug.o OBJS-$(CONFIG_LIBNUT_DEMUXER) += libnut.o OBJS-$(CONFIG_LIBNUT_MUXER) += libnut.o @@ -418,6 +435,7 @@ OBJS-$(CONFIG_DATA_PROTOCOL) += data_uri.o OBJS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpcrypt.o rtmpdh.o OBJS-$(CONFIG_FFRTMPHTTP_PROTOCOL) += rtmphttp.o OBJS-$(CONFIG_FILE_PROTOCOL) += file.o +OBJS-$(CONFIG_FTP_PROTOCOL) += ftp.o OBJS-$(CONFIG_GOPHER_PROTOCOL) += gopher.o OBJS-$(CONFIG_HLS_PROTOCOL) += hlsproto.o OBJS-$(CONFIG_HTTP_PROTOCOL) += http.o httpauth.o urldecode.o @@ -439,14 +457,16 @@ OBJS-$(CONFIG_SRTP_PROTOCOL) += srtpproto.o srtp.o OBJS-$(CONFIG_TCP_PROTOCOL) += tcp.o OBJS-$(CONFIG_TLS_PROTOCOL) += tls.o OBJS-$(CONFIG_UDP_PROTOCOL) += udp.o +OBJS-$(CONFIG_UNIX_PROTOCOL) += unix.o SKIPHEADERS-$(CONFIG_FFRTMPCRYPT_PROTOCOL) += rtmpdh.h SKIPHEADERS-$(CONFIG_NETWORK) += network.h rtsp.h -TESTPROGS = noproxy \ - seek \ +TESTPROGS = seek \ srtp \ url \ +TESTPROGS-$(CONFIG_NETWORK) += noproxy + TOOLS = aviocat \ ismindex \ pktdumper \ diff --git a/chromium/third_party/ffmpeg/libavformat/aacdec.c b/chromium/third_party/ffmpeg/libavformat/aacdec.c index 7c17dd05fa6..d93e75ec52c 100644 --- a/chromium/third_party/ffmpeg/libavformat/aacdec.c +++ b/chromium/third_party/ffmpeg/libavformat/aacdec.c @@ -25,7 +25,7 @@ #include "internal.h" #include "rawdec.h" #include "id3v1.h" - +#include "apetag.h" static int adts_aac_probe(AVProbeData *p) { @@ -55,9 +55,9 @@ static int adts_aac_probe(AVProbeData *p) if(buf == buf0) first_frames= frames; } - if (first_frames>=3) return AVPROBE_SCORE_MAX/2+1; - else if(max_frames>500)return AVPROBE_SCORE_MAX/2; - else if(max_frames>=3) return AVPROBE_SCORE_MAX/4; + if (first_frames>=3) return AVPROBE_SCORE_EXTENSION + 1; + else if(max_frames>500)return AVPROBE_SCORE_EXTENSION; + else if(max_frames>=3) return AVPROBE_SCORE_EXTENSION / 2; else if(max_frames>=1) return 1; else return 0; } @@ -75,6 +75,12 @@ static int adts_aac_read_header(AVFormatContext *s) st->need_parsing = AVSTREAM_PARSE_FULL_RAW; ff_id3v1_read(s); + if (s->pb->seekable && + !av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) { + int64_t cur = avio_tell(s->pb); + ff_ape_parse_tag(s); + avio_seek(s->pb, cur, SEEK_SET); + } //LCM of all possible ADTS sample rates avpriv_set_pts_info(st, 64, 1, 28224000); diff --git a/chromium/third_party/ffmpeg/libavformat/ac3dec.c b/chromium/third_party/ffmpeg/libavformat/ac3dec.c index c531f8a179e..3db23397d0d 100644 --- a/chromium/third_party/ffmpeg/libavformat/ac3dec.c +++ b/chromium/third_party/ffmpeg/libavformat/ac3dec.c @@ -79,9 +79,9 @@ static int ac3_eac3_probe(AVProbeData *p, enum AVCodecID expected_codec_id) if(codec_id != expected_codec_id) return 0; // keep this in sync with mp3 probe, both need to avoid // issues with MPEG-files! - if (first_frames>=4) return AVPROBE_SCORE_MAX/2+1; - else if(max_frames>200)return AVPROBE_SCORE_MAX/2; - else if(max_frames>=4) return AVPROBE_SCORE_MAX/4; + if (first_frames>=4) return AVPROBE_SCORE_EXTENSION + 1; + else if(max_frames>200)return AVPROBE_SCORE_EXTENSION; + else if(max_frames>=4) return AVPROBE_SCORE_EXTENSION/2; else if(max_frames>=1) return 1; else return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/act.c b/chromium/third_party/ffmpeg/libavformat/act.c index 78f1d3bb9a6..3f223d57b6a 100644 --- a/chromium/third_party/ffmpeg/libavformat/act.c +++ b/chromium/third_party/ffmpeg/libavformat/act.c @@ -42,7 +42,7 @@ static int probe(AVProbeData *p) (AV_RL32(&p->buf[16]) != 16)) return 0; - //We cant be sure that this is ACT and not regular WAV + //We can't be sure that this is ACT and not regular WAV if (p->buf_size<512) return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/adp.c b/chromium/third_party/ffmpeg/libavformat/adp.c new file mode 100644 index 00000000000..c5feac4fa5b --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/adp.c @@ -0,0 +1,91 @@ +/* + * ADP demuxer + * Copyright (c) 2013 James Almer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "internal.h" + +static int adp_probe(AVProbeData *p) +{ + int i; + + if (p->buf_size < 32) + return 0; + + for (i = 0; i < p->buf_size - 3; i+=32) + if (p->buf[i] != p->buf[i+2] || p->buf[i+1] != p->buf[i+3]) + return 0; + + return p->buf_size < 260 ? 1 : AVPROBE_SCORE_MAX / 4; +} + +static int adp_read_header(AVFormatContext *s) +{ + AVStream *st; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_id = AV_CODEC_ID_ADPCM_DTK; + st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codec->channels = 2; + st->codec->sample_rate = 48000; + st->start_time = 0; + if (s->pb->seekable) + st->duration = av_get_audio_frame_duration(st->codec, avio_size(s->pb)); + + avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + + return 0; +} + +static int adp_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + int ret, size = 1024; + + if (url_feof(s->pb)) + return AVERROR_EOF; + + ret = av_get_packet(s->pb, pkt, size); + + if (ret != size) { + if (ret < 0) { + av_free_packet(pkt); + return ret; + } + av_shrink_packet(pkt, ret); + } + pkt->stream_index = 0; + + return ret; +} + +AVInputFormat ff_adp_demuxer = { + .name = "adp", + .long_name = NULL_IF_CONFIG_SMALL("ADP"), + .read_probe = adp_probe, + .read_header = adp_read_header, + .read_packet = adp_read_packet, + .extensions = "adp,dtk", +}; diff --git a/chromium/third_party/ffmpeg/libavformat/aiff.h b/chromium/third_party/ffmpeg/libavformat/aiff.h index b3ef577ff36..c13bcc065da 100644 --- a/chromium/third_party/ffmpeg/libavformat/aiff.h +++ b/chromium/third_party/ffmpeg/libavformat/aiff.h @@ -45,6 +45,7 @@ static const AVCodecTag ff_codec_aiff_tags[] = { { AV_CODEC_ID_MACE3, MKTAG('M','A','C','3') }, { AV_CODEC_ID_MACE6, MKTAG('M','A','C','6') }, { AV_CODEC_ID_GSM, MKTAG('G','S','M',' ') }, + { AV_CODEC_ID_ADPCM_G722, MKTAG('G','7','2','2') }, { AV_CODEC_ID_ADPCM_G726, MKTAG('G','7','2','6') }, { AV_CODEC_ID_PCM_S16BE, MKTAG('t','w','o','s') }, { AV_CODEC_ID_PCM_S16LE, MKTAG('s','o','w','t') }, diff --git a/chromium/third_party/ffmpeg/libavformat/aiffdec.c b/chromium/third_party/ffmpeg/libavformat/aiffdec.c index 62af3dca7b7..851091e5cbf 100644 --- a/chromium/third_party/ffmpeg/libavformat/aiffdec.c +++ b/chromium/third_party/ffmpeg/libavformat/aiffdec.c @@ -141,6 +141,7 @@ static unsigned int get_aiff_header(AVFormatContext *s, int size, case AV_CODEC_ID_MACE3: codec->block_align = 2*codec->channels; break; + case AV_CODEC_ID_ADPCM_G722: case AV_CODEC_ID_MACE6: codec->block_align = 1*codec->channels; break; diff --git a/chromium/third_party/ffmpeg/libavformat/allformats.c b/chromium/third_party/ffmpeg/libavformat/allformats.c index 80c53f6c6e9..b3b2a3bba53 100644 --- a/chromium/third_party/ffmpeg/libavformat/allformats.c +++ b/chromium/third_party/ffmpeg/libavformat/allformats.c @@ -65,6 +65,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(AC3, ac3); REGISTER_DEMUXER (ACT, act); REGISTER_DEMUXER (ADF, adf); + REGISTER_DEMUXER (ADP, adp); REGISTER_MUXER (ADTS, adts); REGISTER_MUXDEMUX(ADX, adx); REGISTER_DEMUXER (AEA, aea); @@ -92,6 +93,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(BIT, bit); REGISTER_DEMUXER (BMV, bmv); REGISTER_DEMUXER (BRSTM, brstm); + REGISTER_DEMUXER (BOA, boa); REGISTER_DEMUXER (C93, c93); REGISTER_MUXDEMUX(CAF, caf); REGISTER_MUXDEMUX(CAVSVIDEO, cavsvideo); @@ -99,6 +101,7 @@ void av_register_all(void) REGISTER_DEMUXER (CDXL, cdxl); REGISTER_DEMUXER (CONCAT, concat); REGISTER_MUXER (CRC, crc); + REGISTER_MUXDEMUX(DATA, data); REGISTER_MUXDEMUX(DAUD, daud); REGISTER_DEMUXER (DFA, dfa); REGISTER_MUXDEMUX(DIRAC, dirac); @@ -230,10 +233,12 @@ void av_register_all(void) REGISTER_DEMUXER (R3D, r3d); REGISTER_MUXDEMUX(RAWVIDEO, rawvideo); REGISTER_DEMUXER (REALTEXT, realtext); + REGISTER_DEMUXER (REDSPARK, redspark); REGISTER_DEMUXER (RL2, rl2); REGISTER_MUXDEMUX(RM, rm); REGISTER_MUXDEMUX(ROQ, roq); REGISTER_DEMUXER (RPL, rpl); + REGISTER_DEMUXER (RSD, rsd); REGISTER_MUXDEMUX(RSO, rso); REGISTER_MUXDEMUX(RTP, rtp); REGISTER_MUXDEMUX(RTSP, rtsp); @@ -263,7 +268,7 @@ void av_register_all(void) REGISTER_DEMUXER (SUBVIEWER, subviewer); REGISTER_MUXDEMUX(SWF, swf); REGISTER_DEMUXER (TAK, tak); - REGISTER_MUXER (TEE, tee); + REGISTER_MUXER (TEE, tee); REGISTER_DEMUXER (TEDCAPTIONS, tedcaptions); REGISTER_MUXER (TG2, tg2); REGISTER_MUXER (TGP, tgp); @@ -287,7 +292,7 @@ void av_register_all(void) REGISTER_MUXDEMUX(WAV, wav); REGISTER_DEMUXER (WC3, wc3); REGISTER_MUXER (WEBM, webm); - REGISTER_DEMUXER (WEBVTT, webvtt); + REGISTER_MUXDEMUX(WEBVTT, webvtt); REGISTER_DEMUXER (WSAUD, wsaud); REGISTER_DEMUXER (WSVQA, wsvqa); REGISTER_MUXDEMUX(WTV, wtv); @@ -308,6 +313,7 @@ void av_register_all(void) REGISTER_PROTOCOL(FFRTMPCRYPT, ffrtmpcrypt); REGISTER_PROTOCOL(FFRTMPHTTP, ffrtmphttp); REGISTER_PROTOCOL(FILE, file); + REGISTER_PROTOCOL(FTP, ftp); REGISTER_PROTOCOL(GOPHER, gopher); REGISTER_PROTOCOL(HLS, hls); REGISTER_PROTOCOL(HTTP, http); @@ -329,8 +335,10 @@ void av_register_all(void) REGISTER_PROTOCOL(TCP, tcp); REGISTER_PROTOCOL(TLS, tls); REGISTER_PROTOCOL(UDP, udp); + REGISTER_PROTOCOL(UNIX, unix); /* external libraries */ + REGISTER_DEMUXER (LIBGME, libgme); REGISTER_DEMUXER (LIBMODPLUG, libmodplug); REGISTER_MUXDEMUX(LIBNUT, libnut); REGISTER_DEMUXER (LIBQUVI, libquvi); diff --git a/chromium/third_party/ffmpeg/libavformat/ape.c b/chromium/third_party/ffmpeg/libavformat/ape.c index e2b8adae864..bb61a2498dd 100644 --- a/chromium/third_party/ffmpeg/libavformat/ape.c +++ b/chromium/third_party/ffmpeg/libavformat/ape.c @@ -414,6 +414,8 @@ static int ape_read_packet(AVFormatContext * s, AVPacket * pkt) AV_WL32(pkt->data , nblocks); AV_WL32(pkt->data + 4, ape->frames[ape->currentframe].skip); ret = avio_read(s->pb, pkt->data + extra_size, ape->frames[ape->currentframe].size); + if (ret < 0) + return ret; pkt->pts = ape->frames[ape->currentframe].pts; pkt->stream_index = 0; diff --git a/chromium/third_party/ffmpeg/libavformat/apetag.c b/chromium/third_party/ffmpeg/libavformat/apetag.c index a445c84aef3..ab937367183 100644 --- a/chromium/third_party/ffmpeg/libavformat/apetag.c +++ b/chromium/third_party/ffmpeg/libavformat/apetag.c @@ -23,10 +23,12 @@ #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "avformat.h" +#include "avio_internal.h" #include "apetag.h" #include "internal.h" #define APE_TAG_FLAG_CONTAINS_HEADER (1 << 31) +#define APE_TAG_FLAG_CONTAINS_FOOTER (1 << 30) #define APE_TAG_FLAG_IS_HEADER (1 << 29) #define APE_TAG_FLAG_IS_BINARY (1 << 1) @@ -114,7 +116,7 @@ static int ape_tag_read_field(AVFormatContext *s) int64_t ff_ape_parse_tag(AVFormatContext *s) { AVIOContext *pb = s->pb; - int file_size = avio_size(pb); + int64_t file_size = avio_size(pb); uint32_t val, fields, tag_bytes; uint8_t buf[8]; int64_t tag_start; @@ -167,3 +169,73 @@ int64_t ff_ape_parse_tag(AVFormatContext *s) return tag_start; } + +static int string_is_ascii(const uint8_t *str) +{ + while (*str && *str >= 0x20 && *str <= 0x7e ) str++; + return !*str; +} + +int ff_ape_write_tag(AVFormatContext *s) +{ + AVDictionaryEntry *e = NULL; + int size, ret, count = 0; + AVIOContext *dyn_bc = NULL; + uint8_t *dyn_buf = NULL; + + if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) + goto end; + + // flags + avio_wl32(dyn_bc, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER | + APE_TAG_FLAG_IS_HEADER); + ffio_fill(dyn_bc, 0, 8); // reserved + + while ((e = av_dict_get(s->metadata, "", e, AV_DICT_IGNORE_SUFFIX))) { + int val_len; + + if (!string_is_ascii(e->key)) { + av_log(s, AV_LOG_WARNING, "Non ASCII keys are not allowed\n"); + continue; + } + + val_len = strlen(e->value); + avio_wl32(dyn_bc, val_len); // value length + avio_wl32(dyn_bc, 0); // item flags + avio_put_str(dyn_bc, e->key); // key + avio_write(dyn_bc, e->value, val_len); // value + count++; + } + if (!count) + goto end; + + size = avio_close_dyn_buf(dyn_bc, &dyn_buf); + if (size <= 0) + goto end; + size += 20; + + // header + avio_write(s->pb, "APETAGEX", 8); // id + avio_wl32(s->pb, APE_TAG_VERSION); // version + avio_wl32(s->pb, size); + avio_wl32(s->pb, count); + + avio_write(s->pb, dyn_buf, size - 20); + + // footer + avio_write(s->pb, "APETAGEX", 8); // id + avio_wl32(s->pb, APE_TAG_VERSION); // version + avio_wl32(s->pb, size); // size + avio_wl32(s->pb, count); // tag count + + // flags + avio_wl32(s->pb, APE_TAG_FLAG_CONTAINS_HEADER | APE_TAG_FLAG_CONTAINS_FOOTER); + ffio_fill(s->pb, 0, 8); // reserved + +end: + if (dyn_bc && !dyn_buf) + avio_close_dyn_buf(dyn_bc, &dyn_buf); + av_freep(&dyn_buf); + + return ret; +} diff --git a/chromium/third_party/ffmpeg/libavformat/apetag.h b/chromium/third_party/ffmpeg/libavformat/apetag.h index 0330c8986ae..cf2a5f8ab48 100644 --- a/chromium/third_party/ffmpeg/libavformat/apetag.h +++ b/chromium/third_party/ffmpeg/libavformat/apetag.h @@ -37,8 +37,8 @@ int64_t ff_ape_parse_tag(AVFormatContext *s); /** - * Write an APEv2 tag + * Write an APE tag into a file. */ -void ff_ape_write(AVFormatContext *s); +int ff_ape_write_tag(AVFormatContext *s); #endif /* AVFORMAT_APETAG_H */ diff --git a/chromium/third_party/ffmpeg/libavformat/apetagenc.c b/chromium/third_party/ffmpeg/libavformat/apetagenc.c deleted file mode 100644 index 42f58362a6b..00000000000 --- a/chromium/third_party/ffmpeg/libavformat/apetagenc.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * APE tag writer - * Copyright (c) 2012 Paul B Mahol - * - * This file is part of FFmpeg. - * - * FFmpeg is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "libavutil/dict.h" -#include "avio_internal.h" -#include "avformat.h" -#include "apetag.h" - -static int string_is_ascii(const uint8_t *str) -{ - while (*str && *str >= 0x20 && *str <= 0x7e ) str++; - return !*str; -} - -void ff_ape_write(AVFormatContext *s) -{ - int64_t tag_bytes; - AVDictionaryEntry *t = NULL; - AVIOContext *pb = s->pb; - int tags = 0, vlen; - - tag_bytes = avio_tell(s->pb); - while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) { - if (!string_is_ascii(t->key)) { - av_log(s, AV_LOG_WARNING, "Non ASCII keys are not allowed\n"); - continue; - } - - vlen = strlen(t->value); - avio_wl32(pb, vlen + 1); - avio_wl32(pb, 0); // flags - avio_put_str(pb, t->key); - avio_put_str(pb, t->value); - tags++; - } - tag_bytes = avio_tell(s->pb) - tag_bytes; - - if (!tags) - return; - - avio_write(pb, APE_TAG_PREAMBLE, 8); - avio_wl32(pb, APE_TAG_VERSION); - avio_wl32(pb, tag_bytes + APE_TAG_FOOTER_BYTES); - avio_wl32(pb, tags); // item count - avio_wl32(pb, 0); // global flags - ffio_fill(pb, 0, 8); // reserved -} diff --git a/chromium/third_party/ffmpeg/libavformat/aqtitledec.c b/chromium/third_party/ffmpeg/libavformat/aqtitledec.c index a78fd814d7f..810f95b4935 100644 --- a/chromium/third_party/ffmpeg/libavformat/aqtitledec.c +++ b/chromium/third_party/ffmpeg/libavformat/aqtitledec.c @@ -43,7 +43,7 @@ static int aqt_probe(AVProbeData *p) const char *ptr = p->buf; if (sscanf(ptr, "-->> %d", &frame) == 1) - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/asf.h b/chromium/third_party/ffmpeg/libavformat/asf.h index 5ffc7465a86..30d6c1e4884 100644 --- a/chromium/third_party/ffmpeg/libavformat/asf.h +++ b/chromium/third_party/ffmpeg/libavformat/asf.h @@ -39,8 +39,10 @@ typedef struct ASFStream { /* use for reading */ AVPacket pkt; int frag_offset; + int packet_obj_size; int timestamp; int64_t duration; + int skip_to_key; int ds_span; /* descrambling */ int ds_packet_size; diff --git a/chromium/third_party/ffmpeg/libavformat/asfdec.c b/chromium/third_party/ffmpeg/libavformat/asfdec.c index 1d7f26cefe8..0d6370dc9ab 100644 --- a/chromium/third_party/ffmpeg/libavformat/asfdec.c +++ b/chromium/third_party/ffmpeg/libavformat/asfdec.c @@ -19,14 +19,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -//#define DEBUG - #include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/bswap.h" #include "libavutil/common.h" #include "libavutil/dict.h" +#include "libavutil/internal.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "avformat.h" @@ -69,7 +68,6 @@ typedef struct { unsigned int packet_frag_size; int64_t packet_frag_timestamp; int packet_multi_size; - int packet_obj_size; int packet_time_delta; int packet_time_start; int64_t packet_pos; @@ -368,14 +366,8 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ - asf_st = av_mallocz(sizeof(ASFStream)); - if (!asf_st) - return AVERROR(ENOMEM); - st->priv_data = asf_st; start_time = asf->hdr.preroll; - asf_st->stream_language_index = 128; // invalid stream index means no language info - if (!(asf->hdr.flags & 0x01)) { // if we aren't streaming... int64_t fsize = avio_size(pb); if (fsize <= 0 || (int64_t)asf->hdr.file_size <= 0 || FFABS(fsize - (int64_t)asf->hdr.file_size) < 10000) @@ -407,6 +399,7 @@ static int asf_read_stream_properties(AVFormatContext *s, int64_t size) st->id = avio_rl16(pb) & 0x7f; /* stream id */ // mapping of asf ID to AV stream ID; asf->asfid2avid[st->id] = s->nb_streams - 1; + asf_st = &asf->streams[st->id]; avio_rl32(pb); @@ -731,6 +724,10 @@ static int asf_read_header(AVFormatContext *s) avio_r8(pb); avio_r8(pb); memset(&asf->asfid2avid, -1, sizeof(asf->asfid2avid)); + + for (i = 0; i<128; i++) + asf->streams[i].stream_language_index = 128; // invalid stream index means no language info + for (;;) { uint64_t gpos = avio_tell(pb); ff_get_guid(pb, &g); @@ -883,7 +880,7 @@ static int asf_read_header(AVFormatContext *s) * @param pb context to read data from * @return 0 on success, <0 on error */ -static int ff_asf_get_packet(AVFormatContext *s, AVIOContext *pb) +static int asf_get_packet(AVFormatContext *s, AVIOContext *pb) { ASFContext *asf = s->priv_data; uint32_t packet_length, padsize; @@ -1009,10 +1006,10 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb) if (asf->packet_replic_size >= 8) { int64_t end = avio_tell(pb) + asf->packet_replic_size; AVRational aspect; - asf->packet_obj_size = avio_rl32(pb); - if (asf->packet_obj_size >= (1 << 24) || asf->packet_obj_size <= 0) { + asfst->packet_obj_size = avio_rl32(pb); + if (asfst->packet_obj_size >= (1 << 24) || asfst->packet_obj_size <= 0) { av_log(s, AV_LOG_ERROR, "packet_obj_size invalid\n"); - asf->packet_obj_size = 0; + asfst->packet_obj_size = 0; return AVERROR_INVALIDDATA; } asf->packet_frag_timestamp = avio_rl32(pb); // timestamp @@ -1110,7 +1107,7 @@ static int asf_read_frame_header(AVFormatContext *s, AVIOContext *pb) * @return 0 if data was stored in pkt, <0 on error or 1 if more ASF * packets need to be loaded (through asf_get_packet()) */ -static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) +static int asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) { ASFContext *asf = s->priv_data; ASFStream *asf_st = 0; @@ -1141,7 +1138,7 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk if (asf->stream_index < 0 || s->streams[asf->stream_index]->discard >= AVDISCARD_ALL || (!asf->packet_key_frame && - s->streams[asf->stream_index]->discard >= AVDISCARD_NONKEY)) { + (s->streams[asf->stream_index]->discard >= AVDISCARD_NONKEY || asf->streams[s->streams[asf->stream_index]->id].skip_to_key))) { asf->packet_time_start = 0; /* unhandled packet (should not happen) */ avio_skip(pb, asf->packet_frag_size); @@ -1151,7 +1148,8 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk asf->packet_frag_size); continue; } - asf->asf_st = s->streams[asf->stream_index]->priv_data; + asf->asf_st = &asf->streams[s->streams[asf->stream_index]->id]; + asf->asf_st->skip_to_key = 0; } asf_st = asf->asf_st; av_assert0(asf_st); @@ -1160,37 +1158,30 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk // frag_offset is here used as the beginning timestamp asf->packet_frag_timestamp = asf->packet_time_start; asf->packet_time_start += asf->packet_time_delta; - asf->packet_obj_size = asf->packet_frag_size = avio_r8(pb); + asf_st->packet_obj_size = asf->packet_frag_size = avio_r8(pb); asf->packet_size_left--; asf->packet_multi_size--; - if (asf->packet_multi_size < asf->packet_obj_size) { + if (asf->packet_multi_size < asf_st->packet_obj_size) { asf->packet_time_start = 0; avio_skip(pb, asf->packet_multi_size); asf->packet_size_left -= asf->packet_multi_size; continue; } - asf->packet_multi_size -= asf->packet_obj_size; - } - if (asf_st->frag_offset + asf->packet_frag_size <= asf_st->pkt.size && - asf_st->frag_offset + asf->packet_frag_size > asf->packet_obj_size) { - av_log(s, AV_LOG_INFO, "ignoring invalid packet_obj_size (%d %d %d %d)\n", - asf_st->frag_offset, asf->packet_frag_size, - asf->packet_obj_size, asf_st->pkt.size); - asf->packet_obj_size = asf_st->pkt.size; + asf->packet_multi_size -= asf_st->packet_obj_size; } - if (asf_st->pkt.size != asf->packet_obj_size || + if (asf_st->pkt.size != asf_st->packet_obj_size || // FIXME is this condition sufficient? asf_st->frag_offset + asf->packet_frag_size > asf_st->pkt.size) { if (asf_st->pkt.data) { av_log(s, AV_LOG_INFO, "freeing incomplete packet size %d, new %d\n", - asf_st->pkt.size, asf->packet_obj_size); + asf_st->pkt.size, asf_st->packet_obj_size); asf_st->frag_offset = 0; av_free_packet(&asf_st->pkt); } /* new packet */ - av_new_packet(&asf_st->pkt, asf->packet_obj_size); + av_new_packet(&asf_st->pkt, asf_st->packet_obj_size); asf_st->seq = asf->packet_seq; asf_st->pkt.dts = asf->packet_frag_timestamp - asf->hdr.preroll; asf_st->pkt.stream_index = asf->stream_index; @@ -1211,7 +1202,7 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk asf->stream_index, asf->packet_key_frame, asf_st->pkt.flags & AV_PKT_FLAG_KEY, s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO, - asf->packet_obj_size); + asf_st->packet_obj_size); if (s->streams[asf->stream_index]->codec->codec_type == AVMEDIA_TYPE_AUDIO) asf->packet_key_frame = 1; if (asf->packet_key_frame) @@ -1310,7 +1301,9 @@ static int ff_asf_parse_packet(AVFormatContext *s, AVIOContext *pb, AVPacket *pk asf_st->frag_offset = 0; *pkt = asf_st->pkt; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS asf_st->pkt.destruct = NULL; +FF_ENABLE_DEPRECATION_WARNINGS #endif asf_st->pkt.buf = 0; asf_st->pkt.size = 0; @@ -1331,9 +1324,9 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt) int ret; /* parse cached packets, if any */ - if ((ret = ff_asf_parse_packet(s, s->pb, pkt)) <= 0) + if ((ret = asf_parse_packet(s, s->pb, pkt)) <= 0) return ret; - if ((ret = ff_asf_get_packet(s, s->pb)) < 0) + if ((ret = asf_get_packet(s, s->pb)) < 0) assert(asf->packet_size_left < FRAME_HEADER_SIZE || asf->packet_segments < 1); asf->packet_time_start = 0; @@ -1364,21 +1357,34 @@ static void asf_reset_header(AVFormatContext *s) asf->packet_frag_size = 0; asf->packet_frag_timestamp = 0; asf->packet_multi_size = 0; - asf->packet_obj_size = 0; asf->packet_time_delta = 0; asf->packet_time_start = 0; - for (i = 0; i < s->nb_streams; i++) { - asf_st = s->streams[i]->priv_data; - if (!asf_st) - continue; + for (i = 0; i < 128; i++) { + asf_st = &asf->streams[i]; av_free_packet(&asf_st->pkt); + asf_st->packet_obj_size = 0; asf_st->frag_offset = 0; asf_st->seq = 0; } asf->asf_st = NULL; } +static void skip_to_key(AVFormatContext *s) +{ + ASFContext *asf = s->priv_data; + int i; + + for (i = 0; i < 128; i++) { + int j = asf->asfid2avid[i]; + ASFStream *asf_st = &asf->streams[i]; + if (j < 0 || s->streams[j]->codec->codec_type != AVMEDIA_TYPE_VIDEO) + continue; + + asf_st->skip_to_key = 1; + } +} + static int asf_read_close(AVFormatContext *s) { asf_reset_header(s); @@ -1389,6 +1395,7 @@ static int asf_read_close(AVFormatContext *s) static int64_t asf_read_pts(AVFormatContext *s, int stream_index, int64_t *ppos, int64_t pos_limit) { + ASFContext *asf = s->priv_data; AVPacket pkt1, *pkt = &pkt1; ASFStream *asf_st; int64_t pts; @@ -1407,6 +1414,7 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, if (avio_seek(s->pb, pos, SEEK_SET) < 0) return AV_NOPTS_VALUE; + ff_read_frame_flush(s); asf_reset_header(s); for (;;) { if (av_read_frame(s, pkt) < 0) { @@ -1420,8 +1428,7 @@ static int64_t asf_read_pts(AVFormatContext *s, int stream_index, if (pkt->flags & AV_PKT_FLAG_KEY) { i = pkt->stream_index; - asf_st = s->streams[i]->priv_data; - av_assert0(asf_st); + asf_st = &asf->streams[s->streams[i]->id]; // assert((asf_st->packet_pos - s->data_offset) % s->packet_size == 0); pos = asf_st->packet_pos; @@ -1528,6 +1535,7 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, if(avio_seek(s->pb, pos, SEEK_SET) < 0) return -1; asf_reset_header(s); + skip_to_key(s); return 0; } } @@ -1535,6 +1543,7 @@ static int asf_read_seek(AVFormatContext *s, int stream_index, if (ff_seek_frame_binary(s, stream_index, pts, flags) < 0) return -1; asf_reset_header(s); + skip_to_key(s); return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/audiointerleave.c b/chromium/third_party/ffmpeg/libavformat/audiointerleave.c index 35dd8d5e625..2aa95f3dc6a 100644 --- a/chromium/third_party/ffmpeg/libavformat/audiointerleave.c +++ b/chromium/third_party/ffmpeg/libavformat/audiointerleave.c @@ -74,8 +74,8 @@ int ff_audio_interleave_init(AVFormatContext *s, return 0; } -static int ff_interleave_new_audio_packet(AVFormatContext *s, AVPacket *pkt, - int stream_index, int flush) +static int interleave_new_audio_packet(AVFormatContext *s, AVPacket *pkt, + int stream_index, int flush) { AVStream *st = s->streams[stream_index]; AudioInterleaveContext *aic = st->priv_data; @@ -134,7 +134,7 @@ int ff_audio_rechunk_interleave(AVFormatContext *s, AVPacket *out, AVPacket *pkt if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { AVPacket new_pkt; int ret; - while ((ret = ff_interleave_new_audio_packet(s, &new_pkt, i, flush)) > 0) { + while ((ret = interleave_new_audio_packet(s, &new_pkt, i, flush)) > 0) { ret = ff_interleave_add_packet(s, &new_pkt, compare_ts); if (ret < 0) return ret; diff --git a/chromium/third_party/ffmpeg/libavformat/avformat.h b/chromium/third_party/ffmpeg/libavformat/avformat.h index 80d693a1137..77efc61e72b 100644 --- a/chromium/third_party/ffmpeg/libavformat/avformat.h +++ b/chromium/third_party/ffmpeg/libavformat/avformat.h @@ -337,8 +337,10 @@ typedef struct AVProbeData { int buf_size; /**< Size of buf except extra allocated bytes */ } AVProbeData; -#define AVPROBE_SCORE_MAX 100 ///< maximum score, half of that is used for file-extension-based detection #define AVPROBE_SCORE_RETRY (AVPROBE_SCORE_MAX/4) +#define AVPROBE_SCORE_EXTENSION 50 ///< score for file extension +#define AVPROBE_SCORE_MAX 100 ///< maximum score + #define AVPROBE_PADDING_SIZE 32 ///< extra allocated bytes at the end of the probe buffer /// Demuxer will use avio_open, no opened file should be provided by the caller. @@ -354,8 +356,8 @@ typedef struct AVProbeData { #define AVFMT_VARIABLE_FPS 0x0400 /**< Format allows variable fps. */ #define AVFMT_NODIMENSIONS 0x0800 /**< Format does not need width/height */ #define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ -#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fallback to binary search via read_timestamp */ -#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fallback to generic search */ +#define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fall back on binary search via read_timestamp */ +#define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fall back on generic search */ #define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */ #define AVFMT_ALLOW_FLUSH 0x10000 /**< Format allows flushing. If not set, the muxer will not receive a NULL packet in the write_packet function. */ #if LIBAVFORMAT_VERSION_MAJOR <= 54 @@ -366,6 +368,14 @@ typedef struct AVProbeData { /**< Format does not require strictly increasing timestamps, but they must still be monotonic */ +#define AVFMT_TS_NEGATIVE 0x40000 /**< Format allows muxing negative + timestamps. If not set the timestamp + will be shifted in av_write_frame and + av_interleaved_write_frame so they + start from 0. + The user or muxer can override this through + AVFormatContext.avoid_negative_ts + */ #define AVFMT_SEEK_TO_PTS 0x4000000 /**< Seeking is based on PTS */ @@ -626,6 +636,13 @@ typedef struct AVIndexEntry { #define AV_DISPOSITION_ATTACHED_PIC 0x0400 /** + * To specify text track kind (different from subtitles default). + */ +#define AV_DISPOSITION_CAPTIONS 0x10000 +#define AV_DISPOSITION_DESCRIPTIONS 0x20000 +#define AV_DISPOSITION_METADATA 0x40000 + +/** * Options for behavior on timestamp wrap detection. */ #define AV_PTS_WRAP_IGNORE 0 ///< ignore the wrap @@ -723,19 +740,6 @@ typedef struct AVStream { */ AVPacket attached_pic; - /** - * Real base framerate of the stream. - * This is the lowest framerate with which all timestamps can be - * represented accurately (it is the least common multiple of all - * framerates in the stream). Note, this value is just a guess! - * For example, if the time base is 1/90000 and all frames have either - * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. - * - * Code outside avformat should access this field using: - * av_stream_get/set_r_frame_rate(stream) - */ - AVRational r_frame_rate; - /***************************************************************** * All fields below this line are not part of the public API. They * may not be used outside of libavformat and can be changed and @@ -796,16 +800,6 @@ typedef struct AVStream { */ int codec_info_nb_frames; - /** - * Stream Identifier - * This is the MPEG-TS stream identifier +1 - * 0 means unknown - */ - int stream_identifier; - - int64_t interleaver_chunk_size; - int64_t interleaver_chunk_duration; - /* av_read_frame() support */ enum AVStreamParseType need_parsing; struct AVCodecParserContext *parser; @@ -824,6 +818,29 @@ typedef struct AVStream { unsigned int index_entries_allocated_size; /** + * Real base framerate of the stream. + * This is the lowest framerate with which all timestamps can be + * represented accurately (it is the least common multiple of all + * framerates in the stream). Note, this value is just a guess! + * For example, if the time base is 1/90000 and all frames have either + * approximately 3600 or 1800 timer ticks, then r_frame_rate will be 50/1. + * + * Code outside avformat should access this field using: + * av_stream_get/set_r_frame_rate(stream) + */ + AVRational r_frame_rate; + + /** + * Stream Identifier + * This is the MPEG-TS stream identifier +1 + * 0 means unknown + */ + int stream_identifier; + + int64_t interleaver_chunk_size; + int64_t interleaver_chunk_duration; + + /** * stream probing state * -1 -> probing finished * 0 -> no probing requested @@ -1259,6 +1276,18 @@ typedef struct AVFormatContext { int raw_packet_buffer_remaining_size; /** + * Offset to remap timestamps to be non-negative. + * Expressed in timebase units. + * @see AVStream.mux_ts_offset + */ + int64_t offset; + + /** + * Timebase for the timestamp offset. + */ + AVRational offset_timebase; + + /** * IO repositioned flag. * This is set by avformat when the underlaying IO context read pointer * is repositioned, for example when doing byte based seeking. @@ -1376,6 +1405,9 @@ const AVClass *avformat_get_class(void); * * When muxing, should be called by the user before avformat_write_header(). * + * User is required to call avcodec_close() and avformat_free_context() to + * clean up the allocation by avformat_new_stream(). + * * @param c If non-NULL, the AVCodecContext corresponding to the new stream * will be initialized to use this codec. This is needed for e.g. codec-specific * defaults to be set, so codec should be provided if it is known. @@ -1391,12 +1423,6 @@ AVProgram *av_new_program(AVFormatContext *s, int id); */ -#if FF_API_PKT_DUMP -attribute_deprecated void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload); -attribute_deprecated void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, - int dump_payload); -#endif - #if FF_API_ALLOC_OUTPUT_CONTEXT /** * @deprecated deprecated in favor of avformat_alloc_output_context2() @@ -1487,7 +1513,7 @@ int av_probe_input_buffer(AVIOContext *pb, AVInputFormat **fmt, /** * Open an input stream and read the header. The codecs are not opened. - * The stream must be closed with av_close_input_file(). + * The stream must be closed with avformat_close_input(). * * @param ps Pointer to user-supplied AVFormatContext (allocated by avformat_alloc_context). * May be a pointer to NULL, in which case an AVFormatContext is allocated by this @@ -1622,8 +1648,8 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt); * information possible for decoding. * * If pkt->buf is NULL, then the packet is valid until the next - * av_read_frame() or until av_close_input_file(). Otherwise the packet is valid - * indefinitely. In both cases the packet must be freed with + * av_read_frame() or until avformat_close_input(). Otherwise the packet + * is valid indefinitely. In both cases the packet must be freed with * av_free_packet when it is no longer needed. For video, the packet contains * exactly one frame. For audio, it contains an integer number of frames if each * frame has a known fixed size (e.g. PCM or ADPCM data). If the audio frames @@ -1667,6 +1693,7 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, * or if stream_index is -1, in AV_TIME_BASE units. * If flags contain AVSEEK_FLAG_ANY, then non-keyframes are treated as * keyframes (this may not be supported by all demuxers). + * If flags contain AVSEEK_FLAG_BACKWARD, it is ignored. * * @param stream_index index of the stream which is used as time base reference * @param min_ts smallest acceptable timestamp @@ -1753,7 +1780,7 @@ void av_set_pts_info(AVStream *s, int pts_wrap_bits, * * @param s Media file handle, must be allocated with avformat_alloc_context(). * Its oformat field must be set to the desired output format; - * Its pb field must be set to an already openened AVIOContext. + * Its pb field must be set to an already opened AVIOContext. * @param options An AVDictionary filled with AVFormatContext and muxer-private options. * On return this parameter will be destroyed and replaced with a dict containing * options that were not found. May be NULL. diff --git a/chromium/third_party/ffmpeg/libavformat/avidec.c b/chromium/third_party/ffmpeg/libavformat/avidec.c index 3105d339ca3..2827064331f 100644 --- a/chromium/third_party/ffmpeg/libavformat/avidec.c +++ b/chromium/third_party/ffmpeg/libavformat/avidec.c @@ -19,36 +19,38 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/intreadwrite.h" -#include "libavutil/mathematics.h" +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" #include "libavutil/bswap.h" #include "libavutil/opt.h" #include "libavutil/dict.h" -#include "libavutil/avstring.h" -#include "libavutil/avassert.h" +#include "libavutil/internal.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/mathematics.h" #include "avformat.h" -#include "internal.h" #include "avi.h" #include "dv.h" +#include "internal.h" #include "riff.h" typedef struct AVIStream { - int64_t frame_offset; /* current frame (video) or byte (audio) counter - (used to compute the pts) */ + int64_t frame_offset; /* current frame (video) or byte (audio) counter + * (used to compute the pts) */ int remaining; int packet_size; uint32_t scale; uint32_t rate; - int sample_size; /* size of one sample (or packet) (in the rate/scale sense) in bytes */ + int sample_size; /* size of one sample (or packet) + * (in the rate/scale sense) in bytes */ - int64_t cum_len; /* temporary storage (used during seek) */ - - int prefix; ///< normally 'd'<<8 + 'c' or 'w'<<8 + 'b' + int64_t cum_len; /* temporary storage (used during seek) */ + int prefix; /* normally 'd'<<8 + 'c' or 'w'<<8 + 'b' */ int prefix_count; uint32_t pal[256]; int has_pal; - int dshow_block_align; ///< block align variable used to emulate bugs in the MS dshow demuxer + int dshow_block_align; /* block align variable used to emulate bugs in + * the MS dshow demuxer */ AVFormatContext *sub_ctx; AVPacket sub_pkt; @@ -59,9 +61,9 @@ typedef struct AVIStream { typedef struct { const AVClass *class; - int64_t riff_end; - int64_t movi_end; - int64_t fsize; + int64_t riff_end; + int64_t movi_end; + int64_t fsize; int64_t io_fsize; int64_t movi_list; int64_t last_pkt_pos; @@ -69,7 +71,7 @@ typedef struct { int is_odml; int non_interleaved; int stream_index; - DVDemuxContext* dv_demux; + DVDemuxContext *dv_demux; int odml_depth; int use_odml; #define MAX_ODML_DEPTH 1000 @@ -92,11 +94,11 @@ static const AVClass demuxer_class = { static const char avi_headers[][8] = { - { 'R', 'I', 'F', 'F', 'A', 'V', 'I', ' ' }, - { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 'X' }, - { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 0x19}, - { 'O', 'N', '2', ' ', 'O', 'N', '2', 'f' }, - { 'R', 'I', 'F', 'F', 'A', 'M', 'V', ' ' }, + { 'R', 'I', 'F', 'F', 'A', 'V', 'I', ' ' }, + { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 'X' }, + { 'R', 'I', 'F', 'F', 'A', 'V', 'I', 0x19 }, + { 'O', 'N', '2', ' ', 'O', 'N', '2', 'f' }, + { 'R', 'I', 'F', 'F', 'A', 'M', 'V', ' ' }, { 0 } }; @@ -108,20 +110,21 @@ static const AVMetadataConv avi_metadata_conv[] = { static int avi_load_index(AVFormatContext *s); static int guess_ni_flag(AVFormatContext *s); -#define print_tag(str, tag, size) \ - av_dlog(NULL, "%s: tag=%c%c%c%c size=0x%x\n", \ - str, tag & 0xff, \ - (tag >> 8) & 0xff, \ - (tag >> 16) & 0xff, \ - (tag >> 24) & 0xff, \ - size) +#define print_tag(str, tag, size) \ + av_dlog(NULL, "%s: tag=%c%c%c%c size=0x%x\n", \ + str, tag & 0xff, \ + (tag >> 8) & 0xff, \ + (tag >> 16) & 0xff, \ + (tag >> 24) & 0xff, \ + size) -static inline int get_duration(AVIStream *ast, int len){ - if(ast->sample_size){ +static inline int get_duration(AVIStream *ast, int len) +{ + if (ast->sample_size) return len; - }else if (ast->dshow_block_align){ - return (len + ast->dshow_block_align - 1)/ast->dshow_block_align; - }else + else if (ast->dshow_block_align) + return (len + ast->dshow_block_align - 1) / ast->dshow_block_align; + else return 1; } @@ -133,164 +136,180 @@ static int get_riff(AVFormatContext *s, AVIOContext *pb) /* check RIFF header */ avio_read(pb, header, 4); - avi->riff_end = avio_rl32(pb); /* RIFF chunk size */ + avi->riff_end = avio_rl32(pb); /* RIFF chunk size */ avi->riff_end += avio_tell(pb); /* RIFF chunk end */ - avio_read(pb, header+4, 4); + avio_read(pb, header + 4, 4); - for(i=0; avi_headers[i][0]; i++) - if(!memcmp(header, avi_headers[i], 8)) + for (i = 0; avi_headers[i][0]; i++) + if (!memcmp(header, avi_headers[i], 8)) break; - if(!avi_headers[i][0]) + if (!avi_headers[i][0]) return AVERROR_INVALIDDATA; - if(header[7] == 0x19) - av_log(s, AV_LOG_INFO, "This file has been generated by a totally broken muxer.\n"); + if (header[7] == 0x19) + av_log(s, AV_LOG_INFO, + "This file has been generated by a totally broken muxer.\n"); return 0; } -static int read_braindead_odml_indx(AVFormatContext *s, int frame_num){ - AVIContext *avi = s->priv_data; - AVIOContext *pb = s->pb; - int longs_pre_entry= avio_rl16(pb); - int index_sub_type = avio_r8(pb); - int index_type = avio_r8(pb); - int entries_in_use = avio_rl32(pb); - int chunk_id = avio_rl32(pb); - int64_t base = avio_rl64(pb); - int stream_id= 10*((chunk_id&0xFF) - '0') + (((chunk_id>>8)&0xFF) - '0'); +static int read_braindead_odml_indx(AVFormatContext *s, int frame_num) +{ + AVIContext *avi = s->priv_data; + AVIOContext *pb = s->pb; + int longs_pre_entry = avio_rl16(pb); + int index_sub_type = avio_r8(pb); + int index_type = avio_r8(pb); + int entries_in_use = avio_rl32(pb); + int chunk_id = avio_rl32(pb); + int64_t base = avio_rl64(pb); + int stream_id = ((chunk_id & 0xFF) - '0') * 10 + + ((chunk_id >> 8 & 0xFF) - '0'); AVStream *st; AVIStream *ast; int i; - int64_t last_pos= -1; - int64_t filesize= avi->fsize; - - av_dlog(s, "longs_pre_entry:%d index_type:%d entries_in_use:%d chunk_id:%X base:%16"PRIX64"\n", - longs_pre_entry,index_type, entries_in_use, chunk_id, base); - - if(stream_id >= s->nb_streams || stream_id < 0) + int64_t last_pos = -1; + int64_t filesize = avi->fsize; + + av_dlog(s, + "longs_pre_entry:%d index_type:%d entries_in_use:%d " + "chunk_id:%X base:%16"PRIX64"\n", + longs_pre_entry, + index_type, + entries_in_use, + chunk_id, + base); + + if (stream_id >= s->nb_streams || stream_id < 0) return AVERROR_INVALIDDATA; - st= s->streams[stream_id]; + st = s->streams[stream_id]; ast = st->priv_data; - if(index_sub_type) + if (index_sub_type) return AVERROR_INVALIDDATA; avio_rl32(pb); - if(index_type && longs_pre_entry != 2) + if (index_type && longs_pre_entry != 2) return AVERROR_INVALIDDATA; - if(index_type>1) + if (index_type > 1) return AVERROR_INVALIDDATA; - if(filesize > 0 && base >= filesize){ + if (filesize > 0 && base >= filesize) { av_log(s, AV_LOG_ERROR, "ODML index invalid\n"); - if(base>>32 == (base & 0xFFFFFFFF) && (base & 0xFFFFFFFF) < filesize && filesize <= 0xFFFFFFFF) + if (base >> 32 == (base & 0xFFFFFFFF) && + (base & 0xFFFFFFFF) < filesize && + filesize <= 0xFFFFFFFF) base &= 0xFFFFFFFF; else return AVERROR_INVALIDDATA; } - for(i=0; i<entries_in_use; i++){ - if(index_type){ - int64_t pos= avio_rl32(pb) + base - 8; - int len = avio_rl32(pb); - int key= len >= 0; + for (i = 0; i < entries_in_use; i++) { + if (index_type) { + int64_t pos = avio_rl32(pb) + base - 8; + int len = avio_rl32(pb); + int key = len >= 0; len &= 0x7FFFFFFF; #ifdef DEBUG_SEEK av_log(s, AV_LOG_ERROR, "pos:%"PRId64", len:%X\n", pos, len); #endif - if(url_feof(pb)) + if (url_feof(pb)) return AVERROR_INVALIDDATA; - if(last_pos == pos || pos == base - 8) - avi->non_interleaved= 1; - if(last_pos != pos && (len || !ast->sample_size)) - av_add_index_entry(st, pos, ast->cum_len, len, 0, key ? AVINDEX_KEYFRAME : 0); + if (last_pos == pos || pos == base - 8) + avi->non_interleaved = 1; + if (last_pos != pos && (len || !ast->sample_size)) + av_add_index_entry(st, pos, ast->cum_len, len, 0, + key ? AVINDEX_KEYFRAME : 0); ast->cum_len += get_duration(ast, len); - last_pos= pos; - }else{ + last_pos = pos; + } else { int64_t offset, pos; int duration; offset = avio_rl64(pb); avio_rl32(pb); /* size */ duration = avio_rl32(pb); - if(url_feof(pb)) + if (url_feof(pb)) return AVERROR_INVALIDDATA; pos = avio_tell(pb); - if(avi->odml_depth > MAX_ODML_DEPTH){ + if (avi->odml_depth > MAX_ODML_DEPTH) { av_log(s, AV_LOG_ERROR, "Too deeply nested ODML indexes\n"); return AVERROR_INVALIDDATA; } - if(avio_seek(pb, offset+8, SEEK_SET) < 0) + if (avio_seek(pb, offset + 8, SEEK_SET) < 0) return -1; avi->odml_depth++; read_braindead_odml_indx(s, frame_num); avi->odml_depth--; frame_num += duration; - if(avio_seek(pb, pos, SEEK_SET) < 0) { + if (avio_seek(pb, pos, SEEK_SET) < 0) { av_log(s, AV_LOG_ERROR, "Failed to restore position after reading index\n"); return -1; } } } - avi->index_loaded=2; + avi->index_loaded = 2; return 0; } -static void clean_index(AVFormatContext *s){ +static void clean_index(AVFormatContext *s) +{ int i; int64_t j; - for(i=0; i<s->nb_streams; i++){ - AVStream *st = s->streams[i]; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; AVIStream *ast = st->priv_data; - int n= st->nb_index_entries; - int max= ast->sample_size; + int n = st->nb_index_entries; + int max = ast->sample_size; int64_t pos, size, ts; - if(n != 1 || ast->sample_size==0) + if (n != 1 || ast->sample_size == 0) continue; - while(max < 1024) max+=max; + while (max < 1024) + max += max; - pos= st->index_entries[0].pos; - size= st->index_entries[0].size; - ts= st->index_entries[0].timestamp; + pos = st->index_entries[0].pos; + size = st->index_entries[0].size; + ts = st->index_entries[0].timestamp; - for(j=0; j<size; j+=max){ - av_add_index_entry(st, pos+j, ts+j, FFMIN(max, size-j), 0, AVINDEX_KEYFRAME); - } + for (j = 0; j < size; j += max) + av_add_index_entry(st, pos + j, ts + j, FFMIN(max, size - j), 0, + AVINDEX_KEYFRAME); } } -static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, uint32_t size) +static int avi_read_tag(AVFormatContext *s, AVStream *st, uint32_t tag, + uint32_t size) { AVIOContext *pb = s->pb; - char key[5] = {0}, *value; + char key[5] = { 0 }; + char *value; size += (size & 1); if (size == UINT_MAX) return AVERROR(EINVAL); - value = av_malloc(size+1); + value = av_malloc(size + 1); if (!value) return AVERROR(ENOMEM); avio_read(pb, value, size); - value[size]=0; + value[size] = 0; AV_WL32(key, tag); return av_dict_set(st ? &st->metadata : &s->metadata, key, value, - AV_DICT_DONT_STRDUP_VAL); + AV_DICT_DONT_STRDUP_VAL); } static const char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", @@ -303,10 +322,10 @@ static void avi_metadata_creation_time(AVDictionary **metadata, char *date) /* parse standard AVI date format (ie. "Mon Mar 10 15:04:43 2003") */ if (sscanf(date, "%*3s%*[ ]%3s%*[ ]%2d%*[ ]%8s%*[ ]%4d", month, &day, time, &year) == 4) { - for (i=0; i<12; i++) + for (i = 0; i < 12; i++) if (!av_strcasecmp(month, months[i])) { snprintf(buffer, sizeof(buffer), "%.4d-%.2d-%.2d %s", - year, i+1, day, time); + year, i + 1, day, time); av_dict_set(metadata, "creation_time", buffer, 0); } } else if (date[4] == '/' && date[7] == '/') { @@ -321,19 +340,25 @@ static void avi_read_nikon(AVFormatContext *s, uint64_t end) uint32_t tag = avio_rl32(s->pb); uint32_t size = avio_rl32(s->pb); switch (tag) { - case MKTAG('n', 'c', 't', 'g'): { /* Nikon Tags */ + case MKTAG('n', 'c', 't', 'g'): /* Nikon Tags */ + { uint64_t tag_end = avio_tell(s->pb) + size; while (avio_tell(s->pb) < tag_end) { - uint16_t tag = avio_rl16(s->pb); - uint16_t size = avio_rl16(s->pb); + uint16_t tag = avio_rl16(s->pb); + uint16_t size = avio_rl16(s->pb); const char *name = NULL; - char buffer[64] = {0}; + char buffer[64] = { 0 }; size -= avio_read(s->pb, buffer, - FFMIN(size, sizeof(buffer)-1)); + FFMIN(size, sizeof(buffer) - 1)); switch (tag) { - case 0x03: name = "maker"; break; - case 0x04: name = "model"; break; - case 0x13: name = "creation_time"; + case 0x03: + name = "maker"; + break; + case 0x04: + name = "model"; + break; + case 0x13: + name = "creation_time"; if (buffer[4] == ':' && buffer[7] == ':') buffer[4] = buffer[7] = '-'; break; @@ -360,13 +385,14 @@ static int avi_read_header(AVFormatContext *s) unsigned int size; int i; AVStream *st; - AVIStream *ast = NULL; - int avih_width=0, avih_height=0; - int amv_file_format=0; - uint64_t list_end = 0; + AVIStream *ast = NULL; + int avih_width = 0, avih_height = 0; + int amv_file_format = 0; + uint64_t list_end = 0; int ret; + AVDictionaryEntry *dict_entry; - avi->stream_index= -1; + avi->stream_index = -1; ret = get_riff(s, pb); if (ret < 0) @@ -375,22 +401,22 @@ static int avi_read_header(AVFormatContext *s) av_log(avi, AV_LOG_DEBUG, "use odml:%d\n", avi->use_odml); avi->io_fsize = avi->fsize = avio_size(pb); - if(avi->fsize<=0 || avi->fsize < avi->riff_end) - avi->fsize= avi->riff_end == 8 ? INT64_MAX : avi->riff_end; + if (avi->fsize <= 0 || avi->fsize < avi->riff_end) + avi->fsize = avi->riff_end == 8 ? INT64_MAX : avi->riff_end; /* first list tag */ stream_index = -1; - codec_type = -1; + codec_type = -1; frame_period = 0; - for(;;) { + for (;;) { if (url_feof(pb)) goto fail; - tag = avio_rl32(pb); + tag = avio_rl32(pb); size = avio_rl32(pb); print_tag("tag", tag, size); - switch(tag) { + switch (tag) { case MKTAG('L', 'I', 'S', 'T'): list_end = avio_tell(pb) + size; /* Ignored, except at start of video packets. */ @@ -400,21 +426,23 @@ static int avi_read_header(AVFormatContext *s) if (tag1 == MKTAG('m', 'o', 'v', 'i')) { avi->movi_list = avio_tell(pb) - 4; - if(size) avi->movi_end = avi->movi_list + size + (size & 1); - else avi->movi_end = avi->fsize; + if (size) + avi->movi_end = avi->movi_list + size + (size & 1); + else + avi->movi_end = avi->fsize; av_dlog(NULL, "movi end=%"PRIx64"\n", avi->movi_end); goto end_of_header; - } - else if (tag1 == MKTAG('I', 'N', 'F', 'O')) + } else if (tag1 == MKTAG('I', 'N', 'F', 'O')) ff_read_riff_info(s, size - 4); else if (tag1 == MKTAG('n', 'c', 'd', 't')) avi_read_nikon(s, list_end); break; - case MKTAG('I', 'D', 'I', 'T'): { - unsigned char date[64] = {0}; + case MKTAG('I', 'D', 'I', 'T'): + { + unsigned char date[64] = { 0 }; size += (size & 1); - size -= avio_read(pb, date, FFMIN(size, sizeof(date)-1)); + size -= avio_read(pb, date, FFMIN(size, sizeof(date) - 1)); avio_skip(pb, size); avi_metadata_creation_time(&s->metadata, date); break; @@ -424,7 +452,7 @@ static int avi_read_header(AVFormatContext *s) avio_skip(pb, size + (size & 1)); break; case MKTAG('a', 'm', 'v', 'h'): - amv_file_format=1; + amv_file_format = 1; case MKTAG('a', 'v', 'i', 'h'): /* AVI header */ /* using frame_period is bad idea */ @@ -436,51 +464,51 @@ static int avi_read_header(AVFormatContext *s) avio_skip(pb, 2 * 4); avio_rl32(pb); avio_rl32(pb); - avih_width=avio_rl32(pb); - avih_height=avio_rl32(pb); + avih_width = avio_rl32(pb); + avih_height = avio_rl32(pb); avio_skip(pb, size - 10 * 4); break; case MKTAG('s', 't', 'r', 'h'): /* stream header */ - tag1 = avio_rl32(pb); + tag1 = avio_rl32(pb); handler = avio_rl32(pb); /* codec tag */ - if(tag1 == MKTAG('p', 'a', 'd', 's')){ + if (tag1 == MKTAG('p', 'a', 'd', 's')) { avio_skip(pb, size - 8); break; - }else{ + } else { stream_index++; st = avformat_new_stream(s, NULL); if (!st) goto fail; st->id = stream_index; - ast = av_mallocz(sizeof(AVIStream)); + ast = av_mallocz(sizeof(AVIStream)); if (!ast) goto fail; st->priv_data = ast; } - if(amv_file_format) - tag1 = stream_index ? MKTAG('a','u','d','s') : MKTAG('v','i','d','s'); + if (amv_file_format) + tag1 = stream_index ? MKTAG('a', 'u', 'd', 's') + : MKTAG('v', 'i', 'd', 's'); print_tag("strh", tag1, -1); - if(tag1 == MKTAG('i', 'a', 'v', 's') || tag1 == MKTAG('i', 'v', 'a', 's')){ + if (tag1 == MKTAG('i', 'a', 'v', 's') || + tag1 == MKTAG('i', 'v', 'a', 's')) { int64_t dv_dur; - /* - * After some consideration -- I don't think we - * have to support anything but DV in type1 AVIs. - */ + /* After some consideration -- I don't think we + * have to support anything but DV in type1 AVIs. */ if (s->nb_streams != 1) goto fail; if (handler != MKTAG('d', 'v', 's', 'd') && handler != MKTAG('d', 'v', 'h', 'd') && handler != MKTAG('d', 'v', 's', 'l')) - goto fail; + goto fail; ast = s->streams[0]->priv_data; av_freep(&s->streams[0]->codec->extradata); @@ -498,46 +526,48 @@ static int avi_read_header(AVFormatContext *s) s->streams[0]->priv_data = ast; avio_skip(pb, 3 * 4); ast->scale = avio_rl32(pb); - ast->rate = avio_rl32(pb); + ast->rate = avio_rl32(pb); avio_skip(pb, 4); /* start time */ dv_dur = avio_rl32(pb); if (ast->scale > 0 && ast->rate > 0 && dv_dur > 0) { - dv_dur *= AV_TIME_BASE; + dv_dur *= AV_TIME_BASE; s->duration = av_rescale(dv_dur, ast->scale, ast->rate); } - /* - * else, leave duration alone; timing estimation in utils.c - * will make a guess based on bitrate. - */ + /* else, leave duration alone; timing estimation in utils.c + * will make a guess based on bitrate. */ stream_index = s->nb_streams - 1; - avio_skip(pb, size - 9*4); + avio_skip(pb, size - 9 * 4); break; } av_assert0(stream_index < s->nb_streams); - st->codec->stream_codec_tag= handler; + st->codec->stream_codec_tag = handler; avio_rl32(pb); /* flags */ avio_rl16(pb); /* priority */ avio_rl16(pb); /* language */ avio_rl32(pb); /* initial frame */ ast->scale = avio_rl32(pb); - ast->rate = avio_rl32(pb); - if(!(ast->scale && ast->rate)){ - av_log(s, AV_LOG_WARNING, "scale/rate is %u/%u which is invalid. (This file has been generated by broken software.)\n", ast->scale, ast->rate); - if(frame_period){ - ast->rate = 1000000; + ast->rate = avio_rl32(pb); + if (!(ast->scale && ast->rate)) { + av_log(s, AV_LOG_WARNING, + "scale/rate is %u/%u which is invalid. " + "(This file has been generated by broken software.)\n", + ast->scale, + ast->rate); + if (frame_period) { + ast->rate = 1000000; ast->scale = frame_period; - }else{ - ast->rate = 25; + } else { + ast->rate = 25; ast->scale = 1; } } avpriv_set_pts_info(st, 64, ast->scale, ast->rate); - ast->cum_len=avio_rl32(pb); /* start */ + ast->cum_len = avio_rl32(pb); /* start */ st->nb_frames = avio_rl32(pb); st->start_time = 0; @@ -548,11 +578,11 @@ static int avi_read_header(AVFormatContext *s) return AVERROR_INVALIDDATA; } ast->sample_size = avio_rl32(pb); /* sample ssize */ - ast->cum_len *= FFMAX(1, ast->sample_size); + ast->cum_len *= FFMAX(1, ast->sample_size); av_dlog(s, "%"PRIu32" %"PRIu32" %d\n", ast->rate, ast->scale, ast->sample_size); - switch(tag1) { + switch (tag1) { case MKTAG('v', 'i', 'd', 's'): codec_type = AVMEDIA_TYPE_VIDEO; @@ -570,14 +600,14 @@ static int avi_read_header(AVFormatContext *s) default: av_log(s, AV_LOG_INFO, "unknown stream type %X\n", tag1); } - if(ast->sample_size == 0) { + if (ast->sample_size == 0) { st->duration = st->nb_frames; if (st->duration > 0 && avi->io_fsize > 0 && avi->riff_end > avi->io_fsize) { av_log(s, AV_LOG_DEBUG, "File is truncated adjusting duration\n"); st->duration = av_rescale(st->duration, avi->io_fsize, avi->riff_end); } } - ast->frame_offset= ast->cum_len; + ast->frame_offset = ast->cum_len; avio_skip(pb, size - 12 * 4); break; case MKTAG('s', 't', 'r', 'f'): @@ -592,49 +622,59 @@ static int avi_read_header(AVFormatContext *s) if (cur_pos < list_end) size = FFMIN(size, list_end - cur_pos); st = s->streams[stream_index]; - switch(codec_type) { + switch (codec_type) { case AVMEDIA_TYPE_VIDEO: - if(amv_file_format){ - st->codec->width=avih_width; - st->codec->height=avih_height; + if (amv_file_format) { + st->codec->width = avih_width; + st->codec->height = avih_height; st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_AMV; + st->codec->codec_id = AV_CODEC_ID_AMV; avio_skip(pb, size); break; } tag1 = ff_get_bmp_header(pb, st, &esize); - if (tag1 == MKTAG('D', 'X', 'S', 'B') || tag1 == MKTAG('D','X','S','A')) { + if (tag1 == MKTAG('D', 'X', 'S', 'B') || + tag1 == MKTAG('D', 'X', 'S', 'A')) { st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; - st->codec->codec_tag = tag1; - st->codec->codec_id = AV_CODEC_ID_XSUB; + st->codec->codec_tag = tag1; + st->codec->codec_id = AV_CODEC_ID_XSUB; break; } - if(size > 10*4 && size<(1<<30) && size < avi->fsize){ - if(esize == size-1 && (esize&1)) st->codec->extradata_size= esize - 10*4; - else st->codec->extradata_size= size - 10*4; - st->codec->extradata= av_malloc(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (size > 10 * 4 && size < (1 << 30) && size < avi->fsize) { + if (esize == size-1 && (esize&1)) { + st->codec->extradata_size = esize - 10 * 4; + } else + st->codec->extradata_size = size - 10 * 4; + st->codec->extradata = av_malloc(st->codec->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) { - st->codec->extradata_size= 0; + st->codec->extradata_size = 0; return AVERROR(ENOMEM); } - avio_read(pb, st->codec->extradata, st->codec->extradata_size); + avio_read(pb, + st->codec->extradata, + st->codec->extradata_size); } - if(st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly + // FIXME: check if the encoder really did this correctly + if (st->codec->extradata_size & 1) avio_r8(pb); - /* Extract palette from extradata if bpp <= 8. */ - /* This code assumes that extradata contains only palette. */ - /* This is true for all paletted codecs implemented in FFmpeg. */ - if (st->codec->extradata_size && (st->codec->bits_per_coded_sample <= 8)) { + /* Extract palette from extradata if bpp <= 8. + * This code assumes that extradata contains only palette. + * This is true for all paletted codecs implemented in + * FFmpeg. */ + if (st->codec->extradata_size && + (st->codec->bits_per_coded_sample <= 8)) { int pal_size = (1 << st->codec->bits_per_coded_sample) << 2; const uint8_t *pal_src; pal_size = FFMIN(pal_size, st->codec->extradata_size); - pal_src = st->codec->extradata + st->codec->extradata_size - pal_size; - for (i = 0; i < pal_size/4; i++) + pal_src = st->codec->extradata + + st->codec->extradata_size - pal_size; + for (i = 0; i < pal_size / 4; i++) ast->pal[i] = 0xFFU<<24 | AV_RL32(pal_src+4*i); ast->has_pal = 1; } @@ -642,17 +682,25 @@ static int avi_read_header(AVFormatContext *s) print_tag("video", tag1, 0); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_tag = tag1; - st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, tag1); - st->need_parsing = AVSTREAM_PARSE_HEADERS; // This is needed to get the pict type which is necessary for generating correct pts. - - if(st->codec->codec_tag==0 && st->codec->height > 0 && st->codec->extradata_size < 1U<<30){ - st->codec->extradata_size+= 9; - st->codec->extradata= av_realloc_f(st->codec->extradata, 1, st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - if(st->codec->extradata) - memcpy(st->codec->extradata + st->codec->extradata_size - 9, "BottomUp", 9); + st->codec->codec_tag = tag1; + st->codec->codec_id = ff_codec_get_id(ff_codec_bmp_tags, + tag1); + /* This is needed to get the pict type which is necessary + * for generating correct pts. */ + st->need_parsing = AVSTREAM_PARSE_HEADERS; + + if (st->codec->codec_tag == 0 && st->codec->height > 0 && + st->codec->extradata_size < 1U << 30) { + st->codec->extradata_size += 9; + st->codec->extradata = av_realloc_f(st->codec->extradata, + 1, + st->codec->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (st->codec->extradata) + memcpy(st->codec->extradata + st->codec->extradata_size - 9, + "BottomUp", 9); } - st->codec->height= FFABS(st->codec->height); + st->codec->height = FFABS(st->codec->height); // avio_skip(pb, size - 5 * 4); break; @@ -660,12 +708,19 @@ static int avi_read_header(AVFormatContext *s) ret = ff_get_wav_header(pb, st->codec, size); if (ret < 0) return ret; - ast->dshow_block_align= st->codec->block_align; - if(ast->sample_size && st->codec->block_align && ast->sample_size != st->codec->block_align){ - av_log(s, AV_LOG_WARNING, "sample size (%d) != block align (%d)\n", ast->sample_size, st->codec->block_align); - ast->sample_size= st->codec->block_align; + ast->dshow_block_align = st->codec->block_align; + if (ast->sample_size && st->codec->block_align && + ast->sample_size != st->codec->block_align) { + av_log(s, + AV_LOG_WARNING, + "sample size (%d) != block align (%d)\n", + ast->sample_size, + st->codec->block_align); + ast->sample_size = st->codec->block_align; } - if (size&1) /* 2-aligned (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */ + /* 2-aligned + * (fix for Stargate SG-1 - 3x18 - Shades of Grey.avi) */ + if (size & 1) avio_skip(pb, 1); /* Force parsing as several audio frames can be in * one packet and timestamps refer to packet start. */ @@ -673,24 +728,25 @@ static int avi_read_header(AVFormatContext *s) /* ADTS header is in extradata, AAC without header must be * stored as exact frames. Parser not needed and it will * fail. */ - if (st->codec->codec_id == AV_CODEC_ID_AAC && st->codec->extradata_size) + if (st->codec->codec_id == AV_CODEC_ID_AAC && + st->codec->extradata_size) st->need_parsing = AVSTREAM_PARSE_NONE; /* AVI files with Xan DPCM audio (wrongly) declare PCM * audio in the header but have Axan as stream_code_tag. */ - if (st->codec->stream_codec_tag == AV_RL32("Axan")){ + if (st->codec->stream_codec_tag == AV_RL32("Axan")) { st->codec->codec_id = AV_CODEC_ID_XAN_DPCM; st->codec->codec_tag = 0; ast->dshow_block_align = 0; } - if (amv_file_format){ - st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_AMV; + if (amv_file_format) { + st->codec->codec_id = AV_CODEC_ID_ADPCM_IMA_AMV; ast->dshow_block_align = 0; } - if(st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align <= 4 && ast->dshow_block_align) { + if (st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align <= 4 && ast->dshow_block_align) { av_log(s, AV_LOG_DEBUG, "overriding invalid dshow_block_align of %d\n", ast->dshow_block_align); ast->dshow_block_align = 0; } - if(st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 1024 && ast->sample_size == 1024 || + if (st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 1024 && ast->sample_size == 1024 || st->codec->codec_id == AV_CODEC_ID_AAC && ast->dshow_block_align == 4096 && ast->sample_size == 4096 || st->codec->codec_id == AV_CODEC_ID_MP3 && ast->dshow_block_align == 1152 && ast->sample_size == 1152) { av_log(s, AV_LOG_DEBUG, "overriding sample_size\n"); @@ -704,15 +760,17 @@ static int avi_read_header(AVFormatContext *s) break; default: st->codec->codec_type = AVMEDIA_TYPE_DATA; - st->codec->codec_id= AV_CODEC_ID_NONE; - st->codec->codec_tag= 0; + st->codec->codec_id = AV_CODEC_ID_NONE; + st->codec->codec_tag = 0; avio_skip(pb, size); break; } } break; case MKTAG('s', 't', 'r', 'd'): - if (stream_index >= (unsigned)s->nb_streams || s->streams[stream_index]->codec->extradata_size) { + if (stream_index >= (unsigned)s->nb_streams + || s->streams[stream_index]->codec->extradata_size + || s->streams[stream_index]->codec->codec_tag == MKTAG('H','2','6','4')) { avio_skip(pb, size); } else { uint64_t cur_pos = avio_tell(pb); @@ -720,7 +778,7 @@ static int avi_read_header(AVFormatContext *s) size = FFMIN(size, list_end - cur_pos); st = s->streams[stream_index]; - if(size<(1<<30)){ + if (size<(1<<30)) { st->codec->extradata_size= size; st->codec->extradata= av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); if (!st->codec->extradata) { @@ -730,19 +788,21 @@ static int avi_read_header(AVFormatContext *s) avio_read(pb, st->codec->extradata, st->codec->extradata_size); } - if(st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly + if (st->codec->extradata_size & 1) //FIXME check if the encoder really did this correctly avio_r8(pb); } break; case MKTAG('i', 'n', 'd', 'x'): - i= avio_tell(pb); - if(pb->seekable && !(s->flags & AVFMT_FLAG_IGNIDX) && avi->use_odml && - read_braindead_odml_indx(s, 0) < 0 && (s->error_recognition & AV_EF_EXPLODE)) + i = avio_tell(pb); + if (pb->seekable && !(s->flags & AVFMT_FLAG_IGNIDX) && + avi->use_odml && + read_braindead_odml_indx(s, 0) < 0 && + (s->error_recognition & AV_EF_EXPLODE)) goto fail; - avio_seek(pb, i+size, SEEK_SET); + avio_seek(pb, i + size, SEEK_SET); break; case MKTAG('v', 'p', 'r', 'p'): - if(stream_index < (unsigned)s->nb_streams && size > 9*4){ + if (stream_index < (unsigned)s->nb_streams && size > 9 * 4) { AVRational active, active_aspect; st = s->streams[stream_index]; @@ -752,33 +812,35 @@ static int avi_read_header(AVFormatContext *s) avio_rl32(pb); avio_rl32(pb); - active_aspect.den= avio_rl16(pb); - active_aspect.num= avio_rl16(pb); - active.num = avio_rl32(pb); - active.den = avio_rl32(pb); - avio_rl32(pb); //nbFieldsPerFrame + active_aspect.den = avio_rl16(pb); + active_aspect.num = avio_rl16(pb); + active.num = avio_rl32(pb); + active.den = avio_rl32(pb); + avio_rl32(pb); // nbFieldsPerFrame - if(active_aspect.num && active_aspect.den && active.num && active.den){ - st->sample_aspect_ratio= av_div_q(active_aspect, active); + if (active_aspect.num && active_aspect.den && + active.num && active.den) { + st->sample_aspect_ratio = av_div_q(active_aspect, active); av_dlog(s, "vprp %d/%d %d/%d\n", active_aspect.num, active_aspect.den, active.num, active.den); } - size -= 9*4; + size -= 9 * 4; } avio_skip(pb, size); break; case MKTAG('s', 't', 'r', 'n'): - if(s->nb_streams){ - ret = avi_read_tag(s, s->streams[s->nb_streams-1], tag, size); + if (s->nb_streams) { + ret = avi_read_tag(s, s->streams[s->nb_streams - 1], tag, size); if (ret < 0) return ret; break; } default: - if(size > 1000000){ - av_log(s, AV_LOG_ERROR, "Something went wrong during header parsing, " - "I will ignore it and try to continue anyway.\n"); + if (size > 1000000) { + av_log(s, AV_LOG_ERROR, + "Something went wrong during header parsing, " + "I will ignore it and try to continue anyway.\n"); if (s->error_recognition & AV_EF_EXPLODE) goto fail; avi->movi_list = avio_tell(pb) - 4; @@ -791,32 +853,45 @@ static int avi_read_header(AVFormatContext *s) break; } } - end_of_header: + +end_of_header: /* check stream number */ if (stream_index != s->nb_streams - 1) { - fail: + +fail: return AVERROR_INVALIDDATA; } - if(!avi->index_loaded && pb->seekable) + if (!avi->index_loaded && pb->seekable) avi_load_index(s); - avi->index_loaded |= 1; + avi->index_loaded |= 1; avi->non_interleaved |= guess_ni_flag(s) | (s->flags & AVFMT_FLAG_SORT_DTS); - for(i=0; i<s->nb_streams; i++){ + + dict_entry = av_dict_get(s->metadata, "ISFT", NULL, 0); + if (dict_entry && !strcmp(dict_entry->value, "PotEncoder")) + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + if ( st->codec->codec_id == AV_CODEC_ID_MPEG1VIDEO + || st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) + st->need_parsing = AVSTREAM_PARSE_FULL; + } + + for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if(st->nb_index_entries) + if (st->nb_index_entries) break; } // DV-in-AVI cannot be non-interleaved, if set this must be // a mis-detection. - if(avi->dv_demux) - avi->non_interleaved=0; - if(i==s->nb_streams && avi->non_interleaved) { - av_log(s, AV_LOG_WARNING, "non-interleaved AVI without index, switching to interleaved\n"); - avi->non_interleaved=0; + if (avi->dv_demux) + avi->non_interleaved = 0; + if (i == s->nb_streams && avi->non_interleaved) { + av_log(s, AV_LOG_WARNING, + "Non-interleaved AVI without index, switching to interleaved\n"); + avi->non_interleaved = 0; } - if(avi->non_interleaved) { + if (avi->non_interleaved) { av_log(s, AV_LOG_INFO, "non-interleaved AVI\n"); clean_index(s); } @@ -827,16 +902,17 @@ static int avi_read_header(AVFormatContext *s) return 0; } -static int read_gab2_sub(AVStream *st, AVPacket *pkt) { - if (pkt->data && !strcmp(pkt->data, "GAB2") && AV_RL16(pkt->data+5) == 2) { +static int read_gab2_sub(AVStream *st, AVPacket *pkt) +{ + if (pkt->data && !strcmp(pkt->data, "GAB2") && AV_RL16(pkt->data + 5) == 2) { uint8_t desc[256]; - int score = AVPROBE_SCORE_MAX / 2, ret; + int score = AVPROBE_SCORE_EXTENSION, ret; AVIStream *ast = st->priv_data; AVInputFormat *sub_demuxer; AVRational time_base; - AVIOContext *pb = avio_alloc_context( pkt->data + 7, - pkt->size - 7, - 0, NULL, NULL, NULL, NULL); + AVIOContext *pb = avio_alloc_context(pkt->data + 7, + pkt->size - 7, + 0, NULL, NULL, NULL, NULL); AVProbeData pd; unsigned int desc_len = avio_rl32(pb); @@ -851,14 +927,15 @@ static int read_gab2_sub(AVStream *st, AVPacket *pkt) { avio_rl16(pb); /* flags? */ avio_rl32(pb); /* data size */ - pd = (AVProbeData) { .buf = pb->buf_ptr, .buf_size = pb->buf_end - pb->buf_ptr }; + pd = (AVProbeData) { .buf = pb->buf_ptr, + .buf_size = pb->buf_end - pb->buf_ptr }; if (!(sub_demuxer = av_probe_input_format2(&pd, 1, &score))) goto error; if (!(ast->sub_ctx = avformat_alloc_context())) goto error; - ast->sub_ctx->pb = pb; + ast->sub_ctx->pb = pb; if (!avformat_open_input(&ast->sub_ctx, "", sub_demuxer, NULL)) { ff_read_packet(ast->sub_ctx, &ast->sub_pkt); *st->codec = *ast->sub_ctx->streams[0]->codec; @@ -869,6 +946,7 @@ static int read_gab2_sub(AVStream *st, AVPacket *pkt) { ast->sub_buffer = pkt->data; memset(pkt, 0, sizeof(*pkt)); return 1; + error: av_freep(&pb); } @@ -886,7 +964,7 @@ static AVStream *get_subtitle_pkt(AVFormatContext *s, AVStream *next_st, next_ts = av_rescale_q(next_ast->frame_offset, next_st->time_base, AV_TIME_BASE_Q); - for (i=0; i<s->nb_streams; i++) { + for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; ast = st->priv_data; if (st->discard < AVDISCARD_ALL && ast && ast->sub_pkt.data) { @@ -899,21 +977,23 @@ static AVStream *get_subtitle_pkt(AVFormatContext *s, AVStream *next_st, } if (sub_st) { - ast = sub_st->priv_data; - *pkt = ast->sub_pkt; + ast = sub_st->priv_data; + *pkt = ast->sub_pkt; pkt->stream_index = sub_st->index; + if (ff_read_packet(ast->sub_ctx, &ast->sub_pkt) < 0) ast->sub_pkt.data = NULL; } return sub_st; } -static int get_stream_idx(int *d){ - if( d[0] >= '0' && d[0] <= '9' - && d[1] >= '0' && d[1] <= '9'){ +static int get_stream_idx(int *d) +{ + if (d[0] >= '0' && d[0] <= '9' && + d[1] >= '0' && d[1] <= '9') { return (d[0] - '0') * 10 + (d[1] - '0'); - }else{ - return 100; //invalid stream ID + } else { + return 100; // invalid stream ID } } @@ -932,52 +1012,53 @@ static int avi_sync(AVFormatContext *s, int exit_early) start_sync: memset(d, -1, sizeof(d)); - for(i=sync=avio_tell(pb); !url_feof(pb); i++) { + for (i = sync = avio_tell(pb); !url_feof(pb); i++) { int j; - for(j=0; j<7; j++) - d[j]= d[j+1]; - d[7]= avio_r8(pb); + for (j = 0; j < 7; j++) + d[j] = d[j + 1]; + d[7] = avio_r8(pb); - size= d[4] + (d[5]<<8) + (d[6]<<16) + (d[7]<<24); + size = d[4] + (d[5] << 8) + (d[6] << 16) + (d[7] << 24); - n= get_stream_idx(d+2); + n = get_stream_idx(d + 2); av_dlog(s, "%X %X %X %X %X %X %X %X %"PRId64" %u %d\n", d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7], i, size, n); - if(i*(avi->io_fsize>0) + (uint64_t)size > avi->fsize || d[0] > 127) + if (i*(avi->io_fsize>0) + (uint64_t)size > avi->fsize || d[0] > 127) continue; - //parse ix## - if( (d[0] == 'i' && d[1] == 'x' && n < s->nb_streams) - //parse JUNK - ||(d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K') - ||(d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1')){ + // parse ix## + if ((d[0] == 'i' && d[1] == 'x' && n < s->nb_streams) || + // parse JUNK + (d[0] == 'J' && d[1] == 'U' && d[2] == 'N' && d[3] == 'K') || + (d[0] == 'i' && d[1] == 'd' && d[2] == 'x' && d[3] == '1')) { avio_skip(pb, size); goto start_sync; } - //parse stray LIST - if(d[0] == 'L' && d[1] == 'I' && d[2] == 'S' && d[3] == 'T'){ + // parse stray LIST + if (d[0] == 'L' && d[1] == 'I' && d[2] == 'S' && d[3] == 'T') { avio_skip(pb, 4); goto start_sync; } - n= get_stream_idx(d); + n = get_stream_idx(d); - if(!((i-avi->last_pkt_pos)&1) && get_stream_idx(d+1) < s->nb_streams) + if (!((i - avi->last_pkt_pos) & 1) && + get_stream_idx(d + 1) < s->nb_streams) continue; - //detect ##ix chunk and skip - if(d[2] == 'i' && d[3] == 'x' && n < s->nb_streams){ + // detect ##ix chunk and skip + if (d[2] == 'i' && d[3] == 'x' && n < s->nb_streams) { avio_skip(pb, size); goto start_sync; } - //parse ##dc/##wb - if(n < s->nb_streams){ + // parse ##dc/##wb + if (n < s->nb_streams) { AVStream *st; AVIStream *ast; - st = s->streams[n]; + st = s->streams[n]; ast = st->priv_data; if (!ast) { @@ -985,67 +1066,74 @@ start_sync: continue; } - if(s->nb_streams>=2){ - AVStream *st1 = s->streams[1]; - AVIStream *ast1= st1->priv_data; - //workaround for broken small-file-bug402.avi - if( d[2] == 'w' && d[3] == 'b' - && n==0 + if (s->nb_streams >= 2) { + AVStream *st1 = s->streams[1]; + AVIStream *ast1 = st1->priv_data; + // workaround for broken small-file-bug402.avi + if ( d[2] == 'w' && d[3] == 'b' + && n == 0 && st ->codec->codec_type == AVMEDIA_TYPE_VIDEO && st1->codec->codec_type == AVMEDIA_TYPE_AUDIO && ast->prefix == 'd'*256+'c' && (d[2]*256+d[3] == ast1->prefix || !ast1->prefix_count) - ){ - n=1; - st = st1; + ) { + n = 1; + st = st1; ast = ast1; - av_log(s, AV_LOG_WARNING, "Invalid stream + prefix combination, assuming audio.\n"); + av_log(s, AV_LOG_WARNING, + "Invalid stream + prefix combination, assuming audio.\n"); } } - - if( (st->discard >= AVDISCARD_DEFAULT && size==0) - /*|| (st->discard >= AVDISCARD_NONKEY && !(pkt->flags & AV_PKT_FLAG_KEY))*/ //FIXME needs a little reordering - || st->discard >= AVDISCARD_ALL){ + if (!avi->dv_demux && + ((st->discard >= AVDISCARD_DEFAULT && size == 0) /* || + // FIXME: needs a little reordering + (st->discard >= AVDISCARD_NONKEY && + !(pkt->flags & AV_PKT_FLAG_KEY)) */ + || st->discard >= AVDISCARD_ALL)) { if (!exit_early) { ast->frame_offset += get_duration(ast, size); + avio_skip(pb, size); + goto start_sync; } - avio_skip(pb, size); - goto start_sync; } - if (d[2] == 'p' && d[3] == 'c' && size<=4*256+4) { - int k = avio_r8(pb); + if (d[2] == 'p' && d[3] == 'c' && size <= 4 * 256 + 4) { + int k = avio_r8(pb); int last = (k + avio_r8(pb) - 1) & 0xFF; - avio_rl16(pb); //flags + avio_rl16(pb); // flags + // b + (g << 8) + (r << 16); for (; k <= last; k++) - ast->pal[k] = 0xFFU<<24 | avio_rb32(pb)>>8;// b + (g << 8) + (r << 16); - ast->has_pal= 1; - goto start_sync; - } else if( ((ast->prefix_count<5 || sync+9 > i) && d[2]<128 && d[3]<128) || - d[2]*256+d[3] == ast->prefix /*|| - (d[2] == 'd' && d[3] == 'c') || - (d[2] == 'w' && d[3] == 'b')*/) { + ast->pal[k] = 0xFFU<<24 | avio_rb32(pb)>>8; + ast->has_pal = 1; + goto start_sync; + } else if (((ast->prefix_count < 5 || sync + 9 > i) && + d[2] < 128 && d[3] < 128) || + d[2] * 256 + d[3] == ast->prefix /* || + (d[2] == 'd' && d[3] == 'c') || + (d[2] == 'w' && d[3] == 'b') */) { if (exit_early) return 0; - if(d[2]*256+d[3] == ast->prefix) + if (d[2] * 256 + d[3] == ast->prefix) ast->prefix_count++; - else{ - ast->prefix= d[2]*256+d[3]; - ast->prefix_count= 0; + else { + ast->prefix = d[2] * 256 + d[3]; + ast->prefix_count = 0; } - avi->stream_index= n; - ast->packet_size= size + 8; - ast->remaining= size; + avi->stream_index = n; + ast->packet_size = size + 8; + ast->remaining = size; - if(size || !ast->sample_size){ - uint64_t pos= avio_tell(pb) - 8; - if(!st->index_entries || !st->nb_index_entries || st->index_entries[st->nb_index_entries - 1].pos < pos){ - av_add_index_entry(st, pos, ast->frame_offset, size, 0, AVINDEX_KEYFRAME); + if (size || !ast->sample_size) { + uint64_t pos = avio_tell(pb) - 8; + if (!st->index_entries || !st->nb_index_entries || + st->index_entries[st->nb_index_entries - 1].pos < pos) { + av_add_index_entry(st, pos, ast->frame_offset, size, + 0, AVINDEX_KEYFRAME); } } return 0; @@ -1053,7 +1141,7 @@ start_sync: } } - if(pb->error) + if (pb->error) return pb->error; return AVERROR_EOF; } @@ -1064,7 +1152,7 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; int err; #if FF_API_DESTRUCT_PACKET - void* dstr; + void *dstr; #endif if (CONFIG_DV_DEMUXER && avi->dv_demux) { @@ -1073,97 +1161,106 @@ static int avi_read_packet(AVFormatContext *s, AVPacket *pkt) return size; } - if(avi->non_interleaved){ + if (avi->non_interleaved) { int best_stream_index = 0; - AVStream *best_st= NULL; + AVStream *best_st = NULL; AVIStream *best_ast; - int64_t best_ts= INT64_MAX; + int64_t best_ts = INT64_MAX; int i; - for(i=0; i<s->nb_streams; i++){ - AVStream *st = s->streams[i]; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; AVIStream *ast = st->priv_data; - int64_t ts= ast->frame_offset; + int64_t ts = ast->frame_offset; int64_t last_ts; - if(!st->nb_index_entries) + if (!st->nb_index_entries) continue; last_ts = st->index_entries[st->nb_index_entries - 1].timestamp; - if(!ast->remaining && ts > last_ts) + if (!ast->remaining && ts > last_ts) continue; - ts = av_rescale_q(ts, st->time_base, (AVRational){FFMAX(1, ast->sample_size), AV_TIME_BASE}); + ts = av_rescale_q(ts, st->time_base, + (AVRational) { FFMAX(1, ast->sample_size), + AV_TIME_BASE }); av_dlog(s, "%"PRId64" %d/%d %"PRId64"\n", ts, st->time_base.num, st->time_base.den, ast->frame_offset); - if(ts < best_ts){ - best_ts= ts; - best_st= st; - best_stream_index= i; + if (ts < best_ts) { + best_ts = ts; + best_st = st; + best_stream_index = i; } } - if(!best_st) + if (!best_st) return AVERROR_EOF; best_ast = best_st->priv_data; - best_ts = best_ast->frame_offset; - if(best_ast->remaining) - i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY | AVSEEK_FLAG_BACKWARD); - else{ - i= av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY); - if(i>=0) - best_ast->frame_offset= best_st->index_entries[i].timestamp; + best_ts = best_ast->frame_offset; + if (best_ast->remaining) { + i = av_index_search_timestamp(best_st, + best_ts, + AVSEEK_FLAG_ANY | + AVSEEK_FLAG_BACKWARD); + } else { + i = av_index_search_timestamp(best_st, best_ts, AVSEEK_FLAG_ANY); + if (i >= 0) + best_ast->frame_offset = best_st->index_entries[i].timestamp; } - if(i>=0){ - int64_t pos= best_st->index_entries[i].pos; + if (i >= 0) { + int64_t pos = best_st->index_entries[i].pos; pos += best_ast->packet_size - best_ast->remaining; - if(avio_seek(s->pb, pos + 8, SEEK_SET) < 0) + if (avio_seek(s->pb, pos + 8, SEEK_SET) < 0) return AVERROR_EOF; av_assert0(best_ast->remaining <= best_ast->packet_size); - avi->stream_index= best_stream_index; - if(!best_ast->remaining) - best_ast->packet_size= - best_ast->remaining= best_st->index_entries[i].size; + avi->stream_index = best_stream_index; + if (!best_ast->remaining) + best_ast->packet_size = + best_ast->remaining = best_st->index_entries[i].size; } else return AVERROR_EOF; } resync: - if(avi->stream_index >= 0){ - AVStream *st= s->streams[ avi->stream_index ]; - AVIStream *ast= st->priv_data; + if (avi->stream_index >= 0) { + AVStream *st = s->streams[avi->stream_index]; + AVIStream *ast = st->priv_data; int size, err; - if(get_subtitle_pkt(s, st, pkt)) + if (get_subtitle_pkt(s, st, pkt)) return 0; - if(ast->sample_size <= 1) // minorityreport.AVI block_align=1024 sample_size=1 IMA-ADPCM - size= INT_MAX; - else if(ast->sample_size < 32) + // minorityreport.AVI block_align=1024 sample_size=1 IMA-ADPCM + if (ast->sample_size <= 1) + size = INT_MAX; + else if (ast->sample_size < 32) // arbitrary multiplier to avoid tiny packets for raw PCM data - size= 1024*ast->sample_size; + size = 1024 * ast->sample_size; else - size= ast->sample_size; + size = ast->sample_size; - if(size > ast->remaining) - size= ast->remaining; - avi->last_pkt_pos= avio_tell(pb); - err= av_get_packet(pb, pkt, size); - if(err<0) + if (size > ast->remaining) + size = ast->remaining; + avi->last_pkt_pos = avio_tell(pb); + err = av_get_packet(pb, pkt, size); + if (err < 0) return err; size = err; - if(ast->has_pal && pkt->size<(unsigned)INT_MAX/2){ + if (ast->has_pal && pkt->size < (unsigned)INT_MAX / 2) { uint8_t *pal; - pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); - if(!pal){ - av_log(s, AV_LOG_ERROR, "Failed to allocate data for palette\n"); - }else{ + pal = av_packet_new_side_data(pkt, + AV_PKT_DATA_PALETTE, + AVPALETTE_SIZE); + if (!pal) { + av_log(s, AV_LOG_ERROR, + "Failed to allocate data for palette\n"); + } else { memcpy(pal, ast->pal, AVPALETTE_SIZE); ast->has_pal = 0; } @@ -1172,32 +1269,44 @@ resync: if (CONFIG_DV_DEMUXER && avi->dv_demux) { AVBufferRef *avbuf = pkt->buf; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS dstr = pkt->destruct; +FF_ENABLE_DEPRECATION_WARNINGS #endif size = avpriv_dv_produce_packet(avi->dv_demux, pkt, - pkt->data, pkt->size, pkt->pos); + pkt->data, pkt->size, pkt->pos); #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS pkt->destruct = dstr; +FF_ENABLE_DEPRECATION_WARNINGS #endif - pkt->buf = avbuf; + pkt->buf = avbuf; pkt->flags |= AV_PKT_FLAG_KEY; if (size < 0) av_free_packet(pkt); - } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE - && !st->codec->codec_tag && read_gab2_sub(st, pkt)) { + } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE && + !st->codec->codec_tag && read_gab2_sub(st, pkt)) { ast->frame_offset++; avi->stream_index = -1; - ast->remaining = 0; + ast->remaining = 0; goto resync; } else { /* XXX: How to handle B-frames in AVI? */ pkt->dts = ast->frame_offset; // pkt->dts += ast->start; - if(ast->sample_size) + if (ast->sample_size) pkt->dts /= ast->sample_size; - av_dlog(s, "dts:%"PRId64" offset:%"PRId64" %d/%d smpl_siz:%d base:%d st:%d size:%d\n", - pkt->dts, ast->frame_offset, ast->scale, ast->rate, - ast->sample_size, AV_TIME_BASE, avi->stream_index, size); + av_dlog(s, + "dts:%"PRId64" offset:%"PRId64" %d/%d smpl_siz:%d " + "base:%d st:%d size:%d\n", + pkt->dts, + ast->frame_offset, + ast->scale, + ast->rate, + ast->sample_size, + AV_TIME_BASE, + avi->stream_index, + size); pkt->stream_index = avi->stream_index; if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { @@ -1205,17 +1314,17 @@ resync: int index; av_assert0(st->index_entries); - index= av_index_search_timestamp(st, ast->frame_offset, 0); - e= &st->index_entries[index]; + index = av_index_search_timestamp(st, ast->frame_offset, 0); + e = &st->index_entries[index]; - if(index >= 0 && e->timestamp == ast->frame_offset){ - if (index == st->nb_index_entries-1){ + if (index >= 0 && e->timestamp == ast->frame_offset) { + if (index == st->nb_index_entries-1) { int key=1; int i; uint32_t state=-1; - for(i=0; i<FFMIN(size,256); i++){ - if(st->codec->codec_id == AV_CODEC_ID_MPEG4){ - if(state == 0x1B6){ + for (i=0; i<FFMIN(size,256); i++) { + if (st->codec->codec_id == AV_CODEC_ID_MPEG4) { + if (state == 0x1B6) { key= !(pkt->data[i]&0xC0); break; } @@ -1223,7 +1332,7 @@ resync: break; state= (state<<8) + pkt->data[i]; } - if(!key) + if (!key) e->flags &= ~AVINDEX_KEYFRAME; } if (e->flags & AVINDEX_KEYFRAME) @@ -1235,24 +1344,24 @@ resync: ast->frame_offset += get_duration(ast, pkt->size); } ast->remaining -= err; - if(!ast->remaining){ - avi->stream_index= -1; - ast->packet_size= 0; + if (!ast->remaining) { + avi->stream_index = -1; + ast->packet_size = 0; } - if(!avi->non_interleaved && pkt->pos >= 0 && ast->seek_pos > pkt->pos){ + if (!avi->non_interleaved && pkt->pos >= 0 && ast->seek_pos > pkt->pos) { av_free_packet(pkt); goto resync; } ast->seek_pos= 0; - if(!avi->non_interleaved && st->nb_index_entries>1 && avi->index_loaded>1){ + if (!avi->non_interleaved && st->nb_index_entries>1 && avi->index_loaded>1) { int64_t dts= av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q); - if(avi->dts_max - dts > 2*AV_TIME_BASE){ + if (avi->dts_max - dts > 2*AV_TIME_BASE) { avi->non_interleaved= 1; av_log(s, AV_LOG_INFO, "Switching to NI mode, due to poor interleaving\n"); - }else if(avi->dts_max < dts) + }else if (avi->dts_max < dts) avi->dts_max = dts; } @@ -1265,7 +1374,7 @@ resync: } /* XXX: We make the implicit supposition that the positions are sorted - for each stream. */ + * for each stream. */ static int avi_read_idx1(AVFormatContext *s, int size) { AVIContext *avi = s->priv_data; @@ -1274,8 +1383,8 @@ static int avi_read_idx1(AVFormatContext *s, int size) AVStream *st; AVIStream *ast; unsigned int index, tag, flags, pos, len, first_packet = 1; - unsigned last_pos= -1; - unsigned last_idx= -1; + unsigned last_pos = -1; + unsigned last_idx = -1; int64_t idx1_pos, first_packet_pos = 0, data_offset = 0; int anykey = 0; @@ -1284,39 +1393,38 @@ static int avi_read_idx1(AVFormatContext *s, int size) return AVERROR_INVALIDDATA; idx1_pos = avio_tell(pb); - avio_seek(pb, avi->movi_list+4, SEEK_SET); - if (avi_sync(s, 1) == 0) { + avio_seek(pb, avi->movi_list + 4, SEEK_SET); + if (avi_sync(s, 1) == 0) first_packet_pos = avio_tell(pb) - 8; - } avi->stream_index = -1; avio_seek(pb, idx1_pos, SEEK_SET); - if (s->nb_streams == 1 && s->streams[0]->codec->codec_tag == AV_RL32("MMES")){ + if (s->nb_streams == 1 && s->streams[0]->codec->codec_tag == AV_RL32("MMES")) { first_packet_pos = 0; data_offset = avi->movi_list; } /* Read the entries and sort them in each stream component. */ - for(i = 0; i < nb_index_entries; i++) { - if(url_feof(pb)) + for (i = 0; i < nb_index_entries; i++) { + if (url_feof(pb)) return -1; - tag = avio_rl32(pb); + tag = avio_rl32(pb); flags = avio_rl32(pb); - pos = avio_rl32(pb); - len = avio_rl32(pb); + pos = avio_rl32(pb); + len = avio_rl32(pb); av_dlog(s, "%d: tag=0x%x flags=0x%x pos=0x%x len=%d/", i, tag, flags, pos, len); - index = ((tag & 0xff) - '0') * 10; - index += ((tag >> 8) & 0xff) - '0'; + index = ((tag & 0xff) - '0') * 10; + index += (tag >> 8 & 0xff) - '0'; if (index >= s->nb_streams) continue; - st = s->streams[index]; + st = s->streams[index]; ast = st->priv_data; - if(first_packet && first_packet_pos && len) { - data_offset = first_packet_pos - pos; + if (first_packet && first_packet_pos && len) { + data_offset = first_packet_pos - pos; first_packet = 0; } pos += data_offset; @@ -1325,15 +1433,16 @@ static int avi_read_idx1(AVFormatContext *s, int size) // even if we have only a single stream, we should // switch to non-interleaved to get correct timestamps - if(last_pos == pos) - avi->non_interleaved= 1; - if(last_idx != pos && len) { - av_add_index_entry(st, pos, ast->cum_len, len, 0, (flags&AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0); + if (last_pos == pos) + avi->non_interleaved = 1; + if (last_idx != pos && len) { + av_add_index_entry(st, pos, ast->cum_len, len, 0, + (flags & AVIIF_INDEX) ? AVINDEX_KEYFRAME : 0); last_idx= pos; } ast->cum_len += get_duration(ast, len); - last_pos= pos; - anykey |= flags&AVIIF_INDEX; + last_pos = pos; + anykey |= flags&AVIIF_INDEX; } if (!anykey) { for (index = 0; index < s->nb_streams; index++) { @@ -1345,34 +1454,35 @@ static int avi_read_idx1(AVFormatContext *s, int size) return 0; } -static int guess_ni_flag(AVFormatContext *s){ +static int guess_ni_flag(AVFormatContext *s) +{ int i; - int64_t last_start=0; - int64_t first_end= INT64_MAX; - int64_t oldpos= avio_tell(s->pb); + int64_t last_start = 0; + int64_t first_end = INT64_MAX; + int64_t oldpos = avio_tell(s->pb); int *idx; int64_t min_pos, pos; - for(i=0; i<s->nb_streams; i++){ + for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - int n= st->nb_index_entries; + int n = st->nb_index_entries; unsigned int size; - if(n <= 0) + if (n <= 0) continue; - if(n >= 2){ - int64_t pos= st->index_entries[0].pos; + if (n >= 2) { + int64_t pos = st->index_entries[0].pos; avio_seek(s->pb, pos + 4, SEEK_SET); - size= avio_rl32(s->pb); - if(pos + size > st->index_entries[1].pos) - last_start= INT64_MAX; + size = avio_rl32(s->pb); + if (pos + size > st->index_entries[1].pos) + last_start = INT64_MAX; } - if(st->index_entries[0].pos > last_start) - last_start= st->index_entries[0].pos; - if(st->index_entries[n-1].pos < first_end) - first_end= st->index_entries[n-1].pos; + if (st->index_entries[0].pos > last_start) + last_start = st->index_entries[0].pos; + if (st->index_entries[n - 1].pos < first_end) + first_end = st->index_entries[n - 1].pos; } avio_seek(s->pb, oldpos, SEEK_SET); if (last_start > first_end) @@ -1384,17 +1494,18 @@ static int guess_ni_flag(AVFormatContext *s){ for (i=0; i<s->nb_streams; i++) { AVStream *st = s->streams[i]; + AVIStream *ast = st->priv_data; int n= st->nb_index_entries; while (idx[i]<n && st->index_entries[idx[i]].pos < pos) idx[i]++; if (idx[i] < n) { - min_dts = FFMIN(min_dts, av_rescale_q(st->index_entries[idx[i]].timestamp, st->time_base, AV_TIME_BASE_Q)); + min_dts = FFMIN(min_dts, av_rescale_q(st->index_entries[idx[i]].timestamp/FFMAX(ast->sample_size, 1), st->time_base, AV_TIME_BASE_Q)); min_pos = FFMIN(min_pos, st->index_entries[idx[i]].pos); } if (idx[i]) - max_dts = FFMAX(max_dts, av_rescale_q(st->index_entries[idx[i]-1].timestamp, st->time_base, AV_TIME_BASE_Q)); + max_dts = FFMAX(max_dts, av_rescale_q(st->index_entries[idx[i]-1].timestamp/FFMAX(ast->sample_size, 1), st->time_base, AV_TIME_BASE_Q)); } - if(max_dts - min_dts > 2*AV_TIME_BASE) { + if (max_dts - min_dts > 2*AV_TIME_BASE) { av_free(idx); return 1; } @@ -1408,15 +1519,15 @@ static int avi_load_index(AVFormatContext *s) AVIContext *avi = s->priv_data; AVIOContext *pb = s->pb; uint32_t tag, size; - int64_t pos= avio_tell(pb); + int64_t pos = avio_tell(pb); int64_t next; - int ret = -1; + int ret = -1; if (avio_seek(pb, avi->movi_end, SEEK_SET) < 0) goto the_end; // maybe truncated file av_dlog(s, "movi_end=0x%"PRIx64"\n", avi->movi_end); - for(;;) { - tag = avio_rl32(pb); + for (;;) { + tag = avio_rl32(pb); size = avio_rl32(pb); if (url_feof(pb)) break; @@ -1433,18 +1544,19 @@ static int avi_load_index(AVFormatContext *s) avi_read_idx1(s, size) >= 0) { avi->index_loaded=2; ret = 0; - }else if(tag == MKTAG('L', 'I', 'S', 'T')) { + }else if (tag == MKTAG('L', 'I', 'S', 'T')) { uint32_t tag1 = avio_rl32(pb); if (tag1 == MKTAG('I', 'N', 'F', 'O')) ff_read_riff_info(s, size - 4); - }else if(!ret) + }else if (!ret) break; if (avio_seek(pb, next, SEEK_SET) < 0) break; // something is wrong here } - the_end: + +the_end: avio_seek(pb, pos, SEEK_SET); return ret; } @@ -1452,14 +1564,15 @@ static int avi_load_index(AVFormatContext *s) static void seek_subtitle(AVStream *st, AVStream *st2, int64_t timestamp) { AVIStream *ast2 = st2->priv_data; - int64_t ts2 = av_rescale_q(timestamp, st->time_base, st2->time_base); + int64_t ts2 = av_rescale_q(timestamp, st->time_base, st2->time_base); av_free_packet(&ast2->sub_pkt); if (avformat_seek_file(ast2->sub_ctx, 0, INT64_MIN, ts2, ts2, 0) >= 0 || avformat_seek_file(ast2->sub_ctx, 0, ts2, ts2, INT64_MAX, 0) >= 0) ff_read_packet(ast2->sub_ctx, &ast2->sub_pkt); } -static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +static int avi_read_seek(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) { AVIContext *avi = s->priv_data; AVStream *st; @@ -1472,12 +1585,14 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp avi_load_index(s); avi->index_loaded |= 1; } - av_assert0(stream_index>= 0); - - st = s->streams[stream_index]; - ast= st->priv_data; - index= av_index_search_timestamp(st, timestamp * FFMAX(ast->sample_size, 1), flags); - if (index<0) { + av_assert0(stream_index >= 0); + + st = s->streams[stream_index]; + ast = st->priv_data; + index = av_index_search_timestamp(st, + timestamp * FFMAX(ast->sample_size, 1), + flags); + if (index < 0) { if (st->nb_index_entries > 0) av_log(s, AV_LOG_DEBUG, "Failed to find timestamp %"PRId64 " in index %"PRId64 " .. %"PRId64 "\n", timestamp * FFMAX(ast->sample_size, 1), @@ -1487,7 +1602,7 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp } /* find the position */ - pos = st->index_entries[index].pos; + pos = st->index_entries[index].pos; timestamp = st->index_entries[index].timestamp / FFMAX(ast->sample_size, 1); av_dlog(s, "XX %"PRId64" %d %"PRId64"\n", @@ -1499,24 +1614,24 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp /* the av_index_search_timestamp call above. */ av_assert0(stream_index == 0); - if(avio_seek(s->pb, pos, SEEK_SET) < 0) + if (avio_seek(s->pb, pos, SEEK_SET) < 0) return -1; /* Feed the DV video stream version of the timestamp to the */ /* DV demux so it can synthesize correct timestamps. */ ff_dv_offset_reset(avi->dv_demux, timestamp); - avi->stream_index= -1; + avi->stream_index = -1; return 0; } - pos_min= pos; - for(i = 0; i < s->nb_streams; i++) { - AVStream *st2 = s->streams[i]; + pos_min = pos; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st2 = s->streams[i]; AVIStream *ast2 = st2->priv_data; - ast2->packet_size= - ast2->remaining= 0; + ast2->packet_size = + ast2->remaining = 0; if (ast2->sub_ctx) { seek_subtitle(st, st2, timestamp); @@ -1527,17 +1642,22 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp continue; // av_assert1(st2->codec->block_align); - av_assert0((int64_t)st2->time_base.num*ast2->rate == (int64_t)st2->time_base.den*ast2->scale); - index = av_index_search_timestamp( - st2, - av_rescale_q(timestamp, st->time_base, st2->time_base) * FFMAX(ast2->sample_size, 1), - flags | AVSEEK_FLAG_BACKWARD | (st2->codec->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0)); - if(index<0) - index=0; - ast2->seek_pos= st2->index_entries[index].pos; - pos_min= FFMIN(pos_min,ast2->seek_pos); + av_assert0((int64_t)st2->time_base.num * ast2->rate == + (int64_t)st2->time_base.den * ast2->scale); + index = av_index_search_timestamp(st2, + av_rescale_q(timestamp, + st->time_base, + st2->time_base) * + FFMAX(ast2->sample_size, 1), + flags | + AVSEEK_FLAG_BACKWARD | + (st2->codec->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0)); + if (index < 0) + index = 0; + ast2->seek_pos = st2->index_entries[index].pos; + pos_min = FFMIN(pos_min,ast2->seek_pos); } - for(i = 0; i < s->nb_streams; i++) { + for (i = 0; i < s->nb_streams; i++) { AVStream *st2 = s->streams[i]; AVIStream *ast2 = st2->priv_data; @@ -1548,9 +1668,9 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp st2, av_rescale_q(timestamp, st->time_base, st2->time_base) * FFMAX(ast2->sample_size, 1), flags | AVSEEK_FLAG_BACKWARD | (st2->codec->codec_type != AVMEDIA_TYPE_VIDEO ? AVSEEK_FLAG_ANY : 0)); - if(index<0) - index=0; - while(!avi->non_interleaved && index>0 && st2->index_entries[index-1].pos >= pos_min) + if (index < 0) + index = 0; + while (!avi->non_interleaved && index>0 && st2->index_entries[index-1].pos >= pos_min) index--; ast2->frame_offset = st2->index_entries[index].timestamp; } @@ -1560,8 +1680,8 @@ static int avi_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp av_log(s, AV_LOG_ERROR, "Seek failed\n"); return -1; } - avi->stream_index= -1; - avi->dts_max= INT_MIN; + avi->stream_index = -1; + avi->dts_max = INT_MIN; return 0; } @@ -1570,8 +1690,8 @@ static int avi_read_close(AVFormatContext *s) int i; AVIContext *avi = s->priv_data; - for(i=0;i<s->nb_streams;i++) { - AVStream *st = s->streams[i]; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; AVIStream *ast = st->priv_data; if (ast) { if (ast->sub_ctx) { @@ -1593,9 +1713,9 @@ static int avi_probe(AVProbeData *p) int i; /* check file header */ - for(i=0; avi_headers[i][0]; i++) - if(!memcmp(p->buf , avi_headers[i] , 4) && - !memcmp(p->buf+8, avi_headers[i]+4, 4)) + for (i = 0; avi_headers[i][0]; i++) + if (!memcmp(p->buf, avi_headers[i], 4) && + !memcmp(p->buf + 8, avi_headers[i] + 4, 4)) return AVPROBE_SCORE_MAX; return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/avienc.c b/chromium/third_party/ffmpeg/libavformat/avienc.c index f2fa9dc8a3b..3511c8181df 100644 --- a/chromium/third_party/ffmpeg/libavformat/avienc.c +++ b/chromium/third_party/ffmpeg/libavformat/avienc.c @@ -523,7 +523,7 @@ static int avi_write_packet(AVFormatContext *s, AVPacket *pkt) int size= pkt->size; av_dlog(s, "dts:%s packet_count:%d stream_index:%d\n", av_ts2str(pkt->dts), avist->packet_count, stream_index); - while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB){ + while(enc->block_align==0 && pkt->dts != AV_NOPTS_VALUE && pkt->dts > avist->packet_count && enc->codec_id != AV_CODEC_ID_XSUB && avist->packet_count){ AVPacket empty_packet; if(pkt->dts - avist->packet_count > 60000){ diff --git a/chromium/third_party/ffmpeg/libavformat/avio.c b/chromium/third_party/ffmpeg/libavformat/avio.c index f6af0cb9e6d..2c7a35eced5 100644 --- a/chromium/third_party/ffmpeg/libavformat/avio.c +++ b/chromium/third_party/ffmpeg/libavformat/avio.c @@ -241,6 +241,8 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags, return url_alloc_for_protocol (puc, up, filename, flags, int_cb); } *puc = NULL; + if (!strcmp("https", proto_str)) + av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile with openssl or gnutls enabled.\n"); return AVERROR_PROTOCOL_NOT_FOUND; } @@ -271,6 +273,8 @@ static inline int retry_transfer_wrapper(URLContext *h, unsigned char *buf, int len = 0; while (len < size_min) { + if (ff_check_interrupt(&h->interrupt_callback)) + return AVERROR_EXIT; ret = transfer_func(h, buf+len, size-len); if (ret == AVERROR(EINTR)) continue; @@ -290,12 +294,10 @@ static inline int retry_transfer_wrapper(URLContext *h, unsigned char *buf, int av_usleep(1000); } } else if (ret < 1) - return ret < 0 ? ret : len; + return (ret < 0 && ret != AVERROR_EOF) ? ret : len; if (ret) fast_retries = FFMAX(fast_retries, 2); len += ret; - if (len < size && ff_check_interrupt(&h->interrupt_callback)) - return AVERROR_EXIT; } return len; } diff --git a/chromium/third_party/ffmpeg/libavformat/avio_internal.h b/chromium/third_party/ffmpeg/libavformat/avio_internal.h index cf3676402b9..e67ba738122 100644 --- a/chromium/third_party/ffmpeg/libavformat/avio_internal.h +++ b/chromium/third_party/ffmpeg/libavformat/avio_internal.h @@ -38,6 +38,23 @@ int ffio_init_context(AVIOContext *s, /** + * Read size bytes from AVIOContext, returning a pointer. + * Note that the data pointed at by the returned pointer is only + * valid until the next call that references the same IO context. + * @param s IO context + * @param buf pointer to buffer into which to assemble the requested + * data if it is not available in contiguous addresses in the + * underlying buffer + * @param size number of bytes requested + * @param data address at which to store pointer: this will be a + * a direct pointer into the underlying buffer if the requested + * number of bytes are available at contiguous addresses, otherwise + * will be a copy of buf + * @return number of bytes read or AVERROR + */ +int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data); + +/** * Read size bytes from AVIOContext into buf. * This reads at most 1 packet. If that is not enough fewer bytes will be * returned. @@ -71,6 +88,15 @@ uint64_t ffio_read_varlen(AVIOContext *bc); /** @warning must be called before any I/O */ int ffio_set_buf_size(AVIOContext *s, int buf_size); +/** + * Ensures that the requested seekback buffer size will be available + * + * Will ensure that when reading sequentially up to buf_size, seeking + * within the current pos and pos+buf_size is possible. + * Once the stream position moves outside this window this gurantee is lost. + */ +int ffio_ensure_seekback(AVIOContext *s, int buf_size); + int ffio_limit(AVIOContext *s, int size); void ffio_init_checksum(AVIOContext *s, diff --git a/chromium/third_party/ffmpeg/libavformat/aviobuf.c b/chromium/third_party/ffmpeg/libavformat/aviobuf.c index 966e0e6a3db..3707fda8bf9 100644 --- a/chromium/third_party/ffmpeg/libavformat/aviobuf.c +++ b/chromium/third_party/ffmpeg/libavformat/aviobuf.c @@ -92,7 +92,7 @@ int ffio_init_context(AVIOContext *s, s->must_flush = 0; s->eof_reached = 0; s->error = 0; - s->seekable = AVIO_SEEKABLE_NORMAL; + s->seekable = seek ? AVIO_SEEKABLE_NORMAL : 0; s->max_packet_size = 0; s->update_checksum = NULL; @@ -392,12 +392,11 @@ void avio_wb24(AVIOContext *s, unsigned int val) static void fill_buffer(AVIOContext *s) { - uint8_t *dst = !s->max_packet_size && - s->buf_end - s->buffer < s->buffer_size ? - s->buf_end : s->buffer; - int len = s->buffer_size - (dst - s->buffer); int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; + uint8_t *dst = s->buf_end - s->buffer + max_buffer_size < s->buffer_size ? + s->buf_end : s->buffer; + int len = s->buffer_size - (dst - s->buffer); /* can't fill the buffer without read_packet, just set EOF if appropriate */ if (!s->read_packet && s->buf_ptr >= s->buf_end) @@ -416,10 +415,13 @@ static void fill_buffer(AVIOContext *s) /* make buffer smaller in case it ended up large after probing */ if (s->read_packet && s->buffer_size > max_buffer_size) { - ffio_set_buf_size(s, max_buffer_size); + if (dst == s->buffer) { + ffio_set_buf_size(s, max_buffer_size); - s->checksum_ptr = dst = s->buffer; - len = s->buffer_size; + s->checksum_ptr = dst = s->buffer; + } + av_assert0(len >= max_buffer_size); + len = max_buffer_size; } if (s->read_packet) @@ -523,6 +525,18 @@ int avio_read(AVIOContext *s, unsigned char *buf, int size) return size1 - size; } +int ffio_read_indirect(AVIOContext *s, unsigned char *buf, int size, const unsigned char **data) +{ + if (s->buf_end - s->buf_ptr >= size && !s->write_flag) { + *data = s->buf_ptr; + s->buf_ptr += size; + return size; + } else { + *data = buf; + return avio_read(s, buf, size); + } +} + int ffio_read_partial(AVIOContext *s, unsigned char *buf, int size) { int len; @@ -723,6 +737,31 @@ int ffio_fdopen(AVIOContext **s, URLContext *h) return 0; } +int ffio_ensure_seekback(AVIOContext *s, int buf_size) +{ + uint8_t *buffer; + int max_buffer_size = s->max_packet_size ? + s->max_packet_size : IO_BUFFER_SIZE; + + buf_size += s->buf_ptr - s->buffer + max_buffer_size; + + if (buf_size < s->buffer_size || s->seekable) + return 0; + av_assert0(!s->write_flag); + + buffer = av_malloc(buf_size); + if (!buffer) + return AVERROR(ENOMEM); + + memcpy(buffer, s->buffer, s->buffer_size); + av_free(s->buffer); + s->buf_ptr = buffer + (s->buf_ptr - s->buffer); + s->buf_end = buffer + (s->buf_end - s->buffer); + s->buffer = buffer; + s->buffer_size = buf_size; + return 0; +} + int ffio_set_buf_size(AVIOContext *s, int buf_size) { uint8_t *buffer; diff --git a/chromium/third_party/ffmpeg/libavformat/avisynth.c b/chromium/third_party/ffmpeg/libavformat/avisynth.c index a5a4fcc6c98..afacf04dd18 100644 --- a/chromium/third_party/ffmpeg/libavformat/avisynth.c +++ b/chromium/third_party/ffmpeg/libavformat/avisynth.c @@ -36,6 +36,7 @@ #include <windows.h> #undef EXTERN_C #include "compat/avisynth/avisynth_c.h" + #include "compat/avisynth/avisynth_c_25.h" #define AVISYNTH_LIB "avisynth" #else #include <dlfcn.h> @@ -62,19 +63,20 @@ typedef struct { void *library; #define AVSC_DECLARE_FUNC(name) name##_func name + AVSC_DECLARE_FUNC(avs_bit_blt); + AVSC_DECLARE_FUNC(avs_clip_get_error); AVSC_DECLARE_FUNC(avs_create_script_environment); AVSC_DECLARE_FUNC(avs_delete_script_environment); + AVSC_DECLARE_FUNC(avs_get_audio); AVSC_DECLARE_FUNC(avs_get_error); - AVSC_DECLARE_FUNC(avs_clip_get_error); - AVSC_DECLARE_FUNC(avs_invoke); - AVSC_DECLARE_FUNC(avs_release_value); + AVSC_DECLARE_FUNC(avs_get_frame); + AVSC_DECLARE_FUNC(avs_get_version); AVSC_DECLARE_FUNC(avs_get_video_info); - AVSC_DECLARE_FUNC(avs_take_clip); + AVSC_DECLARE_FUNC(avs_invoke); AVSC_DECLARE_FUNC(avs_release_clip); - AVSC_DECLARE_FUNC(avs_bit_blt); - AVSC_DECLARE_FUNC(avs_get_audio); - AVSC_DECLARE_FUNC(avs_get_frame); + AVSC_DECLARE_FUNC(avs_release_value); AVSC_DECLARE_FUNC(avs_release_video_frame); + AVSC_DECLARE_FUNC(avs_take_clip); #undef AVSC_DECLARE_FUNC } AviSynthLibrary; @@ -127,19 +129,20 @@ static av_cold int avisynth_load_library(void) { if(!continue_on_fail && !avs_library->name) \ goto fail; \ } + LOAD_AVS_FUNC(avs_bit_blt, 0); + LOAD_AVS_FUNC(avs_clip_get_error, 0); LOAD_AVS_FUNC(avs_create_script_environment, 0); LOAD_AVS_FUNC(avs_delete_script_environment, 0); + LOAD_AVS_FUNC(avs_get_audio, 0); LOAD_AVS_FUNC(avs_get_error, 1); // New to AviSynth 2.6 - LOAD_AVS_FUNC(avs_clip_get_error, 0); - LOAD_AVS_FUNC(avs_invoke, 0); - LOAD_AVS_FUNC(avs_release_value, 0); + LOAD_AVS_FUNC(avs_get_frame, 0); + LOAD_AVS_FUNC(avs_get_version, 0); LOAD_AVS_FUNC(avs_get_video_info, 0); - LOAD_AVS_FUNC(avs_take_clip, 0); + LOAD_AVS_FUNC(avs_invoke, 0); LOAD_AVS_FUNC(avs_release_clip, 0); - LOAD_AVS_FUNC(avs_bit_blt, 0); - LOAD_AVS_FUNC(avs_get_audio, 0); - LOAD_AVS_FUNC(avs_get_frame, 0); + LOAD_AVS_FUNC(avs_release_value, 0); LOAD_AVS_FUNC(avs_release_video_frame, 0); + LOAD_AVS_FUNC(avs_take_clip, 0); #undef LOAD_AVS_FUNC atexit(avisynth_atexit_handler); @@ -239,37 +242,37 @@ static int avisynth_create_stream_video(AVFormatContext *s, AVStream *st) { switch (avs->vi->pixel_type) { #ifdef _WIN32 case AVS_CS_YV24: - st->codec->pix_fmt = PIX_FMT_YUV444P; + st->codec->pix_fmt = AV_PIX_FMT_YUV444P; planar = 1; break; case AVS_CS_YV16: - st->codec->pix_fmt = PIX_FMT_YUV422P; + st->codec->pix_fmt = AV_PIX_FMT_YUV422P; planar = 1; break; case AVS_CS_YV411: - st->codec->pix_fmt = PIX_FMT_YUV411P; + st->codec->pix_fmt = AV_PIX_FMT_YUV411P; planar = 1; break; case AVS_CS_Y8: - st->codec->pix_fmt = PIX_FMT_GRAY8; + st->codec->pix_fmt = AV_PIX_FMT_GRAY8; planar = 2; break; #endif case AVS_CS_BGR24: - st->codec->pix_fmt = PIX_FMT_BGR24; + st->codec->pix_fmt = AV_PIX_FMT_BGR24; break; case AVS_CS_BGR32: - st->codec->pix_fmt = PIX_FMT_RGB32; + st->codec->pix_fmt = AV_PIX_FMT_RGB32; break; case AVS_CS_YUY2: - st->codec->pix_fmt = PIX_FMT_YUYV422; + st->codec->pix_fmt = AV_PIX_FMT_YUYV422; break; case AVS_CS_YV12: - st->codec->pix_fmt = PIX_FMT_YUV420P; + st->codec->pix_fmt = AV_PIX_FMT_YUV420P; planar = 1; break; case AVS_CS_I420: // Is this even used anywhere? - st->codec->pix_fmt = PIX_FMT_YUV420P; + st->codec->pix_fmt = AV_PIX_FMT_YUV420P; planar = 1; break; default: @@ -355,11 +358,22 @@ static int avisynth_open_file(AVFormatContext *s) { AviSynthContext *avs = (AviSynthContext *)s->priv_data; AVS_Value arg, val; int ret; +#ifdef _WIN32 + char filename_ansi[MAX_PATH * 4]; + wchar_t filename_wc[MAX_PATH * 4]; +#endif if (ret = avisynth_context_create(s)) return ret; +#ifdef _WIN32 + // Convert UTF-8 to ANSI code page + MultiByteToWideChar(CP_UTF8, 0, s->filename, -1, filename_wc, MAX_PATH * 4); + WideCharToMultiByte(CP_THREAD_ACP, 0, filename_wc, -1, filename_ansi, MAX_PATH * 4, NULL, NULL); + arg = avs_new_value_string(filename_ansi); +#else arg = avs_new_value_string(s->filename); +#endif val = avs_library->avs_invoke(avs->env, "Import", arg, 0); if (avs_is_error(val)) { av_log(s, AV_LOG_ERROR, "%s\n", avs_as_error(val)); @@ -458,9 +472,20 @@ static int avisynth_read_packet_video(AVFormatContext *s, AVPacket *pkt, int dis for (i = 0; i < avs->n_planes; i++) { plane = avs->planes[i]; src_p = avs_get_read_ptr_p(frame, plane); + pitch = avs_get_pitch_p(frame, plane); + +#ifdef _WIN32 + if (avs_library->avs_get_version(avs->clip) == 3) { + rowsize = avs_get_row_size_p_25(frame, plane); + planeheight = avs_get_height_p_25(frame, plane); + } else { + rowsize = avs_get_row_size_p(frame, plane); + planeheight = avs_get_height_p(frame, plane); + } +#else rowsize = avs_get_row_size_p(frame, plane); planeheight = avs_get_height_p(frame, plane); - pitch = avs_get_pitch_p(frame, plane); +#endif // Flip RGB video. if (avs_is_rgb24(avs->vi) || avs_is_rgb(avs->vi)) { diff --git a/chromium/third_party/ffmpeg/libavformat/avr.c b/chromium/third_party/ffmpeg/libavformat/avr.c index 473136ec3cb..e03f1a46f7d 100644 --- a/chromium/third_party/ffmpeg/libavformat/avr.c +++ b/chromium/third_party/ffmpeg/libavformat/avr.c @@ -27,7 +27,7 @@ static int avr_probe(AVProbeData *p) { if (AV_RL32(p->buf) == MKTAG('2', 'B', 'I', 'T')) - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/avs.c b/chromium/third_party/ffmpeg/libavformat/avs.c index ec9198b7e59..78143012444 100644 --- a/chromium/third_party/ffmpeg/libavformat/avs.c +++ b/chromium/third_party/ffmpeg/libavformat/avs.c @@ -50,7 +50,9 @@ static int avs_probe(AVProbeData * p) d = p->buf; if (d[0] == 'w' && d[1] == 'W' && d[2] == 0x10 && d[3] == 0) - return 55; + /* Ensure the buffer probe scores higher than the extension probe. + * This avoids problems with misdetection as AviSynth scripts. */ + return AVPROBE_SCORE_EXTENSION + 5; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/bfi.c b/chromium/third_party/ffmpeg/libavformat/bfi.c index a28e09a4f1c..7a4f436bf37 100644 --- a/chromium/third_party/ffmpeg/libavformat/bfi.c +++ b/chromium/third_party/ffmpeg/libavformat/bfi.c @@ -81,6 +81,8 @@ static int bfi_read_header(AVFormatContext * s) /*Load the palette to extradata */ avio_skip(pb, 8); vstream->codec->extradata = av_malloc(768); + if (!vstream->codec->extradata) + return AVERROR(ENOMEM); vstream->codec->extradata_size = 768; avio_read(pb, vstream->codec->extradata, vstream->codec->extradata_size); diff --git a/chromium/third_party/ffmpeg/libavformat/bit.c b/chromium/third_party/ffmpeg/libavformat/bit.c index 9b2246ca85e..0be471ac4f8 100644 --- a/chromium/third_party/ffmpeg/libavformat/bit.c +++ b/chromium/third_party/ffmpeg/libavformat/bit.c @@ -44,7 +44,7 @@ static int probe(AVProbeData *p) return 0; i+=j; } - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; } static int read_header(AVFormatContext *s) diff --git a/chromium/third_party/ffmpeg/libavformat/boadec.c b/chromium/third_party/ffmpeg/libavformat/boadec.c new file mode 100644 index 00000000000..45f6b3976b8 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/boadec.c @@ -0,0 +1,78 @@ +/* + * Black ops audio demuxer + * Copyright (c) 2013 Michael Niedermayer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/intreadwrite.h" +#include "avformat.h" + +static int probe(AVProbeData *p) +{ + if (p->buf_size < 2096) + return 0; + if ( AV_RL32(p->buf ) != 1 + || AV_RL32(p->buf + 8) > 100000 + || AV_RL32(p->buf + 12) > 8 + || AV_RL32(p->buf + 16) != 2096 + ||!AV_RL32(p->buf + 21) + || AV_RL16(p->buf + 25) != 2096 + || AV_RL32(p->buf + 48) % AV_RL32(p->buf + 21) + ) + return 0; + return AVPROBE_SCORE_EXTENSION; +} + + +static int read_header(AVFormatContext *s) +{ + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_id = AV_CODEC_ID_ADPCM_MS; + + avio_rl32(s->pb); + avio_rl32(s->pb); + st->codec->sample_rate = avio_rl32(s->pb); + st->codec->channels = avio_rl32(s->pb); + s->data_offset = avio_rl32(s->pb); + avio_r8(s->pb); + st->codec->block_align = st->codec->channels * avio_rl32(s->pb); + + avio_seek(s->pb, s->data_offset, SEEK_SET); + + return 0; +} + +static int read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVStream *st = s->streams[0]; + + return av_get_packet(s->pb, pkt, st->codec->block_align); +} + +AVInputFormat ff_boa_demuxer = { + .name = "boa", + .long_name = NULL_IF_CONFIG_SMALL("Black Ops Audio"), + .read_probe = probe, + .read_header = read_header, + .read_packet = read_packet, + .flags = AVFMT_GENERIC_INDEX, +}; diff --git a/chromium/third_party/ffmpeg/libavformat/cafenc.c b/chromium/third_party/ffmpeg/libavformat/cafenc.c index 11bb0559657..cd3a0be907f 100644 --- a/chromium/third_party/ffmpeg/libavformat/cafenc.c +++ b/chromium/third_party/ffmpeg/libavformat/cafenc.c @@ -86,8 +86,9 @@ static uint32_t samples_per_packet(enum AVCodecID codec_id, int channels) { return 1152; case AV_CODEC_ID_AC3: return 1536; - case AV_CODEC_ID_ALAC: case AV_CODEC_ID_QDM2: + return 2048 * channels; + case AV_CODEC_ID_ALAC: return 4096; case AV_CODEC_ID_ADPCM_IMA_WAV: return (1024 - 4 * channels) * 8 / (4 * channels) + 1; diff --git a/chromium/third_party/ffmpeg/libavformat/cavsvideodec.c b/chromium/third_party/ffmpeg/libavformat/cavsvideodec.c index c035128bcf3..5ca3c80b32f 100644 --- a/chromium/third_party/ffmpeg/libavformat/cavsvideodec.c +++ b/chromium/third_party/ffmpeg/libavformat/cavsvideodec.c @@ -61,7 +61,7 @@ static int cavsvideo_probe(AVProbeData *p) } } if(seq && seq*9<=pic*10) - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/cdxl.c b/chromium/third_party/ffmpeg/libavformat/cdxl.c index 185b745bb00..ab8a846cc51 100644 --- a/chromium/third_party/ffmpeg/libavformat/cdxl.c +++ b/chromium/third_party/ffmpeg/libavformat/cdxl.c @@ -41,7 +41,7 @@ typedef struct CDXLDemuxContext { static int cdxl_read_probe(AVProbeData *p) { - int score = AVPROBE_SCORE_MAX / 2 + 10; + int score = AVPROBE_SCORE_EXTENSION + 10; if (p->buf_size < CDXL_HEADER_SIZE) return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/concatdec.c b/chromium/third_party/ffmpeg/libavformat/concatdec.c index 5359ad149d4..428c749ab24 100644 --- a/chromium/third_party/ffmpeg/libavformat/concatdec.c +++ b/chromium/third_party/ffmpeg/libavformat/concatdec.c @@ -23,6 +23,7 @@ #include "libavutil/parseutils.h" #include "avformat.h" #include "internal.h" +#include "url.h" typedef struct { char *url; @@ -216,6 +217,8 @@ static int concat_read_header(AVFormatContext *avf) } if (ret < 0) FAIL(ret); + if (!cat->nb_files) + FAIL(AVERROR_INVALIDDATA); for (i = 0; i < cat->nb_files; i++) { if (cat->files[i].start_time == AV_NOPTS_VALUE) @@ -341,7 +344,7 @@ static int real_seek(AVFormatContext *avf, int stream, return ret; ret = try_seek(avf, stream, min_ts, ts, max_ts, flags); - if (ret < 0 && !(flags & AVSEEK_FLAG_BACKWARD) && + if (ret < 0 && left < cat->nb_files - 1 && cat->files[left + 1].start_time < max_ts) { if ((ret = open_file(avf, left + 1)) < 0) diff --git a/chromium/third_party/ffmpeg/libavformat/dtsdec.c b/chromium/third_party/ffmpeg/libavformat/dtsdec.c index 5c05758327f..23cbe93516a 100644 --- a/chromium/third_party/ffmpeg/libavformat/dtsdec.c +++ b/chromium/third_party/ffmpeg/libavformat/dtsdec.c @@ -34,6 +34,7 @@ static int dts_probe(AVProbeData *p) uint32_t state = -1; int markers[3] = {0}; int sum, max; + int64_t diff = 0; buf = p->buf; @@ -54,13 +55,17 @@ static int dts_probe(AVProbeData *p) if (state == DCA_MARKER_14B_LE) if ((bytestream_get_be16(&bufp) & 0xF0FF) == 0xF007) markers[2]++; + + if (buf - p->buf >= 4) + diff += FFABS(AV_RL16(buf) - AV_RL16(buf-4)); } sum = markers[0] + markers[1] + markers[2]; max = markers[1] > markers[0]; max = markers[2] > markers[max] ? 2 : max; if (markers[max] > 3 && p->buf_size / markers[max] < 32*1024 && - markers[max] * 4 > sum * 3) - return AVPROBE_SCORE_MAX/2+1; + markers[max] * 4 > sum * 3 && + diff / p->buf_size > 200) + return AVPROBE_SCORE_EXTENSION + 1; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/dv.c b/chromium/third_party/ffmpeg/libavformat/dv.c index a04735ac252..cc48f483eb8 100644 --- a/chromium/third_party/ffmpeg/libavformat/dv.c +++ b/chromium/third_party/ffmpeg/libavformat/dv.c @@ -65,7 +65,7 @@ static inline uint16_t dv_audio_12to16(uint16_t sample) shift--; result = (sample - (256 * shift)) << shift; } else { - shift = 0xe - shift; + shift = 0xe - shift; result = ((sample + ((256 * shift) + 1)) << shift) - 1; } @@ -77,19 +77,19 @@ static inline uint16_t dv_audio_12to16(uint16_t sample) * a fixed offset and if pack isn't there -- fails. We might want * to have a fallback mechanism for complete search of missing packs. */ -static const uint8_t* dv_extract_pack(uint8_t* frame, enum dv_pack_type t) +static const uint8_t *dv_extract_pack(uint8_t *frame, enum dv_pack_type t) { int offs; switch (t) { case dv_audio_source: - offs = (80*6 + 80*16*3 + 3); + offs = (80 * 6 + 80 * 16 * 3 + 3); break; case dv_audio_control: - offs = (80*6 + 80*16*4 + 3); + offs = (80 * 6 + 80 * 16 * 4 + 3); break; case dv_video_control: - offs = (80*5 + 48 + 5); + offs = (80 * 5 + 48 + 5); break; case dv_timecode: offs = (80*1 + 3 + 3); @@ -113,29 +113,29 @@ static const int dv_audio_frequency[3] = { * 3. Audio is always returned as 16bit linear samples: 12bit nonlinear samples * are converted into 16bit linear ones. */ -static int dv_extract_audio(uint8_t* frame, uint8_t* ppcm[4], +static int dv_extract_audio(uint8_t *frame, uint8_t *ppcm[4], const DVprofile *sys) { int size, chan, i, j, d, of, smpls, freq, quant, half_ch; uint16_t lc, rc; - const uint8_t* as_pack; + const uint8_t *as_pack; uint8_t *pcm, ipcm; as_pack = dv_extract_pack(frame, dv_audio_source); if (!as_pack) /* No audio ? */ return 0; - smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */ - freq = (as_pack[4] >> 3) & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */ - quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */ + smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */ + freq = as_pack[4] >> 3 & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */ + quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */ if (quant > 1) - return -1; /* unsupported quantization */ + return -1; /* unsupported quantization */ if (freq >= FF_ARRAY_ELEMS(dv_audio_frequency)) return AVERROR_INVALIDDATA; - size = (sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */ + size = (sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */ half_ch = sys->difseg_size / 2; /* We work with 720p frames split in half, thus even frames have @@ -169,32 +169,41 @@ static int dv_extract_audio(uint8_t* frame, uint8_t* ppcm[4], for (j = 0; j < 9; j++) { for (d = 8; d < 80; d += 2) { if (quant == 0) { /* 16bit quantization */ - of = sys->audio_shuffle[i][j] + (d - 8) / 2 * sys->audio_stride; - if (of*2 >= size) + of = sys->audio_shuffle[i][j] + + (d - 8) / 2 * sys->audio_stride; + if (of * 2 >= size) continue; - pcm[of*2] = frame[d+1]; // FIXME: maybe we have to admit - pcm[of*2+1] = frame[d]; // that DV is a big-endian PCM - if (pcm[of*2+1] == 0x80 && pcm[of*2] == 0x00) - pcm[of*2+1] = 0; + /* FIXME: maybe we have to admit that DV is a + * big-endian PCM */ + pcm[of * 2] = frame[d + 1]; + pcm[of * 2 + 1] = frame[d]; + + if (pcm[of * 2 + 1] == 0x80 && pcm[of * 2] == 0x00) + pcm[of * 2 + 1] = 0; } else { /* 12bit quantization */ - lc = ((uint16_t)frame[d] << 4) | - ((uint16_t)frame[d+2] >> 4); - rc = ((uint16_t)frame[d+1] << 4) | - ((uint16_t)frame[d+2] & 0x0f); + lc = ((uint16_t)frame[d] << 4) | + ((uint16_t)frame[d + 2] >> 4); + rc = ((uint16_t)frame[d + 1] << 4) | + ((uint16_t)frame[d + 2] & 0x0f); lc = (lc == 0x800 ? 0 : dv_audio_12to16(lc)); rc = (rc == 0x800 ? 0 : dv_audio_12to16(rc)); - of = sys->audio_shuffle[i%half_ch][j] + (d - 8) / 3 * sys->audio_stride; - if (of*2 >= size) + of = sys->audio_shuffle[i % half_ch][j] + + (d - 8) / 3 * sys->audio_stride; + if (of * 2 >= size) continue; - pcm[of*2] = lc & 0xff; // FIXME: maybe we have to admit - pcm[of*2+1] = lc >> 8; // that DV is a big-endian PCM - of = sys->audio_shuffle[i%half_ch+half_ch][j] + - (d - 8) / 3 * sys->audio_stride; - pcm[of*2] = rc & 0xff; // FIXME: maybe we have to admit - pcm[of*2+1] = rc >> 8; // that DV is a big-endian PCM + /* FIXME: maybe we have to admit that DV is a + * big-endian PCM */ + pcm[of * 2] = lc & 0xff; + pcm[of * 2 + 1] = lc >> 8; + of = sys->audio_shuffle[i % half_ch + half_ch][j] + + (d - 8) / 3 * sys->audio_stride; + /* FIXME: maybe we have to admit that DV is a + * big-endian PCM */ + pcm[of * 2] = rc & 0xff; + pcm[of * 2 + 1] = rc >> 8; ++d; } } @@ -207,9 +216,9 @@ static int dv_extract_audio(uint8_t* frame, uint8_t* ppcm[4], return size; } -static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame) +static int dv_extract_audio_info(DVDemuxContext *c, uint8_t *frame) { - const uint8_t* as_pack; + const uint8_t *as_pack; int freq, stype, smpls, quant, i, ach; as_pack = dv_extract_pack(frame, dv_audio_source); @@ -218,10 +227,10 @@ static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame) return 0; } - smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */ - freq = (as_pack[4] >> 3) & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */ - stype = (as_pack[3] & 0x1f); /* 0 - 2CH, 2 - 4CH, 3 - 8CH */ - quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */ + smpls = as_pack[1] & 0x3f; /* samples in this frame - min. samples */ + freq = as_pack[4] >> 3 & 0x07; /* 0 - 48kHz, 1 - 44,1kHz, 2 - 32kHz */ + stype = as_pack[3] & 0x1f; /* 0 - 2CH, 2 - 4CH, 3 - 8CH */ + quant = as_pack[4] & 0x07; /* 0 - 16bit linear, 1 - 12bit nonlinear */ if (freq >= FF_ARRAY_ELEMS(dv_audio_frequency)) { av_log(c->fctx, AV_LOG_ERROR, @@ -236,7 +245,7 @@ static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame) } /* note: ach counts PAIRS of channels (i.e. stereo channels) */ - ach = ((int[4]){ 1, 0, 2, 4})[stype]; + ach = ((int[4]) { 1, 0, 2, 4 })[stype]; if (ach == 1 && quant && freq == 2) ach = 2; @@ -256,21 +265,21 @@ static int dv_extract_audio_info(DVDemuxContext* c, uint8_t* frame) c->audio_pkt[i].stream_index = c->ast[i]->index; c->audio_pkt[i].flags |= AV_PKT_FLAG_KEY; } - c->ast[i]->codec->sample_rate = dv_audio_frequency[freq]; - c->ast[i]->codec->channels = 2; + c->ast[i]->codec->sample_rate = dv_audio_frequency[freq]; + c->ast[i]->codec->channels = 2; c->ast[i]->codec->channel_layout = AV_CH_LAYOUT_STEREO; - c->ast[i]->codec->bit_rate = 2 * dv_audio_frequency[freq] * 16; - c->ast[i]->start_time = 0; + c->ast[i]->codec->bit_rate = 2 * dv_audio_frequency[freq] * 16; + c->ast[i]->start_time = 0; } c->ach = i; - return (c->sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */; + return (c->sys->audio_min_samples[freq] + smpls) * 4; /* 2ch, 2bytes */ } -static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame) +static int dv_extract_video_info(DVDemuxContext *c, uint8_t *frame) { - const uint8_t* vsc_pack; - AVCodecContext* avctx; + const uint8_t *vsc_pack; + AVCodecContext *avctx; int apt, is16_9; int size = 0; @@ -279,7 +288,7 @@ static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame) avpriv_set_pts_info(c->vst, 64, c->sys->time_base.num, c->sys->time_base.den); - avctx->time_base= c->sys->time_base; + avctx->time_base = c->sys->time_base; /* finding out SAR is a little bit messy */ vsc_pack = dv_extract_pack(frame, dv_video_control); @@ -287,7 +296,8 @@ static int dv_extract_video_info(DVDemuxContext *c, uint8_t* frame) is16_9 = (vsc_pack && ((vsc_pack[2] & 0x07) == 0x02 || (!apt && (vsc_pack[2] & 0x07) == 0x07))); c->vst->sample_aspect_ratio = c->sys->sar[is16_9]; - avctx->bit_rate = av_rescale_q(c->sys->frame_size, (AVRational){8,1}, + avctx->bit_rate = av_rescale_q(c->sys->frame_size, + (AVRational) { 8, 1 }, c->sys->time_base); size = c->sys->frame_size; } @@ -310,11 +320,9 @@ static int dv_extract_timecode(DVDemuxContext* c, uint8_t* frame, char *tc) return 1; } -/* - * The following 3 functions constitute our interface to the world - */ +/* The following 3 functions constitute our interface to the world */ -DVDemuxContext* avpriv_dv_init_demux(AVFormatContext *s) +DVDemuxContext *avpriv_dv_init_demux(AVFormatContext *s) { DVDemuxContext *c; @@ -344,9 +352,9 @@ int avpriv_dv_get_packet(DVDemuxContext *c, AVPacket *pkt) for (i = 0; i < c->ach; i++) { if (c->ast[i] && c->audio_pkt[i].size) { - *pkt = c->audio_pkt[i]; + *pkt = c->audio_pkt[i]; c->audio_pkt[i].size = 0; - size = pkt->size; + size = pkt->size; break; } } @@ -355,10 +363,10 @@ int avpriv_dv_get_packet(DVDemuxContext *c, AVPacket *pkt) } int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, - uint8_t* buf, int buf_size, int64_t pos) + uint8_t *buf, int buf_size, int64_t pos) { int size, i; - uint8_t *ppcm[4] = {0}; + uint8_t *ppcm[4] = { 0 }; if (buf_size < DV_PROFILE_BYTES || !(c->sys = avpriv_dv_frame_profile(c->sys, buf, buf_size)) || @@ -372,7 +380,8 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, for (i = 0; i < c->ach; i++) { c->audio_pkt[i].pos = pos; c->audio_pkt[i].size = size; - c->audio_pkt[i].pts = c->abytes * 30000 * 8 / c->ast[i]->codec->bit_rate; + c->audio_pkt[i].pts = c->abytes * 30000 * 8 / + c->ast[i]->codec->bit_rate; ppcm[i] = c->audio_buf[i]; } if (c->ach) @@ -385,7 +394,7 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, c->audio_pkt[2].size = c->audio_pkt[3].size = 0; } else { c->audio_pkt[0].size = c->audio_pkt[1].size = 0; - c->abytes += size; + c->abytes += size; } } else { c->abytes += size; @@ -407,30 +416,32 @@ int avpriv_dv_produce_packet(DVDemuxContext *c, AVPacket *pkt, } static int64_t dv_frame_offset(AVFormatContext *s, DVDemuxContext *c, - int64_t timestamp, int flags) + int64_t timestamp, int flags) { // FIXME: sys may be wrong if last dv_read_packet() failed (buffer is junk) - const DVprofile* sys = avpriv_dv_codec_profile(c->vst->codec); + const DVprofile *sys = avpriv_dv_codec_profile(c->vst->codec); int64_t offset; - int64_t size = avio_size(s->pb) - s->data_offset; - int64_t max_offset = ((size-1) / sys->frame_size) * sys->frame_size; + int64_t size = avio_size(s->pb) - s->data_offset; + int64_t max_offset = ((size - 1) / sys->frame_size) * sys->frame_size; offset = sys->frame_size * timestamp; - if (size >= 0 && offset > max_offset) offset = max_offset; - else if (offset < 0) offset = 0; + if (size >= 0 && offset > max_offset) + offset = max_offset; + else if (offset < 0) + offset = 0; return offset + s->data_offset; } void ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset) { - c->frames= frame_offset; + c->frames = frame_offset; if (c->ach) { if (c->sys) { - c->abytes= av_rescale_q(c->frames, c->sys->time_base, - (AVRational){8, c->ast[0]->codec->bit_rate}); - }else + c->abytes = av_rescale_q(c->frames, c->sys->time_base, + (AVRational) { 8, c->ast[0]->codec->bit_rate }); + } else av_log(c->fctx, AV_LOG_ERROR, "cannot adjust audio bytes\n"); } c->audio_pkt[0].size = c->audio_pkt[1].size = 0; @@ -442,7 +453,7 @@ void ff_dv_offset_reset(DVDemuxContext *c, int64_t frame_offset) ************************************************************/ typedef struct RawDVContext { - DVDemuxContext* dv_demux; + DVDemuxContext *dv_demux; uint8_t buf[DV_MAX_FRAME_SIZE]; } RawDVContext; @@ -508,13 +519,17 @@ static int dv_read_header(AVFormatContext *s) avio_seek(s->pb, -DV_PROFILE_BYTES, SEEK_CUR) < 0) return AVERROR(EIO); - c->dv_demux->sys = avpriv_dv_frame_profile(c->dv_demux->sys, c->buf, DV_PROFILE_BYTES); + c->dv_demux->sys = avpriv_dv_frame_profile(c->dv_demux->sys, + c->buf, + DV_PROFILE_BYTES); if (!c->dv_demux->sys) { - av_log(s, AV_LOG_ERROR, "Can't determine profile of DV input stream.\n"); + av_log(s, AV_LOG_ERROR, + "Can't determine profile of DV input stream.\n"); return -1; } - s->bit_rate = av_rescale_q(c->dv_demux->sys->frame_size, (AVRational){8,1}, + s->bit_rate = av_rescale_q(c->dv_demux->sys->frame_size, + (AVRational) { 8, 1 }, c->dv_demux->sys->time_base); if (s->pb->seekable) @@ -523,7 +538,6 @@ static int dv_read_header(AVFormatContext *s) return 0; } - static int dv_read_packet(AVFormatContext *s, AVPacket *pkt) { int size; @@ -546,7 +560,7 @@ static int dv_read_packet(AVFormatContext *s, AVPacket *pkt) } static int dv_read_seek(AVFormatContext *s, int stream_index, - int64_t timestamp, int flags) + int64_t timestamp, int flags) { RawDVContext *r = s->priv_data; DVDemuxContext *c = r->dv_demux; @@ -570,7 +584,7 @@ static int dv_probe(AVProbeData *p) { unsigned state, marker_pos = 0; int i; - int matches = 0; + int matches = 0; int secondary_matches = 0; if (p->buf_size < 5) @@ -591,10 +605,13 @@ static int dv_probe(AVProbeData *p) state = (state << 8) | p->buf[i]; } - if (matches && p->buf_size / matches < 1024*1024) { - if (matches > 4 || (secondary_matches >= 10 && p->buf_size / secondary_matches < 24000)) - return AVPROBE_SCORE_MAX*3/4; // not max to avoid dv in mov to match - return AVPROBE_SCORE_MAX/4; + if (matches && p->buf_size / matches < 1024 * 1024) { + if (matches > 4 || + (secondary_matches >= 10 && + p->buf_size / secondary_matches < 24000)) + // not max to avoid dv in mov to match + return AVPROBE_SCORE_MAX * 3 / 4; + return AVPROBE_SCORE_MAX / 4; } return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/electronicarts.c b/chromium/third_party/ffmpeg/libavformat/electronicarts.c index dae40b1dd99..69e4cbf952e 100644 --- a/chromium/third_party/ffmpeg/libavformat/electronicarts.c +++ b/chromium/third_party/ffmpeg/libavformat/electronicarts.c @@ -30,35 +30,35 @@ #include "internal.h" #define SCHl_TAG MKTAG('S', 'C', 'H', 'l') -#define SEAD_TAG MKTAG('S', 'E', 'A', 'D') /* Sxxx header */ -#define SNDC_TAG MKTAG('S', 'N', 'D', 'C') /* Sxxx data */ -#define SEND_TAG MKTAG('S', 'E', 'N', 'D') /* Sxxx end */ -#define SHEN_TAG MKTAG('S', 'H', 'E', 'N') /* SxEN header */ -#define SDEN_TAG MKTAG('S', 'D', 'E', 'N') /* SxEN data */ -#define SEEN_TAG MKTAG('S', 'E', 'E', 'N') /* SxEN end */ -#define ISNh_TAG MKTAG('1', 'S', 'N', 'h') /* 1SNx header */ +#define SEAD_TAG MKTAG('S', 'E', 'A', 'D') /* Sxxx header */ +#define SNDC_TAG MKTAG('S', 'N', 'D', 'C') /* Sxxx data */ +#define SEND_TAG MKTAG('S', 'E', 'N', 'D') /* Sxxx end */ +#define SHEN_TAG MKTAG('S', 'H', 'E', 'N') /* SxEN header */ +#define SDEN_TAG MKTAG('S', 'D', 'E', 'N') /* SxEN data */ +#define SEEN_TAG MKTAG('S', 'E', 'E', 'N') /* SxEN end */ +#define ISNh_TAG MKTAG('1', 'S', 'N', 'h') /* 1SNx header */ #define EACS_TAG MKTAG('E', 'A', 'C', 'S') -#define ISNd_TAG MKTAG('1', 'S', 'N', 'd') /* 1SNx data */ -#define ISNe_TAG MKTAG('1', 'S', 'N', 'e') /* 1SNx end */ +#define ISNd_TAG MKTAG('1', 'S', 'N', 'd') /* 1SNx data */ +#define ISNe_TAG MKTAG('1', 'S', 'N', 'e') /* 1SNx end */ #define PT00_TAG MKTAG('P', 'T', 0x0, 0x0) #define GSTR_TAG MKTAG('G', 'S', 'T', 'R') #define SCDl_TAG MKTAG('S', 'C', 'D', 'l') #define SCEl_TAG MKTAG('S', 'C', 'E', 'l') -#define kVGT_TAG MKTAG('k', 'V', 'G', 'T') /* TGV i-frame */ -#define fVGT_TAG MKTAG('f', 'V', 'G', 'T') /* TGV p-frame */ -#define mTCD_TAG MKTAG('m', 'T', 'C', 'D') /* MDEC */ -#define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD i-frame */ -#define MADm_TAG MKTAG('M', 'A', 'D', 'm') /* MAD p-frame */ -#define MADe_TAG MKTAG('M', 'A', 'D', 'e') /* MAD lqp-frame */ -#define MPCh_TAG MKTAG('M', 'P', 'C', 'h') /* MPEG2 */ -#define TGQs_TAG MKTAG('T', 'G', 'Q', 's') /* TGQ i-frame (appears in .TGQ files) */ -#define pQGT_TAG MKTAG('p', 'Q', 'G', 'T') /* TGQ i-frame (appears in .UV files) */ -#define pIQT_TAG MKTAG('p', 'I', 'Q', 'T') /* TQI/UV2 i-frame (.UV2/.WVE) */ +#define kVGT_TAG MKTAG('k', 'V', 'G', 'T') /* TGV I-frame */ +#define fVGT_TAG MKTAG('f', 'V', 'G', 'T') /* TGV P-frame */ +#define mTCD_TAG MKTAG('m', 'T', 'C', 'D') /* MDEC */ +#define MADk_TAG MKTAG('M', 'A', 'D', 'k') /* MAD I-frame */ +#define MADm_TAG MKTAG('M', 'A', 'D', 'm') /* MAD P-frame */ +#define MADe_TAG MKTAG('M', 'A', 'D', 'e') /* MAD lqp-frame */ +#define MPCh_TAG MKTAG('M', 'P', 'C', 'h') /* MPEG-2 */ +#define TGQs_TAG MKTAG('T', 'G', 'Q', 's') /* TGQ I-frame (appears in .TGQ files) */ +#define pQGT_TAG MKTAG('p', 'Q', 'G', 'T') /* TGQ I-frame (appears in .UV files) */ +#define pIQT_TAG MKTAG('p', 'I', 'Q', 'T') /* TQI/UV2 I-frame (.UV2/.WVE) */ #define MVhd_TAG MKTAG('M', 'V', 'h', 'd') #define MV0K_TAG MKTAG('M', 'V', '0', 'K') #define MV0F_TAG MKTAG('M', 'V', '0', 'F') -#define MVIh_TAG MKTAG('M', 'V', 'I', 'h') /* CMV header */ -#define MVIf_TAG MKTAG('M', 'V', 'I', 'f') /* CMV i-frame */ +#define MVIh_TAG MKTAG('M', 'V', 'I', 'h') /* CMV header */ +#define MVIf_TAG MKTAG('M', 'V', 'I', 'f') /* CMV I-frame */ typedef struct EaDemuxContext { int big_endian; @@ -78,7 +78,8 @@ typedef struct EaDemuxContext { int num_samples; } EaDemuxContext; -static uint32_t read_arbitary(AVIOContext *pb) { +static uint32_t read_arbitrary(AVIOContext *pb) +{ uint8_t size, byte; int i; uint32_t word; @@ -87,108 +88,135 @@ static uint32_t read_arbitary(AVIOContext *pb) { word = 0; for (i = 0; i < size; i++) { - byte = avio_r8(pb); + byte = avio_r8(pb); word <<= 8; - word |= byte; + word |= byte; } return word; } -/* - * Process PT/GSTR sound header - * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx - */ static int process_audio_header_elements(AVFormatContext *s) { - int inHeader = 1; EaDemuxContext *ea = s->priv_data; - AVIOContext *pb = s->pb; + AVIOContext *pb = s->pb; + int in_header = 1; int compression_type = -1, revision = -1, revision2 = -1; - ea->bytes = 2; - ea->sample_rate = -1; + ea->bytes = 2; + ea->sample_rate = -1; ea->num_channels = 1; - while (!url_feof(pb) && inHeader) { - int inSubheader; + while (!url_feof(pb) && in_header) { + int in_subheader; uint8_t byte; byte = avio_r8(pb); switch (byte) { case 0xFD: - av_log (s, AV_LOG_DEBUG, "entered audio subheader\n"); - inSubheader = 1; - while (!url_feof(pb) && inSubheader) { + av_log(s, AV_LOG_DEBUG, "entered audio subheader\n"); + in_subheader = 1; + while (!url_feof(pb) && in_subheader) { uint8_t subbyte; subbyte = avio_r8(pb); switch (subbyte) { case 0x80: - revision = read_arbitary(pb); - av_log (s, AV_LOG_DEBUG, "revision (element 0x80) set to 0x%08x\n", revision); + revision = read_arbitrary(pb); + av_log(s, AV_LOG_DEBUG, + "revision (element 0x80) set to 0x%08x\n", revision); break; case 0x82: - ea->num_channels = read_arbitary(pb); - av_log (s, AV_LOG_DEBUG, "num_channels (element 0x82) set to 0x%08x\n", ea->num_channels); + ea->num_channels = read_arbitrary(pb); + av_log(s, AV_LOG_DEBUG, + "num_channels (element 0x82) set to 0x%08x\n", + ea->num_channels); break; case 0x83: - compression_type = read_arbitary(pb); - av_log (s, AV_LOG_DEBUG, "compression_type (element 0x83) set to 0x%08x\n", compression_type); + compression_type = read_arbitrary(pb); + av_log(s, AV_LOG_DEBUG, + "compression_type (element 0x83) set to 0x%08x\n", + compression_type); break; case 0x84: - ea->sample_rate = read_arbitary(pb); - av_log (s, AV_LOG_DEBUG, "sample_rate (element 0x84) set to %i\n", ea->sample_rate); + ea->sample_rate = read_arbitrary(pb); + av_log(s, AV_LOG_DEBUG, + "sample_rate (element 0x84) set to %i\n", + ea->sample_rate); break; case 0x85: - ea->num_samples = read_arbitary(pb); - av_log (s, AV_LOG_DEBUG, "num_samples (element 0x85) set to 0x%08x\n", ea->num_samples); + ea->num_samples = read_arbitrary(pb); + av_log(s, AV_LOG_DEBUG, + "num_samples (element 0x85) set to 0x%08x\n", + ea->num_samples); break; case 0x8A: - av_log (s, AV_LOG_DEBUG, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb)); - av_log (s, AV_LOG_DEBUG, "exited audio subheader\n"); - inSubheader = 0; + av_log(s, AV_LOG_DEBUG, + "element 0x%02x set to 0x%08x\n", + subbyte, read_arbitrary(pb)); + av_log(s, AV_LOG_DEBUG, "exited audio subheader\n"); + in_subheader = 0; break; case 0xA0: - revision2 = read_arbitary(pb); - av_log (s, AV_LOG_DEBUG, "revision2 (element 0xA0) set to 0x%08x\n", revision2); + revision2 = read_arbitrary(pb); + av_log(s, AV_LOG_DEBUG, + "revision2 (element 0xA0) set to 0x%08x\n", + revision2); break; case 0xFF: - av_log (s, AV_LOG_DEBUG, "end of header block reached (within audio subheader)\n"); - inSubheader = 0; - inHeader = 0; + av_log(s, AV_LOG_DEBUG, + "end of header block reached (within audio subheader)\n"); + in_subheader = 0; + in_header = 0; break; default: - av_log (s, AV_LOG_DEBUG, "element 0x%02x set to 0x%08x\n", subbyte, read_arbitary(pb)); + av_log(s, AV_LOG_DEBUG, + "element 0x%02x set to 0x%08x\n", + subbyte, read_arbitrary(pb)); break; } } break; case 0xFF: - av_log (s, AV_LOG_DEBUG, "end of header block reached\n"); - inHeader = 0; + av_log(s, AV_LOG_DEBUG, "end of header block reached\n"); + in_header = 0; break; default: - av_log (s, AV_LOG_DEBUG, "header element 0x%02x set to 0x%08x\n", byte, read_arbitary(pb)); + av_log(s, AV_LOG_DEBUG, + "header element 0x%02x set to 0x%08x\n", + byte, read_arbitrary(pb)); break; } } switch (compression_type) { - case 0: ea->audio_codec = AV_CODEC_ID_PCM_S16LE; break; - case 7: ea->audio_codec = AV_CODEC_ID_ADPCM_EA; break; + case 0: + ea->audio_codec = AV_CODEC_ID_PCM_S16LE; + break; + case 7: + ea->audio_codec = AV_CODEC_ID_ADPCM_EA; + break; case -1: switch (revision) { - case 1: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R1; break; - case 2: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2; break; - case 3: ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R3; break; - case -1: break; + case 1: + ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R1; + break; + case 2: + ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R2; + break; + case 3: + ea->audio_codec = AV_CODEC_ID_ADPCM_EA_R3; + break; + case -1: + break; default: avpriv_request_sample(s, "stream type; revision=%i", revision); return 0; } switch (revision2) { - case 8: ea->audio_codec = AV_CODEC_ID_PCM_S16LE_PLANAR; break; + case 8: + ea->audio_codec = AV_CODEC_ID_PCM_S16LE_PLANAR; + break; case 10: switch (revision) { case -1: @@ -199,8 +227,11 @@ static int process_audio_header_elements(AVFormatContext *s) return 0; } break; - case 16: ea->audio_codec = AV_CODEC_ID_MP3; break; - case -1: break; + case 16: + ea->audio_codec = AV_CODEC_ID_MP3; + break; + case -1: + break; default: ea->audio_codec = AV_CODEC_ID_NONE; avpriv_request_sample(s, "stream type; revision2=%i", revision2); @@ -208,24 +239,22 @@ static int process_audio_header_elements(AVFormatContext *s) } break; default: - avpriv_request_sample(s, "stream type; compression_type=%i", compression_type); + avpriv_request_sample(s, + "stream type; compression_type=%i", + compression_type); return 0; } if (ea->sample_rate == -1) - ea->sample_rate = revision==3 ? 48000 : 22050; + ea->sample_rate = revision == 3 ? 48000 : 22050; return 1; } -/* - * Process EACS sound header - * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx - */ -static int process_audio_header_eacs(AVFormatContext *s) +static void process_audio_header_eacs(AVFormatContext *s) { EaDemuxContext *ea = s->priv_data; - AVIOContext *pb = s->pb; + AVIOContext *pb = s->pb; int compression_type; ea->sample_rate = ea->big_endian ? avio_rb32(pb) : avio_rl32(pb); @@ -237,52 +266,54 @@ static int process_audio_header_eacs(AVFormatContext *s) switch (compression_type) { case 0: switch (ea->bytes) { - case 1: ea->audio_codec = AV_CODEC_ID_PCM_S8; break; - case 2: ea->audio_codec = AV_CODEC_ID_PCM_S16LE; break; + case 1: + ea->audio_codec = AV_CODEC_ID_PCM_S8; + break; + case 2: + ea->audio_codec = AV_CODEC_ID_PCM_S16LE; + break; } break; - case 1: ea->audio_codec = AV_CODEC_ID_PCM_MULAW; ea->bytes = 1; break; - case 2: ea->audio_codec = AV_CODEC_ID_ADPCM_IMA_EA_EACS; break; + case 1: + ea->audio_codec = AV_CODEC_ID_PCM_MULAW; + ea->bytes = 1; + break; + case 2: + ea->audio_codec = AV_CODEC_ID_ADPCM_IMA_EA_EACS; + break; default: - avpriv_request_sample(s, "stream type; audio compression_type=%i", compression_type); + avpriv_request_sample(s, + "stream type; audio compression_type=%i", + compression_type); } - - return 1; } -/* - * Process SEAD sound header - * return 1 if success, 0 if invalid format, otherwise AVERROR_xxx - */ -static int process_audio_header_sead(AVFormatContext *s) +static void process_audio_header_sead(AVFormatContext *s) { EaDemuxContext *ea = s->priv_data; - AVIOContext *pb = s->pb; + AVIOContext *pb = s->pb; ea->sample_rate = avio_rl32(pb); ea->bytes = avio_rl32(pb); /* 1=8-bit, 2=16-bit */ ea->num_channels = avio_rl32(pb); ea->audio_codec = AV_CODEC_ID_ADPCM_IMA_EA_SEAD; - - return 1; } -static int process_video_header_mdec(AVFormatContext *s) +static void process_video_header_mdec(AVFormatContext *s) { EaDemuxContext *ea = s->priv_data; - AVIOContext *pb = s->pb; + AVIOContext *pb = s->pb; avio_skip(pb, 4); - ea->width = avio_rl16(pb); - ea->height = avio_rl16(pb); - ea->time_base = (AVRational){1,15}; + ea->width = avio_rl16(pb); + ea->height = avio_rl16(pb); + ea->time_base = (AVRational) { 1, 15 }; ea->video_codec = AV_CODEC_ID_MDEC; - return 1; } static int process_video_header_vp6(AVFormatContext *s) { EaDemuxContext *ea = s->priv_data; - AVIOContext *pb = s->pb; + AVIOContext *pb = s->pb; avio_skip(pb, 8); ea->nb_frames = avio_rl32(pb); @@ -293,12 +324,12 @@ static int process_video_header_vp6(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "Timebase is invalid\n"); return AVERROR_INVALIDDATA; } - ea->video_codec = AV_CODEC_ID_VP6; + ea->video_codec = AV_CODEC_ID_VP6; return 1; } -static int process_video_header_cmv(AVFormatContext *s) +static void process_video_header_cmv(AVFormatContext *s) { EaDemuxContext *ea = s->priv_data; int fps; @@ -306,90 +337,87 @@ static int process_video_header_cmv(AVFormatContext *s) avio_skip(s->pb, 10); fps = avio_rl16(s->pb); if (fps) - ea->time_base = (AVRational){1, fps}; + ea->time_base = (AVRational) { 1, fps }; ea->video_codec = AV_CODEC_ID_CMV; - - return 0; } -/* - * Process EA file header - * Returns 1 if the EA file is valid and successfully opened, 0 otherwise - */ -static int process_ea_header(AVFormatContext *s) { +/* Process EA file header. + * Return 1 if the EA file is valid and successfully opened, 0 otherwise. */ +static int process_ea_header(AVFormatContext *s) +{ uint32_t blockid, size = 0; EaDemuxContext *ea = s->priv_data; - AVIOContext *pb = s->pb; + AVIOContext *pb = s->pb; int i; - for (i=0; i<5 && (!ea->audio_codec || !ea->video_codec); i++) { + for (i = 0; i < 5 && (!ea->audio_codec || !ea->video_codec); i++) { unsigned int startpos = avio_tell(pb); - int err = 0; + int err = 0; blockid = avio_rl32(pb); - size = avio_rl32(pb); + size = avio_rl32(pb); if (i == 0) ea->big_endian = size > 0x000FFFFF; if (ea->big_endian) size = av_bswap32(size); switch (blockid) { - case ISNh_TAG: - if (avio_rl32(pb) != EACS_TAG) { - avpriv_request_sample(s, "unknown 1SNh headerid"); - return 0; - } - err = process_audio_header_eacs(s); - break; + case ISNh_TAG: + if (avio_rl32(pb) != EACS_TAG) { + avpriv_request_sample(s, "unknown 1SNh headerid"); + return 0; + } + process_audio_header_eacs(s); + break; - case SCHl_TAG : - case SHEN_TAG : - blockid = avio_rl32(pb); - if (blockid == GSTR_TAG) { - avio_skip(pb, 4); - } else if ((blockid & 0xFFFF)!=PT00_TAG) { - avpriv_request_sample(s, "unknown SCHl headerid"); - return 0; - } - err = process_audio_header_elements(s); - break; + case SCHl_TAG: + case SHEN_TAG: + blockid = avio_rl32(pb); + if (blockid == GSTR_TAG) { + avio_skip(pb, 4); + } else if ((blockid & 0xFFFF) != PT00_TAG) { + avpriv_request_sample(s, "unknown SCHl headerid"); + return 0; + } + err = process_audio_header_elements(s); + break; - case SEAD_TAG: - err = process_audio_header_sead(s); - break; + case SEAD_TAG: + process_audio_header_sead(s); + break; - case MVIh_TAG : - err = process_video_header_cmv(s); - break; + case MVIh_TAG: + process_video_header_cmv(s); + break; - case kVGT_TAG: - ea->video_codec = AV_CODEC_ID_TGV; - break; + case kVGT_TAG: + ea->video_codec = AV_CODEC_ID_TGV; + break; - case mTCD_TAG : - err = process_video_header_mdec(s); - break; + case mTCD_TAG: + process_video_header_mdec(s); + break; - case MPCh_TAG: - ea->video_codec = AV_CODEC_ID_MPEG2VIDEO; - break; + case MPCh_TAG: + ea->video_codec = AV_CODEC_ID_MPEG2VIDEO; + break; - case pQGT_TAG: - case TGQs_TAG: - ea->video_codec = AV_CODEC_ID_TGQ; - break; + case pQGT_TAG: + case TGQs_TAG: + ea->video_codec = AV_CODEC_ID_TGQ; + break; - case pIQT_TAG: - ea->video_codec = AV_CODEC_ID_TQI; - break; + case pIQT_TAG: + ea->video_codec = AV_CODEC_ID_TQI; + break; - case MADk_TAG : - ea->video_codec = AV_CODEC_ID_MAD; - break; + case MADk_TAG: + ea->video_codec = AV_CODEC_ID_MAD; + break; - case MVhd_TAG : - err = process_video_header_vp6(s); - break; + case MVhd_TAG: + err = process_video_header_vp6(s); + break; } if (err < 0) { @@ -405,7 +433,6 @@ static int process_ea_header(AVFormatContext *s) { return 1; } - static int ea_probe(AVProbeData *p) { switch (AV_RL32(&p->buf[0])) { @@ -424,6 +451,7 @@ static int ea_probe(AVProbeData *p) } if (AV_RL32(&p->buf[4]) > 0xfffff && AV_RB32(&p->buf[4]) > 0xfffff) return 0; + return AVPROBE_SCORE_MAX; } @@ -441,34 +469,37 @@ static int ea_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); ea->video_stream_index = st->index; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = ea->video_codec; + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = ea->video_codec; // parsing is necessary to make FFmpeg generate correct timestamps if (st->codec->codec_id == AV_CODEC_ID_MPEG2VIDEO) st->need_parsing = AVSTREAM_PARSE_HEADERS; - st->codec->codec_tag = 0; /* no fourcc */ - st->codec->width = ea->width; - st->codec->height = ea->height; - st->duration = st->nb_frames = ea->nb_frames; + st->codec->codec_tag = 0; /* no fourcc */ + st->codec->width = ea->width; + st->codec->height = ea->height; + st->duration = st->nb_frames = ea->nb_frames; if (ea->time_base.num) avpriv_set_pts_info(st, 64, ea->time_base.num, ea->time_base.den); - st->r_frame_rate = - st->avg_frame_rate = av_inv_q(ea->time_base); + st->r_frame_rate = + st->avg_frame_rate = av_inv_q(ea->time_base); } if (ea->audio_codec) { if (ea->num_channels <= 0) { - av_log(s, AV_LOG_WARNING, "Unsupported number of channels: %d\n", ea->num_channels); + av_log(s, AV_LOG_WARNING, + "Unsupported number of channels: %d\n", ea->num_channels); ea->audio_codec = 0; return 1; } if (ea->sample_rate <= 0) { - av_log(s, AV_LOG_ERROR, "Unsupported sample rate: %d\n", ea->sample_rate); + av_log(s, AV_LOG_ERROR, + "Unsupported sample rate: %d\n", ea->sample_rate); ea->audio_codec = 0; return 1; } if (ea->bytes <= 0) { - av_log(s, AV_LOG_ERROR, "Invalid number of bytes per sample: %d\n", ea->bytes); + av_log(s, AV_LOG_ERROR, + "Invalid number of bytes per sample: %d\n", ea->bytes); ea->audio_codec = AV_CODEC_ID_NONE; return 1; } @@ -478,32 +509,31 @@ static int ea_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); avpriv_set_pts_info(st, 33, 1, ea->sample_rate); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = ea->audio_codec; - st->codec->codec_tag = 0; /* no tag */ - st->codec->channels = ea->num_channels; - st->codec->sample_rate = ea->sample_rate; + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_id = ea->audio_codec; + st->codec->codec_tag = 0; /* no tag */ + st->codec->channels = ea->num_channels; + st->codec->sample_rate = ea->sample_rate; st->codec->bits_per_coded_sample = ea->bytes * 8; - st->codec->bit_rate = st->codec->channels * st->codec->sample_rate * - st->codec->bits_per_coded_sample / 4; - st->codec->block_align = st->codec->channels*st->codec->bits_per_coded_sample; - ea->audio_stream_index = st->index; - st->start_time = 0; + st->codec->bit_rate = st->codec->channels * + st->codec->sample_rate * + st->codec->bits_per_coded_sample / 4; + st->codec->block_align = st->codec->channels * + st->codec->bits_per_coded_sample; + ea->audio_stream_index = st->index; + st->start_time = 0; } return 1; } -static int ea_read_packet(AVFormatContext *s, - AVPacket *pkt) +static int ea_read_packet(AVFormatContext *s, AVPacket *pkt) { EaDemuxContext *ea = s->priv_data; - AVIOContext *pb = s->pb; - int ret = 0; - int packet_read = 0; + AVIOContext *pb = s->pb; int partial_packet = 0; unsigned int chunk_type, chunk_size; - int key = 0; + int ret = 0, packet_read = 0, key = 0; int av_uninit(num_samples); while (!packet_read || partial_packet) { @@ -516,7 +546,7 @@ static int ea_read_packet(AVFormatContext *s, switch (chunk_type) { /* audio data */ case ISNh_TAG: - /* header chunk also contains data; skip over the header portion*/ + /* header chunk also contains data; skip over the header portion */ if (chunk_size < 32) return AVERROR_INVALIDDATA; avio_skip(pb, 32); @@ -576,7 +606,7 @@ static int ea_read_packet(AVFormatContext *s, case SCEl_TAG: case SEND_TAG: case SEEN_TAG: - ret = AVERROR(EIO); + ret = AVERROR(EIO); packet_read = 1; break; @@ -590,12 +620,12 @@ static int ea_read_packet(AVFormatContext *s, case fVGT_TAG: case MADm_TAG: case MADe_TAG: - avio_seek(pb, -8, SEEK_CUR); // include chunk preamble + avio_seek(pb, -8, SEEK_CUR); // include chunk preamble chunk_size += 8; goto get_video_packet; case mTCD_TAG: - avio_skip(pb, 8); // skip ea dct header + avio_skip(pb, 8); // skip ea DCT header chunk_size -= 8; goto get_video_packet; @@ -615,8 +645,8 @@ get_video_packet: } partial_packet = chunk_type == MVIh_TAG; pkt->stream_index = ea->video_stream_index; - pkt->flags |= key; - packet_read = 1; + pkt->flags |= key; + packet_read = 1; break; default: diff --git a/chromium/third_party/ffmpeg/libavformat/ffmenc.c b/chromium/third_party/ffmpeg/libavformat/ffmenc.c index 522945ec586..eb809eb64ce 100644 --- a/chromium/third_party/ffmpeg/libavformat/ffmenc.c +++ b/chromium/third_party/ffmpeg/libavformat/ffmenc.c @@ -277,4 +277,5 @@ AVOutputFormat ff_ffm_muxer = { .write_header = ffm_write_header, .write_packet = ffm_write_packet, .write_trailer = ffm_write_trailer, + .flags = AVFMT_TS_NEGATIVE, }; diff --git a/chromium/third_party/ffmpeg/libavformat/file.c b/chromium/third_party/ffmpeg/libavformat/file.c index e09a64b37cf..2defc75e5f7 100644 --- a/chromium/third_party/ffmpeg/libavformat/file.c +++ b/chromium/third_party/ffmpeg/libavformat/file.c @@ -20,6 +20,7 @@ */ #include "libavutil/avstring.h" +#include "libavutil/internal.h" #include "libavutil/opt.h" #include "avformat.h" #include <fcntl.h> @@ -49,10 +50,17 @@ typedef struct FileContext { const AVClass *class; int fd; int trunc; + int blocksize; } FileContext; static const AVOption file_options[] = { { "truncate", "Truncate existing files on write", offsetof(FileContext, trunc), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, AV_OPT_FLAG_ENCODING_PARAM }, + { "blocksize", "set I/O operation maximum block size", offsetof(FileContext, blocksize), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + { NULL } +}; + +static const AVOption pipe_options[] = { + { "blocksize", "set I/O operation maximum block size", offsetof(FileContext, blocksize), AV_OPT_TYPE_INT, { .i64 = INT_MAX }, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM }, { NULL } }; @@ -63,17 +71,28 @@ static const AVClass file_class = { .version = LIBAVUTIL_VERSION_INT, }; +static const AVClass pipe_class = { + .class_name = "pipe", + .item_name = av_default_item_name, + .option = pipe_options, + .version = LIBAVUTIL_VERSION_INT, +}; + static int file_read(URLContext *h, unsigned char *buf, int size) { FileContext *c = h->priv_data; - int r = read(c->fd, buf, size); + int r; + size = FFMIN(size, c->blocksize); + r = read(c->fd, buf, size); return (-1 == r)?AVERROR(errno):r; } static int file_write(URLContext *h, const unsigned char *buf, int size) { FileContext *c = h->priv_data; - int r = write(c->fd, buf, size); + int r; + size = FFMIN(size, c->blocksize); + r = write(c->fd, buf, size); return (-1 == r)?AVERROR(errno):r; } @@ -132,7 +151,7 @@ static int file_open(URLContext *h, const char *filename, int flags) #ifdef O_BINARY access |= O_BINARY; #endif - fd = open(filename, access, 0666); + fd = avpriv_open(filename, access, 0666); if (fd == -1) return AVERROR(errno); c->fd = fd; @@ -213,6 +232,7 @@ URLProtocol ff_pipe_protocol = { .url_get_file_handle = file_get_handle, .url_check = file_check, .priv_data_size = sizeof(FileContext), + .priv_data_class = &pipe_class, }; #endif /* CONFIG_PIPE_PROTOCOL */ diff --git a/chromium/third_party/ffmpeg/libavformat/file_open.c b/chromium/third_party/ffmpeg/libavformat/file_open.c new file mode 100644 index 00000000000..494a5d37a4a --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/file_open.c @@ -0,0 +1 @@ +#include "libavutil/file_open.c" diff --git a/chromium/third_party/ffmpeg/libavformat/flacdec.c b/chromium/third_party/ffmpeg/libavformat/flacdec.c index d5aacfd15f8..8384076b3d8 100644 --- a/chromium/third_party/ffmpeg/libavformat/flacdec.c +++ b/chromium/third_party/ffmpeg/libavformat/flacdec.c @@ -21,139 +21,13 @@ #include "libavcodec/flac.h" #include "avformat.h" -#include "id3v2.h" +#include "flacdec.h" #include "internal.h" #include "rawdec.h" #include "oggdec.h" #include "vorbiscomment.h" #include "libavcodec/bytestream.h" -#define RETURN_ERROR(code) do { ret = (code); goto fail; } while (0) - -static int parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) -{ - const CodecMime *mime = ff_id3v2_mime_tags; - enum AVCodecID id = AV_CODEC_ID_NONE; - AVBufferRef *data = NULL; - uint8_t mimetype[64], *desc = NULL; - AVIOContext *pb = NULL; - AVStream *st; - int type, width, height; - int len, ret = 0; - - pb = avio_alloc_context(buf, buf_size, 0, NULL, NULL, NULL, NULL); - if (!pb) - return AVERROR(ENOMEM); - - /* read the picture type */ - type = avio_rb32(pb); - if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) { - av_log(s, AV_LOG_ERROR, "Invalid picture type: %d.\n", type); - if (s->error_recognition & AV_EF_EXPLODE) { - RETURN_ERROR(AVERROR_INVALIDDATA); - } - type = 0; - } - - /* picture mimetype */ - len = avio_rb32(pb); - if (len <= 0 || - avio_read(pb, mimetype, FFMIN(len, sizeof(mimetype) - 1)) != len) { - av_log(s, AV_LOG_ERROR, "Could not read mimetype from an attached " - "picture.\n"); - if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR_INVALIDDATA; - goto fail; - } - mimetype[len] = 0; - - while (mime->id != AV_CODEC_ID_NONE) { - if (!strncmp(mime->str, mimetype, sizeof(mimetype))) { - id = mime->id; - break; - } - mime++; - } - if (id == AV_CODEC_ID_NONE) { - av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n", - mimetype); - if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR_INVALIDDATA; - goto fail; - } - - /* picture description */ - len = avio_rb32(pb); - if (len > 0) { - if (!(desc = av_malloc(len + 1))) { - RETURN_ERROR(AVERROR(ENOMEM)); - } - - if (avio_read(pb, desc, len) != len) { - av_log(s, AV_LOG_ERROR, "Error reading attached picture description.\n"); - if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR(EIO); - goto fail; - } - desc[len] = 0; - } - - /* picture metadata */ - width = avio_rb32(pb); - height = avio_rb32(pb); - avio_skip(pb, 8); - - /* picture data */ - len = avio_rb32(pb); - if (len <= 0) { - av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len); - if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR_INVALIDDATA; - goto fail; - } - if (!(data = av_buffer_alloc(len))) { - RETURN_ERROR(AVERROR(ENOMEM)); - } - if (avio_read(pb, data->data, len) != len) { - av_log(s, AV_LOG_ERROR, "Error reading attached picture data.\n"); - if (s->error_recognition & AV_EF_EXPLODE) - ret = AVERROR(EIO); - goto fail; - } - - st = avformat_new_stream(s, NULL); - if (!st) { - RETURN_ERROR(AVERROR(ENOMEM)); - } - - av_init_packet(&st->attached_pic); - st->attached_pic.buf = data; - st->attached_pic.data = data->data; - st->attached_pic.size = len; - st->attached_pic.stream_index = st->index; - st->attached_pic.flags |= AV_PKT_FLAG_KEY; - - st->disposition |= AV_DISPOSITION_ATTACHED_PIC; - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = id; - st->codec->width = width; - st->codec->height = height; - av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0); - if (desc) - av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL); - - av_freep(&pb); - - return 0; - -fail: - av_buffer_unref(&data); - av_freep(&desc); - av_freep(&pb); - return ret; - -} - static int flac_read_header(AVFormatContext *s) { int ret, metadata_last=0, metadata_type, metadata_size, found_streaminfo=0; @@ -248,7 +122,7 @@ static int flac_read_header(AVFormatContext *s) } av_freep(&buffer); } else if (metadata_type == FLAC_METADATA_TYPE_PICTURE) { - ret = parse_picture(s, buffer, metadata_size); + ret = ff_flac_parse_picture(s, buffer, metadata_size); av_freep(&buffer); if (ret < 0) { av_log(s, AV_LOG_ERROR, "Error parsing attached picture.\n"); @@ -280,7 +154,7 @@ static int flac_probe(AVProbeData *p) { if (p->buf_size < 4 || memcmp(p->buf, "fLaC", 4)) return 0; - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; } AVInputFormat ff_flac_demuxer = { diff --git a/chromium/third_party/ffmpeg/libavformat/flacdec.h b/chromium/third_party/ffmpeg/libavformat/flacdec.h new file mode 100644 index 00000000000..dff0660311b --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/flacdec.h @@ -0,0 +1,31 @@ +/* + * Raw FLAC demuxer + * Copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_FLACDEC_H +#define AVFORMAT_FLACDEC_H + +#include "avformat.h" + +#define RETURN_ERROR(code) do { ret = (code); goto fail; } while (0) + +int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size); + +#endif /* AVFORMAT_FLACDEC_H */ diff --git a/chromium/third_party/ffmpeg/libavformat/flacdec_picture.c b/chromium/third_party/ffmpeg/libavformat/flacdec_picture.c new file mode 100644 index 00000000000..1b0bea2dd0d --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/flacdec_picture.c @@ -0,0 +1,150 @@ +/* + * Raw FLAC demuxer + * Copyright (c) 2001 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "avformat.h" +#include "flacdec.h" +#include "id3v2.h" +#include "internal.h" + +int ff_flac_parse_picture(AVFormatContext *s, uint8_t *buf, int buf_size) +{ + const CodecMime *mime = ff_id3v2_mime_tags; + enum AVCodecID id = AV_CODEC_ID_NONE; + AVBufferRef *data = NULL; + uint8_t mimetype[64], *desc = NULL; + AVIOContext *pb = NULL; + AVStream *st; + int type, width, height; + int len, ret = 0; + + pb = avio_alloc_context(buf, buf_size, 0, NULL, NULL, NULL, NULL); + if (!pb) + return AVERROR(ENOMEM); + + /* read the picture type */ + type = avio_rb32(pb); + if (type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types) || type < 0) { + av_log(s, AV_LOG_ERROR, "Invalid picture type: %d.\n", type); + if (s->error_recognition & AV_EF_EXPLODE) { + RETURN_ERROR(AVERROR_INVALIDDATA); + } + type = 0; + } + + /* picture mimetype */ + len = avio_rb32(pb); + if (len <= 0 || + avio_read(pb, mimetype, FFMIN(len, sizeof(mimetype) - 1)) != len) { + av_log(s, AV_LOG_ERROR, "Could not read mimetype from an attached " + "picture.\n"); + if (s->error_recognition & AV_EF_EXPLODE) + ret = AVERROR_INVALIDDATA; + goto fail; + } + av_assert0(len < sizeof(mimetype)); + mimetype[len] = 0; + + while (mime->id != AV_CODEC_ID_NONE) { + if (!strncmp(mime->str, mimetype, sizeof(mimetype))) { + id = mime->id; + break; + } + mime++; + } + if (id == AV_CODEC_ID_NONE) { + av_log(s, AV_LOG_ERROR, "Unknown attached picture mimetype: %s.\n", + mimetype); + if (s->error_recognition & AV_EF_EXPLODE) + ret = AVERROR_INVALIDDATA; + goto fail; + } + + /* picture description */ + len = avio_rb32(pb); + if (len > 0) { + if (!(desc = av_malloc(len + 1))) { + RETURN_ERROR(AVERROR(ENOMEM)); + } + + if (avio_read(pb, desc, len) != len) { + av_log(s, AV_LOG_ERROR, "Error reading attached picture description.\n"); + if (s->error_recognition & AV_EF_EXPLODE) + ret = AVERROR(EIO); + goto fail; + } + desc[len] = 0; + } + + /* picture metadata */ + width = avio_rb32(pb); + height = avio_rb32(pb); + avio_skip(pb, 8); + + /* picture data */ + len = avio_rb32(pb); + if (len <= 0) { + av_log(s, AV_LOG_ERROR, "Invalid attached picture size: %d.\n", len); + if (s->error_recognition & AV_EF_EXPLODE) + ret = AVERROR_INVALIDDATA; + goto fail; + } + if (!(data = av_buffer_alloc(len))) { + RETURN_ERROR(AVERROR(ENOMEM)); + } + if (avio_read(pb, data->data, len) != len) { + av_log(s, AV_LOG_ERROR, "Error reading attached picture data.\n"); + if (s->error_recognition & AV_EF_EXPLODE) + ret = AVERROR(EIO); + goto fail; + } + + st = avformat_new_stream(s, NULL); + if (!st) { + RETURN_ERROR(AVERROR(ENOMEM)); + } + + av_init_packet(&st->attached_pic); + st->attached_pic.buf = data; + st->attached_pic.data = data->data; + st->attached_pic.size = len; + st->attached_pic.stream_index = st->index; + st->attached_pic.flags |= AV_PKT_FLAG_KEY; + + st->disposition |= AV_DISPOSITION_ATTACHED_PIC; + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = id; + st->codec->width = width; + st->codec->height = height; + av_dict_set(&st->metadata, "comment", ff_id3v2_picture_types[type], 0); + if (desc) + av_dict_set(&st->metadata, "title", desc, AV_DICT_DONT_STRDUP_VAL); + + av_freep(&pb); + + return 0; + +fail: + av_buffer_unref(&data); + av_freep(&desc); + av_freep(&pb); + return ret; +} diff --git a/chromium/third_party/ffmpeg/libavformat/flacenc.c b/chromium/third_party/ffmpeg/libavformat/flacenc.c index 8c1a1bb7bd3..87e93625f28 100644 --- a/chromium/third_party/ffmpeg/libavformat/flacenc.c +++ b/chromium/third_party/ffmpeg/libavformat/flacenc.c @@ -21,6 +21,7 @@ #include "libavcodec/flac.h" #include "avformat.h" +#include "avio_internal.h" #include "flacenc.h" #include "vorbiscomment.h" #include "libavcodec/bytestream.h" @@ -31,10 +32,7 @@ static int flac_write_block_padding(AVIOContext *pb, unsigned int n_padding_byte { avio_w8(pb, last_block ? 0x81 : 0x01); avio_wb24(pb, n_padding_bytes); - while (n_padding_bytes > 0) { - avio_w8(pb, 0); - n_padding_bytes--; - } + ffio_fill(pb, 0, n_padding_bytes); return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/flic.c b/chromium/third_party/ffmpeg/libavformat/flic.c index 8d49116acf9..2835cf557b6 100644 --- a/chromium/third_party/ffmpeg/libavformat/flic.c +++ b/chromium/third_party/ffmpeg/libavformat/flic.c @@ -80,7 +80,7 @@ static int flic_probe(AVProbeData *p) return 0; - return AVPROBE_SCORE_MAX; + return AVPROBE_SCORE_MAX - 1; } static int flic_read_header(AVFormatContext *s) diff --git a/chromium/third_party/ffmpeg/libavformat/flvdec.c b/chromium/third_party/ffmpeg/libavformat/flvdec.c index 8bb56e85c0c..e0b79bb7540 100644 --- a/chromium/third_party/ffmpeg/libavformat/flvdec.c +++ b/chromium/third_party/ffmpeg/libavformat/flvdec.c @@ -41,12 +41,12 @@ typedef struct { const AVClass *class; ///< Class for private options. - int trust_metadata; ///< configure streams according onMetaData - int wrong_dts; ///< wrong dts due to negative cts + int trust_metadata; ///< configure streams according onMetaData + int wrong_dts; ///< wrong dts due to negative cts uint8_t *new_extradata[FLV_STREAM_TYPE_NB]; - int new_extradata_size[FLV_STREAM_TYPE_NB]; - int last_sample_rate; - int last_channels; + int new_extradata_size[FLV_STREAM_TYPE_NB]; + int last_sample_rate; + int last_channels; struct { int64_t dts; int64_t pos; @@ -61,7 +61,11 @@ static int flv_probe(AVProbeData *p) const uint8_t *d; d = p->buf; - if (d[0] == 'F' && d[1] == 'L' && d[2] == 'V' && d[3] < 5 && d[5]==0 && AV_RB32(d+5)>8) { + if (d[0] == 'F' && + d[1] == 'L' && + d[2] == 'V' && + d[3] < 5 && d[5] == 0 && + AV_RB32(d + 5) > 8) { return AVPROBE_SCORE_MAX; } return 0; @@ -73,7 +77,7 @@ static AVStream *create_stream(AVFormatContext *s, int codec_type) if (!st) return NULL; st->codec->codec_type = codec_type; - if(s->nb_streams>=3 ||( s->nb_streams==2 + if (s->nb_streams>=3 ||( s->nb_streams==2 && s->streams[0]->codec->codec_type != AVMEDIA_TYPE_DATA && s->streams[1]->codec->codec_type != AVMEDIA_TYPE_DATA)) s->ctx_flags &= ~AVFMTCTX_NOHEADER; @@ -81,10 +85,11 @@ static AVStream *create_stream(AVFormatContext *s, int codec_type) avpriv_set_pts_info(st, 32, 1, 1000); /* 32 bit pts in ms */ return st; } + static int flv_same_audio_codec(AVCodecContext *acodec, int flags) { int bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8; - int flv_codecid = flags & FLV_AUDIO_CODECID_MASK; + int flv_codecid = flags & FLV_AUDIO_CODECID_MASK; int codec_id; if (!acodec->codec_id && !acodec->codec_tag) @@ -93,18 +98,21 @@ static int flv_same_audio_codec(AVCodecContext *acodec, int flags) if (acodec->bits_per_coded_sample != bits_per_coded_sample) return 0; - switch(flv_codecid) { - //no distinction between S16 and S8 PCM codec flags + switch (flv_codecid) { + // no distinction between S16 and S8 PCM codec flags case FLV_CODECID_PCM: - codec_id = bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 : + codec_id = bits_per_coded_sample == 8 + ? AV_CODEC_ID_PCM_U8 #if HAVE_BIGENDIAN - AV_CODEC_ID_PCM_S16BE; + : AV_CODEC_ID_PCM_S16BE; #else - AV_CODEC_ID_PCM_S16LE; + : AV_CODEC_ID_PCM_S16LE; #endif return codec_id == acodec->codec_id; case FLV_CODECID_PCM_LE: - codec_id = bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 : AV_CODEC_ID_PCM_S16LE; + codec_id = bits_per_coded_sample == 8 + ? AV_CODEC_ID_PCM_U8 + : AV_CODEC_ID_PCM_S16LE; return codec_id == acodec->codec_id; case FLV_CODECID_AAC: return acodec->codec_id == AV_CODEC_ID_AAC; @@ -120,57 +128,72 @@ static int flv_same_audio_codec(AVCodecContext *acodec, int flags) return acodec->codec_id == AV_CODEC_ID_NELLYMOSER; case FLV_CODECID_PCM_MULAW: return acodec->sample_rate == 8000 && - acodec->codec_id == AV_CODEC_ID_PCM_MULAW; + acodec->codec_id == AV_CODEC_ID_PCM_MULAW; case FLV_CODECID_PCM_ALAW: - return acodec->sample_rate = 8000 && - acodec->codec_id == AV_CODEC_ID_PCM_ALAW; + return acodec->sample_rate == 8000 && + acodec->codec_id == AV_CODEC_ID_PCM_ALAW; default: return acodec->codec_tag == (flv_codecid >> FLV_AUDIO_CODECID_OFFSET); } } -static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, AVCodecContext *acodec, int flv_codecid) { - switch(flv_codecid) { - //no distinction between S16 and S8 PCM codec flags - case FLV_CODECID_PCM: - acodec->codec_id = acodec->bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 : +static void flv_set_audio_codec(AVFormatContext *s, AVStream *astream, + AVCodecContext *acodec, int flv_codecid) +{ + switch (flv_codecid) { + // no distinction between S16 and S8 PCM codec flags + case FLV_CODECID_PCM: + acodec->codec_id = acodec->bits_per_coded_sample == 8 + ? AV_CODEC_ID_PCM_U8 #if HAVE_BIGENDIAN - AV_CODEC_ID_PCM_S16BE; + : AV_CODEC_ID_PCM_S16BE; #else - AV_CODEC_ID_PCM_S16LE; + : AV_CODEC_ID_PCM_S16LE; #endif - break; - case FLV_CODECID_PCM_LE: - acodec->codec_id = acodec->bits_per_coded_sample == 8 ? AV_CODEC_ID_PCM_U8 : AV_CODEC_ID_PCM_S16LE; break; - case FLV_CODECID_AAC : acodec->codec_id = AV_CODEC_ID_AAC; break; - case FLV_CODECID_ADPCM: acodec->codec_id = AV_CODEC_ID_ADPCM_SWF; break; - case FLV_CODECID_SPEEX: - acodec->codec_id = AV_CODEC_ID_SPEEX; - acodec->sample_rate = 16000; - break; - case FLV_CODECID_MP3 : acodec->codec_id = AV_CODEC_ID_MP3 ; astream->need_parsing = AVSTREAM_PARSE_FULL; break; - case FLV_CODECID_NELLYMOSER_8KHZ_MONO: - acodec->sample_rate = 8000; //in case metadata does not otherwise declare samplerate - acodec->codec_id = AV_CODEC_ID_NELLYMOSER; - break; - case FLV_CODECID_NELLYMOSER_16KHZ_MONO: - acodec->sample_rate = 16000; - acodec->codec_id = AV_CODEC_ID_NELLYMOSER; - break; - case FLV_CODECID_NELLYMOSER: - acodec->codec_id = AV_CODEC_ID_NELLYMOSER; - break; - case FLV_CODECID_PCM_MULAW: - acodec->sample_rate = 8000; - acodec->codec_id = AV_CODEC_ID_PCM_MULAW; - break; - case FLV_CODECID_PCM_ALAW: - acodec->sample_rate = 8000; - acodec->codec_id = AV_CODEC_ID_PCM_ALAW; - break; - default: - av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", flv_codecid >> FLV_AUDIO_CODECID_OFFSET); - acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET; + break; + case FLV_CODECID_PCM_LE: + acodec->codec_id = acodec->bits_per_coded_sample == 8 + ? AV_CODEC_ID_PCM_U8 + : AV_CODEC_ID_PCM_S16LE; + break; + case FLV_CODECID_AAC: + acodec->codec_id = AV_CODEC_ID_AAC; + break; + case FLV_CODECID_ADPCM: + acodec->codec_id = AV_CODEC_ID_ADPCM_SWF; + break; + case FLV_CODECID_SPEEX: + acodec->codec_id = AV_CODEC_ID_SPEEX; + acodec->sample_rate = 16000; + break; + case FLV_CODECID_MP3: + acodec->codec_id = AV_CODEC_ID_MP3; + astream->need_parsing = AVSTREAM_PARSE_FULL; + break; + case FLV_CODECID_NELLYMOSER_8KHZ_MONO: + // in case metadata does not otherwise declare samplerate + acodec->sample_rate = 8000; + acodec->codec_id = AV_CODEC_ID_NELLYMOSER; + break; + case FLV_CODECID_NELLYMOSER_16KHZ_MONO: + acodec->sample_rate = 16000; + acodec->codec_id = AV_CODEC_ID_NELLYMOSER; + break; + case FLV_CODECID_NELLYMOSER: + acodec->codec_id = AV_CODEC_ID_NELLYMOSER; + break; + case FLV_CODECID_PCM_MULAW: + acodec->sample_rate = 8000; + acodec->codec_id = AV_CODEC_ID_PCM_MULAW; + break; + case FLV_CODECID_PCM_ALAW: + acodec->sample_rate = 8000; + acodec->codec_id = AV_CODEC_ID_PCM_ALAW; + break; + default: + av_log(s, AV_LOG_INFO, "Unsupported audio codec (%x)\n", + flv_codecid >> FLV_AUDIO_CODECID_OFFSET); + acodec->codec_tag = flv_codecid >> FLV_AUDIO_CODECID_OFFSET; } } @@ -182,63 +205,75 @@ static int flv_same_video_codec(AVCodecContext *vcodec, int flags) return 1; switch (flv_codecid) { - case FLV_CODECID_H263: - return vcodec->codec_id == AV_CODEC_ID_FLV1; - case FLV_CODECID_SCREEN: - return vcodec->codec_id == AV_CODEC_ID_FLASHSV; - case FLV_CODECID_SCREEN2: - return vcodec->codec_id == AV_CODEC_ID_FLASHSV2; - case FLV_CODECID_VP6: - return vcodec->codec_id == AV_CODEC_ID_VP6F; - case FLV_CODECID_VP6A: - return vcodec->codec_id == AV_CODEC_ID_VP6A; - case FLV_CODECID_H264: - return vcodec->codec_id == AV_CODEC_ID_H264; - default: - return vcodec->codec_tag == flv_codecid; + case FLV_CODECID_H263: + return vcodec->codec_id == AV_CODEC_ID_FLV1; + case FLV_CODECID_SCREEN: + return vcodec->codec_id == AV_CODEC_ID_FLASHSV; + case FLV_CODECID_SCREEN2: + return vcodec->codec_id == AV_CODEC_ID_FLASHSV2; + case FLV_CODECID_VP6: + return vcodec->codec_id == AV_CODEC_ID_VP6F; + case FLV_CODECID_VP6A: + return vcodec->codec_id == AV_CODEC_ID_VP6A; + case FLV_CODECID_H264: + return vcodec->codec_id == AV_CODEC_ID_H264; + default: + return vcodec->codec_tag == flv_codecid; } } -static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, int flv_codecid, int read) { +static int flv_set_video_codec(AVFormatContext *s, AVStream *vstream, + int flv_codecid, int read) +{ AVCodecContext *vcodec = vstream->codec; - switch(flv_codecid) { - case FLV_CODECID_H263 : vcodec->codec_id = AV_CODEC_ID_FLV1 ; break; - case FLV_CODECID_REALH263: vcodec->codec_id = AV_CODEC_ID_H263 ; break; // Really mean it this time - case FLV_CODECID_SCREEN: vcodec->codec_id = AV_CODEC_ID_FLASHSV; break; - case FLV_CODECID_SCREEN2: vcodec->codec_id = AV_CODEC_ID_FLASHSV2; break; - case FLV_CODECID_VP6 : vcodec->codec_id = AV_CODEC_ID_VP6F ; - case FLV_CODECID_VP6A : - if(flv_codecid == FLV_CODECID_VP6A) - vcodec->codec_id = AV_CODEC_ID_VP6A; - if (read) { - if (vcodec->extradata_size != 1) { - vcodec->extradata = av_malloc(1 + FF_INPUT_BUFFER_PADDING_SIZE); - if (vcodec->extradata) - vcodec->extradata_size = 1; - } + switch (flv_codecid) { + case FLV_CODECID_H263: + vcodec->codec_id = AV_CODEC_ID_FLV1; + break; + case FLV_CODECID_REALH263: + vcodec->codec_id = AV_CODEC_ID_H263; + break; // Really mean it this time + case FLV_CODECID_SCREEN: + vcodec->codec_id = AV_CODEC_ID_FLASHSV; + break; + case FLV_CODECID_SCREEN2: + vcodec->codec_id = AV_CODEC_ID_FLASHSV2; + break; + case FLV_CODECID_VP6: + vcodec->codec_id = AV_CODEC_ID_VP6F; + case FLV_CODECID_VP6A: + if (flv_codecid == FLV_CODECID_VP6A) + vcodec->codec_id = AV_CODEC_ID_VP6A; + if (read) { + if (vcodec->extradata_size != 1) { + vcodec->extradata = av_malloc(1 + FF_INPUT_BUFFER_PADDING_SIZE); if (vcodec->extradata) - vcodec->extradata[0] = avio_r8(s->pb); - else - avio_skip(s->pb, 1); + vcodec->extradata_size = 1; } - return 1; // 1 byte body size adjustment for flv_read_packet() - case FLV_CODECID_H264: - vcodec->codec_id = AV_CODEC_ID_H264; - return 3; // not 4, reading packet type will consume one byte - case FLV_CODECID_MPEG4: - vcodec->codec_id = AV_CODEC_ID_MPEG4; - return 3; - default: - av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid); - vcodec->codec_tag = flv_codecid; + if (vcodec->extradata) + vcodec->extradata[0] = avio_r8(s->pb); + else + avio_skip(s->pb, 1); + } + return 1; // 1 byte body size adjustment for flv_read_packet() + case FLV_CODECID_H264: + vcodec->codec_id = AV_CODEC_ID_H264; + return 3; // not 4, reading packet type will consume one byte + case FLV_CODECID_MPEG4: + vcodec->codec_id = AV_CODEC_ID_MPEG4; + return 3; + default: + av_log(s, AV_LOG_INFO, "Unsupported video codec (%x)\n", flv_codecid); + vcodec->codec_tag = flv_codecid; } return 0; } -static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize) { +static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize) +{ int length = avio_rb16(ioc); - if(length >= buffsize) { + if (length >= buffsize) { avio_skip(ioc, length); return -1; } @@ -250,16 +285,18 @@ static int amf_get_string(AVIOContext *ioc, char *buffer, int buffsize) { return length; } -static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream *vstream, int64_t max_pos) { - FLVContext *flv = s->priv_data; +static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, + AVStream *vstream, int64_t max_pos) +{ + FLVContext *flv = s->priv_data; unsigned int timeslen = 0, fileposlen = 0, i; char str_val[256]; - int64_t *times = NULL; + int64_t *times = NULL; int64_t *filepositions = NULL; - int ret = AVERROR(ENOSYS); - int64_t initial_pos = avio_tell(ioc); + int ret = AVERROR(ENOSYS); + int64_t initial_pos = avio_tell(ioc); - if(vstream->nb_index_entries>0){ + if (vstream->nb_index_entries>0) { av_log(s, AV_LOG_WARNING, "Skiping duplicate index\n"); return 0; } @@ -267,8 +304,9 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream if (s->flags & AVFMT_FLAG_IGNIDX) return 0; - while (avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) { - int64_t** current_array; + while (avio_tell(ioc) < max_pos - 2 && + amf_get_string(ioc, str_val, sizeof(str_val)) > 0) { + int64_t **current_array; unsigned int arraylen; // Expect array object in context @@ -276,16 +314,19 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream break; arraylen = avio_rb32(ioc); - if(arraylen>>28) + if (arraylen>>28) break; - if (!strcmp(KEYFRAMES_TIMESTAMP_TAG , str_val) && !times){ - current_array= × - timeslen= arraylen; - }else if (!strcmp(KEYFRAMES_BYTEOFFSET_TAG, str_val) && !filepositions){ - current_array= &filepositions; - fileposlen= arraylen; - }else // unexpected metatag inside keyframes, will not use such metadata for indexing + if (!strcmp(KEYFRAMES_TIMESTAMP_TAG , str_val) && !times) { + current_array = × + timeslen = arraylen; + } else if (!strcmp(KEYFRAMES_BYTEOFFSET_TAG, str_val) && + !filepositions) { + current_array = &filepositions; + fileposlen = arraylen; + } else + // unexpected metatag inside keyframes, will not use such + // metadata for indexing break; if (!(*current_array = av_mallocz(sizeof(**current_array) * arraylen))) { @@ -308,12 +349,12 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream if (timeslen == fileposlen && fileposlen>1 && max_pos <= filepositions[0]) { for (i = 0; i < fileposlen; i++) { - av_add_index_entry(vstream, filepositions[i], times[i]*1000, + av_add_index_entry(vstream, filepositions[i], times[i] * 1000, 0, 0, AVINDEX_KEYFRAME); if (i < 2) { flv->validate_index[i].pos = filepositions[i]; flv->validate_index[i].dts = times[i] * 1000; - flv->validate_count = i + 1; + flv->validate_count = i + 1; } } } else { @@ -328,7 +369,10 @@ finish: return ret; } -static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vstream, const char *key, int64_t max_pos, int depth) { +static int amf_parse_object(AVFormatContext *s, AVStream *astream, + AVStream *vstream, const char *key, + int64_t max_pos, int depth) +{ AVCodecContext *acodec, *vcodec; FLVContext *flv = s->priv_data; AVIOContext *ioc; @@ -336,74 +380,85 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst char str_val[256]; double num_val; - num_val = 0; - ioc = s->pb; - + num_val = 0; + ioc = s->pb; amf_type = avio_r8(ioc); - switch(amf_type) { - case AMF_DATA_TYPE_NUMBER: - num_val = av_int2double(avio_rb64(ioc)); break; - case AMF_DATA_TYPE_BOOL: - num_val = avio_r8(ioc); break; - case AMF_DATA_TYPE_STRING: - if(amf_get_string(ioc, str_val, sizeof(str_val)) < 0) - return -1; - break; - case AMF_DATA_TYPE_OBJECT: - if ((vstream || astream) && ioc->seekable && key && !strcmp(KEYFRAMES_TAG, key) && depth == 1) - if (parse_keyframes_index(s, ioc, vstream ? vstream : astream, - max_pos) < 0) - av_log(s, AV_LOG_ERROR, "Keyframe index parsing failed\n"); - - while (avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) { - if (amf_parse_object(s, astream, vstream, str_val, max_pos, depth + 1) < 0) - return -1; //if we couldn't skip, bomb out. - } - if(avio_r8(ioc) != AMF_END_OF_OBJECT) - return -1; - break; - case AMF_DATA_TYPE_NULL: - case AMF_DATA_TYPE_UNDEFINED: - case AMF_DATA_TYPE_UNSUPPORTED: - break; //these take up no additional space - case AMF_DATA_TYPE_MIXEDARRAY: - avio_skip(ioc, 4); //skip 32-bit max array index - while(avio_tell(ioc) < max_pos - 2 && amf_get_string(ioc, str_val, sizeof(str_val)) > 0) { - //this is the only case in which we would want a nested parse to not skip over the object - if(amf_parse_object(s, astream, vstream, str_val, max_pos, depth + 1) < 0) - return -1; - } - if(avio_r8(ioc) != AMF_END_OF_OBJECT) + switch (amf_type) { + case AMF_DATA_TYPE_NUMBER: + num_val = av_int2double(avio_rb64(ioc)); + break; + case AMF_DATA_TYPE_BOOL: + num_val = avio_r8(ioc); + break; + case AMF_DATA_TYPE_STRING: + if (amf_get_string(ioc, str_val, sizeof(str_val)) < 0) + return -1; + break; + case AMF_DATA_TYPE_OBJECT: + if ((vstream || astream) && key && + ioc->seekable && + !strcmp(KEYFRAMES_TAG, key) && depth == 1) + if (parse_keyframes_index(s, ioc, vstream ? vstream : astream, + max_pos) < 0) + av_log(s, AV_LOG_ERROR, "Keyframe index parsing failed\n"); + + while (avio_tell(ioc) < max_pos - 2 && + amf_get_string(ioc, str_val, sizeof(str_val)) > 0) + if (amf_parse_object(s, astream, vstream, str_val, max_pos, + depth + 1) < 0) + return -1; // if we couldn't skip, bomb out. + if (avio_r8(ioc) != AMF_END_OF_OBJECT) + return -1; + break; + case AMF_DATA_TYPE_NULL: + case AMF_DATA_TYPE_UNDEFINED: + case AMF_DATA_TYPE_UNSUPPORTED: + break; // these take up no additional space + case AMF_DATA_TYPE_MIXEDARRAY: + avio_skip(ioc, 4); // skip 32-bit max array index + while (avio_tell(ioc) < max_pos - 2 && + amf_get_string(ioc, str_val, sizeof(str_val)) > 0) + // this is the only case in which we would want a nested + // parse to not skip over the object + if (amf_parse_object(s, astream, vstream, str_val, max_pos, + depth + 1) < 0) return -1; - break; - case AMF_DATA_TYPE_ARRAY: { - unsigned int arraylen, i; - - arraylen = avio_rb32(ioc); - for(i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) { - if(amf_parse_object(s, NULL, NULL, NULL, max_pos, depth + 1) < 0) - return -1; //if we couldn't skip, bomb out. - } - } - break; - case AMF_DATA_TYPE_DATE: - avio_skip(ioc, 8 + 2); //timestamp (double) and UTC offset (int16) - break; - default: //unsupported type, we couldn't skip + if (avio_r8(ioc) != AMF_END_OF_OBJECT) return -1; + break; + case AMF_DATA_TYPE_ARRAY: + { + unsigned int arraylen, i; + + arraylen = avio_rb32(ioc); + for (i = 0; i < arraylen && avio_tell(ioc) < max_pos - 1; i++) + if (amf_parse_object(s, NULL, NULL, NULL, max_pos, + depth + 1) < 0) + return -1; // if we couldn't skip, bomb out. + } + break; + case AMF_DATA_TYPE_DATE: + avio_skip(ioc, 8 + 2); // timestamp (double) and UTC offset (int16) + break; + default: // unsupported type, we couldn't skip + return -1; } - if(depth == 1 && key) { //only look for metadata values when we are not nested and key != NULL + // only look for metadata values when we are not nested and key != NULL + if (depth == 1 && key) { acodec = astream ? astream->codec : NULL; vcodec = vstream ? vstream->codec : NULL; - if (amf_type == AMF_DATA_TYPE_NUMBER || amf_type == AMF_DATA_TYPE_BOOL) { + if (amf_type == AMF_DATA_TYPE_NUMBER || + amf_type == AMF_DATA_TYPE_BOOL) { if (!strcmp(key, "duration")) s->duration = num_val * AV_TIME_BASE; - else if (!strcmp(key, "videodatarate") && vcodec && 0 <= (int)(num_val * 1024.0)) + else if (!strcmp(key, "videodatarate") && vcodec && + 0 <= (int)(num_val * 1024.0)) vcodec->bit_rate = num_val * 1024.0; - else if (!strcmp(key, "audiodatarate") && acodec && 0 <= (int)(num_val * 1024.0)) + else if (!strcmp(key, "audiodatarate") && acodec && + 0 <= (int)(num_val * 1024.0)) acodec->bit_rate = num_val * 1024.0; else if (!strcmp(key, "datastream")) { AVStream *st = create_stream(s, AVMEDIA_TYPE_DATA); @@ -413,25 +468,21 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst } else if (flv->trust_metadata) { if (!strcmp(key, "videocodecid") && vcodec) { flv_set_video_codec(s, vstream, num_val, 0); - } else - if (!strcmp(key, "audiocodecid") && acodec) { + } else if (!strcmp(key, "audiocodecid") && acodec) { int id = ((int)num_val) << FLV_AUDIO_CODECID_OFFSET; flv_set_audio_codec(s, astream, acodec, id); - } else - if (!strcmp(key, "audiosamplerate") && acodec) { + } else if (!strcmp(key, "audiosamplerate") && acodec) { acodec->sample_rate = num_val; } else if (!strcmp(key, "audiosamplesize") && acodec) { acodec->bits_per_coded_sample = num_val; } else if (!strcmp(key, "stereo") && acodec) { - acodec->channels = num_val + 1; + acodec->channels = num_val + 1; acodec->channel_layout = acodec->channels == 2 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; - } else - if (!strcmp(key, "width") && vcodec) { + } else if (!strcmp(key, "width") && vcodec) { vcodec->width = num_val; - } else - if (!strcmp(key, "height") && vcodec) { + } else if (!strcmp(key, "height") && vcodec) { vcodec->height = num_val; } } @@ -456,10 +507,11 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst !strcmp(key, "audiocodecid")) return 0; - if(amf_type == AMF_DATA_TYPE_BOOL) { - av_strlcpy(str_val, num_val > 0 ? "true" : "false", sizeof(str_val)); + if (amf_type == AMF_DATA_TYPE_BOOL) { + av_strlcpy(str_val, num_val > 0 ? "true" : "false", + sizeof(str_val)); av_dict_set(&s->metadata, key, str_val, 0); - } else if(amf_type == AMF_DATA_TYPE_NUMBER) { + } else if (amf_type == AMF_DATA_TYPE_NUMBER) { snprintf(str_val, sizeof(str_val), "%.f", num_val); av_dict_set(&s->metadata, key, str_val, 0); } else if (amf_type == AMF_DATA_TYPE_STRING) @@ -469,17 +521,23 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream, AVStream *vst return 0; } -static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) { +static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) +{ AMFDataType type; - AVStream *stream, *astream, *vstream, *dstream; + AVStream *stream, *astream, *vstream; + AVStream av_unused *dstream; AVIOContext *ioc; int i; - char buffer[11]; //only needs to hold the string "onMetaData". Anything longer is something we don't want. + // only needs to hold the string "onMetaData". + // Anything longer is something we don't want. + char buffer[11]; - vstream = astream = dstream = NULL; - ioc = s->pb; + astream = NULL; + vstream = NULL; + dstream = NULL; + ioc = s->pb; - //first object needs to be "onMetaData" string + // first object needs to be "onMetaData" string type = avio_r8(ioc); if (type != AMF_DATA_TYPE_STRING || amf_get_string(ioc, buffer, sizeof(buffer)) < 0) @@ -491,16 +549,20 @@ static int flv_read_metabody(AVFormatContext *s, int64_t next_pos) { if (strcmp(buffer, "onMetaData")) return -1; - //find the streams now so that amf_parse_object doesn't need to do the lookup every time it is called. - for(i = 0; i < s->nb_streams; i++) { + // find the streams now so that amf_parse_object doesn't need to do + // the lookup every time it is called. + for (i = 0; i < s->nb_streams; i++) { stream = s->streams[i]; - if(stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) vstream = stream; - else if(stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) astream = stream; - else if(stream->codec->codec_type == AVMEDIA_TYPE_DATA) dstream = stream; + if (stream->codec->codec_type == AVMEDIA_TYPE_VIDEO) + vstream = stream; + else if (stream->codec->codec_type == AVMEDIA_TYPE_AUDIO) + astream = stream; + else if (stream->codec->codec_type == AVMEDIA_TYPE_DATA) + dstream = stream; } - //parse the second object (we want a mixed array) - if(amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0) + // parse the second object (we want a mixed array) + if (amf_parse_object(s, astream, vstream, buffer, next_pos, 0) < 0) return -1; return 0; @@ -516,19 +578,19 @@ static int flv_read_header(AVFormatContext *s) /* FIXME: better fix needed */ if (!flags) { flags = FLV_HEADER_FLAG_HASVIDEO | FLV_HEADER_FLAG_HASAUDIO; - av_log(s, AV_LOG_WARNING, "Broken FLV file, which says no streams present, this might fail\n"); + av_log(s, AV_LOG_WARNING, + "Broken FLV file, which says no streams present, " + "this might fail\n"); } s->ctx_flags |= AVFMTCTX_NOHEADER; - if(flags & FLV_HEADER_FLAG_HASVIDEO){ - if(!create_stream(s, AVMEDIA_TYPE_VIDEO)) + if (flags & FLV_HEADER_FLAG_HASVIDEO) + if (!create_stream(s, AVMEDIA_TYPE_VIDEO)) return AVERROR(ENOMEM); - } - if(flags & FLV_HEADER_FLAG_HASAUDIO){ - if(!create_stream(s, AVMEDIA_TYPE_AUDIO)) + if (flags & FLV_HEADER_FLAG_HASAUDIO) + if (!create_stream(s, AVMEDIA_TYPE_AUDIO)) return AVERROR(ENOMEM); - } // Flag doesn't indicate whether or not there is script-data present. Must // create that stream if it's encountered. @@ -545,7 +607,7 @@ static int flv_read_close(AVFormatContext *s) { int i; FLVContext *flv = s->priv_data; - for(i=0; i<FLV_STREAM_TYPE_NB; i++) + for (i=0; i<FLV_STREAM_TYPE_NB; i++) av_freep(&flv->new_extradata[i]); return 0; } @@ -565,7 +627,8 @@ static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream, int size) { av_free(flv->new_extradata[stream]); - flv->new_extradata[stream] = av_mallocz(size + FF_INPUT_BUFFER_PADDING_SIZE); + flv->new_extradata[stream] = av_mallocz(size + + FF_INPUT_BUFFER_PADDING_SIZE); if (!flv->new_extradata[stream]) return AVERROR(ENOMEM); flv->new_extradata_size[stream] = size; @@ -576,52 +639,48 @@ static int flv_queue_extradata(FLVContext *flv, AVIOContext *pb, int stream, static void clear_index_entries(AVFormatContext *s, int64_t pos) { int i, j, out; - av_log(s, AV_LOG_WARNING, "Found invalid index entries, clearing the index.\n"); + av_log(s, AV_LOG_WARNING, + "Found invalid index entries, clearing the index.\n"); for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; /* Remove all index entries that point to >= pos */ out = 0; - for (j = 0; j < st->nb_index_entries; j++) { + for (j = 0; j < st->nb_index_entries; j++) if (st->index_entries[j].pos < pos) st->index_entries[out++] = st->index_entries[j]; - } st->nb_index_entries = out; } } - static int flv_data_packet(AVFormatContext *s, AVPacket *pkt, int64_t dts, int64_t next) { - int ret = AVERROR_INVALIDDATA, i; AVIOContext *pb = s->pb; - AVStream *st = NULL; + AVStream *st = NULL; AMFDataType type; char buf[20]; - int length; + int ret, i, length; type = avio_r8(pb); if (type == AMF_DATA_TYPE_MIXEDARRAY) avio_seek(pb, 4, SEEK_CUR); else if (type != AMF_DATA_TYPE_OBJECT) - goto out; + return AVERROR_INVALIDDATA; amf_get_string(pb, buf, sizeof(buf)); if (strcmp(buf, "type") || avio_r8(pb) != AMF_DATA_TYPE_STRING) - goto out; + return AVERROR_INVALIDDATA; amf_get_string(pb, buf, sizeof(buf)); - //FIXME parse it as codec_id + // FIXME parse it as codec_id amf_get_string(pb, buf, sizeof(buf)); if (strcmp(buf, "text") || avio_r8(pb) != AMF_DATA_TYPE_STRING) - goto out; + return AVERROR_INVALIDDATA; length = avio_rb16(pb); - ret = av_get_packet(s->pb, pkt, length); - if (ret < 0) { - ret = AVERROR(EIO); - goto out; - } + ret = av_get_packet(s->pb, pkt, length); + if (ret < 0) + return AVERROR(EIO); for (i = 0; i < s->nb_streams; i++) { st = s->streams[i]; @@ -632,7 +691,7 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt, if (i == s->nb_streams) { st = create_stream(s, AVMEDIA_TYPE_DATA); if (!st) - goto out; + return AVERROR_INVALIDDATA; st->codec->codec_id = AV_CODEC_ID_TEXT; } @@ -641,10 +700,10 @@ static int flv_data_packet(AVFormatContext *s, AVPacket *pkt, pkt->size = ret; pkt->stream_index = st->index; - pkt->flags |= AV_PKT_FLAG_KEY; + pkt->flags |= AV_PKT_FLAG_KEY; avio_seek(s->pb, next + 4, SEEK_SET); -out: + return ret; } @@ -653,131 +712,131 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt) FLVContext *flv = s->priv_data; int ret, i, type, size, flags; int stream_type=-1; - int64_t next, pos; + int64_t next, pos, meta_pos; int64_t dts, pts = AV_NOPTS_VALUE; int av_uninit(channels); int av_uninit(sample_rate); - AVStream *st = NULL; - - for(;;avio_skip(s->pb, 4)){ /* pkt size is repeated at end. skip it */ - pos = avio_tell(s->pb); - type = avio_r8(s->pb); - size = avio_rb24(s->pb); - dts = avio_rb24(s->pb); - dts |= avio_r8(s->pb) << 24; - av_dlog(s, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts); - if (url_feof(s->pb)) - return AVERROR_EOF; - avio_skip(s->pb, 3); /* stream id, always 0 */ - flags = 0; - - if (flv->validate_next < flv->validate_count) { - int64_t validate_pos = flv->validate_index[flv->validate_next].pos; - if (pos == validate_pos) { - if (FFABS(dts - flv->validate_index[flv->validate_next].dts) <= - VALIDATE_INDEX_TS_THRESH) { - flv->validate_next++; - } else { + AVStream *st = NULL; + + /* pkt size is repeated at end. skip it */ + for (;; avio_skip(s->pb, 4)) { + pos = avio_tell(s->pb); + type = avio_r8(s->pb); + size = avio_rb24(s->pb); + dts = avio_rb24(s->pb); + dts |= avio_r8(s->pb) << 24; + av_dlog(s, "type:%d, size:%d, dts:%"PRId64"\n", type, size, dts); + if (url_feof(s->pb)) + return AVERROR_EOF; + avio_skip(s->pb, 3); /* stream id, always 0 */ + flags = 0; + + if (flv->validate_next < flv->validate_count) { + int64_t validate_pos = flv->validate_index[flv->validate_next].pos; + if (pos == validate_pos) { + if (FFABS(dts - flv->validate_index[flv->validate_next].dts) <= + VALIDATE_INDEX_TS_THRESH) { + flv->validate_next++; + } else { + clear_index_entries(s, validate_pos); + flv->validate_count = 0; + } + } else if (pos > validate_pos) { clear_index_entries(s, validate_pos); flv->validate_count = 0; } - } else if (pos > validate_pos) { - clear_index_entries(s, validate_pos); - flv->validate_count = 0; } - } - - if(size == 0) - continue; - - next= size + avio_tell(s->pb); - if (type == FLV_TAG_TYPE_AUDIO) { - stream_type=FLV_STREAM_TYPE_AUDIO; - flags = avio_r8(s->pb); - size--; - } else if (type == FLV_TAG_TYPE_VIDEO) { - stream_type=FLV_STREAM_TYPE_VIDEO; - flags = avio_r8(s->pb); - size--; - if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD) - goto skip; - } else if (type == FLV_TAG_TYPE_META) { - if (size > 13+1+4 && dts == 0) { // Header-type metadata stuff - flv_read_metabody(s, next); - goto skip; - } else if (dts != 0) { // Script-data "special" metadata frames - don't skip + if (size == 0) + continue; + + next = size + avio_tell(s->pb); + + if (type == FLV_TAG_TYPE_AUDIO) { + stream_type = FLV_STREAM_TYPE_AUDIO; + flags = avio_r8(s->pb); + size--; + } else if (type == FLV_TAG_TYPE_VIDEO) { + stream_type = FLV_STREAM_TYPE_VIDEO; + flags = avio_r8(s->pb); + size--; + if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD) + goto skip; + } else if (type == FLV_TAG_TYPE_META) { stream_type=FLV_STREAM_TYPE_DATA; + if (size > 13 + 1 + 4 && dts == 0) { // Header-type metadata stuff + meta_pos = avio_tell(s->pb); + if (flv_read_metabody(s, next) == 0) { + goto skip; + } + avio_seek(s->pb, meta_pos, SEEK_SET); + } } else { - goto skip; + av_log(s, AV_LOG_DEBUG, + "skipping flv packet: type %d, size %d, flags %d\n", + type, size, flags); +skip: + avio_seek(s->pb, next, SEEK_SET); + continue; } - } else { - av_log(s, AV_LOG_DEBUG, "skipping flv packet: type %d, size %d, flags %d\n", type, size, flags); - skip: - avio_seek(s->pb, next, SEEK_SET); - continue; - } - - /* skip empty data packets */ - if (!size) - continue; - /* now find stream */ - for(i=0;i<s->nb_streams;i++) { - st = s->streams[i]; - if (stream_type == FLV_STREAM_TYPE_AUDIO) { - if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && - (s->audio_codec_id || flv_same_audio_codec(st->codec, flags))) { - break; - } - } else - if (stream_type == FLV_STREAM_TYPE_VIDEO) { - if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && - (s->video_codec_id || flv_same_video_codec(st->codec, flags))) { - break; + /* skip empty data packets */ + if (!size) + continue; + + /* now find stream */ + for (i = 0; i < s->nb_streams; i++) { + st = s->streams[i]; + if (stream_type == FLV_STREAM_TYPE_AUDIO) { + if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO && + (s->audio_codec_id || flv_same_audio_codec(st->codec, flags))) + break; + } else if (stream_type == FLV_STREAM_TYPE_VIDEO) { + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + (s->video_codec_id || flv_same_video_codec(st->codec, flags))) + break; + } else if (stream_type == FLV_STREAM_TYPE_DATA) { + if (st->codec->codec_type == AVMEDIA_TYPE_DATA) + break; } - } else if (stream_type == FLV_STREAM_TYPE_DATA) { - if (st->codec->codec_type == AVMEDIA_TYPE_DATA) - break; } - } - if(i == s->nb_streams){ - static const enum AVMediaType stream_types[] = {AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_DATA}; - av_log(s, AV_LOG_WARNING, "Stream discovered after head already parsed\n"); - st = create_stream(s, - stream_types[stream_type]); - if (!st) - return AVERROR(ENOMEM); + if (i == s->nb_streams) { + static const enum AVMediaType stream_types[] = {AVMEDIA_TYPE_VIDEO, AVMEDIA_TYPE_AUDIO, AVMEDIA_TYPE_DATA}; + av_log(s, AV_LOG_WARNING, "Stream discovered after head already parsed\n"); + st = create_stream(s, stream_types[stream_type]); + if (!st) + return AVERROR(ENOMEM); + } + av_dlog(s, "%d %X %d \n", stream_type, flags, st->discard); + if ( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || (stream_type == FLV_STREAM_TYPE_AUDIO))) + ||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && (stream_type == FLV_STREAM_TYPE_VIDEO))) + || st->discard >= AVDISCARD_ALL + ) { + avio_seek(s->pb, next, SEEK_SET); + continue; + } + if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || stream_type == FLV_STREAM_TYPE_AUDIO) + av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME); + break; } - av_dlog(s, "%d %X %d \n", stream_type, flags, st->discard); - if( (st->discard >= AVDISCARD_NONKEY && !((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || (stream_type == FLV_STREAM_TYPE_AUDIO))) - ||(st->discard >= AVDISCARD_BIDIR && ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_DISP_INTER && (stream_type == FLV_STREAM_TYPE_VIDEO))) - || st->discard >= AVDISCARD_ALL - ){ - avio_seek(s->pb, next, SEEK_SET); - continue; - } - if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_KEY || stream_type == FLV_STREAM_TYPE_AUDIO) - av_add_index_entry(st, pos, dts, size, 0, AVINDEX_KEYFRAME); - break; - } - // if not streamed and no duration from metadata then seek to end to find the duration from the timestamps - if(s->pb->seekable && (!s->duration || s->duration==AV_NOPTS_VALUE) && !flv->searched_for_end){ + // if not streamed and no duration from metadata then seek to end to find + // the duration from the timestamps + if (s->pb->seekable && (!s->duration || s->duration == AV_NOPTS_VALUE) && !flv->searched_for_end) { int size; - const int64_t pos= avio_tell(s->pb); - int64_t fsize= avio_size(s->pb); + const int64_t pos = avio_tell(s->pb); + int64_t fsize = avio_size(s->pb); retry_duration: - avio_seek(s->pb, fsize-4, SEEK_SET); - size= avio_rb32(s->pb); - avio_seek(s->pb, fsize-3-size, SEEK_SET); - if(size == avio_rb24(s->pb) + 11){ + avio_seek(s->pb, fsize - 4, SEEK_SET); + size = avio_rb32(s->pb); + avio_seek(s->pb, fsize - 3 - size, SEEK_SET); + if (size == avio_rb24(s->pb) + 11) { uint32_t ts = avio_rb24(s->pb); - ts |= avio_r8(s->pb) << 24; - if(ts) + ts |= avio_r8(s->pb) << 24; + if (ts) s->duration = ts * (int64_t)AV_TIME_BASE / 1000; - else if (fsize >= 8 && fsize - 8 >= size){ + else if (fsize >= 8 && fsize - 8 >= size) { fsize -= size+4; goto retry_duration; } @@ -787,29 +846,35 @@ retry_duration: flv->searched_for_end = 1; } - if(stream_type == FLV_STREAM_TYPE_AUDIO){ + if (stream_type == FLV_STREAM_TYPE_AUDIO) { int bits_per_coded_sample; - channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1; - sample_rate = (44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> FLV_AUDIO_SAMPLERATE_OFFSET) >> 3); + channels = (flags & FLV_AUDIO_CHANNEL_MASK) == FLV_STEREO ? 2 : 1; + sample_rate = 44100 << ((flags & FLV_AUDIO_SAMPLERATE_MASK) >> + FLV_AUDIO_SAMPLERATE_OFFSET) >> 3; bits_per_coded_sample = (flags & FLV_AUDIO_SAMPLESIZE_MASK) ? 16 : 8; - if(!st->codec->channels || !st->codec->sample_rate || !st->codec->bits_per_coded_sample) { + if (!st->codec->channels || !st->codec->sample_rate || + !st->codec->bits_per_coded_sample) { st->codec->channels = channels; - st->codec->channel_layout = channels == 1 ? AV_CH_LAYOUT_MONO : - AV_CH_LAYOUT_STEREO; + st->codec->channel_layout = channels == 1 + ? AV_CH_LAYOUT_MONO + : AV_CH_LAYOUT_STEREO; st->codec->sample_rate = sample_rate; st->codec->bits_per_coded_sample = bits_per_coded_sample; } - if(!st->codec->codec_id){ - flv_set_audio_codec(s, st, st->codec, flags & FLV_AUDIO_CODECID_MASK); - flv->last_sample_rate = sample_rate = st->codec->sample_rate; - flv->last_channels = channels = st->codec->channels; + if (!st->codec->codec_id) { + flv_set_audio_codec(s, st, st->codec, + flags & FLV_AUDIO_CODECID_MASK); + flv->last_sample_rate = + sample_rate = st->codec->sample_rate; + flv->last_channels = + channels = st->codec->channels; } else { AVCodecContext ctx; ctx.sample_rate = sample_rate; flv_set_audio_codec(s, st, &ctx, flags & FLV_AUDIO_CODECID_MASK); sample_rate = ctx.sample_rate; } - } else if(stream_type == FLV_STREAM_TYPE_VIDEO) { + } else if (stream_type == FLV_STREAM_TYPE_VIDEO) { size -= flv_set_video_codec(s, st, flags & FLV_VIDEO_CODECID_MASK, 1); } @@ -819,11 +884,13 @@ retry_duration: int type = avio_r8(s->pb); size--; if (st->codec->codec_id == AV_CODEC_ID_H264 || st->codec->codec_id == AV_CODEC_ID_MPEG4) { - int32_t cts = (avio_rb24(s->pb)+0xff800000)^0xff800000; // sign extension + // sign extension + int32_t cts = (avio_rb24(s->pb) + 0xff800000) ^ 0xff800000; pts = dts + cts; if (cts < 0) { // dts are wrong flv->wrong_dts = 1; - av_log(s, AV_LOG_WARNING, "negative cts, previous timestamps might be wrong\n"); + av_log(s, AV_LOG_WARNING, + "negative cts, previous timestamps might be wrong\n"); } if (flv->wrong_dts) dts = AV_NOPTS_VALUE; @@ -841,7 +908,7 @@ retry_duration: MPEG4AudioConfig cfg; if (avpriv_mpeg4audio_get_config(&cfg, st->codec->extradata, st->codec->extradata_size * 8, 1) >= 0) { - st->codec->channels = cfg.channels; + st->codec->channels = cfg.channels; st->codec->channel_layout = 0; if (cfg.ext_sample_rate) st->codec->sample_rate = cfg.ext_sample_rate; @@ -863,11 +930,11 @@ retry_duration: goto leave; } - ret= av_get_packet(s->pb, pkt, size); + ret = av_get_packet(s->pb, pkt, size); if (ret < 0) return ret; - pkt->dts = dts; - pkt->pts = pts == AV_NOPTS_VALUE ? dts : pts; + pkt->dts = dts; + pkt->pts = pts == AV_NOPTS_VALUE ? dts : pts; pkt->stream_index = st->index; if (flv->new_extradata[stream_type]) { uint8_t *side = av_packet_new_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA, @@ -879,8 +946,9 @@ retry_duration: flv->new_extradata_size[stream_type] = 0; } } - if (stream_type == FLV_STREAM_TYPE_AUDIO && (sample_rate != flv->last_sample_rate || - channels != flv->last_channels)) { + if (stream_type == FLV_STREAM_TYPE_AUDIO && + (sample_rate != flv->last_sample_rate || + channels != flv->last_channels)) { flv->last_sample_rate = sample_rate; flv->last_channels = channels; ff_add_param_change(pkt, channels, 0, sample_rate, 0, 0); @@ -897,7 +965,7 @@ leave: } static int flv_read_seek(AVFormatContext *s, int stream_index, - int64_t ts, int flags) + int64_t ts, int flags) { FLVContext *flv = s->priv_data; flv->validate_count = 0; @@ -907,11 +975,11 @@ static int flv_read_seek(AVFormatContext *s, int stream_index, #define OFFSET(x) offsetof(FLVContext, x) #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM static const AVOption options[] = { - { "flv_metadata", "Allocate streams according the onMetaData array", OFFSET(trust_metadata), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VD}, + { "flv_metadata", "Allocate streams according the onMetaData array", OFFSET(trust_metadata), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VD }, { NULL } }; -static const AVClass class = { +static const AVClass flv_class = { .class_name = "flvdec", .item_name = av_default_item_name, .option = options, @@ -928,5 +996,5 @@ AVInputFormat ff_flv_demuxer = { .read_seek = flv_read_seek, .read_close = flv_read_close, .extensions = "flv", - .priv_class = &class, + .priv_class = &flv_class, }; diff --git a/chromium/third_party/ffmpeg/libavformat/format.c b/chromium/third_party/ffmpeg/libavformat/format.c new file mode 100644 index 00000000000..ac9100b6045 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/format.c @@ -0,0 +1,184 @@ +/* + * Format register and lookup + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "avformat.h" +#include "internal.h" +#include "libavutil/atomic.h" +#include "libavutil/avstring.h" + +/** + * @file + * Format register and lookup + */ +/** head of registered input format linked list */ +static AVInputFormat *first_iformat = NULL; +/** head of registered output format linked list */ +static AVOutputFormat *first_oformat = NULL; + +AVInputFormat *av_iformat_next(AVInputFormat *f) +{ + if (f) + return f->next; + else + return first_iformat; +} + +AVOutputFormat *av_oformat_next(AVOutputFormat *f) +{ + if (f) + return f->next; + else + return first_oformat; +} + +void av_register_input_format(AVInputFormat *format) +{ + AVInputFormat **p = &first_iformat; + + format->next = NULL; + while(avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format)) + p = &(*p)->next; +} + +void av_register_output_format(AVOutputFormat *format) +{ + AVOutputFormat **p = &first_oformat; + + format->next = NULL; + while(avpriv_atomic_ptr_cas((void * volatile *)p, NULL, format)) + p = &(*p)->next; +} + +int av_match_ext(const char *filename, const char *extensions) +{ + const char *ext, *p; + char ext1[32], *q; + + if (!filename) + return 0; + + ext = strrchr(filename, '.'); + if (ext) { + ext++; + p = extensions; + for (;;) { + q = ext1; + while (*p != '\0' && *p != ',' && q - ext1 < sizeof(ext1) - 1) + *q++ = *p++; + *q = '\0'; + if (!av_strcasecmp(ext1, ext)) + return 1; + if (*p == '\0') + break; + p++; + } + } + return 0; +} + +static int match_format(const char *name, const char *names) +{ + const char *p; + int len, namelen; + + if (!name || !names) + return 0; + + namelen = strlen(name); + while ((p = strchr(names, ','))) { + len = FFMAX(p - names, namelen); + if (!av_strncasecmp(name, names, len)) + return 1; + names = p + 1; + } + return !av_strcasecmp(name, names); +} + +AVOutputFormat *av_guess_format(const char *short_name, const char *filename, + const char *mime_type) +{ + AVOutputFormat *fmt = NULL, *fmt_found; + int score_max, score; + + /* specific test for image sequences */ +#if CONFIG_IMAGE2_MUXER + if (!short_name && filename && + av_filename_number_test(filename) && + ff_guess_image2_codec(filename) != AV_CODEC_ID_NONE) { + return av_guess_format("image2", NULL, NULL); + } +#endif + /* Find the proper file type. */ + fmt_found = NULL; + score_max = 0; + while ((fmt = av_oformat_next(fmt))) { + score = 0; + if (fmt->name && short_name && match_format(short_name, fmt->name)) + score += 100; + if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type)) + score += 10; + if (filename && fmt->extensions && + av_match_ext(filename, fmt->extensions)) { + score += 5; + } + if (score > score_max) { + score_max = score; + fmt_found = fmt; + } + } + return fmt_found; +} + +enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, + const char *filename, const char *mime_type, + enum AVMediaType type) +{ + if (!strcmp(fmt->name, "segment") || !strcmp(fmt->name, "ssegment")) { + fmt = av_guess_format(NULL, filename, NULL); + } + + if (type == AVMEDIA_TYPE_VIDEO) { + enum AVCodecID codec_id = AV_CODEC_ID_NONE; + +#if CONFIG_IMAGE2_MUXER + if (!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")) { + codec_id = ff_guess_image2_codec(filename); + } +#endif + if (codec_id == AV_CODEC_ID_NONE) + codec_id = fmt->video_codec; + return codec_id; + } else if (type == AVMEDIA_TYPE_AUDIO) + return fmt->audio_codec; + else if (type == AVMEDIA_TYPE_SUBTITLE) + return fmt->subtitle_codec; + else + return AV_CODEC_ID_NONE; +} + +AVInputFormat *av_find_input_format(const char *short_name) +{ + AVInputFormat *fmt = NULL; + while ((fmt = av_iformat_next(fmt))) + if (match_format(short_name, fmt->name)) + return fmt; + return NULL; +} diff --git a/chromium/third_party/ffmpeg/libavformat/framecrcenc.c b/chromium/third_party/ffmpeg/libavformat/framecrcenc.c index df0ae79330a..dbe49b5ba1e 100644 --- a/chromium/third_party/ffmpeg/libavformat/framecrcenc.c +++ b/chromium/third_party/ffmpeg/libavformat/framecrcenc.c @@ -34,13 +34,22 @@ static int framecrc_write_packet(struct AVFormatContext *s, AVPacket *pkt) if (pkt->flags != AV_PKT_FLAG_KEY) av_strlcatf(buf, sizeof(buf), ", F=0x%0X", pkt->flags); if (pkt->side_data_elems) { - int i; + int i, j; av_strlcatf(buf, sizeof(buf), ", S=%d", pkt->side_data_elems); for (i=0; i<pkt->side_data_elems; i++) { - uint32_t side_data_crc = av_adler32_update(0, - pkt->side_data[i].data, - pkt->side_data[i].size); + uint32_t side_data_crc = 0; + if (HAVE_BIGENDIAN && AV_PKT_DATA_PALETTE == pkt->side_data[i].type) { + for (j=0; j<pkt->side_data[i].size; j++) { + side_data_crc = av_adler32_update(side_data_crc, + pkt->side_data[i].data + (j^3), + 1); + } + } else { + side_data_crc = av_adler32_update(0, + pkt->side_data[i].data, + pkt->side_data[i].size); + } av_strlcatf(buf, sizeof(buf), ", %8d, 0x%08x", pkt->side_data[i].size, side_data_crc); } } @@ -56,5 +65,6 @@ AVOutputFormat ff_framecrc_muxer = { .video_codec = AV_CODEC_ID_RAWVIDEO, .write_header = ff_framehash_write_header, .write_packet = framecrc_write_packet, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + AVFMT_TS_NEGATIVE, }; diff --git a/chromium/third_party/ffmpeg/libavformat/ftp.c b/chromium/third_party/ffmpeg/libavformat/ftp.c new file mode 100644 index 00000000000..1a4708109b3 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/ftp.c @@ -0,0 +1,721 @@ +/* + * Copyright (c) 2013 Lukasz Marek <lukasz.m.luki@gmail.com> + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avstring.h" +#include "avformat.h" +#include "internal.h" +#include "url.h" +#include "libavutil/opt.h" +#include "libavutil/bprint.h" + +#define CONTROL_BUFFER_SIZE 1024 +#define CREDENTIALS_BUFFER_SIZE 128 + +typedef enum { + UNKNOWN, + READY, + DOWNLOADING, + UPLOADING, + DISCONNECTED +} FTPState; + +typedef struct { + const AVClass *class; + URLContext *conn_control; /**< Control connection */ + URLContext *conn_data; /**< Data connection, NULL when not connected */ + uint8_t control_buffer[CONTROL_BUFFER_SIZE]; /**< Control connection buffer */ + uint8_t *control_buf_ptr, *control_buf_end; + int server_data_port; /**< Data connection port opened by server, -1 on error. */ + int server_control_port; /**< Control connection port, default is 21 */ + char hostname[512]; /**< Server address. */ + char credencials[CREDENTIALS_BUFFER_SIZE]; /**< Authentication data */ + char path[MAX_URL_SIZE]; /**< Path to resource on server. */ + int64_t filesize; /**< Size of file on server, -1 on error. */ + int64_t position; /**< Current position, calculated. */ + int rw_timeout; /**< Network timeout. */ + const char *anonymous_password; /**< Password to be used for anonymous user. An email should be used. */ + int write_seekable; /**< Control seekability, 0 = disable, 1 = enable. */ + FTPState state; /**< State of data connection */ +} FTPContext; + +#define OFFSET(x) offsetof(FTPContext, x) +#define D AV_OPT_FLAG_DECODING_PARAM +#define E AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + {"timeout", "set timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E }, + {"ftp-write-seekable", "control seekability of connection during encoding", OFFSET(write_seekable), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E }, + {"ftp-anonymous-password", "password for anonymous login. E-mail address should be used.", OFFSET(anonymous_password), AV_OPT_TYPE_STRING, { 0 }, 0, 0, D|E }, + {NULL} +}; + +static const AVClass ftp_context_class = { + .class_name = "ftp", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static int ftp_getc(FTPContext *s) +{ + int len; + if (s->control_buf_ptr >= s->control_buf_end) { + len = ffurl_read(s->conn_control, s->control_buffer, CONTROL_BUFFER_SIZE); + if (len < 0) { + return len; + } else if (!len) { + return -1; + } else { + s->control_buf_ptr = s->control_buffer; + s->control_buf_end = s->control_buffer + len; + } + } + return *s->control_buf_ptr++; +} + +static int ftp_get_line(FTPContext *s, char *line, int line_size) +{ + int ch; + char *q = line; + + for (;;) { + ch = ftp_getc(s); + if (ch < 0) { + return ch; + } + if (ch == '\n') { + /* process line */ + if (q > line && q[-1] == '\r') + q--; + *q = '\0'; + return 0; + } else { + if ((q - line) < line_size - 1) + *q++ = ch; + } + } +} + +/* + * This routine returns ftp server response code. + * Server may send more than one response for a certain command. + * First expected code is returned. + */ +static int ftp_status(FTPContext *s, char **line, const int response_codes[]) +{ + int err, i, dash = 0, result = 0, code_found = 0; + char buf[CONTROL_BUFFER_SIZE]; + AVBPrint line_buffer; + + if (line) + av_bprint_init(&line_buffer, 0, AV_BPRINT_SIZE_AUTOMATIC); + + while (!code_found || dash) { + if ((err = ftp_get_line(s, buf, sizeof(buf))) < 0) { + av_bprint_finalize(&line_buffer, NULL); + return err; + } + + av_log(s, AV_LOG_DEBUG, "%s\n", buf); + + if (strlen(buf) < 4) + continue; + + err = 0; + for (i = 0; i < 3; ++i) { + if (buf[i] < '0' || buf[i] > '9') + continue; + err *= 10; + err += buf[i] - '0'; + } + dash = !!(buf[3] == '-'); + + for (i = 0; response_codes[i]; ++i) { + if (err == response_codes[i]) { + if (line) + av_bprintf(&line_buffer, "%s", buf); + code_found = 1; + result = err; + break; + } + } + } + + if (line) + av_bprint_finalize(&line_buffer, line); + return result; +} + +static int ftp_send_command(FTPContext *s, const char *command, + const int response_codes[], char **response) +{ + int err; + + if ((err = ffurl_write(s->conn_control, command, strlen(command))) < 0) + return err; + if (!err) + return -1; + + /* return status */ + if (response_codes) { + return ftp_status(s, response, response_codes); + } + return 0; +} + +static void ftp_close_data_connection(FTPContext *s) +{ + ffurl_closep(&s->conn_data); + s->position = 0; + s->state = DISCONNECTED; +} + +static void ftp_close_both_connections(FTPContext *s) +{ + ffurl_closep(&s->conn_control); + ftp_close_data_connection(s); +} + +static int ftp_auth(FTPContext *s) +{ + const char *user = NULL, *pass = NULL; + char *end = NULL, buf[CONTROL_BUFFER_SIZE], credencials[CREDENTIALS_BUFFER_SIZE]; + int err; + const int user_codes[] = {331, 230, 500, 530, 0}; /* 500, 530 are incorrect codes */ + const int pass_codes[] = {230, 503, 530, 0}; /* 503, 530 are incorrect codes */ + + /* Authentication may be repeated, original string has to be saved */ + av_strlcpy(credencials, s->credencials, sizeof(credencials)); + + user = av_strtok(credencials, ":", &end); + pass = av_strtok(end, ":", &end); + + if (!user) { + user = "anonymous"; + pass = s->anonymous_password ? s->anonymous_password : "nopassword"; + } + + snprintf(buf, sizeof(buf), "USER %s\r\n", user); + err = ftp_send_command(s, buf, user_codes, NULL); + if (err == 331) { + if (pass) { + snprintf(buf, sizeof(buf), "PASS %s\r\n", pass); + err = ftp_send_command(s, buf, pass_codes, NULL); + } else + return AVERROR(EACCES); + } + if (err != 230) + return AVERROR(EACCES); + + return 0; +} + +static int ftp_passive_mode(FTPContext *s) +{ + char *res = NULL, *start = NULL, *end = NULL; + int i; + const char *command = "PASV\r\n"; + const int pasv_codes[] = {227, 501, 0}; /* 501 is incorrect code */ + + if (ftp_send_command(s, command, pasv_codes, &res) != 227 || !res) + goto fail; + + for (i = 0; res[i]; ++i) { + if (res[i] == '(') { + start = res + i + 1; + } else if (res[i] == ')') { + end = res + i; + break; + } + } + if (!start || !end) + goto fail; + + *end = '\0'; + /* skip ip */ + if (!av_strtok(start, ",", &end)) goto fail; + if (!av_strtok(end, ",", &end)) goto fail; + if (!av_strtok(end, ",", &end)) goto fail; + if (!av_strtok(end, ",", &end)) goto fail; + + /* parse port number */ + start = av_strtok(end, ",", &end); + if (!start) goto fail; + s->server_data_port = atoi(start) * 256; + start = av_strtok(end, ",", &end); + if (!start) goto fail; + s->server_data_port += atoi(start); + av_dlog(s, "Server data port: %d\n", s->server_data_port); + + av_free(res); + return 0; + + fail: + av_free(res); + s->server_data_port = -1; + return AVERROR(EIO); +} + +static int ftp_current_dir(FTPContext *s) +{ + char *res = NULL, *start = NULL, *end = NULL; + int i; + const char *command = "PWD\r\n"; + const int pwd_codes[] = {257, 0}; + + if (ftp_send_command(s, command, pwd_codes, &res) != 257 || !res) + goto fail; + + for (i = 0; res[i]; ++i) { + if (res[i] == '"') { + if (!start) { + start = res + i + 1; + continue; + } + end = res + i; + break; + } + } + + if (!end) + goto fail; + + if (end > res && end[-1] == '/') { + end[-1] = '\0'; + } else + *end = '\0'; + av_strlcpy(s->path, start, sizeof(s->path)); + + av_free(res); + return 0; + + fail: + av_free(res); + return AVERROR(EIO); +} + +static int ftp_file_size(FTPContext *s) +{ + char command[CONTROL_BUFFER_SIZE]; + char *res = NULL; + const int size_codes[] = {213, 501, 550, 0}; /* 501, 550 are incorrect codes */ + + snprintf(command, sizeof(command), "SIZE %s\r\n", s->path); + if (ftp_send_command(s, command, size_codes, &res) == 213 && res) { + s->filesize = strtoll(&res[4], NULL, 10); + } else { + s->filesize = -1; + av_free(res); + return AVERROR(EIO); + } + + av_free(res); + return 0; +} + +static int ftp_retrieve(FTPContext *s) +{ + char command[CONTROL_BUFFER_SIZE]; + const int retr_codes[] = {150, 550, 554, 0}; /* 550, 554 are incorrect codes */ + + snprintf(command, sizeof(command), "RETR %s\r\n", s->path); + if (ftp_send_command(s, command, retr_codes, NULL) != 150) + return AVERROR(EIO); + + s->state = DOWNLOADING; + + return 0; +} + +static int ftp_store(FTPContext *s) +{ + char command[CONTROL_BUFFER_SIZE]; + const int stor_codes[] = {150, 0}; + + snprintf(command, sizeof(command), "STOR %s\r\n", s->path); + if (ftp_send_command(s, command, stor_codes, NULL) != 150) + return AVERROR(EIO); + + s->state = UPLOADING; + + return 0; +} + +static int ftp_type(FTPContext *s) +{ + const char *command = "TYPE I\r\n"; + const int type_codes[] = {200, 500, 504, 0}; /* 500, 504 are incorrect codes */ + + if (ftp_send_command(s, command, type_codes, NULL) != 200) + return AVERROR(EIO); + + return 0; +} + +static int ftp_restart(FTPContext *s, int64_t pos) +{ + char command[CONTROL_BUFFER_SIZE]; + const int rest_codes[] = {350, 500, 501, 0}; /* 500, 501 are incorrect codes */ + + snprintf(command, sizeof(command), "REST %"PRId64"\r\n", pos); + if (ftp_send_command(s, command, rest_codes, NULL) != 350) + return AVERROR(EIO); + + return 0; +} + +static int ftp_connect_control_connection(URLContext *h) +{ + char buf[CONTROL_BUFFER_SIZE], opts_format[20], *response = NULL; + int err; + AVDictionary *opts = NULL; + FTPContext *s = h->priv_data; + const int connect_codes[] = {220, 0}; + + if (!s->conn_control) { + ff_url_join(buf, sizeof(buf), "tcp", NULL, + s->hostname, s->server_control_port, NULL); + if (s->rw_timeout != -1) { + snprintf(opts_format, sizeof(opts_format), "%d", s->rw_timeout); + av_dict_set(&opts, "timeout", opts_format, 0); + } /* if option is not given, don't pass it and let tcp use its own default */ + err = ffurl_open(&s->conn_control, buf, AVIO_FLAG_READ_WRITE, + &h->interrupt_callback, &opts); + av_dict_free(&opts); + if (err < 0) { + av_log(h, AV_LOG_ERROR, "Cannot open control connection\n"); + return err; + } + + /* check if server is ready */ + if (ftp_status(s, ((h->flags & AVIO_FLAG_WRITE) ? &response : NULL), connect_codes) != 220) { + av_log(h, AV_LOG_ERROR, "FTP server not ready for new users\n"); + return AVERROR(EACCES); + } + + if ((h->flags & AVIO_FLAG_WRITE) && av_stristr(response, "pure-ftpd")) { + av_log(h, AV_LOG_WARNING, "Pure-FTPd server is used as an output protocol. It is known issue this implementation may produce incorrect content and it cannot be fixed at this moment."); + } + av_free(response); + + if ((err = ftp_auth(s)) < 0) { + av_log(h, AV_LOG_ERROR, "FTP authentication failed\n"); + return err; + } + + if ((err = ftp_type(s)) < 0) { + av_dlog(h, "Set content type failed\n"); + return err; + } + } + return 0; +} + +static int ftp_connect_data_connection(URLContext *h) +{ + int err; + char buf[CONTROL_BUFFER_SIZE], opts_format[20]; + AVDictionary *opts = NULL; + FTPContext *s = h->priv_data; + + if (!s->conn_data) { + /* Enter passive mode */ + if ((err = ftp_passive_mode(s)) < 0) { + av_dlog(h, "Set passive mode failed\n"); + return err; + } + /* Open data connection */ + ff_url_join(buf, sizeof(buf), "tcp", NULL, s->hostname, s->server_data_port, NULL); + if (s->rw_timeout != -1) { + snprintf(opts_format, sizeof(opts_format), "%d", s->rw_timeout); + av_dict_set(&opts, "timeout", opts_format, 0); + } /* if option is not given, don't pass it and let tcp use its own default */ + err = ffurl_open(&s->conn_data, buf, h->flags, + &h->interrupt_callback, &opts); + av_dict_free(&opts); + if (err < 0) + return err; + + if (s->position) + if ((err = ftp_restart(s, s->position)) < 0) + return err; + } + s->state = READY; + return 0; +} + +static int ftp_abort(URLContext *h) +{ + const char *command = "ABOR\r\n"; + int err; + const int abor_codes[] = {225, 226, 0}; + FTPContext *s = h->priv_data; + + /* According to RCF 959: + "ABOR command tells the server to abort the previous FTP + service command and any associated transfer of data." + + There are FTP server implementations that don't response + to any commands during data transfer in passive mode (including ABOR). + + This implementation closes data connection by force. + */ + + if (ftp_send_command(s, command, NULL, NULL) < 0) { + ftp_close_both_connections(s); + if ((err = ftp_connect_control_connection(h)) < 0) { + av_log(h, AV_LOG_ERROR, "Reconnect failed.\n"); + return err; + } + } else { + ftp_close_data_connection(s); + } + + if (ftp_status(s, NULL, abor_codes) < 225) { + /* wu-ftpd also closes control connection after data connection closing */ + ffurl_closep(&s->conn_control); + if ((err = ftp_connect_control_connection(h)) < 0) { + av_log(h, AV_LOG_ERROR, "Reconnect failed.\n"); + return err; + } + } + + return 0; +} + +static int ftp_open(URLContext *h, const char *url, int flags) +{ + char proto[10], path[MAX_URL_SIZE]; + int err; + FTPContext *s = h->priv_data; + + av_dlog(h, "ftp protocol open\n"); + + s->state = DISCONNECTED; + s->filesize = -1; + s->position = 0; + + av_url_split(proto, sizeof(proto), + s->credencials, sizeof(s->credencials), + s->hostname, sizeof(s->hostname), + &s->server_control_port, + path, sizeof(path), + url); + + if (s->server_control_port < 0 || s->server_control_port > 65535) + s->server_control_port = 21; + + if ((err = ftp_connect_control_connection(h)) < 0) + goto fail; + + if ((err = ftp_current_dir(s)) < 0) + goto fail; + av_strlcat(s->path, path, sizeof(s->path)); + + if (ftp_restart(s, 0) < 0) { + h->is_streamed = 1; + } else { + if (ftp_file_size(s) < 0 && flags & AVIO_FLAG_READ) + h->is_streamed = 1; + if (s->write_seekable != 1 && flags & AVIO_FLAG_WRITE) + h->is_streamed = 1; + } + + return 0; + + fail: + av_log(h, AV_LOG_ERROR, "FTP open failed\n"); + ffurl_closep(&s->conn_control); + ffurl_closep(&s->conn_data); + return err; +} + +static int64_t ftp_seek(URLContext *h, int64_t pos, int whence) +{ + FTPContext *s = h->priv_data; + int err; + int64_t new_pos, fake_pos; + + av_dlog(h, "ftp protocol seek %"PRId64" %d\n", pos, whence); + + switch(whence) { + case AVSEEK_SIZE: + return s->filesize; + case SEEK_SET: + new_pos = pos; + break; + case SEEK_CUR: + new_pos = s->position + pos; + break; + case SEEK_END: + if (s->filesize < 0) + return AVERROR(EIO); + new_pos = s->filesize + pos; + break; + default: + return AVERROR(EINVAL); + } + + if (h->is_streamed) + return AVERROR(EIO); + + /* XXX: Simulate behaviour of lseek in file protocol, which could be treated as a reference */ + new_pos = FFMAX(0, new_pos); + fake_pos = s->filesize != -1 ? FFMIN(new_pos, s->filesize) : new_pos; + + if (fake_pos != s->position) { + if ((err = ftp_abort(h)) < 0) + return err; + s->position = fake_pos; + } + return new_pos; +} + +static int ftp_read(URLContext *h, unsigned char *buf, int size) +{ + FTPContext *s = h->priv_data; + int read, err, retry_done = 0; + + av_dlog(h, "ftp protocol read %d bytes\n", size); + retry: + if (s->state == DISCONNECTED) { + /* optimization */ + if (s->position >= s->filesize) + return 0; + if ((err = ftp_connect_data_connection(h)) < 0) + return err; + } + if (s->state == READY) { + if (s->position >= s->filesize) + return 0; + if ((err = ftp_retrieve(s)) < 0) + return err; + } + if (s->conn_data && s->state == DOWNLOADING) { + read = ffurl_read(s->conn_data, buf, size); + if (read >= 0) { + s->position += read; + if (s->position >= s->filesize) { + /* server will terminate, but keep current position to avoid madness */ + /* save position to restart from it */ + int64_t pos = s->position; + if (ftp_abort(h) < 0) { + s->position = pos; + return AVERROR(EIO); + } + s->position = pos; + } + } + if (read <= 0 && s->position < s->filesize && !h->is_streamed) { + /* Server closed connection. Probably due to inactivity */ + int64_t pos = s->position; + av_log(h, AV_LOG_INFO, "Reconnect to FTP server.\n"); + if ((err = ftp_abort(h)) < 0) + return err; + if ((err = ftp_seek(h, pos, SEEK_SET)) < 0) { + av_log(h, AV_LOG_ERROR, "Position cannot be restored.\n"); + return err; + } + if (!retry_done) { + retry_done = 1; + goto retry; + } + } + return read; + } + + av_log(h, AV_LOG_DEBUG, "FTP read failed\n"); + return AVERROR(EIO); +} + +static int ftp_write(URLContext *h, const unsigned char *buf, int size) +{ + int err; + FTPContext *s = h->priv_data; + int written; + + av_dlog(h, "ftp protocol write %d bytes\n", size); + + if (s->state == DISCONNECTED) { + if ((err = ftp_connect_data_connection(h)) < 0) + return err; + } + if (s->state == READY) { + if ((err = ftp_store(s)) < 0) + return err; + } + if (s->conn_data && s->state == UPLOADING) { + written = ffurl_write(s->conn_data, buf, size); + if (written > 0) { + s->position += written; + s->filesize = FFMAX(s->filesize, s->position); + } + return written; + } + + av_log(h, AV_LOG_ERROR, "FTP write failed\n"); + return AVERROR(EIO); +} + +static int ftp_close(URLContext *h) +{ + av_dlog(h, "ftp protocol close\n"); + + ftp_close_both_connections(h->priv_data); + + return 0; +} + +static int ftp_get_file_handle(URLContext *h) +{ + FTPContext *s = h->priv_data; + + av_dlog(h, "ftp protocol get_file_handle\n"); + + if (s->conn_data) + return ffurl_get_file_handle(s->conn_data); + + return AVERROR(EIO); +} + +static int ftp_shutdown(URLContext *h, int flags) +{ + FTPContext *s = h->priv_data; + + av_dlog(h, "ftp protocol shutdown\n"); + + if (s->conn_data) + return ffurl_shutdown(s->conn_data, flags); + + return AVERROR(EIO); +} + +URLProtocol ff_ftp_protocol = { + .name = "ftp", + .url_open = ftp_open, + .url_read = ftp_read, + .url_write = ftp_write, + .url_seek = ftp_seek, + .url_close = ftp_close, + .url_get_file_handle = ftp_get_file_handle, + .url_shutdown = ftp_shutdown, + .priv_data_size = sizeof(FTPContext), + .priv_data_class = &ftp_context_class, + .flags = URL_PROTOCOL_FLAG_NETWORK, +}; diff --git a/chromium/third_party/ffmpeg/libavformat/g723_1.c b/chromium/third_party/ffmpeg/libavformat/g723_1.c index 8d35f885a8a..4f3ce8f0aeb 100644 --- a/chromium/third_party/ffmpeg/libavformat/g723_1.c +++ b/chromium/third_party/ffmpeg/libavformat/g723_1.c @@ -24,13 +24,14 @@ * G.723.1 demuxer */ +#include "libavutil/attributes.h" #include "libavutil/channel_layout.h" #include "avformat.h" #include "internal.h" static const uint8_t frame_size[4] = { 24, 20, 4, 1 }; -static int g723_1_init(AVFormatContext *s) +static av_cold int g723_1_init(AVFormatContext *s) { AVStream *st; diff --git a/chromium/third_party/ffmpeg/libavformat/gif.c b/chromium/third_party/ffmpeg/libavformat/gif.c index d459bd6032a..f6e76254da3 100644 --- a/chromium/third_party/ffmpeg/libavformat/gif.c +++ b/chromium/third_party/ffmpeg/libavformat/gif.c @@ -52,21 +52,24 @@ static int gif_image_write_header(AVIOContext *pb, int width, int height, avio_w8(pb, 0); /* aspect ratio */ } - /* "NETSCAPE EXTENSION" for looped animation GIF */ - avio_w8(pb, 0x21); /* GIF Extension code */ - avio_w8(pb, 0xff); /* Application Extension Label */ - avio_w8(pb, 0x0b); /* Length of Application Block */ - avio_write(pb, "NETSCAPE2.0", sizeof("NETSCAPE2.0") - 1); - avio_w8(pb, 0x03); /* Length of Data Sub-Block */ - avio_w8(pb, 0x01); - avio_wl16(pb, (uint16_t)loop_count); - avio_w8(pb, 0x00); /* Data Sub-block Terminator */ + + if (loop_count >= 0 ) { + /* "NETSCAPE EXTENSION" for looped animation GIF */ + avio_w8(pb, 0x21); /* GIF Extension code */ + avio_w8(pb, 0xff); /* Application Extension Label */ + avio_w8(pb, 0x0b); /* Length of Application Block */ + avio_write(pb, "NETSCAPE2.0", sizeof("NETSCAPE2.0") - 1); + avio_w8(pb, 0x03); /* Length of Data Sub-Block */ + avio_w8(pb, 0x01); + avio_wl16(pb, (uint16_t)loop_count); + avio_w8(pb, 0x00); /* Data Sub-block Terminator */ + } return 0; } typedef struct { - AVClass *class; /** Class for private options. */ + AVClass *class; int loop; int last_delay; AVPacket *prev_pkt; @@ -189,8 +192,8 @@ static int gif_write_trailer(AVFormatContext *s) #define OFFSET(x) offsetof(GIFContext, x) #define ENC AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { - { "loop", "Number of times to loop the output.", OFFSET(loop), - AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 65535, ENC }, + { "loop", "Number of times to loop the output: -1 - no loop, 0 - infinite loop", OFFSET(loop), + AV_OPT_TYPE_INT, { .i64 = 0 }, -1, 65535, ENC }, { "final_delay", "Force delay (in ms) after the last frame", OFFSET(last_delay), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 65535, ENC }, { NULL }, diff --git a/chromium/third_party/ffmpeg/libavformat/gsmdec.c b/chromium/third_party/ffmpeg/libavformat/gsmdec.c index 98992661737..a51822ad235 100644 --- a/chromium/third_party/ffmpeg/libavformat/gsmdec.c +++ b/chromium/third_party/ffmpeg/libavformat/gsmdec.c @@ -80,7 +80,7 @@ static const AVOption options[] = { { NULL }, }; -static const AVClass class = { +static const AVClass gsm_class = { .class_name = "gsm demuxer", .item_name = av_default_item_name, .option = options, @@ -96,5 +96,5 @@ AVInputFormat ff_gsm_demuxer = { .flags = AVFMT_GENERIC_INDEX, .extensions = "gsm", .raw_codec_id = AV_CODEC_ID_GSM, - .priv_class = &class, + .priv_class = &gsm_class, }; diff --git a/chromium/third_party/ffmpeg/libavformat/gxf.c b/chromium/third_party/ffmpeg/libavformat/gxf.c index 86e629135d9..e15d06aaf9b 100644 --- a/chromium/third_party/ffmpeg/libavformat/gxf.c +++ b/chromium/third_party/ffmpeg/libavformat/gxf.c @@ -116,12 +116,10 @@ static int get_sindex(AVFormatContext *s, int id, int format) { st->codec->codec_id = AV_CODEC_ID_MJPEG; break; case 13: - case 15: - st->codec->codec_type = AVMEDIA_TYPE_VIDEO; - st->codec->codec_id = AV_CODEC_ID_DVVIDEO; - break; case 14: + case 15: case 16: + case 25: st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = AV_CODEC_ID_DVVIDEO; break; @@ -165,6 +163,12 @@ static int get_sindex(AVFormatContext *s, int id, int format) { st->codec->channel_layout = AV_CH_LAYOUT_STEREO; st->codec->sample_rate = 48000; break; + case 26: /* AVCi50 / AVCi100 (AVC Intra) */ + case 29: /* AVCHD */ + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = CODEC_ID_H264; + st->need_parsing = AVSTREAM_PARSE_HEADERS; + break; // timecode tracks: case 7: case 8: @@ -172,6 +176,10 @@ static int get_sindex(AVFormatContext *s, int id, int format) { st->codec->codec_type = AVMEDIA_TYPE_DATA; st->codec->codec_id = AV_CODEC_ID_NONE; break; + case 30: + st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->codec->codec_id = AV_CODEC_ID_DNXHD; + break; default: st->codec->codec_type = AVMEDIA_TYPE_UNKNOWN; st->codec->codec_id = AV_CODEC_ID_NONE; diff --git a/chromium/third_party/ffmpeg/libavformat/gxfenc.c b/chromium/third_party/ffmpeg/libavformat/gxfenc.c index 9322f7b88b7..57bb26cd0d3 100644 --- a/chromium/third_party/ffmpeg/libavformat/gxfenc.c +++ b/chromium/third_party/ffmpeg/libavformat/gxfenc.c @@ -217,12 +217,27 @@ static int gxf_write_mpeg_auxiliary(AVIOContext *pb, AVStream *st) return size + 3; } +static int gxf_write_dv_auxiliary(AVIOContext *pb, AVStream *st) +{ + int64_t track_aux_data = 0; + + avio_w8(pb, TRACK_AUX); + avio_w8(pb, 8); + if (st->codec->pix_fmt == AV_PIX_FMT_YUV420P) + track_aux_data |= 0x01; /* marks stream as DVCAM instead of DVPRO */ + track_aux_data |= 0x40000000; /* aux data is valid */ + avio_wl64(pb, track_aux_data); + return 8; +} + static int gxf_write_timecode_auxiliary(AVIOContext *pb, GXFContext *gxf) { uint32_t timecode = GXF_TIMECODE(gxf->tc.color, gxf->tc.drop, gxf->tc.hh, gxf->tc.mm, gxf->tc.ss, gxf->tc.ff); + avio_w8(pb, TRACK_AUX); + avio_w8(pb, 8); avio_wl32(pb, timecode); /* reserved */ avio_wl32(pb, 0); @@ -234,7 +249,6 @@ static int gxf_write_track_description(AVFormatContext *s, GXFStreamContext *sc, GXFContext *gxf = s->priv_data; AVIOContext *pb = s->pb; int64_t pos; - int mpeg = sc->track_type == 4 || sc->track_type == 9; /* track description section */ avio_w8(pb, sc->media_type + 0x80); @@ -250,13 +264,21 @@ static int gxf_write_track_description(AVFormatContext *s, GXFStreamContext *sc, avio_wb16(pb, sc->media_info); avio_w8(pb, 0); - if (!mpeg) { - /* auxiliary information */ - avio_w8(pb, TRACK_AUX); - avio_w8(pb, 8); - if (sc->track_type == 3) + switch (sc->track_type) { + case 3: /* timecode */ gxf_write_timecode_auxiliary(pb, gxf); - else + break; + case 4: /* MPEG2 */ + case 9: /* MPEG1 */ + gxf_write_mpeg_auxiliary(pb, s->streams[index]); + break; + case 5: /* DV25 */ + case 6: /* DV50 */ + gxf_write_dv_auxiliary(pb, s->streams[index]); + break; + default: + avio_w8(pb, TRACK_AUX); + avio_w8(pb, 8); avio_wl64(pb, 0); } @@ -265,9 +287,6 @@ static int gxf_write_track_description(AVFormatContext *s, GXFStreamContext *sc, avio_w8(pb, 4); avio_wb32(pb, 0); - if (mpeg) - gxf_write_mpeg_auxiliary(pb, s->streams[index]); - /* frame rate */ avio_w8(pb, TRACK_FPS); avio_w8(pb, 4); @@ -534,13 +553,20 @@ static int gxf_write_umf_media_timecode(AVIOContext *pb, int drop) return 32; } -static int gxf_write_umf_media_dv(AVIOContext *pb, GXFStreamContext *sc) +static int gxf_write_umf_media_dv(AVIOContext *pb, GXFStreamContext *sc, AVStream *st) { - int i; + int dv_umf_data = 0; - for (i = 0; i < 8; i++) { - avio_wb32(pb, 0); - } + if (st->codec->pix_fmt == AV_PIX_FMT_YUV420P) + dv_umf_data |= 0x20; /* marks as DVCAM instead of DVPRO */ + avio_wl32(pb, dv_umf_data); + avio_wl32(pb, 0); + avio_wl32(pb, 0); + avio_wl32(pb, 0); + avio_wl32(pb, 0); + avio_wl32(pb, 0); + avio_wl32(pb, 0); + avio_wl32(pb, 0); return 32; } @@ -604,7 +630,7 @@ static int gxf_write_umf_media_description(AVFormatContext *s) gxf_write_umf_media_audio(pb, sc); break; case AV_CODEC_ID_DVVIDEO: - gxf_write_umf_media_dv(pb, sc); + gxf_write_umf_media_dv(pb, sc, st); break; } } diff --git a/chromium/third_party/ffmpeg/libavformat/h261dec.c b/chromium/third_party/ffmpeg/libavformat/h261dec.c index 1b254d613ac..8d882aec61a 100644 --- a/chromium/third_party/ffmpeg/libavformat/h261dec.c +++ b/chromium/third_party/ffmpeg/libavformat/h261dec.c @@ -33,7 +33,7 @@ static int h261_probe(AVProbeData *p) int src_fmt=0; GetBitContext gb; - init_get_bits(&gb, p->buf, p->buf_size*8); + init_get_bits8(&gb, p->buf, p->buf_size); for(i=0; i<p->buf_size*8; i++){ if ((code & 0x01ff0000) || !(code & 0xff00)) { @@ -56,9 +56,9 @@ static int h261_probe(AVProbeData *p) } } if(valid_psc > 2*invalid_psc + 6){ - return 50; + return AVPROBE_SCORE_EXTENSION; }else if(valid_psc > 2*invalid_psc + 2) - return 25; + return AVPROBE_SCORE_EXTENSION / 2; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/h263dec.c b/chromium/third_party/ffmpeg/libavformat/h263dec.c index 667fdbdcbbc..e6e0345b690 100644 --- a/chromium/third_party/ffmpeg/libavformat/h263dec.c +++ b/chromium/third_party/ffmpeg/libavformat/h263dec.c @@ -56,9 +56,9 @@ static int h263_probe(AVProbeData *p) } } if(valid_psc > 2*invalid_psc + 2*res_change + 3){ - return 50; + return AVPROBE_SCORE_EXTENSION; }else if(valid_psc > 2*invalid_psc) - return 25; + return AVPROBE_SCORE_EXTENSION / 2; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/h264dec.c b/chromium/third_party/ffmpeg/libavformat/h264dec.c index 9c67ab9545d..5de582be667 100644 --- a/chromium/third_party/ffmpeg/libavformat/h264dec.c +++ b/chromium/third_party/ffmpeg/libavformat/h264dec.c @@ -63,7 +63,7 @@ static int h264_probe(AVProbeData *p) } } if(sps && pps && (idr||sli>3) && res<(sps+pps+idr)) - return AVPROBE_SCORE_MAX/2+1; // +1 for .mpg + return AVPROBE_SCORE_EXTENSION + 1; // 1 more than .mpg return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/hls.c b/chromium/third_party/ffmpeg/libavformat/hls.c index 7de6059c5a2..8554b7e84f1 100644 --- a/chromium/third_party/ffmpeg/libavformat/hls.c +++ b/chromium/third_party/ffmpeg/libavformat/hls.c @@ -56,7 +56,7 @@ enum KeyType { }; struct segment { - int duration; + int64_t duration; char url[MAX_URL_SIZE]; char key[MAX_URL_SIZE]; enum KeyType key_type; @@ -81,7 +81,7 @@ struct variant { int stream_offset; int finished; - int target_duration; + int64_t target_duration; int start_seq_no; int n_segments; struct segment **segments; @@ -206,7 +206,8 @@ static void handle_key_args(struct key_info *info, const char *key, static int parse_playlist(HLSContext *c, const char *url, struct variant *var, AVIOContext *in) { - int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0; + int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0; + int64_t duration = 0; enum KeyType key_type = KEY_NONE; uint8_t iv[16] = ""; int has_iv = 0; @@ -218,7 +219,7 @@ static int parse_playlist(HLSContext *c, const char *url, if (!in) { AVDictionary *opts = NULL; close_in = 1; - /* Some HLS servers dont like being sent the range header */ + /* Some HLS servers don't like being sent the range header */ av_dict_set(&opts, "seekable", "0", 0); // broker prior HTTP options that should be consistent across requests @@ -271,7 +272,7 @@ static int parse_playlist(HLSContext *c, const char *url, goto fail; } } - var->target_duration = atoi(ptr); + var->target_duration = atoi(ptr) * AV_TIME_BASE; } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { if (!var) { var = new_variant(c, 0, url, NULL); @@ -286,7 +287,7 @@ static int parse_playlist(HLSContext *c, const char *url, var->finished = 1; } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; - duration = atoi(ptr); + duration = atof(ptr) * AV_TIME_BASE; } else if (av_strstart(line, "#", NULL)) { continue; } else if (line[0]) { @@ -413,7 +414,6 @@ restart: int64_t reload_interval = v->n_segments > 0 ? v->segments[v->n_segments - 1]->duration : v->target_duration; - reload_interval *= 1000000; reload: if (!v->finished && @@ -423,7 +423,7 @@ reload: /* If we need to reload the playlist again below (if * there's still no more segments), switch to a reload * interval of half the target duration. */ - reload_interval = v->target_duration * 500000LL; + reload_interval = v->target_duration / 2; } if (v->cur_seq_no < v->start_seq_no) { av_log(NULL, AV_LOG_WARNING, @@ -457,7 +457,8 @@ reload: c->end_of_segment = 1; c->cur_seq_no = v->cur_seq_no; - if (v->ctx && v->ctx->nb_streams && v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) { + if (v->ctx && v->ctx->nb_streams && + v->parent->nb_streams >= v->stream_offset + v->ctx->nb_streams) { v->needed = 0; for (i = v->stream_offset; i < v->stream_offset + v->ctx->nb_streams; i++) { @@ -526,7 +527,7 @@ static int hls_read_header(AVFormatContext *s) int64_t duration = 0; for (i = 0; i < c->variants[0]->n_segments; i++) duration += c->variants[0]->segments[i]->duration; - s->duration = duration * AV_TIME_BASE; + s->duration = duration; } /* Open the demuxer for each variant */ @@ -534,7 +535,8 @@ static int hls_read_header(AVFormatContext *s) struct variant *v = c->variants[i]; AVInputFormat *in_fmt = NULL; char bitrate_str[20]; - AVProgram *program = NULL; + AVProgram *program; + if (v->n_segments == 0) continue; @@ -570,18 +572,17 @@ static int hls_read_header(AVFormatContext *s) goto fail; } v->ctx->pb = &v->pb; + v->stream_offset = stream_offset; ret = avformat_open_input(&v->ctx, v->segments[0]->url, in_fmt, NULL); if (ret < 0) goto fail; - v->stream_offset = stream_offset; v->ctx->ctx_flags &= ~AVFMTCTX_NOHEADER; ret = avformat_find_stream_info(v->ctx, NULL); if (ret < 0) goto fail; snprintf(bitrate_str, sizeof(bitrate_str), "%d", v->bandwidth); - /* Create new AVprogram for variant i */ program = av_new_program(s, i); if (!program) goto fail; @@ -678,8 +679,11 @@ start: reset_packet(&var->pkt); break; } else { - if (c->first_timestamp == AV_NOPTS_VALUE) - c->first_timestamp = var->pkt.dts; + if (c->first_timestamp == AV_NOPTS_VALUE && + var->pkt.dts != AV_NOPTS_VALUE) + c->first_timestamp = av_rescale_q(var->pkt.dts, + var->ctx->streams[var->pkt.stream_index]->time_base, + AV_TIME_BASE_Q); } if (c->seek_timestamp == AV_NOPTS_VALUE) @@ -699,24 +703,34 @@ start: c->seek_timestamp = AV_NOPTS_VALUE; break; } + av_free_packet(&var->pkt); + reset_packet(&var->pkt); } } - /* Check if this stream has the packet with the lowest dts */ + /* Check if this stream still is on an earlier segment number, or + * has the packet with the lowest dts */ if (var->pkt.data) { - if(minvariant < 0) { + struct variant *minvar = c->variants[minvariant]; + if (minvariant < 0 || var->cur_seq_no < minvar->cur_seq_no) { minvariant = i; - } else { - struct variant *minvar = c->variants[minvariant]; - int64_t dts = var->pkt.dts; - int64_t mindts = minvar->pkt.dts; - AVStream *st = var->ctx->streams[ var->pkt.stream_index]; - AVStream *minst= minvar->ctx->streams[minvar->pkt.stream_index]; - - if( st->start_time != AV_NOPTS_VALUE) dts -= st->start_time; - if(minst->start_time != AV_NOPTS_VALUE) mindts -= minst->start_time; + } else if (var->cur_seq_no == minvar->cur_seq_no) { + int64_t dts = var->pkt.dts; + int64_t mindts = minvar->pkt.dts; + AVStream *st = var->ctx->streams[var->pkt.stream_index]; + AVStream *minst = minvar->ctx->streams[minvar->pkt.stream_index]; - if (av_compare_ts(dts, st->time_base, mindts, minst->time_base) < 0) + if (dts == AV_NOPTS_VALUE) { minvariant = i; + } else if (mindts != AV_NOPTS_VALUE) { + if (st->start_time != AV_NOPTS_VALUE) + dts -= st->start_time; + if (minst->start_time != AV_NOPTS_VALUE) + mindts -= minst->start_time; + + if (av_compare_ts(dts, st->time_base, + mindts, minst->time_base) < 0) + minvariant = i; + } } } } @@ -757,7 +771,7 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, s->streams[stream_index]->time_base.den, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); - timestamp = av_rescale_rnd(timestamp, 1, stream_index >= 0 ? + timestamp = av_rescale_rnd(timestamp, AV_TIME_BASE, stream_index >= 0 ? s->streams[stream_index]->time_base.den : AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? AV_ROUND_DOWN : AV_ROUND_UP); @@ -770,12 +784,9 @@ static int hls_read_seek(AVFormatContext *s, int stream_index, for (i = 0; i < c->n_variants; i++) { /* Reset reading */ struct variant *var = c->variants[i]; - int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? 0 : - av_rescale_rnd(c->first_timestamp, 1, stream_index >= 0 ? - s->streams[stream_index]->time_base.den : - AV_TIME_BASE, flags & AVSEEK_FLAG_BACKWARD ? - AV_ROUND_DOWN : AV_ROUND_UP); - if (var->input) { + int64_t pos = c->first_timestamp == AV_NOPTS_VALUE ? + 0 : c->first_timestamp; + if (var->input) { ffurl_close(var->input); var->input = NULL; } diff --git a/chromium/third_party/ffmpeg/libavformat/hlsenc.c b/chromium/third_party/ffmpeg/libavformat/hlsenc.c index 18914c026a9..dcd53e5f406 100644 --- a/chromium/third_party/ffmpeg/libavformat/hlsenc.c +++ b/chromium/third_party/ffmpeg/libavformat/hlsenc.c @@ -49,7 +49,7 @@ typedef struct HLSContext { int has_video; int64_t start_pts; int64_t end_pts; - int64_t duration; ///< last segment duration computed so far, in seconds + int64_t duration; // last segment duration computed so far, in seconds int nb_entries; ListEntry *list; ListEntry *end_list; @@ -164,14 +164,12 @@ static int hls_start(AVFormatContext *s) AVFormatContext *oc = c->avf; int err = 0; - if (c->wrap) - c->number %= c->wrap; - if (av_get_frame_filename(oc->filename, sizeof(oc->filename), - c->basename, c->number++) < 0) { + c->basename, c->wrap ? c->number % c->wrap : c->number) < 0) { av_log(oc, AV_LOG_ERROR, "Invalid segment filename template '%s'\n", c->basename); return AVERROR(EINVAL); } + c->number++; if ((err = avio_open2(&oc->pb, oc->filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL)) < 0) @@ -253,25 +251,28 @@ static int hls_write_packet(AVFormatContext *s, AVPacket *pkt) AVFormatContext *oc = hls->avf; AVStream *st = s->streams[pkt->stream_index]; int64_t end_pts = hls->recording_time * hls->number; - int ret, is_ref_pkt = 0; + int is_ref_pkt = 1; + int ret, can_split = 1; if (hls->start_pts == AV_NOPTS_VALUE) { hls->start_pts = pkt->pts; hls->end_pts = pkt->pts; } - if ((hls->has_video && st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && - pkt->pts != AV_NOPTS_VALUE) { - is_ref_pkt = 1; - hls->duration = av_rescale(pkt->pts - hls->end_pts, - st->time_base.num, st->time_base.den); + if (hls->has_video) { + can_split = st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + pkt->flags & AV_PKT_FLAG_KEY; + is_ref_pkt = st->codec->codec_type == AVMEDIA_TYPE_VIDEO; } + if (pkt->pts == AV_NOPTS_VALUE) + is_ref_pkt = can_split = 0; - if (is_ref_pkt && - av_compare_ts(pkt->pts - hls->start_pts, st->time_base, - end_pts, AV_TIME_BASE_Q) >= 0 && - pkt->flags & AV_PKT_FLAG_KEY) { + if (is_ref_pkt) + hls->duration = av_rescale(pkt->pts - hls->end_pts, + st->time_base.num, st->time_base.den); + if (can_split && av_compare_ts(pkt->pts - hls->start_pts, st->time_base, + end_pts, AV_TIME_BASE_Q) >= 0) { ret = append_entry(hls, hls->duration); if (ret) return ret; diff --git a/chromium/third_party/ffmpeg/libavformat/hlsproto.c b/chromium/third_party/ffmpeg/libavformat/hlsproto.c index 4e35043a3e6..f6fcbe5e0eb 100644 --- a/chromium/third_party/ffmpeg/libavformat/hlsproto.c +++ b/chromium/third_party/ffmpeg/libavformat/hlsproto.c @@ -45,7 +45,7 @@ */ struct segment { - int duration; + int64_t duration; char url[MAX_URL_SIZE]; }; @@ -56,7 +56,7 @@ struct variant { typedef struct HLSContext { char playlisturl[MAX_URL_SIZE]; - int target_duration; + int64_t target_duration; int start_seq_no; int finished; int n_segments; @@ -111,7 +111,8 @@ static int parse_playlist(URLContext *h, const char *url) { HLSContext *s = h->priv_data; AVIOContext *in; - int ret = 0, duration = 0, is_segment = 0, is_variant = 0, bandwidth = 0; + int ret = 0, is_segment = 0, is_variant = 0, bandwidth = 0; + int64_t duration = 0; char line[1024]; const char *ptr; @@ -134,14 +135,14 @@ static int parse_playlist(URLContext *h, const char *url) &info); bandwidth = atoi(info.bandwidth); } else if (av_strstart(line, "#EXT-X-TARGETDURATION:", &ptr)) { - s->target_duration = atoi(ptr); + s->target_duration = atoi(ptr) * AV_TIME_BASE; } else if (av_strstart(line, "#EXT-X-MEDIA-SEQUENCE:", &ptr)) { s->start_seq_no = atoi(ptr); } else if (av_strstart(line, "#EXT-X-ENDLIST", &ptr)) { s->finished = 1; } else if (av_strstart(line, "#EXTINF:", &ptr)) { is_segment = 1; - duration = atoi(ptr); + duration = atof(ptr) * AV_TIME_BASE; } else if (av_strstart(line, "#", NULL)) { continue; } else if (line[0]) { @@ -270,7 +271,6 @@ start: reload_interval = s->n_segments > 0 ? s->segments[s->n_segments - 1]->duration : s->target_duration; - reload_interval *= 1000000; retry: if (!s->finished) { int64_t now = av_gettime(); @@ -280,7 +280,7 @@ retry: /* If we need to reload the playlist again below (if * there's still no more segments), switch to a reload * interval of half the target duration. */ - reload_interval = s->target_duration * 500000LL; + reload_interval = s->target_duration / 2; } } if (s->cur_seq_no < s->start_seq_no) { diff --git a/chromium/third_party/ffmpeg/libavformat/http.c b/chromium/third_party/ffmpeg/libavformat/http.c index 7f33ecaf292..3edddbfb173 100644 --- a/chromium/third_party/ffmpeg/libavformat/http.c +++ b/chromium/third_party/ffmpeg/libavformat/http.c @@ -29,6 +29,10 @@ #include "url.h" #include "libavutil/opt.h" +#if CONFIG_ZLIB +#include <zlib.h> +#endif + /* XXX: POST protocol is not completely implemented because ffmpeg uses only a subset of it. */ @@ -49,6 +53,8 @@ typedef struct { char *content_type; char *user_agent; int64_t off, filesize; + int icy_data_read; ///< how much data was read since last ICY metadata packet + int icy_metaint; ///< after how many bytes of read data a new metadata packet will be found char location[MAX_URL_SIZE]; HTTPAuthState auth_state; HTTPAuthState proxy_auth_state; @@ -65,12 +71,20 @@ typedef struct { int rw_timeout; char *mime_type; char *cookies; ///< holds newline (\n) delimited Set-Cookie header field values (without the "Set-Cookie: " field name) + int icy; + char *icy_metadata_headers; + char *icy_metadata_packet; +#if CONFIG_ZLIB + int compressed; + z_stream inflate_stream; + uint8_t *inflate_buffer; +#endif } HTTPContext; #define OFFSET(x) offsetof(HTTPContext, x) #define D AV_OPT_FLAG_DECODING_PARAM #define E AV_OPT_FLAG_ENCODING_PARAM -#define DEFAULT_USER_AGENT "Mozilla/5.0 Lavf/" AV_STRINGIFY(LIBAVFORMAT_VERSION) +#define DEFAULT_USER_AGENT "Lavf/" AV_STRINGIFY(LIBAVFORMAT_VERSION) static const AVOption options[] = { {"seekable", "control seekability of connection", OFFSET(seekable), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, D }, {"chunked_post", "use chunked transfer-encoding for posts", OFFSET(chunked_post), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E }, @@ -82,6 +96,9 @@ static const AVOption options[] = { {"timeout", "set timeout of socket I/O operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E }, {"mime_type", "set MIME type", OFFSET(mime_type), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 }, {"cookies", "set cookies to be sent in applicable future requests, use newline delimited Set-Cookie HTTP field value syntax", OFFSET(cookies), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 }, +{"icy", "request ICY metadata", OFFSET(icy), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D }, +{"icy_metadata_headers", "return ICY metadata headers", OFFSET(icy_metadata_headers), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 }, +{"icy_metadata_packet", "return current ICY metadata packet", OFFSET(icy_metadata_packet), AV_OPT_TYPE_STRING, {0}, 0, 0, 0 }, {NULL} }; #define HTTP_CLASS(flavor)\ @@ -218,6 +235,7 @@ int ff_http_do_new_request(URLContext *h, const char *uri) HTTPContext *s = h->priv_data; s->off = 0; + s->icy_data_read = 0; av_strlcpy(s->location, uri, sizeof(s->location)); return http_open_cnx(h); @@ -289,6 +307,7 @@ static int process_line(URLContext *h, char *line, int line_count, { HTTPContext *s = h->priv_data; char *tag, *p, *end; + char redirected_location[MAX_URL_SIZE]; /* end of header */ if (line[0] == '\0') { @@ -328,7 +347,8 @@ static int process_line(URLContext *h, char *line, int line_count, while (av_isspace(*p)) p++; if (!av_strcasecmp(tag, "Location")) { - av_strlcpy(s->location, p, sizeof(s->location)); + ff_make_absolute_url(redirected_location, sizeof(redirected_location), s->location, p); + av_strlcpy(s->location, redirected_location, sizeof(s->location)); *new_location = 1; } else if (!av_strcasecmp (tag, "Content-Length") && s->filesize == -1) { s->filesize = strtoll(p, NULL, 10); @@ -375,6 +395,41 @@ static int process_line(URLContext *h, char *line, int line_count, snprintf(s->cookies, str_size, "%s\n%s", tmp, p); av_free(tmp); } + } else if (!av_strcasecmp (tag, "Icy-MetaInt")) { + s->icy_metaint = strtoll(p, NULL, 10); + } else if (!av_strncasecmp(tag, "Icy-", 4)) { + // Concat all Icy- header lines + char *buf = av_asprintf("%s%s: %s\n", + s->icy_metadata_headers ? s->icy_metadata_headers : "", tag, p); + if (!buf) + return AVERROR(ENOMEM); + av_freep(&s->icy_metadata_headers); + s->icy_metadata_headers = buf; + } else if (!av_strcasecmp (tag, "Content-Encoding")) { + if (!av_strncasecmp(p, "gzip", 4) || !av_strncasecmp(p, "deflate", 7)) { +#if CONFIG_ZLIB + s->compressed = 1; + inflateEnd(&s->inflate_stream); + if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) { + av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s\n", + s->inflate_stream.msg); + return AVERROR(ENOSYS); + } + if (zlibCompileFlags() & (1 << 17)) { + av_log(h, AV_LOG_WARNING, "Your zlib was compiled without gzip support.\n"); + return AVERROR(ENOSYS); + } +#else + av_log(h, AV_LOG_WARNING, "Compressed (%s) content, need zlib with gzip support\n", p); + return AVERROR(ENOSYS); +#endif + } else if (!av_strncasecmp(p, "identity", 8)) { + // The normal, no-encoding case (although servers shouldn't include + // the header at all if this is the case). + } else { + av_log(h, AV_LOG_WARNING, "Unknown content coding: %s\n", p); + return AVERROR(ENOSYS); + } } } return 1; @@ -421,6 +476,8 @@ static int get_cookies(HTTPContext *s, char **cookies, const char *path, cvalue = av_strdup(param); } } + if (!cdomain) + cdomain = av_strdup(domain); // ensure all of the necessary values are valid if (!cdomain || !cpath || !cvalue) { @@ -578,6 +635,10 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, av_free(cookies); } } + if (!has_header(s->headers, "\r\nIcy-MetaData: ") && s->icy) { + len += av_strlcatf(headers + len, sizeof(headers) - len, + "Icy-MetaData: %d\r\n", 1); + } /* now add in custom headers */ if (s->headers) @@ -611,6 +672,7 @@ static int http_connect(URLContext *h, const char *path, const char *local_path, s->buf_end = s->buffer; s->line_count = 0; s->off = 0; + s->icy_data_read = 0; s->filesize = -1; s->willclose = 0; s->end_chunked_post = 0; @@ -650,12 +712,45 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) } if (len > 0) { s->off += len; + s->icy_data_read += len; if (s->chunksize > 0) s->chunksize -= len; } return len; } +#if CONFIG_ZLIB +#define DECOMPRESS_BUF_SIZE (256 * 1024) +static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size) +{ + HTTPContext *s = h->priv_data; + int ret; + + if (!s->inflate_buffer) { + s->inflate_buffer = av_malloc(DECOMPRESS_BUF_SIZE); + if (!s->inflate_buffer) + return AVERROR(ENOMEM); + } + + if (s->inflate_stream.avail_in == 0) { + int read = http_buf_read(h, s->inflate_buffer, DECOMPRESS_BUF_SIZE); + if (read <= 0) + return read; + s->inflate_stream.next_in = s->inflate_buffer; + s->inflate_stream.avail_in = read; + } + + s->inflate_stream.avail_out = size; + s->inflate_stream.next_out = buf; + + ret = inflate(&s->inflate_stream, Z_SYNC_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + av_log(h, AV_LOG_WARNING, "inflate return value: %d, %s\n", ret, s->inflate_stream.msg); + + return size - s->inflate_stream.avail_out; +} +#endif + static int http_read(URLContext *h, uint8_t *buf, int size) { HTTPContext *s = h->priv_data; @@ -691,6 +786,36 @@ static int http_read(URLContext *h, uint8_t *buf, int size) } size = FFMIN(size, s->chunksize); } + if (s->icy_metaint > 0) { + int remaining = s->icy_metaint - s->icy_data_read; /* until next metadata packet */ + if (!remaining) { + // The metadata packet is variable sized. It has a 1 byte header + // which sets the length of the packet (divided by 16). If it's 0, + // the metadata doesn't change. After the packet, icy_metaint bytes + // of normal data follow. + int ch = http_getc(s); + if (ch < 0) + return ch; + if (ch > 0) { + char data[255 * 16 + 1]; + int n; + int ret; + ch *= 16; + for (n = 0; n < ch; n++) + data[n] = http_getc(s); + data[ch + 1] = 0; + if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0) + return ret; + } + s->icy_data_read = 0; + remaining = s->icy_metaint; + } + size = FFMIN(size, remaining); + } +#if CONFIG_ZLIB + if (s->compressed) + return http_buf_read_compressed(h, buf, size); +#endif return http_buf_read(h, buf, size); } @@ -742,6 +867,11 @@ static int http_close(URLContext *h) int ret = 0; HTTPContext *s = h->priv_data; +#if CONFIG_ZLIB + inflateEnd(&s->inflate_stream); + av_freep(&s->inflate_buffer); +#endif + if (!s->end_chunked_post) { /* Close the write direction by sending the end of chunked encoding. */ ret = http_shutdown(h, h->flags); diff --git a/chromium/third_party/ffmpeg/libavformat/id3v2.c b/chromium/third_party/ffmpeg/libavformat/id3v2.c index 3567bbc57b0..4bc76a321ca 100644 --- a/chromium/third_party/ffmpeg/libavformat/id3v2.c +++ b/chromium/third_party/ffmpeg/libavformat/id3v2.c @@ -32,72 +32,71 @@ #include <zlib.h> #endif -#include "id3v2.h" -#include "id3v1.h" #include "libavutil/avstring.h" -#include "libavutil/intreadwrite.h" #include "libavutil/dict.h" +#include "libavutil/intreadwrite.h" #include "avio_internal.h" #include "internal.h" +#include "id3v1.h" +#include "id3v2.h" const AVMetadataConv ff_id3v2_34_metadata_conv[] = { - { "TALB", "album"}, - { "TCOM", "composer"}, - { "TCON", "genre"}, - { "TCOP", "copyright"}, - { "TENC", "encoded_by"}, - { "TIT2", "title"}, - { "TLAN", "language"}, - { "TPE1", "artist"}, - { "TPE2", "album_artist"}, - { "TPE3", "performer"}, - { "TPOS", "disc"}, - { "TPUB", "publisher"}, - { "TRCK", "track"}, - { "TSSE", "encoder"}, + { "TALB", "album" }, + { "TCOM", "composer" }, + { "TCON", "genre" }, + { "TCOP", "copyright" }, + { "TENC", "encoded_by" }, + { "TIT2", "title" }, + { "TLAN", "language" }, + { "TPE1", "artist" }, + { "TPE2", "album_artist" }, + { "TPE3", "performer" }, + { "TPOS", "disc" }, + { "TPUB", "publisher" }, + { "TRCK", "track" }, + { "TSSE", "encoder" }, { 0 } }; const AVMetadataConv ff_id3v2_4_metadata_conv[] = { - { "TDRL", "date"}, - { "TDRC", "date"}, - { "TDEN", "creation_time"}, - { "TSOA", "album-sort"}, - { "TSOP", "artist-sort"}, - { "TSOT", "title-sort"}, + { "TDRL", "date" }, + { "TDRC", "date" }, + { "TDEN", "creation_time" }, + { "TSOA", "album-sort" }, + { "TSOP", "artist-sort" }, + { "TSOT", "title-sort" }, { 0 } }; static const AVMetadataConv id3v2_2_metadata_conv[] = { - { "TAL", "album"}, - { "TCO", "genre"}, - { "TT2", "title"}, - { "TEN", "encoded_by"}, - { "TP1", "artist"}, - { "TP2", "album_artist"}, - { "TP3", "performer"}, - { "TRK", "track"}, + { "TAL", "album" }, + { "TCO", "genre" }, + { "TT2", "title" }, + { "TEN", "encoded_by" }, + { "TP1", "artist" }, + { "TP2", "album_artist" }, + { "TP3", "performer" }, + { "TRK", "track" }, { 0 } }; - const char ff_id3v2_tags[][4] = { - "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT", - "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED", - "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3", - "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE", - { 0 }, + "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT", + "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED", + "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3", + "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE", + { 0 }, }; const char ff_id3v2_4_tags[][4] = { - "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO", - "TPRO", "TSOA", "TSOP", "TSOT", "TSST", - { 0 }, + "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO", + "TPRO", "TSOA", "TSOP", "TSOT", "TSST", + { 0 }, }; const char ff_id3v2_3_tags[][4] = { - "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER", - { 0 }, + "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER", + { 0 }, }; const char *ff_id3v2_picture_types[21] = { @@ -125,36 +124,36 @@ const char *ff_id3v2_picture_types[21] = { }; const CodecMime ff_id3v2_mime_tags[] = { - {"image/gif" , AV_CODEC_ID_GIF}, - {"image/jpeg", AV_CODEC_ID_MJPEG}, - {"image/jpg", AV_CODEC_ID_MJPEG}, - {"image/png" , AV_CODEC_ID_PNG}, - {"image/tiff", AV_CODEC_ID_TIFF}, - {"image/bmp", AV_CODEC_ID_BMP}, - {"JPG", AV_CODEC_ID_MJPEG}, /* ID3v2.2 */ - {"PNG" , AV_CODEC_ID_PNG}, /* ID3v2.2 */ - {"", AV_CODEC_ID_NONE}, + { "image/gif", AV_CODEC_ID_GIF }, + { "image/jpeg", AV_CODEC_ID_MJPEG }, + { "image/jpg", AV_CODEC_ID_MJPEG }, + { "image/png", AV_CODEC_ID_PNG }, + { "image/tiff", AV_CODEC_ID_TIFF }, + { "image/bmp", AV_CODEC_ID_BMP }, + { "JPG", AV_CODEC_ID_MJPEG }, /* ID3v2.2 */ + { "PNG", AV_CODEC_ID_PNG }, /* ID3v2.2 */ + { "", AV_CODEC_ID_NONE }, }; -int ff_id3v2_match(const uint8_t *buf, const char * magic) +int ff_id3v2_match(const uint8_t *buf, const char *magic) { return buf[0] == magic[0] && buf[1] == magic[1] && buf[2] == magic[2] && - buf[3] != 0xff && - buf[4] != 0xff && - (buf[6] & 0x80) == 0 && - (buf[7] & 0x80) == 0 && - (buf[8] & 0x80) == 0 && - (buf[9] & 0x80) == 0; + buf[3] != 0xff && + buf[4] != 0xff && + (buf[6] & 0x80) == 0 && + (buf[7] & 0x80) == 0 && + (buf[8] & 0x80) == 0 && + (buf[9] & 0x80) == 0; } -int ff_id3v2_tag_len(const uint8_t * buf) +int ff_id3v2_tag_len(const uint8_t *buf) { int len = ((buf[6] & 0x7f) << 21) + ((buf[7] & 0x7f) << 14) + ((buf[8] & 0x7f) << 7) + - (buf[9] & 0x7f) + + (buf[9] & 0x7f) + ID3v2_HEADER_SIZE; if (buf[5] & 0x10) len += ID3v2_HEADER_SIZE; @@ -210,7 +209,6 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, } switch (encoding) { - case ID3v2_ENCODING_ISO8859: while (left && ch) { ch = avio_r8(pb); @@ -246,7 +244,7 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, PUT_UTF8(ch, tmp, avio_w8(dynbuf, tmp);) } if (left < 0) - left += 2; /* did not read last char from pb */ + left += 2; /* did not read last char from pb */ break; case ID3v2_ENCODING_UTF8: @@ -272,7 +270,8 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding, /** * Parse a text tag. */ -static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const char *key) +static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, + AVDictionary **metadata, const char *key) { uint8_t *dst; int encoding, dict_flags = AV_DICT_DONT_OVERWRITE | AV_DICT_DONT_STRDUP_VAL; @@ -289,9 +288,9 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const cha return; } - if (!(strcmp(key, "TCON") && strcmp(key, "TCO")) - && (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1) - && genre <= ID3v1_GENRE_MAX) { + if (!(strcmp(key, "TCON") && strcmp(key, "TCO")) && + (sscanf(dst, "(%d)", &genre) == 1 || sscanf(dst, "%d", &genre) == 1) && + genre <= ID3v1_GENRE_MAX) { av_freep(&dst); dst = av_strdup(ff_id3v1_genre_str[genre]); } else if (!(strcmp(key, "TXXX") && strcmp(key, "TXX"))) { @@ -307,16 +306,17 @@ static void read_ttag(AVFormatContext *s, AVIOContext *pb, int taglen, const cha av_freep(&dst); if (dst) - av_dict_set(&s->metadata, key, dst, dict_flags); + av_dict_set(metadata, key, dst, dict_flags); } /** * Parse GEOB tag into a ID3v2ExtraMetaGEOB struct. */ -static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta) +static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, + char *tag, ID3v2ExtraMeta **extra_meta) { ID3v2ExtraMetaGEOB *geob_data = NULL; - ID3v2ExtraMeta *new_extra = NULL; + ID3v2ExtraMeta *new_extra = NULL; char encoding; unsigned int len; @@ -325,13 +325,15 @@ static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, char * geob_data = av_mallocz(sizeof(ID3v2ExtraMetaGEOB)); if (!geob_data) { - av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", sizeof(ID3v2ExtraMetaGEOB)); + av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", + sizeof(ID3v2ExtraMetaGEOB)); return; } new_extra = av_mallocz(sizeof(ID3v2ExtraMeta)); if (!new_extra) { - av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", sizeof(ID3v2ExtraMeta)); + av_log(s, AV_LOG_ERROR, "Failed to alloc %zu bytes\n", + sizeof(ID3v2ExtraMeta)); goto fail; } @@ -340,18 +342,19 @@ static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, char * taglen--; /* read MIME type (always ISO-8859) */ - if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &geob_data->mime_type, &taglen) < 0 - || taglen <= 0) + if (decode_str(s, pb, ID3v2_ENCODING_ISO8859, &geob_data->mime_type, + &taglen) < 0 || + taglen <= 0) goto fail; /* read file name */ - if (decode_str(s, pb, encoding, &geob_data->file_name, &taglen) < 0 - || taglen <= 0) + if (decode_str(s, pb, encoding, &geob_data->file_name, &taglen) < 0 || + taglen <= 0) goto fail; /* read content description */ - if (decode_str(s, pb, encoding, &geob_data->description, &taglen) < 0 - || taglen < 0) + if (decode_str(s, pb, encoding, &geob_data->description, &taglen) < 0 || + taglen < 0) goto fail; if (taglen) { @@ -362,18 +365,19 @@ static void read_geobtag(AVFormatContext *s, AVIOContext *pb, int taglen, char * goto fail; } if ((len = avio_read(pb, geob_data->data, taglen)) < taglen) - av_log(s, AV_LOG_WARNING, "Error reading GEOB frame, data truncated.\n"); + av_log(s, AV_LOG_WARNING, + "Error reading GEOB frame, data truncated.\n"); geob_data->datasize = len; } else { - geob_data->data = NULL; + geob_data->data = NULL; geob_data->datasize = 0; } /* add data to the list */ - new_extra->tag = "GEOB"; + new_extra->tag = "GEOB"; new_extra->data = geob_data; new_extra->next = *extra_meta; - *extra_meta = new_extra; + *extra_meta = new_extra; return; @@ -386,11 +390,12 @@ fail: static int is_number(const char *str) { - while (*str >= '0' && *str <= '9') str++; + while (*str >= '0' && *str <= '9') + str++; return !*str; } -static AVDictionaryEntry* get_date_tag(AVDictionary *m, const char *tag) +static AVDictionaryEntry *get_date_tag(AVDictionary *m, const char *tag) { AVDictionaryEntry *t; if ((t = av_dict_get(m, tag, NULL, AV_DICT_MATCH_CASE)) && @@ -402,28 +407,29 @@ static AVDictionaryEntry* get_date_tag(AVDictionary *m, const char *tag) static void merge_date(AVDictionary **m) { AVDictionaryEntry *t; - char date[17] = {0}; // YYYY-MM-DD hh:mm + char date[17] = { 0 }; // YYYY-MM-DD hh:mm if (!(t = get_date_tag(*m, "TYER")) && !(t = get_date_tag(*m, "TYE"))) return; av_strlcpy(date, t->value, 5); av_dict_set(m, "TYER", NULL, 0); - av_dict_set(m, "TYE", NULL, 0); + av_dict_set(m, "TYE", NULL, 0); if (!(t = get_date_tag(*m, "TDAT")) && !(t = get_date_tag(*m, "TDA"))) goto finish; snprintf(date + 4, sizeof(date) - 4, "-%.2s-%.2s", t->value + 2, t->value); av_dict_set(m, "TDAT", NULL, 0); - av_dict_set(m, "TDA", NULL, 0); + av_dict_set(m, "TDA", NULL, 0); if (!(t = get_date_tag(*m, "TIME")) && !(t = get_date_tag(*m, "TIM"))) goto finish; - snprintf(date + 10, sizeof(date) - 10, " %.2s:%.2s", t->value, t->value + 2); + snprintf(date + 10, sizeof(date) - 10, + " %.2s:%.2s", t->value, t->value + 2); av_dict_set(m, "TIME", NULL, 0); - av_dict_set(m, "TIM", NULL, 0); + av_dict_set(m, "TIM", NULL, 0); finish: if (date[0]) @@ -438,15 +444,16 @@ static void free_apic(void *obj) av_freep(&apic); } -static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta) +static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, + char *tag, ID3v2ExtraMeta **extra_meta) { int enc, pic_type; - char mimetype[64]; - const CodecMime *mime = ff_id3v2_mime_tags; - enum AVCodecID id = AV_CODEC_ID_NONE; - ID3v2ExtraMetaAPIC *apic = NULL; + char mimetype[64]; + const CodecMime *mime = ff_id3v2_mime_tags; + enum AVCodecID id = AV_CODEC_ID_NONE; + ID3v2ExtraMetaAPIC *apic = NULL; ID3v2ExtraMeta *new_extra = NULL; - int64_t end = avio_tell(pb) + taglen; + int64_t end = avio_tell(pb) + taglen; if (taglen <= 4) goto fail; @@ -469,7 +476,8 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag mime++; } if (id == AV_CODEC_ID_NONE) { - av_log(s, AV_LOG_WARNING, "Unknown attached picture mimetype: %s, skipping.\n", mimetype); + av_log(s, AV_LOG_WARNING, + "Unknown attached picture mimetype: %s, skipping.\n", mimetype); goto fail; } apic->id = id; @@ -478,14 +486,16 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag pic_type = avio_r8(pb); taglen--; if (pic_type < 0 || pic_type >= FF_ARRAY_ELEMS(ff_id3v2_picture_types)) { - av_log(s, AV_LOG_WARNING, "Unknown attached picture type %d.\n", pic_type); + av_log(s, AV_LOG_WARNING, "Unknown attached picture type %d.\n", + pic_type); pic_type = 0; } apic->type = ff_id3v2_picture_types[pic_type]; /* description and picture data */ if (decode_str(s, pb, enc, &apic->description, &taglen) < 0) { - av_log(s, AV_LOG_ERROR, "Error decoding attached picture description.\n"); + av_log(s, AV_LOG_ERROR, + "Error decoding attached picture description.\n"); goto fail; } @@ -494,10 +504,10 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag goto fail; memset(apic->buf->data + taglen, 0, FF_INPUT_BUFFER_PADDING_SIZE); - new_extra->tag = "APIC"; - new_extra->data = apic; - new_extra->next = *extra_meta; - *extra_meta = new_extra; + new_extra->tag = "APIC"; + new_extra->data = apic; + new_extra->next = *extra_meta; + *extra_meta = new_extra; return; @@ -508,47 +518,65 @@ fail: avio_seek(pb, end, SEEK_SET); } -static void read_chapter(AVFormatContext *s, AVIOContext *pb, int taglen, char *tag, ID3v2ExtraMeta **extra_meta) +static void read_chapter(AVFormatContext *s, AVIOContext *pb, int len, char *ttag, ID3v2ExtraMeta **extra_meta) { AVRational time_base = {1, 1000}; - char title[1024]; uint32_t start, end; + AVChapter *chapter; + uint8_t *dst = NULL; + int taglen; + char tag[5]; - taglen -= avio_get_str(pb, taglen, title, sizeof(title)); - if (taglen < 16) + if (decode_str(s, pb, 0, &dst, &len) < 0) + return; + if (len < 16) return; start = avio_rb32(pb); end = avio_rb32(pb); - taglen -= 27; - if (taglen > 0) { - char tag[4]; + avio_skip(pb, 8); + + chapter = avpriv_new_chapter(s, s->nb_chapters + 1, time_base, start, end, dst); + if (!chapter) { + av_free(dst); + return; + } - avio_skip(pb, 8); + len -= 16; + while (len > 10) { avio_read(pb, tag, 4); - if (!memcmp(tag, "TIT2", 4)) { - taglen = FFMIN(taglen, avio_rb32(pb)); - if (taglen < 0) - return; - avio_skip(pb, 3); - avio_get_str(pb, taglen, title, sizeof(title)); + tag[4] = 0; + taglen = avio_rb32(pb); + avio_skip(pb, 2); + len -= 10; + if (taglen < 0 || taglen > len) { + av_free(dst); + return; } + if (tag[0] == 'T') + read_ttag(s, pb, taglen, &chapter->metadata, tag); + else + avio_skip(pb, taglen); + len -= taglen; } - avpriv_new_chapter(s, s->nb_chapters + 1, time_base, start, end, title); + ff_metadata_conv(&chapter->metadata, NULL, ff_id3v2_34_metadata_conv); + ff_metadata_conv(&chapter->metadata, NULL, ff_id3v2_4_metadata_conv); + av_free(dst); } typedef struct ID3v2EMFunc { const char *tag3; const char *tag4; - void (*read)(AVFormatContext*, AVIOContext*, int, char*, ID3v2ExtraMeta **); + void (*read)(AVFormatContext *, AVIOContext *, int, char *, + ID3v2ExtraMeta **); void (*free)(void *obj); } ID3v2EMFunc; static const ID3v2EMFunc id3v2_extra_meta_funcs[] = { { "GEO", "GEOB", read_geobtag, free_geobtag }, - { "PIC", "APIC", read_apic, free_apic }, - { "CHAP","CHAP", read_chapter, NULL }, + { "PIC", "APIC", read_apic, free_apic }, + { "CHAP","CHAP", read_chapter, NULL }, { NULL } }; @@ -571,7 +599,8 @@ static const ID3v2EMFunc *get_extra_meta_func(const char *tag, int isv34) return NULL; } -static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t flags, ID3v2ExtraMeta **extra_meta) +static void id3v2_parse(AVFormatContext *s, int len, uint8_t version, + uint8_t flags, ID3v2ExtraMeta **extra_meta) { int isv34, unsync; unsigned tlen; @@ -582,7 +611,7 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t AVIOContext pb; AVIOContext *pbx; unsigned char *buffer = NULL; - int buffer_size = 0; + int buffer_size = 0; const ID3v2EMFunc *extra_func = NULL; unsigned char *uncompressed_buffer = NULL; int uncompressed_buffer_size = 0; @@ -595,13 +624,13 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t reason = "compression"; goto error; } - isv34 = 0; + isv34 = 0; taghdrlen = 6; break; case 3: case 4: - isv34 = 1; + isv34 = 1; taghdrlen = 10; break; @@ -615,7 +644,8 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t if (isv34 && flags & 0x40) { /* Extended header present, just skip over it */ int extlen = get_size(s->pb, 4); if (version == 4) - extlen -= 4; // in v2.4 the length includes the length field we just read + /* In v2.4 the length includes the length field we just read. */ + extlen -= 4; if (extlen < 0) { reason = "invalid extended header length"; @@ -631,24 +661,24 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t while (len >= taghdrlen) { unsigned int tflags = 0; - int tunsync = 0; - int tcomp = 0; - int tencr = 0; + int tunsync = 0; + int tcomp = 0; + int tencr = 0; unsigned long dlen; if (isv34) { avio_read(s->pb, tag, 4); tag[4] = 0; - if(version==3){ + if (version == 3) { tlen = avio_rb32(s->pb); - }else + } else tlen = get_size(s->pb, 4); - tflags = avio_rb16(s->pb); + tflags = avio_rb16(s->pb); tunsync = tflags & ID3v2_FLAG_UNSYNCH; } else { avio_read(s->pb, tag, 3); tag[3] = 0; - tlen = avio_rb24(s->pb); + tlen = avio_rb24(s->pb); } if (tlen > (1<<28)) break; @@ -661,7 +691,8 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t if (!tlen) { if (tag[0]) - av_log(s, AV_LOG_DEBUG, "Invalid empty frame %s, skipping.\n", tag); + av_log(s, AV_LOG_DEBUG, "Invalid empty frame %s, skipping.\n", + tag); continue; } @@ -689,7 +720,9 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t av_log(s, AV_LOG_WARNING, "Skipping %s ID3v2 frame %s.\n", type, tag); avio_skip(s->pb, tlen); /* check for text tag or supported special meta tag */ - } else if (tag[0] == 'T' || (extra_meta && (extra_func = get_extra_meta_func(tag, isv34)))) { + } else if (tag[0] == 'T' || + (extra_meta && + (extra_func = get_extra_meta_func(tag, isv34)))) { pbx = s->pb; if (unsync || tunsync || tcomp) { @@ -704,16 +737,19 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t uint8_t *b; b = buffer; - while (avio_tell(s->pb) < end && b - buffer < tlen) { + while (avio_tell(s->pb) < end && b - buffer < tlen && !s->pb->eof_reached) { *b++ = avio_r8(s->pb); - if (*(b - 1) == 0xff && avio_tell(s->pb) < end - 1 && b - buffer < tlen) { + if (*(b - 1) == 0xff && avio_tell(s->pb) < end - 1 && + b - buffer < tlen && + !s->pb->eof_reached ) { uint8_t val = avio_r8(s->pb); *b++ = val ? val : avio_r8(s->pb); } } - ffio_init_context(&pb, buffer, b - buffer, 0, NULL, NULL, NULL, NULL); + ffio_init_context(&pb, buffer, b - buffer, 0, NULL, NULL, NULL, + NULL); tlen = b - buffer; - pbx = &pb; // read from sync buffer + pbx = &pb; // read from sync buffer } #if CONFIG_ZLIB @@ -749,12 +785,11 @@ static void ff_id3v2_parse(AVFormatContext *s, int len, uint8_t version, uint8_t #endif if (tag[0] == 'T') /* parse text tag */ - read_ttag(s, pbx, tlen, tag); + read_ttag(s, pbx, tlen, &s->metadata, tag); else /* parse special meta tag */ extra_func->read(s, pbx, tlen, tag, extra_meta); - } - else if (!tag[0]) { + } else if (!tag[0]) { if (tag[1]) av_log(s, AV_LOG_WARNING, "invalid frame id, assuming padding\n"); avio_skip(s->pb, tlen); @@ -765,23 +800,26 @@ seek: avio_seek(s->pb, next, SEEK_SET); } - if (version == 4 && flags & 0x10) /* Footer preset, always 10 bytes, skip over it */ + /* Footer preset, always 10 bytes, skip over it */ + if (version == 4 && flags & 0x10) end += 10; - error: +error: if (reason) - av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", version, reason); + av_log(s, AV_LOG_INFO, "ID3v2.%d tag skipped, cannot handle %s\n", + version, reason); avio_seek(s->pb, end, SEEK_SET); av_free(buffer); av_free(uncompressed_buffer); return; } -void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra_meta) +void ff_id3v2_read(AVFormatContext *s, const char *magic, + ID3v2ExtraMeta **extra_meta) { int len, ret; uint8_t buf[ID3v2_HEADER_SIZE]; - int found_header; + int found_header; int64_t off; do { @@ -799,7 +837,7 @@ void ff_id3v2_read(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **extra ((buf[7] & 0x7f) << 14) | ((buf[8] & 0x7f) << 7) | (buf[9] & 0x7f); - ff_id3v2_parse(s, len, buf[3], buf[5], extra_meta); + id3v2_parse(s, len, buf[3], buf[5], extra_meta); } else { avio_seek(s->pb, off, SEEK_SET); } diff --git a/chromium/third_party/ffmpeg/libavformat/id3v2enc.c b/chromium/third_party/ffmpeg/libavformat/id3v2enc.c index a10d6799462..60522444fc6 100644 --- a/chromium/third_party/ffmpeg/libavformat/id3v2enc.c +++ b/chromium/third_party/ffmpeg/libavformat/id3v2enc.c @@ -26,8 +26,11 @@ #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio.h" +#include "avio_internal.h" #include "id3v2.h" +#define PADDING_BYTES 10 + static void id3v2_put_size(AVIOContext *pb, int size) { avio_w8(pb, size >> 21 & 0x7f); @@ -162,33 +165,31 @@ void ff_id3v2_start(ID3v2EncContext *id3, AVIOContext *pb, int id3v2_version, avio_wb32(pb, 0); } -int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3) +static int write_metadata(AVIOContext *pb, AVDictionary **metadata, + ID3v2EncContext *id3, int enc) { AVDictionaryEntry *t = NULL; - int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM : - ID3v2_ENCODING_UTF8; + int ret; - ff_metadata_conv(&s->metadata, ff_id3v2_34_metadata_conv, NULL); + ff_metadata_conv(metadata, ff_id3v2_34_metadata_conv, NULL); if (id3->version == 3) - id3v2_3_metadata_split_date(&s->metadata); + id3v2_3_metadata_split_date(metadata); else if (id3->version == 4) - ff_metadata_conv(&s->metadata, ff_id3v2_4_metadata_conv, NULL); - - while ((t = av_dict_get(s->metadata, "", t, AV_DICT_IGNORE_SUFFIX))) { - int ret; + ff_metadata_conv(metadata, ff_id3v2_4_metadata_conv, NULL); - if ((ret = id3v2_check_write_tag(id3, s->pb, t, ff_id3v2_tags, enc)) > 0) { + while ((t = av_dict_get(*metadata, "", t, AV_DICT_IGNORE_SUFFIX))) { + if ((ret = id3v2_check_write_tag(id3, pb, t, ff_id3v2_tags, enc)) > 0) { id3->len += ret; continue; } - if ((ret = id3v2_check_write_tag(id3, s->pb, t, id3->version == 3 ? - ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0) { + if ((ret = id3v2_check_write_tag(id3, pb, t, id3->version == 3 ? + ff_id3v2_3_tags : ff_id3v2_4_tags, enc)) > 0) { id3->len += ret; continue; } /* unknown tag, write as TXXX frame */ - if ((ret = id3v2_put_ttag(id3, s->pb, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0) + if ((ret = id3v2_put_ttag(id3, pb, t->key, t->value, MKBETAG('T', 'X', 'X', 'X'), enc)) < 0) return ret; id3->len += ret; } @@ -196,6 +197,64 @@ int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3) return 0; } +static int write_chapter(AVFormatContext *s, ID3v2EncContext *id3, int id, int enc) +{ + const AVRational time_base = {1, 1000}; + AVChapter *ch = s->chapters[id]; + uint8_t *dyn_buf = NULL; + AVIOContext *dyn_bc = NULL; + char name[123]; + int len, start, end, ret; + + if ((ret = avio_open_dyn_buf(&dyn_bc)) < 0) + goto fail; + + start = av_rescale_q(ch->start, ch->time_base, time_base); + end = av_rescale_q(ch->end, ch->time_base, time_base); + + snprintf(name, 122, "ch%d", id); + id3->len += avio_put_str(dyn_bc, name); + avio_wb32(dyn_bc, start); + avio_wb32(dyn_bc, end); + avio_wb32(dyn_bc, 0xFFFFFFFFu); + avio_wb32(dyn_bc, 0xFFFFFFFFu); + + if ((ret = write_metadata(dyn_bc, &ch->metadata, id3, enc)) < 0) + goto fail; + + len = avio_close_dyn_buf(dyn_bc, &dyn_buf); + id3->len += 16 + ID3v2_HEADER_SIZE; + + avio_wb32(s->pb, MKBETAG('C', 'H', 'A', 'P')); + avio_wb32(s->pb, len); + avio_wb16(s->pb, 0); + avio_write(s->pb, dyn_buf, len); + +fail: + if (dyn_bc && !dyn_buf) + avio_close_dyn_buf(dyn_bc, &dyn_buf); + av_freep(&dyn_buf); + + return ret; +} + +int ff_id3v2_write_metadata(AVFormatContext *s, ID3v2EncContext *id3) +{ + int enc = id3->version == 3 ? ID3v2_ENCODING_UTF16BOM : + ID3v2_ENCODING_UTF8; + int i, ret; + + if ((ret = write_metadata(s->pb, &s->metadata, id3, enc)) < 0) + return ret; + + for (i = 0; i < s->nb_chapters; i++) { + if ((ret = write_chapter(s, id3, i, enc)) < 0) + return ret; + } + + return 0; +} + int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt) { AVStream *st = s->streams[pkt->stream_index]; @@ -236,6 +295,10 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt) if ((e = av_dict_get(st->metadata, "title", NULL, 0))) desc = e->value; + /* use UTF16 only for non-ASCII strings */ + if (enc == ID3v2_ENCODING_UTF16BOM && string_is_ascii(desc)) + enc = ID3v2_ENCODING_ISO8859; + /* start writing */ if (avio_open_dyn_buf(&dyn_buf) < 0) return AVERROR(ENOMEM); @@ -263,7 +326,15 @@ int ff_id3v2_write_apic(AVFormatContext *s, ID3v2EncContext *id3, AVPacket *pkt) void ff_id3v2_finish(ID3v2EncContext *id3, AVIOContext *pb) { - int64_t cur_pos = avio_tell(pb); + int64_t cur_pos; + + /* adding an arbitrary amount of padding bytes at the end of the + * ID3 metadata fixes cover art display for some software (iTunes, + * Traktor, Serato, Torq) */ + ffio_fill(pb, 0, PADDING_BYTES); + id3->len += PADDING_BYTES; + + cur_pos = avio_tell(pb); avio_seek(pb, id3->size_pos, SEEK_SET); id3v2_put_size(pb, id3->len); avio_seek(pb, cur_pos, SEEK_SET); diff --git a/chromium/third_party/ffmpeg/libavformat/idcin.c b/chromium/third_party/ffmpeg/libavformat/idcin.c index 2a8af406763..85d538c4f37 100644 --- a/chromium/third_party/ffmpeg/libavformat/idcin.c +++ b/chromium/third_party/ffmpeg/libavformat/idcin.c @@ -93,7 +93,7 @@ typedef struct IdcinDemuxContext { static int idcin_probe(AVProbeData *p) { - unsigned int number; + unsigned int number, sample_rate; /* * This is what you could call a "probabilistic" file check: id CIN @@ -122,22 +122,22 @@ static int idcin_probe(AVProbeData *p) return 0; /* check the audio sample rate */ - number = AV_RL32(&p->buf[8]); - if ((number != 0) && ((number < 8000) | (number > 48000))) + sample_rate = AV_RL32(&p->buf[8]); + if (sample_rate && (sample_rate < 8000 || sample_rate > 48000)) return 0; /* check the audio bytes/sample */ number = AV_RL32(&p->buf[12]); - if (number > 2) + if (number > 2 || sample_rate && !number) return 0; /* check the audio channels */ number = AV_RL32(&p->buf[16]); - if (number > 2) + if (number > 2 || sample_rate && !number) return 0; - /* return half certainly since this check is a bit sketchy */ - return AVPROBE_SCORE_MAX / 2; + /* return half certainty since this check is a bit sketchy */ + return AVPROBE_SCORE_EXTENSION; } static int idcin_read_header(AVFormatContext *s) @@ -196,8 +196,10 @@ static int idcin_read_header(AVFormatContext *s) st->codec->height = height; /* load up the Huffman tables into extradata */ - st->codec->extradata_size = HUFFMAN_TABLE_SIZE; st->codec->extradata = av_malloc(HUFFMAN_TABLE_SIZE); + if (!st->codec->extradata) + return AVERROR(ENOMEM); + st->codec->extradata_size = HUFFMAN_TABLE_SIZE; ret = avio_read(pb, st->codec->extradata, HUFFMAN_TABLE_SIZE); if (ret < 0) { return ret; diff --git a/chromium/third_party/ffmpeg/libavformat/iff.c b/chromium/third_party/ffmpeg/libavformat/iff.c index 1efc1472cc2..edf308b1355 100644 --- a/chromium/third_party/ffmpeg/libavformat/iff.c +++ b/chromium/third_party/ffmpeg/libavformat/iff.c @@ -481,5 +481,5 @@ AVInputFormat ff_iff_demuxer = { .read_probe = iff_probe, .read_header = iff_read_header, .read_packet = iff_read_packet, - .flags = AVFMT_GENERIC_INDEX, + .flags = AVFMT_GENERIC_INDEX | AVFMT_NO_BYTE_SEEK, }; diff --git a/chromium/third_party/ffmpeg/libavformat/img2dec.c b/chromium/third_party/ffmpeg/libavformat/img2dec.c index 12cf46265bf..5163e69f65b 100644 --- a/chromium/third_party/ffmpeg/libavformat/img2dec.c +++ b/chromium/third_party/ffmpeg/libavformat/img2dec.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <sys/stat.h> #include "libavutil/avstring.h" #include "libavutil/log.h" #include "libavutil/opt.h" @@ -63,6 +64,7 @@ typedef struct { int start_number; int start_number_range; int frame_size; + int ts_from_file; } VideoDemuxData; static const int sizes[][2] = { @@ -185,7 +187,7 @@ static int img_read_probe(AVProbeData *p) else if (av_match_ext(p->filename, "raw") || av_match_ext(p->filename, "gif")) return 5; else - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; } return 0; } @@ -223,7 +225,10 @@ static int img_read_header(AVFormatContext *s1) st->need_parsing = AVSTREAM_PARSE_FULL; } - avpriv_set_pts_info(st, 60, s->framerate.den, s->framerate.num); + if (s->ts_from_file) + avpriv_set_pts_info(st, 64, 1, 1); + else + avpriv_set_pts_info(st, 64, s->framerate.den, s->framerate.num); if (s->width && s->height) { st->codec->width = s->width; @@ -267,7 +272,7 @@ static int img_read_header(AVFormatContext *s1) if (find_image_range(&first_index, &last_index, s->path, s->start_number, s->start_number_range) < 0) { av_log(s1, AV_LOG_ERROR, - "Could find no file with with path '%s' and index in the range %d-%d\n", + "Could find no file with path '%s' and index in the range %d-%d\n", s->path, s->start_number, s->start_number + s->start_number_range - 1); return AVERROR(ENOENT); } @@ -296,8 +301,10 @@ static int img_read_header(AVFormatContext *s1) s->img_last = last_index; s->img_number = first_index; /* compute duration */ - st->start_time = 0; - st->duration = last_index - first_index + 1; + if (!s->ts_from_file) { + st->start_time = 0; + st->duration = last_index - first_index + 1; + } } if (s1->video_codec_id) { @@ -381,8 +388,15 @@ static int img_read_packet(AVFormatContext *s1, AVPacket *pkt) return AVERROR(ENOMEM); pkt->stream_index = 0; pkt->flags |= AV_PKT_FLAG_KEY; - if (!s->is_pipe) + if (s->ts_from_file) { + struct stat img_stat; + if (stat(filename, &img_stat)) + return AVERROR(EIO); + pkt->pts = (int64_t)img_stat.st_mtime; + av_add_index_entry(s1->streams[0], s->img_number, pkt->pts, 0, 0, AVINDEX_KEYFRAME); + } else if (!s->is_pipe) { pkt->pts = s->pts; + } pkt->size = 0; for (i = 0; i < 3; i++) { @@ -420,6 +434,15 @@ static int img_read_close(struct AVFormatContext* s1) static int img_read_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { VideoDemuxData *s1 = s->priv_data; + AVStream *st = s->streams[0]; + + if (s1->ts_from_file) { + int index = av_index_search_timestamp(st, timestamp, flags); + if(index < 0) + return -1; + s1->img_number = st->index_entries[index].pos; + return 0; + } if (timestamp < 0 || !s1->loop && timestamp > s1->img_last - s1->img_first) return -1; @@ -444,6 +467,7 @@ static const AVOption options[] = { { "start_number_range", "set range for looking at the first sequence number", OFFSET(start_number_range), AV_OPT_TYPE_INT, {.i64 = 5}, 1, INT_MAX, DEC }, { "video_size", "set video size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, { "frame_size", "force frame size in bytes", OFFSET(frame_size), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, DEC }, + { "ts_from_file", "set frame timestamp from file's one", OFFSET(ts_from_file), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, DEC }, { NULL }, }; diff --git a/chromium/third_party/ffmpeg/libavformat/img2enc.c b/chromium/third_party/ffmpeg/libavformat/img2enc.c index fb297da20bf..11223fba821 100644 --- a/chromium/third_party/ffmpeg/libavformat/img2enc.c +++ b/chromium/third_party/ffmpeg/libavformat/img2enc.c @@ -37,6 +37,7 @@ typedef struct { int split_planes; /**< use independent file for each Y, U, V plane */ char path[1024]; int update; + int use_strftime; } VideoMuxData; static int write_header(AVFormatContext *s) @@ -60,7 +61,7 @@ static int write_header(AVFormatContext *s) && s->nb_streams == 1 && st->codec->codec_id == AV_CODEC_ID_RAWVIDEO && desc - &&(desc->flags & PIX_FMT_PLANAR) + &&(desc->flags & AV_PIX_FMT_FLAG_PLANAR) && desc->nb_components >= 3; return 0; } @@ -77,6 +78,15 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) if (!img->is_pipe) { if (img->update) { av_strlcpy(filename, img->path, sizeof(filename)); + } else if (img->use_strftime) { + time_t now0; + struct tm *tm; + time(&now0); + tm = localtime(&now0); + if (!strftime(filename, sizeof(filename), img->path, tm)) { + av_log(s, AV_LOG_ERROR, "Could not get frame filename with strftime\n"); + return AVERROR(EINVAL); + } } else if (av_get_frame_filename(filename, sizeof(filename), img->path, img->img_number) < 0 && img->img_number > 1) { av_log(s, AV_LOG_ERROR, @@ -101,7 +111,7 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) if (img->split_planes) { int ysize = codec->width * codec->height; - int usize = ((-codec->width)>>desc->log2_chroma_w) * ((-codec->height)>>desc->log2_chroma_h); + int usize = FF_CEIL_RSHIFT(codec->width, desc->log2_chroma_w) * FF_CEIL_RSHIFT(codec->height, desc->log2_chroma_h); if (desc->comp[0].depth_minus1 >= 8) { ysize *= 2; usize *= 2; @@ -132,7 +142,8 @@ static int write_packet(AVFormatContext *s, AVPacket *pkt) static const AVOption muxoptions[] = { { "updatefirst", "continuously overwrite one file", OFFSET(update), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ENC }, { "update", "continuously overwrite one file", OFFSET(update), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ENC }, - { "start_number", "set first number in the sequence", OFFSET(img_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, INT_MAX, ENC }, + { "start_number", "set first number in the sequence", OFFSET(img_number), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, INT_MAX, ENC }, + { "strftime", "use strftime for filename", OFFSET(use_strftime), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ENC }, { NULL }, }; @@ -148,7 +159,7 @@ AVOutputFormat ff_image2_muxer = { .name = "image2", .long_name = NULL_IF_CONFIG_SMALL("image2 sequence"), .extensions = "bmp,dpx,jls,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png," - "ppm,sgi,tga,tif,tiff,jp2,j2c,xwd,sun,ras,rs,im1,im8,im24," + "ppm,sgi,tga,tif,tiff,jp2,j2c,j2k,xwd,sun,ras,rs,im1,im8,im24," "sunras,xbm,xface", .priv_data_size = sizeof(VideoMuxData), .video_codec = AV_CODEC_ID_MJPEG, diff --git a/chromium/third_party/ffmpeg/libavformat/internal.h b/chromium/third_party/ffmpeg/libavformat/internal.h index 4d563883128..1f74069bcc0 100644 --- a/chromium/third_party/ffmpeg/libavformat/internal.h +++ b/chromium/third_party/ffmpeg/libavformat/internal.h @@ -90,31 +90,6 @@ void ff_read_frame_flush(AVFormatContext *s); uint64_t ff_ntp_time(void); /** - * Assemble a URL string from components. This is the reverse operation - * of av_url_split. - * - * Note, this requires networking to be initialized, so the caller must - * ensure ff_network_init has been called. - * - * @see av_url_split - * - * @param str the buffer to fill with the url - * @param size the size of the str buffer - * @param proto the protocol identifier, if null, the separator - * after the identifier is left out, too - * @param authorization an optional authorization string, may be null. - * An empty string is treated the same as a null string. - * @param hostname the host name string - * @param port the port number, left out from the string if negative - * @param fmt a generic format string for everything to add after the - * host/port, may be null - * @return the number of characters written to the destination buffer - */ -int ff_url_join(char *str, int size, const char *proto, - const char *authorization, const char *hostname, - int port, const char *fmt, ...) av_printf_format(7, 8); - -/** * Append the media-specific SDP fragment for the media stream c * to the buffer buff. * @@ -240,17 +215,6 @@ AVChapter *avpriv_new_chapter(AVFormatContext *s, int id, AVRational time_base, */ void ff_reduce_index(AVFormatContext *s, int stream_index); -/** - * Convert a relative url into an absolute url, given a base url. - * - * @param buf the buffer where output absolute url is written - * @param size the size of buf - * @param base the base url, may be equal to buf. - * @param rel the new url, which is interpreted relative to base - */ -void ff_make_absolute_url(char *buf, int size, const char *base, - const char *rel); - enum AVCodecID ff_guess_image2_codec(const char *filename); /** @@ -278,6 +242,9 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, */ void ff_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp); +int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos, + int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )); + /** * Perform a binary search using read_timestamp(). * @@ -390,6 +357,4 @@ AVRational ff_choose_timebase(AVFormatContext *s, AVStream *st, int min_precissi */ void ff_generate_avci_extradata(AVStream *st); -int ff_http_match_no_proxy(const char *no_proxy, const char *hostname); - #endif /* AVFORMAT_INTERNAL_H */ diff --git a/chromium/third_party/ffmpeg/libavformat/isom.c b/chromium/third_party/ffmpeg/libavformat/isom.c index 4078c0d12c5..ec372288cad 100644 --- a/chromium/third_party/ffmpeg/libavformat/isom.c +++ b/chromium/third_party/ffmpeg/libavformat/isom.c @@ -21,8 +21,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -//#define DEBUG - #include "avformat.h" #include "internal.h" #include "isom.h" @@ -188,6 +186,7 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '4', 'p') }, /* MPEG2 IMX PAL 625/50 40mb/s produced by FCP */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'n') }, /* MPEG2 IMX NTSC 525/60 30mb/s produced by FCP */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('m', 'x', '3', 'p') }, /* MPEG2 IMX PAL 625/50 30mb/s produced by FCP */ + { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '1') }, /* XDCAM HD422 720p30 CBR */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '4') }, /* XDCAM HD422 720p24 CBR */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '5') }, /* XDCAM HD422 720p25 CBR */ { AV_CODEC_ID_MPEG2VIDEO, MKTAG('x', 'd', '5', '9') }, /* XDCAM HD422 720p60 CBR */ @@ -244,6 +243,8 @@ const AVCodecTag ff_codec_movvideo_tags[] = { { AV_CODEC_ID_PRORES, MKTAG('a', 'p', '4', 'h') }, /* Apple ProRes 4444 */ { AV_CODEC_ID_FLIC, MKTAG('f', 'l', 'i', 'c') }, + { AV_CODEC_ID_AIC, MKTAG('i', 'c', 'o', 'd') }, + { AV_CODEC_ID_NONE, 0 }, }; diff --git a/chromium/third_party/ffmpeg/libavformat/isom.h b/chromium/third_party/ffmpeg/libavformat/isom.h index 4154baf8278..b0fa453de65 100644 --- a/chromium/third_party/ffmpeg/libavformat/isom.h +++ b/chromium/third_party/ffmpeg/libavformat/isom.h @@ -110,7 +110,7 @@ typedef struct MOVStreamContext { int ctts_index; int ctts_sample; unsigned int sample_size; ///< may contain value calculated from stsd or value from stsz atom - unsigned int alt_sample_size; ///< always contains sample size from stsz atom + unsigned int stsz_sample_size; ///< always contains sample size from stsz atom unsigned int sample_count; int *sample_sizes; int keyframe_absent; @@ -162,6 +162,8 @@ typedef struct MOVContext { int use_absolute_path; int ignore_editlist; int64_t next_root_atom; ///< offset of the next root atom + int *bitrates; ///< bitrates read before streams creation + int bitrates_count; } MOVContext; int ff_mp4_read_descr_len(AVIOContext *pb); diff --git a/chromium/third_party/ffmpeg/libavformat/jacosubdec.c b/chromium/third_party/ffmpeg/libavformat/jacosubdec.c index 89e7e1bf546..da1afadf1b2 100644 --- a/chromium/third_party/ffmpeg/libavformat/jacosubdec.c +++ b/chromium/third_party/ffmpeg/libavformat/jacosubdec.c @@ -60,7 +60,7 @@ static int jacosub_probe(AVProbeData *p) ptr++; if (*ptr != '#' && *ptr != '\n') { if (timed_line(ptr)) - return AVPROBE_SCORE_MAX/2 + 1; + return AVPROBE_SCORE_EXTENSION + 1; return 0; } ptr += strcspn(ptr, "\n") + 1; diff --git a/chromium/third_party/ffmpeg/libavformat/jvdec.c b/chromium/third_party/ffmpeg/libavformat/jvdec.c index e9414927621..69ac8f27fd3 100644 --- a/chromium/third_party/ffmpeg/libavformat/jvdec.c +++ b/chromium/third_party/ffmpeg/libavformat/jvdec.c @@ -33,10 +33,10 @@ #define JV_PREAMBLE_SIZE 5 typedef struct { - int audio_size; /** audio packet size (bytes) */ - int video_size; /** video packet size (bytes) */ - int palette_size; /** palette size (bytes) */ - int video_type; /** per-frame video compression type */ + int audio_size; /**< audio packet size (bytes) */ + int video_size; /**< video packet size (bytes) */ + int palette_size; /**< palette size (bytes) */ + int video_type; /**< per-frame video compression type */ } JVFrame; typedef struct { diff --git a/chromium/third_party/ffmpeg/libavformat/latmenc.c b/chromium/third_party/ffmpeg/libavformat/latmenc.c index 9dfb4e4fab2..b3430d785d3 100644 --- a/chromium/third_party/ffmpeg/libavformat/latmenc.c +++ b/chromium/third_party/ffmpeg/libavformat/latmenc.c @@ -124,7 +124,7 @@ static void latm_write_frame_header(AVFormatContext *s, PutBitContext *bs) if (!ctx->channel_conf) { GetBitContext gb; - init_get_bits(&gb, avctx->extradata, avctx->extradata_size * 8); + init_get_bits8(&gb, avctx->extradata, avctx->extradata_size); skip_bits_long(&gb, ctx->off + 3); avpriv_copy_pce_data(bs, &gb); } diff --git a/chromium/third_party/ffmpeg/libavformat/libgme.c b/chromium/third_party/ffmpeg/libavformat/libgme.c new file mode 100644 index 00000000000..1ae63dc454c --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/libgme.c @@ -0,0 +1,201 @@ +/* + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** +* @file +* libgme demuxer +*/ + +#include <gme/gme.h> +#include "libavutil/avstring.h" +#include "libavutil/eval.h" +#include "libavutil/opt.h" +#include "avformat.h" +#include "internal.h" + +typedef struct GMEContext { + const AVClass *class; + Music_Emu *music_emu; + gme_info_t *info; ///< selected track + + /* options */ + int track_index; + int sample_rate; + int64_t max_size; +} GMEContext; + +#define OFFSET(x) offsetof(GMEContext, x) +#define A AV_OPT_FLAG_AUDIO_PARAM +#define D AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + {"track_index", "set track that should be played", OFFSET(track_index), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, A|D}, + {"sample_rate", "set sample rate", OFFSET(sample_rate), AV_OPT_TYPE_INT, {.i64 = 44100}, 1000, 999999, A|D}, + {"max_size", "set max file size supported (in bytes)", OFFSET(max_size), AV_OPT_TYPE_INT64, {.i64 = 50 * 1024 * 1024}, 0, SIZE_MAX, A|D}, + {NULL} +}; + +static void add_meta(AVFormatContext *s, const char *name, const char *value) +{ + if (value && value[0]) + av_dict_set(&s->metadata, name, value, 0); +} + +static int load_metadata(AVFormatContext *s) +{ + GMEContext *gme = s->priv_data; + gme_info_t *info = gme->info; + char buf[30]; + + add_meta(s, "system", info->system); + add_meta(s, "game", info->game); + add_meta(s, "song", info->song); + add_meta(s, "author", info->author); + add_meta(s, "copyright", info->copyright); + add_meta(s, "comment", info->comment); + add_meta(s, "dumper", info->dumper); + + snprintf(buf, sizeof(buf), "%d", (int)gme_track_count(gme->music_emu)); + add_meta(s, "tracks", buf); + + return 0; +} + +#define AUDIO_PKT_SIZE 512 + +static int read_header_gme(AVFormatContext *s) +{ + AVStream *st; + AVIOContext *pb = s->pb; + GMEContext *gme = s->priv_data; + int64_t sz = avio_size(pb); + char *buf; + char dummy; + + if (sz < 0) { + av_log(s, AV_LOG_WARNING, "Could not determine file size\n"); + sz = gme->max_size; + } else if (gme->max_size && sz > gme->max_size) { + sz = gme->max_size; + } + + buf = av_malloc(sz); + if (!buf) + return AVERROR(ENOMEM); + sz = avio_read(pb, buf, sz); + + // Data left means our buffer (the max_size option) is too small + if (avio_read(pb, &dummy, 1) == 1) { + av_log(s, AV_LOG_ERROR, "File size is larger than max_size option " + "value %"PRIi64", consider increasing the max_size option\n", + gme->max_size); + return AVERROR_BUFFER_TOO_SMALL; + } + + if (gme_open_data(buf, sz, &gme->music_emu, gme->sample_rate)) { + av_freep(&buf); + return AVERROR_INVALIDDATA; + } + av_freep(&buf); + + if (gme_track_info(gme->music_emu, &gme->info, gme->track_index)) + return AVERROR_STREAM_NOT_FOUND; + + if (gme_start_track(gme->music_emu, gme->track_index)) + return AVERROR_UNKNOWN; + + load_metadata(s); + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + avpriv_set_pts_info(st, 64, 1, 1000); + if (st->duration > 0) + st->duration = gme->info->length; + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_id = AV_NE(AV_CODEC_ID_PCM_S16BE, AV_CODEC_ID_PCM_S16LE); + st->codec->channels = 2; + st->codec->sample_rate = gme->sample_rate; + + return 0; +} + +static int read_packet_gme(AVFormatContext *s, AVPacket *pkt) +{ + GMEContext *gme = s->priv_data; + int n_samples = AUDIO_PKT_SIZE / 2; + int ret; + + if (gme_track_ended(gme->music_emu)) + return AVERROR_EOF; + + if ((ret = av_new_packet(pkt, AUDIO_PKT_SIZE)) < 0) + return ret; + + if (gme_play(gme->music_emu, n_samples, (short *)pkt->data)) + return AVERROR_EXTERNAL; + pkt->size = AUDIO_PKT_SIZE; + + return 0; +} + +static int read_close_gme(AVFormatContext *s) +{ + GMEContext *gme = s->priv_data; + gme_free_info(gme->info); + gme_delete(gme->music_emu); + return 0; +} + +static int read_seek_gme(AVFormatContext *s, int stream_idx, int64_t ts, int flags) +{ + GMEContext *gme = s->priv_data; + if (!gme_seek(gme->music_emu, (int)ts)) + return AVERROR_EXTERNAL; + return 0; +} + +static int probe_gme(AVProbeData *p) +{ + // Reads 4 bytes - returns "" if unknown format. + if (gme_identify_header(p->buf)[0]) { + if (p->buf_size < 16384) + return AVPROBE_SCORE_MAX / 4 + 1; + else + return AVPROBE_SCORE_MAX / 2; + } + return 0; +} + +static const AVClass class_gme = { + .class_name = "Game Music Emu demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +AVInputFormat ff_libgme_demuxer = { + .name = "libgme", + .long_name = NULL_IF_CONFIG_SMALL("Game Music Emu demuxer"), + .priv_data_size = sizeof(GMEContext), + .read_probe = probe_gme, + .read_header = read_header_gme, + .read_packet = read_packet_gme, + .read_close = read_close_gme, + .read_seek = read_seek_gme, + .priv_class = &class_gme, +}; diff --git a/chromium/third_party/ffmpeg/libavformat/libmodplug.c b/chromium/third_party/ffmpeg/libavformat/libmodplug.c index aa8edccb598..836b7c2ec06 100644 --- a/chromium/third_party/ffmpeg/libavformat/libmodplug.c +++ b/chromium/third_party/ffmpeg/libavformat/libmodplug.c @@ -166,14 +166,14 @@ static int modplug_read_header(AVFormatContext *s) AVIOContext *pb = s->pb; ModPlug_Settings settings; ModPlugContext *modplug = s->priv_data; - int sz = avio_size(pb); + int64_t sz = avio_size(pb); if (sz < 0) { av_log(s, AV_LOG_WARNING, "Could not determine file size\n"); sz = modplug->max_size; } else if (modplug->max_size && sz > modplug->max_size) { sz = modplug->max_size; - av_log(s, AV_LOG_WARNING, "Max file size reach%s, allocating %dB " + av_log(s, AV_LOG_WARNING, "Max file size reach%s, allocating %"PRIi64"B " "but demuxing is likely to fail due to incomplete buffer\n", sz == FF_MODPLUG_DEF_FILE_SIZE ? " (see -max_size)" : "", sz); } @@ -347,6 +347,19 @@ static int modplug_read_seek(AVFormatContext *s, int stream_idx, int64_t ts, int return 0; } +static const char modplug_extensions[] = "669,abc,amf,ams,dbm,dmf,dsm,far,it,mdl,med,mid,mod,mt2,mtm,okt,psm,ptm,s3m,stm,ult,umx,xm,itgz,itr,itz,mdgz,mdr,mdz,s3gz,s3r,s3z,xmgz,xmr,xmz"; + +static int modplug_probe(AVProbeData *p) +{ + if (av_match_ext(p->filename, modplug_extensions)) { + if (p->buf_size < 16384) + return AVPROBE_SCORE_EXTENSION/2-1; + else + return AVPROBE_SCORE_EXTENSION; + } + return 0; +} + static const AVClass modplug_class = { .class_name = "ModPlug demuxer", .item_name = av_default_item_name, @@ -358,11 +371,11 @@ AVInputFormat ff_libmodplug_demuxer = { .name = "libmodplug", .long_name = NULL_IF_CONFIG_SMALL("ModPlug demuxer"), .priv_data_size = sizeof(ModPlugContext), + .read_probe = modplug_probe, .read_header = modplug_read_header, .read_packet = modplug_read_packet, .read_close = modplug_read_close, .read_seek = modplug_read_seek, - .extensions = "669,abc,amf,ams,dbm,dmf,dsm,far,it,mdl,med,mid,mod,mt2,mtm,okt,psm,ptm,s3m,stm,ult,umx,xm" - ",itgz,itr,itz,mdgz,mdr,mdz,s3gz,s3r,s3z,xmgz,xmr,xmz", // compressed mods + .extensions = modplug_extensions, .priv_class = &modplug_class, }; diff --git a/chromium/third_party/ffmpeg/libavformat/libquvi.c b/chromium/third_party/ffmpeg/libavformat/libquvi.c index fbae74c6c41..ca71f9fd8c1 100644 --- a/chromium/third_party/ffmpeg/libavformat/libquvi.c +++ b/chromium/third_party/ffmpeg/libavformat/libquvi.c @@ -127,7 +127,7 @@ static int libquvi_probe(AVProbeData *p) rc = quvi_init(&q); if (rc != QUVI_OK) return AVERROR(ENOMEM); - score = quvi_supported(q, (char *)p->filename) == QUVI_OK ? AVPROBE_SCORE_MAX/2 : 0; + score = quvi_supported(q, (char *)p->filename) == QUVI_OK ? AVPROBE_SCORE_EXTENSION : 0; quvi_close(&q); return score; } diff --git a/chromium/third_party/ffmpeg/libavformat/loasdec.c b/chromium/third_party/ffmpeg/libavformat/loasdec.c index d3a8dbd6cdd..05ef0fe3ad5 100644 --- a/chromium/third_party/ffmpeg/libavformat/loasdec.c +++ b/chromium/third_party/ffmpeg/libavformat/loasdec.c @@ -52,9 +52,9 @@ static int loas_probe(AVProbeData *p) if(buf == buf0) first_frames= frames; } - if (first_frames>=3) return AVPROBE_SCORE_MAX/2+1; - else if(max_frames>100)return AVPROBE_SCORE_MAX/2; - else if(max_frames>=3) return AVPROBE_SCORE_MAX/4; + if (first_frames>=3) return AVPROBE_SCORE_EXTENSION+1; + else if(max_frames>100)return AVPROBE_SCORE_EXTENSION; + else if(max_frames>=3) return AVPROBE_SCORE_EXTENSION / 2; else return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/lvfdec.c b/chromium/third_party/ffmpeg/libavformat/lvfdec.c index f8dda585711..a809c6767bd 100644 --- a/chromium/third_party/ffmpeg/libavformat/lvfdec.c +++ b/chromium/third_party/ffmpeg/libavformat/lvfdec.c @@ -26,7 +26,7 @@ static int lvf_probe(AVProbeData *p) { if (AV_RL32(p->buf) == MKTAG('L', 'V', 'F', 'F')) - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/lxfdec.c b/chromium/third_party/ffmpeg/libavformat/lxfdec.c index 876f988ef55..5c61d4fcb07 100644 --- a/chromium/third_party/ffmpeg/libavformat/lxfdec.c +++ b/chromium/third_party/ffmpeg/libavformat/lxfdec.c @@ -29,7 +29,6 @@ #define LXF_IDENT "LEITCH\0" #define LXF_IDENT_LENGTH 8 #define LXF_SAMPLERATE 48000 -#define LXF_MAX_AUDIO_PACKET (8008*15*4) ///< 15-channel 32-bit NTSC audio frame static const AVCodecTag lxf_tags[] = { { AV_CODEC_ID_MJPEG, 0 }, @@ -309,13 +308,6 @@ static int lxf_read_packet(AVFormatContext *s, AVPacket *pkt) return AVERROR_INVALIDDATA; } - //make sure the data fits in the de-planerization buffer - if (ast && ret > LXF_MAX_AUDIO_PACKET) { - av_log(s, AV_LOG_ERROR, "audio packet too large (%i > %i)\n", - ret, LXF_MAX_AUDIO_PACKET); - return AVERROR_INVALIDDATA; - } - if ((ret2 = av_new_packet(pkt, ret)) < 0) return ret2; diff --git a/chromium/third_party/ffmpeg/libavformat/m4vdec.c b/chromium/third_party/ffmpeg/libavformat/m4vdec.c index e72fb42f1de..c2fd4d7ab6f 100644 --- a/chromium/third_party/ffmpeg/libavformat/m4vdec.c +++ b/chromium/third_party/ffmpeg/libavformat/m4vdec.c @@ -45,7 +45,7 @@ static int mpeg4video_probe(AVProbeData *probe_packet) } if (VOP >= VISO && VOP >= VOL && VO >= VOL && VOL > 0 && res==0) - return VOP+VO > 3 ? AVPROBE_SCORE_MAX/2 : AVPROBE_SCORE_MAX/4; + return VOP+VO > 3 ? AVPROBE_SCORE_EXTENSION : AVPROBE_SCORE_EXTENSION/2; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/matroska.c b/chromium/third_party/ffmpeg/libavformat/matroska.c index ee57c1820a8..953c5721b6c 100644 --- a/chromium/third_party/ffmpeg/libavformat/matroska.c +++ b/chromium/third_party/ffmpeg/libavformat/matroska.c @@ -57,6 +57,11 @@ const CodecTags ff_mkv_codec_tags[]={ {"A_VORBIS" , AV_CODEC_ID_VORBIS}, {"A_WAVPACK4" , AV_CODEC_ID_WAVPACK}, + {"D_WEBVTT/SUBTITLES" , AV_CODEC_ID_WEBVTT}, + {"D_WEBVTT/CAPTIONS" , AV_CODEC_ID_WEBVTT}, + {"D_WEBVTT/DESCRIPTIONS", AV_CODEC_ID_WEBVTT}, + {"D_WEBVTT/METADATA" , AV_CODEC_ID_WEBVTT}, + {"S_TEXT/UTF8" , AV_CODEC_ID_SUBRIP}, {"S_TEXT/UTF8" , AV_CODEC_ID_TEXT}, {"S_TEXT/UTF8" , AV_CODEC_ID_SRT}, diff --git a/chromium/third_party/ffmpeg/libavformat/matroska.h b/chromium/third_party/ffmpeg/libavformat/matroska.h index 8a7e10b64dc..7cf423c5027 100644 --- a/chromium/third_party/ffmpeg/libavformat/matroska.h +++ b/chromium/third_party/ffmpeg/libavformat/matroska.h @@ -91,6 +91,7 @@ #define MATROSKA_ID_CODECINFOURL 0x3B4040 #define MATROSKA_ID_CODECDOWNLOADURL 0x26B240 #define MATROSKA_ID_CODECDECODEALL 0xAA +#define MATROSKA_ID_SEEKPREROLL 0x56BB #define MATROSKA_ID_TRACKNAME 0x536E #define MATROSKA_ID_TRACKLANGUAGE 0x22B59C #define MATROSKA_ID_TRACKFLAGENABLED 0xB9 @@ -156,6 +157,7 @@ /* IDs in the cuetrackposition master */ #define MATROSKA_ID_CUETRACK 0xF7 #define MATROSKA_ID_CUECLUSTERPOSITION 0xF1 +#define MATROSKA_ID_CUERELATIVEPOSITION 0xF0 #define MATROSKA_ID_CUEBLOCKNUMBER 0x5378 /* IDs in the tags master */ @@ -195,6 +197,7 @@ #define MATROSKA_ID_BLOCK 0xA1 #define MATROSKA_ID_BLOCKDURATION 0x9B #define MATROSKA_ID_BLOCKREFERENCE 0xFB +#define MATROSKA_ID_CODECSTATE 0xA4 /* IDs in the attachments master */ #define MATROSKA_ID_ATTACHEDFILE 0x61A7 @@ -229,6 +232,7 @@ typedef enum { MATROSKA_TRACK_TYPE_LOGO = 0x10, MATROSKA_TRACK_TYPE_SUBTITLE = 0x11, MATROSKA_TRACK_TYPE_CONTROL = 0x20, + MATROSKA_TRACK_TYPE_METADATA = 0x21, } MatroskaTrackType; typedef enum { @@ -261,7 +265,7 @@ typedef enum { */ typedef struct CodecTags{ - char str[20]; + char str[22]; enum AVCodecID id; }CodecTags; diff --git a/chromium/third_party/ffmpeg/libavformat/matroskadec.c b/chromium/third_party/ffmpeg/libavformat/matroskadec.c index d17bf611ac6..a90475d47cf 100644 --- a/chromium/third_party/ffmpeg/libavformat/matroskadec.c +++ b/chromium/third_party/ffmpeg/libavformat/matroskadec.c @@ -570,6 +570,7 @@ static EbmlSyntax matroska_blockgroup[] = { { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, offsetof(MatroskaBlock,bin) }, { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, offsetof(MatroskaBlock,duration) }, { MATROSKA_ID_BLOCKREFERENCE, EBML_UINT, 0, offsetof(MatroskaBlock,reference) }, + { MATROSKA_ID_CODECSTATE, EBML_NONE }, { 1, EBML_UINT, 0, offsetof(MatroskaBlock,non_simple), {.u=1} }, { 0 } }; @@ -633,21 +634,20 @@ static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos) matroska->current_id = 0; matroska->num_levels = 0; - // seek to next position to resync from - if (avio_seek(pb, last_pos + 1, SEEK_SET) < 0 || avio_tell(pb) <= last_pos) + /* seek to next position to resync from */ + if (avio_seek(pb, last_pos + 1, SEEK_SET) < 0) goto eof; id = avio_rb32(pb); // try to find a toplevel element while (!url_feof(pb)) { - if (id == MATROSKA_ID_INFO || id == MATROSKA_ID_TRACKS || - id == MATROSKA_ID_CUES || id == MATROSKA_ID_TAGS || + if (id == MATROSKA_ID_INFO || id == MATROSKA_ID_TRACKS || + id == MATROSKA_ID_CUES || id == MATROSKA_ID_TAGS || id == MATROSKA_ID_SEEKHEAD || id == MATROSKA_ID_ATTACHMENTS || - id == MATROSKA_ID_CLUSTER || id == MATROSKA_ID_CHAPTERS) - { - matroska->current_id = id; - return 0; + id == MATROSKA_ID_CLUSTER || id == MATROSKA_ID_CHAPTERS) { + matroska->current_id = id; + return 0; } id = (id << 8) | avio_r8(pb); } @@ -1066,7 +1066,7 @@ static int matroska_probe(AVProbeData *p) } // probably valid EBML header but no recognized doctype - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; } static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, @@ -1572,7 +1572,8 @@ static int matroska_read_header(AVFormatContext *s) /* Apply some sanity checks. */ if (track->type != MATROSKA_TRACK_TYPE_VIDEO && track->type != MATROSKA_TRACK_TYPE_AUDIO && - track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { + track->type != MATROSKA_TRACK_TYPE_SUBTITLE && + track->type != MATROSKA_TRACK_TYPE_METADATA) { av_log(matroska->ctx, AV_LOG_INFO, "Unknown or unsupported track type %"PRIu64"\n", track->type); @@ -1689,18 +1690,6 @@ static int matroska_read_header(AVFormatContext *s) && (track->codec_priv.data != NULL)) { fourcc = AV_RL32(track->codec_priv.data); codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc); - } else if (codec_id == AV_CODEC_ID_ALAC && track->codec_priv.size && track->codec_priv.size < INT_MAX - 12 - FF_INPUT_BUFFER_PADDING_SIZE) { - /* Only ALAC's magic cookie is stored in Matroska's track headers. - Create the "atom size", "tag", and "tag version" fields the - decoder expects manually. */ - extradata_size = 12 + track->codec_priv.size; - extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (extradata == NULL) - return AVERROR(ENOMEM); - AV_WB32(extradata, extradata_size); - memcpy(&extradata[4], "alac", 4); - AV_WB32(&extradata[8], 0); - memcpy(&extradata[12], track->codec_priv.data, track->codec_priv.size); } else if (codec_id == AV_CODEC_ID_PCM_S16BE) { switch (track->audio.bitdepth) { case 8: codec_id = AV_CODEC_ID_PCM_U8; break; @@ -1731,6 +1720,19 @@ static int matroska_read_header(AVFormatContext *s) extradata_size = 5; } else extradata_size = 2; + } else if (codec_id == AV_CODEC_ID_ALAC && track->codec_priv.size && track->codec_priv.size < INT_MAX - 12 - FF_INPUT_BUFFER_PADDING_SIZE) { + /* Only ALAC's magic cookie is stored in Matroska's track headers. + Create the "atom size", "tag", and "tag version" fields the + decoder expects manually. */ + extradata_size = 12 + track->codec_priv.size; + extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (extradata == NULL) + return AVERROR(ENOMEM); + AV_WB32(extradata, extradata_size); + memcpy(&extradata[4], "alac", 4); + AV_WB32(&extradata[8], 0); + memcpy(&extradata[12], track->codec_priv.data, + track->codec_priv.size); } else if (codec_id == AV_CODEC_ID_TTA) { extradata_size = 30; extradata = av_mallocz(extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); @@ -1742,8 +1744,10 @@ static int matroska_read_header(AVFormatContext *s) avio_wl16(&b, 1); avio_wl16(&b, track->audio.channels); avio_wl16(&b, track->audio.bitdepth); + if (track->audio.out_samplerate < 0 || track->audio.out_samplerate > INT_MAX) + return AVERROR_INVALIDDATA; avio_wl32(&b, track->audio.out_samplerate); - avio_wl32(&b, matroska->ctx->duration * track->audio.out_samplerate); + avio_wl32(&b, av_rescale((matroska->duration * matroska->time_scale), track->audio.out_samplerate, AV_TIME_BASE * 1000)); } else if (codec_id == AV_CODEC_ID_RV10 || codec_id == AV_CODEC_ID_RV20 || codec_id == AV_CODEC_ID_RV30 || codec_id == AV_CODEC_ID_RV40) { extradata_offset = 26; @@ -1771,7 +1775,7 @@ static int matroska_read_header(AVFormatContext *s) track->codec_priv.size = 0; } else { if (codec_id == AV_CODEC_ID_SIPR && flavor < 4) { - const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 }; + static const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 }; track->audio.sub_packet_size = ff_sipr_subpk_size[flavor]; st->codec->bit_rate = sipr_bit_rate[flavor]; } @@ -1871,6 +1875,16 @@ static int matroska_read_header(AVFormatContext *s) st->codec->bits_per_coded_sample = track->audio.bitdepth; if (st->codec->codec_id != AV_CODEC_ID_AAC) st->need_parsing = AVSTREAM_PARSE_HEADERS; + } else if (codec_id == AV_CODEC_ID_WEBVTT) { + st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; + + if (!strcmp(track->codec_id, "D_WEBVTT/CAPTIONS")) { + st->disposition |= AV_DISPOSITION_CAPTIONS; + } else if (!strcmp(track->codec_id, "D_WEBVTT/DESCRIPTIONS")) { + st->disposition |= AV_DISPOSITION_DESCRIPTIONS; + } else if (!strcmp(track->codec_id, "D_WEBVTT/METADATA")) { + st->disposition |= AV_DISPOSITION_METADATA; + } } else if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE) { st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; #if FF_API_ASS_SSA @@ -2160,6 +2174,202 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, return 0; } + +/* reconstruct full wavpack blocks from mangled matroska ones */ +static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src, + uint8_t **pdst, int *size) +{ + uint8_t *dst = NULL; + int dstlen = 0; + int srclen = *size; + uint32_t samples; + uint16_t ver; + int ret, offset = 0; + + if (srclen < 12 || track->stream->codec->extradata_size < 2) + return AVERROR_INVALIDDATA; + + ver = AV_RL16(track->stream->codec->extradata); + + samples = AV_RL32(src); + src += 4; + srclen -= 4; + + while (srclen >= 8) { + int multiblock; + uint32_t blocksize; + uint8_t *tmp; + + uint32_t flags = AV_RL32(src); + uint32_t crc = AV_RL32(src + 4); + src += 8; + srclen -= 8; + + multiblock = (flags & 0x1800) != 0x1800; + if (multiblock) { + if (srclen < 4) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + blocksize = AV_RL32(src); + src += 4; + srclen -= 4; + } else + blocksize = srclen; + + if (blocksize > srclen) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + tmp = av_realloc(dst, dstlen + blocksize + 32); + if (!tmp) { + ret = AVERROR(ENOMEM); + goto fail; + } + dst = tmp; + dstlen += blocksize + 32; + + AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag + AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8 + AV_WL16(dst + offset + 8, ver); // version + AV_WL16(dst + offset + 10, 0); // track/index_no + AV_WL32(dst + offset + 12, 0); // total samples + AV_WL32(dst + offset + 16, 0); // block index + AV_WL32(dst + offset + 20, samples); // number of samples + AV_WL32(dst + offset + 24, flags); // flags + AV_WL32(dst + offset + 28, crc); // crc + memcpy (dst + offset + 32, src, blocksize); // block data + + src += blocksize; + srclen -= blocksize; + offset += blocksize + 32; + } + + *pdst = dst; + *size = dstlen; + + return 0; + +fail: + av_freep(&dst); + return ret; +} + +static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, + MatroskaTrack *track, + AVStream *st, + uint8_t *data, int data_len, + uint64_t timecode, + uint64_t duration, + int64_t pos) +{ + AVPacket *pkt; + uint8_t *id, *settings, *text, *buf; + int id_len, settings_len, text_len; + uint8_t *p, *q; + int err; + + if (data_len <= 0) + return AVERROR_INVALIDDATA; + + p = data; + q = data + data_len; + + id = p; + id_len = -1; + while (p < q) { + if (*p == '\r' || *p == '\n') { + id_len = p - id; + if (*p == '\r') + p++; + break; + } + p++; + } + + if (p >= q || *p != '\n') + return AVERROR_INVALIDDATA; + p++; + + settings = p; + settings_len = -1; + while (p < q) { + if (*p == '\r' || *p == '\n') { + settings_len = p - settings; + if (*p == '\r') + p++; + break; + } + p++; + } + + if (p >= q || *p != '\n') + return AVERROR_INVALIDDATA; + p++; + + text = p; + text_len = q - p; + while (text_len > 0) { + const int len = text_len - 1; + const uint8_t c = p[len]; + if (c != '\r' && c != '\n') + break; + text_len = len; + } + + if (text_len <= 0) + return AVERROR_INVALIDDATA; + + pkt = av_mallocz(sizeof(*pkt)); + err = av_new_packet(pkt, text_len); + if (err < 0) { + av_free(pkt); + return AVERROR(err); + } + + memcpy(pkt->data, text, text_len); + + if (id_len > 0) { + buf = av_packet_new_side_data(pkt, + AV_PKT_DATA_WEBVTT_IDENTIFIER, + id_len); + if (buf == NULL) { + av_free(pkt); + return AVERROR(ENOMEM); + } + memcpy(buf, id, id_len); + } + + if (settings_len > 0) { + buf = av_packet_new_side_data(pkt, + AV_PKT_DATA_WEBVTT_SETTINGS, + settings_len); + if (buf == NULL) { + av_free(pkt); + return AVERROR(ENOMEM); + } + memcpy(buf, settings, settings_len); + } + + // Do we need this for subtitles? + // pkt->flags = AV_PKT_FLAG_KEY; + + pkt->stream_index = st->index; + pkt->pts = timecode; + + // Do we need this for subtitles? + // pkt->dts = timecode; + + pkt->duration = duration; + pkt->pos = pos; + + dynarray_add(&matroska->packets, &matroska->num_packets, pkt); + matroska->prev_pkt = pkt; + + return 0; +} + static int matroska_parse_frame(MatroskaDemuxContext *matroska, MatroskaTrack *track, AVStream *st, @@ -2179,6 +2389,18 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, return res; } + if (st->codec->codec_id == AV_CODEC_ID_WAVPACK) { + uint8_t *wv_data; + res = matroska_parse_wavpack(track, pkt_data, &wv_data, &pkt_size); + if (res < 0) { + av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing a wavpack block.\n"); + goto fail; + } + if (pkt_data != data) + av_freep(&pkt_data); + pkt_data = wv_data; + } + if (st->codec->codec_id == AV_CODEC_ID_PRORES) offset = 8; @@ -2186,7 +2408,8 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, /* XXX: prevent data copy... */ if (av_new_packet(pkt, pkt_size + offset) < 0) { av_free(pkt); - return AVERROR(ENOMEM); + res = AVERROR(ENOMEM); + goto fail; } if (st->codec->codec_id == AV_CODEC_ID_PRORES) { @@ -2198,7 +2421,7 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, memcpy(pkt->data + offset, pkt_data, pkt_size); if (pkt_data != data) - av_free(pkt_data); + av_freep(&pkt_data); pkt->flags = is_keyframe; pkt->stream_index = st->index; @@ -2265,6 +2488,10 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska, #endif return 0; +fail: + if (pkt_data != data) + av_freep(&pkt_data); + return res; } static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, @@ -2281,6 +2508,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, uint32_t *lace_size = NULL; int n, flags, laces = 0; uint64_t num; + int trust_default_duration = 1; if ((n = matroska_ebmlnum_uint(matroska, data, size, &num)) < 0) { av_log(matroska->ctx, AV_LOG_ERROR, "EBML block data error\n"); @@ -2301,7 +2529,7 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, return res; av_assert1(block_duration != AV_NOPTS_VALUE); - block_time = AV_RB16(data); + block_time = sign_extend(AV_RB16(data), 16); data += 2; flags = *data++; size -= 3; @@ -2335,7 +2563,15 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, if (res) goto end; - if (!block_duration) + if (track->audio.samplerate == 8000) { + // If this is needed for more codecs, then add them here + if (st->codec->codec_id == AV_CODEC_ID_AC3) { + if(track->audio.samplerate != st->codec->sample_rate || !st->codec->frame_size) + trust_default_duration = 0; + } + } + + if (!block_duration && trust_default_duration) block_duration = track->default_duration * laces / matroska->time_scale; if (cluster_time != (uint64_t)-1 && (block_time >= 0 || cluster_time >= -block_time)) @@ -2366,6 +2602,14 @@ static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, if (res) goto end; + } else if (st->codec->codec_id == AV_CODEC_ID_WEBVTT) { + res = matroska_parse_webvtt(matroska, track, st, + data, lace_size[n], + timecode, lace_duration, + pos); + if (res) + goto end; + } else { res = matroska_parse_frame(matroska, track, st, data, lace_size[n], timecode, lace_duration, @@ -2441,7 +2685,6 @@ static int matroska_parse_cluster_incremental(MatroskaDemuxContext *matroska) } } - if (res < 0) matroska->done = 1; return res; } @@ -2530,10 +2773,11 @@ static int matroska_read_seek(AVFormatContext *s, int stream_index, if (tracks[i].type == MATROSKA_TRACK_TYPE_SUBTITLE && tracks[i].stream->discard != AVDISCARD_ALL) { index_sub = av_index_search_timestamp(tracks[i].stream, st->index_entries[index].timestamp, AVSEEK_FLAG_BACKWARD); - if (index_sub >= 0 - && st->index_entries[index_sub].pos < st->index_entries[index_min].pos - && st->index_entries[index].timestamp - st->index_entries[index_sub].timestamp < 30000000000/matroska->time_scale) - index_min = index_sub; + while(index_sub >= 0 + && index_min >= 0 + && tracks[i].stream->index_entries[index_sub].pos < st->index_entries[index_min].pos + && st->index_entries[index].timestamp - tracks[i].stream->index_entries[index_sub].timestamp < 30000000000/matroska->time_scale) + index_min--; } } diff --git a/chromium/third_party/ffmpeg/libavformat/matroskaenc.c b/chromium/third_party/ffmpeg/libavformat/matroskaenc.c index 6726fd98124..92df6cbef1c 100644 --- a/chromium/third_party/ffmpeg/libavformat/matroskaenc.c +++ b/chromium/third_party/ffmpeg/libavformat/matroskaenc.c @@ -19,23 +19,28 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "avc.h" #include "avformat.h" +#include "avio_internal.h" +#include "avlanguage.h" +#include "flacenc.h" #include "internal.h" -#include "riff.h" #include "isom.h" #include "matroska.h" -#include "avc.h" -#include "flacenc.h" -#include "avlanguage.h" -#include "libavutil/samplefmt.h" -#include "libavutil/sha.h" -#include "libavutil/intreadwrite.h" +#include "riff.h" +#include "wv.h" + +#include "libavutil/avstring.h" +#include "libavutil/dict.h" #include "libavutil/intfloat.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/lfg.h" #include "libavutil/mathematics.h" +#include "libavutil/opt.h" #include "libavutil/random_seed.h" -#include "libavutil/lfg.h" -#include "libavutil/dict.h" -#include "libavutil/avstring.h" +#include "libavutil/samplefmt.h" +#include "libavutil/sha.h" + #include "libavcodec/xiph.h" #include "libavcodec/mpeg4audio.h" @@ -62,6 +67,7 @@ typedef struct { uint64_t pts; int tracknum; int64_t cluster_pos; ///< file offset of the cluster containing the block + int64_t relative_pos; ///< relative offset from the position of the cluster containing the block } mkv_cuepoint; typedef struct { @@ -79,6 +85,7 @@ typedef struct { #define MODE_WEBM 0x02 typedef struct MatroskaMuxContext { + const AVClass *class; int mode; AVIOContext *dyn_bc; ebml_master segment; @@ -95,6 +102,13 @@ typedef struct MatroskaMuxContext { AVPacket cur_audio_pkt; int have_attachments; + + int reserve_cues_space; + int cluster_size_limit; + int64_t cues_pos; + int64_t cluster_time_limit; + + uint32_t chapter_id_offset; } MatroskaMuxContext; @@ -102,13 +116,16 @@ typedef struct MatroskaMuxContext { * offset, 4 bytes for target EBML ID */ #define MAX_SEEKENTRY_SIZE 21 -/** per-cuepoint-track - 3 1-byte EBML IDs, 3 1-byte EBML sizes, 2 +/** per-cuepoint-track - 4 1-byte EBML IDs, 4 1-byte EBML sizes, 3 * 8-byte uint max */ -#define MAX_CUETRACKPOS_SIZE 22 +#define MAX_CUETRACKPOS_SIZE 32 /** per-cuepoint - 2 1-byte EBML IDs, 2 1-byte EBML sizes, 8-byte uint max */ #define MAX_CUEPOINT_SIZE(num_tracks) 12 + MAX_CUETRACKPOS_SIZE*num_tracks +/** Seek preroll value for opus */ +#define OPUS_SEEK_PREROLL 80000000 + static int ebml_id_size(unsigned int id) { @@ -131,8 +148,7 @@ static void put_ebml_size_unknown(AVIOContext *pb, int bytes) { av_assert0(bytes <= 8); avio_w8(pb, 0x1ff >> bytes); - while (--bytes) - avio_w8(pb, 0xff); + ffio_fill(pb, 0xff, bytes - 1); } /** @@ -222,8 +238,7 @@ static void put_ebml_void(AVIOContext *pb, uint64_t size) put_ebml_num(pb, size-1, 0); else put_ebml_num(pb, size-9, 8); - while(avio_tell(pb) < currentpos + size) - avio_w8(pb, 0); + ffio_fill(pb, 0, currentpos + size - avio_tell(pb)); } static ebml_master start_ebml_master(AVIOContext *pb, unsigned int elementid, uint64_t expectedsize) @@ -246,9 +261,7 @@ static void end_ebml_master(AVIOContext *pb, ebml_master master) static void put_xiph_size(AVIOContext *pb, int size) { - int i; - for (i = 0; i < size / 255; i++) - avio_w8(pb, 255); + ffio_fill(pb, 255, size / 255); avio_w8(pb, size % 255); } @@ -365,7 +378,7 @@ static mkv_cues * mkv_start_cues(int64_t segment_offset) return cues; } -static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t cluster_pos) +static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t cluster_pos, int64_t relative_pos) { mkv_cuepoint *entries = cues->entries; @@ -378,7 +391,8 @@ static int mkv_add_cuepoint(mkv_cues *cues, int stream, int64_t ts, int64_t clus entries[cues->num_entries ].pts = ts; entries[cues->num_entries ].tracknum = stream + 1; - entries[cues->num_entries++].cluster_pos = cluster_pos - cues->segment_offset; + entries[cues->num_entries ].cluster_pos = cluster_pos - cues->segment_offset; + entries[cues->num_entries++].relative_pos = relative_pos; cues->entries = entries; return 0; @@ -412,8 +426,9 @@ static int64_t mkv_write_cues(AVIOContext *pb, mkv_cues *cues, mkv_track *tracks continue; tracks[tracknum].has_cue = 1; track_positions = start_ebml_master(pb, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); - put_ebml_uint(pb, MATROSKA_ID_CUETRACK , entry[j].tracknum ); - put_ebml_uint(pb, MATROSKA_ID_CUECLUSTERPOSITION, entry[j].cluster_pos); + put_ebml_uint(pb, MATROSKA_ID_CUETRACK , entry[j].tracknum ); + put_ebml_uint(pb, MATROSKA_ID_CUECLUSTERPOSITION , entry[j].cluster_pos); + put_ebml_uint(pb, MATROSKA_ID_CUERELATIVEPOSITION, entry[j].relative_pos); end_ebml_master(pb, track_positions); } i += j - 1; @@ -452,6 +467,15 @@ static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, AVCodecContex return 0; } +static int put_wv_codecpriv(AVIOContext *pb, AVCodecContext *codec) +{ + if (codec->extradata && codec->extradata_size == 2) + avio_write(pb, codec->extradata, 2); + else + avio_wl16(pb, 0x403); // fallback to the version mentioned in matroska specs + return 0; +} + static void get_aac_sample_rates(AVFormatContext *s, AVCodecContext *codec, int *sample_rate, int *output_sample_rate) { MPEG4AudioConfig mp4ac; @@ -481,6 +505,8 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, AVCodecCo ret = put_xiph_codecpriv(s, dyn_cp, codec); else if (codec->codec_id == AV_CODEC_ID_FLAC) ret = ff_flac_write_header(dyn_cp, codec, 1); + else if (codec->codec_id == AV_CODEC_ID_WAVPACK) + ret = put_wv_codecpriv(dyn_cp, codec); else if (codec->codec_id == AV_CODEC_ID_H264) ret = ff_isom_write_avcc(dyn_cp, codec->extradata, codec->extradata_size); else if (codec->codec_id == AV_CODEC_ID_ALAC) { @@ -581,7 +607,11 @@ static int mkv_write_tracks(AVFormatContext *s) if ((tag = av_dict_get(st->metadata, "title", NULL, 0))) put_ebml_string(pb, MATROSKA_ID_TRACKNAME, tag->value); tag = av_dict_get(st->metadata, "language", NULL, 0); - put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag ? tag->value:"und"); + if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) { + put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag ? tag->value:"und"); + } else if (tag && tag->value) { + put_ebml_string(pb, MATROSKA_ID_TRACKLANGUAGE, tag->value); + } if (default_stream_exists) { put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGDEFAULT, !!(st->disposition & AV_DISPOSITION_DEFAULT)); @@ -589,20 +619,45 @@ static int mkv_write_tracks(AVFormatContext *s) if (st->disposition & AV_DISPOSITION_FORCED) put_ebml_uint(pb, MATROSKA_ID_TRACKFLAGFORCED, 1); - // look for a codec ID string specific to mkv to use, - // if none are found, use AVI codes - for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { - if (ff_mkv_codec_tags[j].id == codec->codec_id) { - put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str); - native_id = 1; - break; + if (mkv->mode == MODE_WEBM && codec->codec_id == AV_CODEC_ID_WEBVTT) { + const char *codec_id; + if (st->disposition & AV_DISPOSITION_CAPTIONS) { + codec_id = "D_WEBVTT/CAPTIONS"; + native_id = MATROSKA_TRACK_TYPE_SUBTITLE; + } else if (st->disposition & AV_DISPOSITION_DESCRIPTIONS) { + codec_id = "D_WEBVTT/DESCRIPTIONS"; + native_id = MATROSKA_TRACK_TYPE_METADATA; + } else if (st->disposition & AV_DISPOSITION_METADATA) { + codec_id = "D_WEBVTT/METADATA"; + native_id = MATROSKA_TRACK_TYPE_METADATA; + } else { + codec_id = "D_WEBVTT/SUBTITLES"; + native_id = MATROSKA_TRACK_TYPE_SUBTITLE; } + put_ebml_string(pb, MATROSKA_ID_CODECID, codec_id); + } else { + // look for a codec ID string specific to mkv to use, + // if none are found, use AVI codes + for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { + if (ff_mkv_codec_tags[j].id == codec->codec_id) { + put_ebml_string(pb, MATROSKA_ID_CODECID, ff_mkv_codec_tags[j].str); + native_id = 1; + break; + } + } + } + + if (codec->codec_id == AV_CODEC_ID_OPUS) { + put_ebml_uint(pb, MATROSKA_ID_SEEKPREROLL, OPUS_SEEK_PREROLL); } if (mkv->mode == MODE_WEBM && !(codec->codec_id == AV_CODEC_ID_VP8 || - codec->codec_id == AV_CODEC_ID_VORBIS)) { + codec->codec_id == AV_CODEC_ID_VP9 || + ((codec->codec_id == AV_CODEC_ID_OPUS)&&(codec->strict_std_compliance <= FF_COMPLIANCE_EXPERIMENTAL)) || + codec->codec_id == AV_CODEC_ID_VORBIS || + codec->codec_id == AV_CODEC_ID_WEBVTT)) { av_log(s, AV_LOG_ERROR, - "Only VP8 video and Vorbis audio are supported for WebM.\n"); + "Only VP8,VP9 video and Vorbis,Opus(experimental, use -strict -2) audio and WebVTT subtitles are supported for WebM.\n"); return AVERROR(EINVAL); } @@ -655,6 +710,12 @@ static int mkv_write_tracks(AVFormatContext *s) put_ebml_uint(pb, MATROSKA_ID_VIDEOSTEREOMODE, st_mode); } + if ((tag = av_dict_get(st->metadata, "alpha_mode", NULL, 0)) || + (tag = av_dict_get( s->metadata, "alpha_mode", NULL, 0)) || + (codec->pix_fmt == AV_PIX_FMT_YUVA420P)) { + put_ebml_uint(pb, MATROSKA_ID_VIDEOALPHAMODE, 1); + } + if (st->sample_aspect_ratio.num) { int64_t d_width = av_rescale(codec->width, st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); if (d_width > INT_MAX) { @@ -690,18 +751,25 @@ static int mkv_write_tracks(AVFormatContext *s) break; case AVMEDIA_TYPE_SUBTITLE: - put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, MATROSKA_TRACK_TYPE_SUBTITLE); if (!native_id) { av_log(s, AV_LOG_ERROR, "Subtitle codec %d is not supported.\n", codec->codec_id); return AVERROR(ENOSYS); } + + if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) + native_id = MATROSKA_TRACK_TYPE_SUBTITLE; + + put_ebml_uint(pb, MATROSKA_ID_TRACKTYPE, native_id); break; default: av_log(s, AV_LOG_ERROR, "Only audio, video, and subtitles are supported for Matroska.\n"); - break; + return AVERROR(EINVAL); + } + + if (mkv->mode != MODE_WEBM || codec->codec_id != AV_CODEC_ID_WEBVTT) { + ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id); + if (ret < 0) return ret; } - ret = mkv_write_codecprivate(s, pb, codec, native_id, qt_id); - if (ret < 0) return ret; end_ebml_master(pb, track); @@ -736,7 +804,7 @@ static int mkv_write_chapters(AVFormatContext *s) AVDictionaryEntry *t = NULL; chapteratom = start_ebml_master(pb, MATROSKA_ID_CHAPTERATOM, 0); - put_ebml_uint(pb, MATROSKA_ID_CHAPTERUID, c->id); + put_ebml_uint(pb, MATROSKA_ID_CHAPTERUID, c->id + mkv->chapter_id_offset); put_ebml_uint(pb, MATROSKA_ID_CHAPTERTIMESTART, av_rescale_q(c->start, c->time_base, scale)); put_ebml_uint(pb, MATROSKA_ID_CHAPTERTIMEEND, @@ -815,14 +883,26 @@ static int mkv_write_tag(AVFormatContext *s, AVDictionary *m, unsigned int eleme return 0; } +static int mkv_check_tag(AVDictionary *m) +{ + AVDictionaryEntry *t = NULL; + + while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) + if (av_strcasecmp(t->key, "title") && av_strcasecmp(t->key, "stereo_mode")) + return 1; + + return 0; +} + static int mkv_write_tags(AVFormatContext *s) { + MatroskaMuxContext *mkv = s->priv_data; ebml_master tags = {0}; int i, ret; ff_metadata_conv_ctx(s, ff_mkv_metadata_conv, NULL); - if (av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) { + if (mkv_check_tag(s->metadata)) { ret = mkv_write_tag(s, s->metadata, 0, 0, &tags); if (ret < 0) return ret; } @@ -830,7 +910,7 @@ static int mkv_write_tags(AVFormatContext *s) for (i = 0; i < s->nb_streams; i++) { AVStream *st = s->streams[i]; - if (!av_dict_get(st->metadata, "", 0, AV_DICT_IGNORE_SUFFIX)) + if (!mkv_check_tag(st->metadata)) continue; ret = mkv_write_tag(s, st->metadata, MATROSKA_ID_TAGTARGETS_TRACKUID, i + 1, &tags); @@ -840,10 +920,10 @@ static int mkv_write_tags(AVFormatContext *s) for (i = 0; i < s->nb_chapters; i++) { AVChapter *ch = s->chapters[i]; - if (!av_dict_get(ch->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) + if (!mkv_check_tag(ch->metadata)) continue; - ret = mkv_write_tag(s, ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID, ch->id, &tags); + ret = mkv_write_tag(s, ch->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID, ch->id + mkv->chapter_id_offset, &tags); if (ret < 0) return ret; } @@ -1022,6 +1102,9 @@ static int mkv_write_header(AVFormatContext *s) ret = mkv_write_tracks(s); if (ret < 0) return ret; + for (i = 0; i < s->nb_chapters; i++) + mkv->chapter_id_offset = FFMAX(mkv->chapter_id_offset, 1LL - s->chapters[i]->id); + if (mkv->mode != MODE_WEBM) { ret = mkv_write_chapters(s); if (ret < 0) return ret; @@ -1040,11 +1123,31 @@ static int mkv_write_header(AVFormatContext *s) if (mkv->cues == NULL) return AVERROR(ENOMEM); + if (pb->seekable && mkv->reserve_cues_space) { + mkv->cues_pos = avio_tell(pb); + put_ebml_void(pb, mkv->reserve_cues_space); + } + av_init_packet(&mkv->cur_audio_pkt); mkv->cur_audio_pkt.size = 0; mkv->cluster_pos = -1; avio_flush(pb); + + // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or + // after 4k and on a keyframe + if (pb->seekable) { + if (mkv->cluster_time_limit < 0) + mkv->cluster_time_limit = 5000; + if (mkv->cluster_size_limit < 0) + mkv->cluster_size_limit = 5 * 1024 * 1024; + } else { + if (mkv->cluster_time_limit < 0) + mkv->cluster_time_limit = 1000; + if (mkv->cluster_size_limit < 0) + mkv->cluster_size_limit = 32 * 1024; + } + return 0; } @@ -1119,14 +1222,69 @@ static int mkv_write_ass_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *p } #endif +static int mkv_strip_wavpack(const uint8_t *src, uint8_t **pdst, int *size) +{ + uint8_t *dst; + int srclen = *size; + int offset = 0; + int ret; + + dst = av_malloc(srclen); + if (!dst) + return AVERROR(ENOMEM); + + while (srclen >= WV_HEADER_SIZE) { + WvHeader header; + + ret = ff_wv_parse_header(&header, src); + if (ret < 0) + goto fail; + src += WV_HEADER_SIZE; + srclen -= WV_HEADER_SIZE; + + if (srclen < header.blocksize) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + if (header.initial) { + AV_WL32(dst + offset, header.samples); + offset += 4; + } + AV_WL32(dst + offset, header.flags); + AV_WL32(dst + offset + 4, header.crc); + offset += 8; + + if (!(header.initial && header.final)) { + AV_WL32(dst + offset, header.blocksize); + offset += 4; + } + + memcpy(dst + offset, src, header.blocksize); + src += header.blocksize; + srclen -= header.blocksize; + offset += header.blocksize; + } + + *pdst = dst; + *size = offset; + + return 0; +fail: + av_freep(&dst); + return ret; +} + static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, unsigned int blockid, AVPacket *pkt, int flags) { MatroskaMuxContext *mkv = s->priv_data; AVCodecContext *codec = s->streams[pkt->stream_index]->codec; - uint8_t *data = NULL; - int offset = 0, size = pkt->size; + uint8_t *data = NULL, *side_data = NULL; + int offset = 0, size = pkt->size, side_data_size = 0; int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; + uint64_t additional_id = 0; + ebml_master block_group, block_additions, block_more; av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n", @@ -1134,7 +1292,13 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, if (codec->codec_id == AV_CODEC_ID_H264 && codec->extradata_size > 0 && (AV_RB24(codec->extradata) == 1 || AV_RB32(codec->extradata) == 1)) ff_avc_parse_nal_units_buf(pkt->data, &data, &size); - else + else if (codec->codec_id == AV_CODEC_ID_WAVPACK) { + int ret = mkv_strip_wavpack(pkt->data, &data, &size); + if (ret < 0) { + av_log(s, AV_LOG_ERROR, "Error stripping a WavPack packet.\n"); + return; + } + } else data = pkt->data; if (codec->codec_id == AV_CODEC_ID_PRORES) { @@ -1144,6 +1308,20 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, offset = 8; } + side_data = av_packet_get_side_data(pkt, + AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, + &side_data_size); + if (side_data) { + additional_id = AV_RB64(side_data); + side_data += 8; + side_data_size -= 8; + } + + if (side_data_size && additional_id == 1) { + block_group = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, 0); + blockid = MATROSKA_ID_BLOCK; + } + put_ebml_id(pb, blockid); put_ebml_num(pb, size+4, 0); avio_w8(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 @@ -1152,6 +1330,18 @@ static void mkv_write_block(AVFormatContext *s, AVIOContext *pb, avio_write(pb, data + offset, size); if (data != pkt->data) av_free(data); + + if (side_data_size && additional_id == 1) { + block_additions = start_ebml_master(pb, MATROSKA_ID_BLOCKADDITIONS, 0); + block_more = start_ebml_master(pb, MATROSKA_ID_BLOCKMORE, 0); + put_ebml_uint(pb, MATROSKA_ID_BLOCKADDID, 1); + put_ebml_id(pb, MATROSKA_ID_BLOCKADDITIONAL); + put_ebml_num(pb, side_data_size, 0); + avio_write(pb, side_data, side_data_size); + end_ebml_master(pb, block_more); + end_ebml_master(pb, block_additions); + end_ebml_master(pb, block_group); + } } static int srt_get_duration(uint8_t **buf) @@ -1189,6 +1379,44 @@ static int mkv_write_srt_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *p return duration; } +static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, AVPacket *pkt) +{ + MatroskaMuxContext *mkv = s->priv_data; + ebml_master blockgroup; + int id_size, settings_size, size; + uint8_t *id, *settings; + int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; + const int flags = 0; + + id_size = 0; + id = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_IDENTIFIER, + &id_size); + + settings_size = 0; + settings = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_SETTINGS, + &settings_size); + + size = id_size + 1 + settings_size + 1 + pkt->size; + + av_log(s, AV_LOG_DEBUG, "Writing block at offset %" PRIu64 ", size %d, " + "pts %" PRId64 ", dts %" PRId64 ", duration %d, flags %d\n", + avio_tell(pb), size, pkt->pts, pkt->dts, pkt->duration, flags); + + blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(size)); + + put_ebml_id(pb, MATROSKA_ID_BLOCK); + put_ebml_num(pb, size+4, 0); + avio_w8(pb, 0x80 | (pkt->stream_index + 1)); // this assumes stream_index is less than 126 + avio_wb16(pb, ts - mkv->cluster_pts); + avio_w8(pb, flags); + avio_printf(pb, "%.*s\n%.*s\n%.*s", id_size, id, settings_size, settings, pkt->size, pkt->data); + + put_ebml_uint(pb, MATROSKA_ID_BLOCKDURATION, pkt->duration); + end_ebml_master(pb, blockgroup); + + return pkt->duration; +} + static void mkv_flush_dynbuf(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; @@ -1213,6 +1441,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) int duration = pkt->duration; int ret; int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; + int64_t relative_packet_pos; if (ts == AV_NOPTS_VALUE) { av_log(s, AV_LOG_ERROR, "Can't write packet with unknown timestamp\n"); @@ -1236,6 +1465,8 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) mkv->cluster_pts = FFMAX(0, ts); } + relative_packet_pos = avio_tell(s->pb) - mkv->cluster.pos; + if (codec->codec_type != AVMEDIA_TYPE_SUBTITLE) { mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe << 7); #if FF_API_ASS_SSA @@ -1244,6 +1475,8 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) #endif } else if (codec->codec_id == AV_CODEC_ID_SRT) { duration = mkv_write_srt_blocks(s, pb, pkt); + } else if (codec->codec_id == AV_CODEC_ID_WEBVTT) { + duration = mkv_write_vtt_blocks(s, pb, pkt); } else { ebml_master blockgroup = start_ebml_master(pb, MATROSKA_ID_BLOCKGROUP, mkv_blockgroup_size(pkt->size)); /* For backward compatibility, prefer convergence_duration. */ @@ -1256,7 +1489,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) } if (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe) { - ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos); + ret = mkv_add_cuepoint(mkv->cues, pkt->stream_index, ts, mkv->cluster_pos, relative_packet_pos); if (ret < 0) return ret; } @@ -1267,24 +1500,41 @@ static int mkv_write_packet_internal(AVFormatContext *s, AVPacket *pkt) static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) { MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *pb = s->pb->seekable ? s->pb : mkv->dyn_bc; - AVCodecContext *codec = s->streams[pkt->stream_index]->codec; - int ret, keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY); - int64_t ts = mkv->tracks[pkt->stream_index].write_dts ? pkt->dts : pkt->pts; - int cluster_size = avio_tell(pb) - (s->pb->seekable ? mkv->cluster_pos : 0); + int codec_type = s->streams[pkt->stream_index]->codec->codec_type; + int keyframe = !!(pkt->flags & AV_PKT_FLAG_KEY); + int cluster_size; + int64_t cluster_time; + AVIOContext *pb; + int ret; + + if (mkv->tracks[pkt->stream_index].write_dts) + cluster_time = pkt->dts - mkv->cluster_pts; + else + cluster_time = pkt->pts - mkv->cluster_pts; // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or // after 4k and on a keyframe + if (s->pb->seekable) { + pb = s->pb; + cluster_size = avio_tell(pb) - mkv->cluster_pos; + } else { + pb = mkv->dyn_bc; + cluster_size = avio_tell(pb); + } + if (mkv->cluster_pos != -1 && - ((!s->pb->seekable && (cluster_size > 32*1024 || ts > mkv->cluster_pts + 1000)) - || cluster_size > 5*1024*1024 || ts > mkv->cluster_pts + 5000 - || (codec->codec_type == AVMEDIA_TYPE_VIDEO && keyframe && cluster_size > 4*1024))) { + (cluster_size > mkv->cluster_size_limit || + cluster_time > mkv->cluster_time_limit || + (codec_type == AVMEDIA_TYPE_VIDEO && keyframe && + cluster_size > 4 * 1024))) { av_log(s, AV_LOG_DEBUG, "Starting new cluster at offset %" PRIu64 - " bytes, pts %" PRIu64 "\n", avio_tell(pb), ts); + " bytes, pts %" PRIu64 "dts %" PRIu64 "\n", + avio_tell(pb), pkt->pts, pkt->dts); end_ebml_master(pb, mkv->cluster); mkv->cluster_pos = -1; if (mkv->dyn_bc) mkv_flush_dynbuf(s); + avio_flush(s->pb); } // check if we have an audio packet cached @@ -1299,15 +1549,41 @@ static int mkv_write_packet(AVFormatContext *s, AVPacket *pkt) // buffer an audio packet to ensure the packet containing the video // keyframe's timecode is contained in the same cluster for WebM - if (codec->codec_type == AVMEDIA_TYPE_AUDIO) { + if (codec_type == AVMEDIA_TYPE_AUDIO) { mkv->cur_audio_pkt = *pkt; - mkv->cur_audio_pkt.buf = av_buffer_ref(pkt->buf); - ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM); + if (pkt->buf) { + mkv->cur_audio_pkt.buf = av_buffer_ref(pkt->buf); + ret = mkv->cur_audio_pkt.buf ? 0 : AVERROR(ENOMEM); + } else + ret = av_dup_packet(&mkv->cur_audio_pkt); } else ret = mkv_write_packet_internal(s, pkt); return ret; } +static int mkv_write_flush_packet(AVFormatContext *s, AVPacket *pkt) +{ + MatroskaMuxContext *mkv = s->priv_data; + AVIOContext *pb; + if (s->pb->seekable) + pb = s->pb; + else + pb = mkv->dyn_bc; + if (!pkt) { + if (mkv->cluster_pos != -1) { + av_log(s, AV_LOG_DEBUG, "Flushing cluster at offset %" PRIu64 + " bytes\n", avio_tell(pb)); + end_ebml_master(pb, mkv->cluster); + mkv->cluster_pos = -1; + if (mkv->dyn_bc) + mkv_flush_dynbuf(s); + avio_flush(s->pb); + } + return 0; + } + return mkv_write_packet(s, pkt); +} + static int mkv_write_trailer(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; @@ -1334,7 +1610,28 @@ static int mkv_write_trailer(AVFormatContext *s) if (pb->seekable) { if (mkv->cues->num_entries) { - cuespos = mkv_write_cues(pb, mkv->cues, mkv->tracks, s->nb_streams); + if (mkv->reserve_cues_space) { + int64_t cues_end; + + currentpos = avio_tell(pb); + avio_seek(pb, mkv->cues_pos, SEEK_SET); + + cuespos = mkv_write_cues(pb, mkv->cues, mkv->tracks, s->nb_streams); + cues_end = avio_tell(pb); + if (cues_end > cuespos + mkv->reserve_cues_space) { + av_log(s, AV_LOG_ERROR, "Insufficient space reserved for cues: %d " + "(needed: %"PRId64").\n", mkv->reserve_cues_space, + cues_end - cuespos); + return AVERROR(EINVAL); + } + + if (cues_end < cuespos + mkv->reserve_cues_space) + put_ebml_void(pb, mkv->reserve_cues_space - (cues_end - cuespos)); + + avio_seek(pb, currentpos, SEEK_SET); + } else { + cuespos = mkv_write_cues(pb, mkv->cues, mkv->tracks, s->nb_streams); + } ret = mkv_add_seekhead_entry(mkv->main_seekhead, MATROSKA_ID_CUES, cuespos); if (ret < 0) return ret; @@ -1375,7 +1672,7 @@ static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance) return 0; } -const AVCodecTag additional_audio_tags[] = { +static const AVCodecTag additional_audio_tags[] = { { AV_CODEC_ID_ALAC, 0XFFFFFFFF }, { AV_CODEC_ID_EAC3, 0XFFFFFFFF }, { AV_CODEC_ID_MLP, 0xFFFFFFFF }, @@ -1388,11 +1685,10 @@ const AVCodecTag additional_audio_tags[] = { { AV_CODEC_ID_RA_288, 0xFFFFFFFF }, { AV_CODEC_ID_COOK, 0xFFFFFFFF }, { AV_CODEC_ID_TRUEHD, 0xFFFFFFFF }, - { AV_CODEC_ID_WAVPACK, 0xFFFFFFFF }, { AV_CODEC_ID_NONE, 0xFFFFFFFF } }; -const AVCodecTag additional_video_tags[] = { +static const AVCodecTag additional_video_tags[] = { { AV_CODEC_ID_PRORES, 0xFFFFFFFF }, { AV_CODEC_ID_RV10, 0xFFFFFFFF }, { AV_CODEC_ID_RV20, 0xFFFFFFFF }, @@ -1402,7 +1698,23 @@ const AVCodecTag additional_video_tags[] = { { AV_CODEC_ID_NONE, 0xFFFFFFFF } }; +#define OFFSET(x) offsetof(MatroskaMuxContext, x) +#define FLAGS AV_OPT_FLAG_ENCODING_PARAM +static const AVOption options[] = { + { "reserve_index_space", "Reserve a given amount of space (in bytes) at the beginning of the file for the index (cues).", OFFSET(reserve_cues_space), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS }, + { "cluster_size_limit", "Store at most the provided amount of bytes in a cluster. ", OFFSET(cluster_size_limit), AV_OPT_TYPE_INT , { .i64 = -1 }, -1, INT_MAX, FLAGS }, + { "cluster_time_limit", "Store at most the provided number of milliseconds in a cluster.", OFFSET(cluster_time_limit), AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, FLAGS }, + { NULL }, +}; + #if CONFIG_MATROSKA_MUXER +static const AVClass matroska_class = { + .class_name = "matroska muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVOutputFormat ff_matroska_muxer = { .name = "matroska", .long_name = NULL_IF_CONFIG_SMALL("Matroska"), @@ -1414,10 +1726,10 @@ AVOutputFormat ff_matroska_muxer = { .video_codec = CONFIG_LIBX264_ENCODER ? AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4, .write_header = mkv_write_header, - .write_packet = mkv_write_packet, + .write_packet = mkv_write_flush_packet, .write_trailer = mkv_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | - AVFMT_TS_NONSTRICT, + AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH, .codec_tag = (const AVCodecTag* const []){ ff_codec_bmp_tags, ff_codec_wav_tags, additional_audio_tags, additional_video_tags, 0 @@ -1428,10 +1740,18 @@ AVOutputFormat ff_matroska_muxer = { .subtitle_codec = AV_CODEC_ID_ASS, #endif .query_codec = mkv_query_codec, + .priv_class = &matroska_class, }; #endif #if CONFIG_WEBM_MUXER +static const AVClass webm_class = { + .class_name = "webm muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVOutputFormat ff_webm_muxer = { .name = "webm", .long_name = NULL_IF_CONFIG_SMALL("WebM"), @@ -1440,18 +1760,26 @@ AVOutputFormat ff_webm_muxer = { .priv_data_size = sizeof(MatroskaMuxContext), .audio_codec = AV_CODEC_ID_VORBIS, .video_codec = AV_CODEC_ID_VP8, + .subtitle_codec = AV_CODEC_ID_WEBVTT, .write_header = mkv_write_header, - .write_packet = mkv_write_packet, + .write_packet = mkv_write_flush_packet, .write_trailer = mkv_write_trailer, .flags = AVFMT_GLOBALHEADER | AVFMT_VARIABLE_FPS | - AVFMT_TS_NONSTRICT, + AVFMT_TS_NONSTRICT | AVFMT_ALLOW_FLUSH, + .priv_class = &webm_class, }; #endif #if CONFIG_MATROSKA_AUDIO_MUXER +static const AVClass mka_class = { + .class_name = "matroska audio muxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; AVOutputFormat ff_matroska_audio_muxer = { .name = "matroska", - .long_name = NULL_IF_CONFIG_SMALL("Matroska"), + .long_name = NULL_IF_CONFIG_SMALL("Matroska Audio"), .mime_type = "audio/x-matroska", .extensions = "mka", .priv_data_size = sizeof(MatroskaMuxContext), @@ -1459,11 +1787,13 @@ AVOutputFormat ff_matroska_audio_muxer = { AV_CODEC_ID_VORBIS : AV_CODEC_ID_AC3, .video_codec = AV_CODEC_ID_NONE, .write_header = mkv_write_header, - .write_packet = mkv_write_packet, + .write_packet = mkv_write_flush_packet, .write_trailer = mkv_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT, + .flags = AVFMT_GLOBALHEADER | AVFMT_TS_NONSTRICT | + AVFMT_ALLOW_FLUSH, .codec_tag = (const AVCodecTag* const []){ ff_codec_wav_tags, additional_audio_tags, 0 }, + .priv_class = &mka_class, }; #endif diff --git a/chromium/third_party/ffmpeg/libavformat/md5enc.c b/chromium/third_party/ffmpeg/libavformat/md5enc.c index 050efb1513a..270d9fb660f 100644 --- a/chromium/third_party/ffmpeg/libavformat/md5enc.c +++ b/chromium/third_party/ffmpeg/libavformat/md5enc.c @@ -19,21 +19,28 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/md5.h" +#include "libavutil/avassert.h" +#include "libavutil/avstring.h" +#include "libavutil/hash.h" +#include "libavutil/opt.h" #include "avformat.h" #include "internal.h" struct MD5Context { - struct AVMD5 *md5; + const AVClass *avclass; + struct AVHashContext *hash; + char *hash_name; }; static void md5_finish(struct AVFormatContext *s, char *buf) { struct MD5Context *c = s->priv_data; - uint8_t md5[16]; + uint8_t md5[AV_HASH_MAX_SIZE]; int i, offset = strlen(buf); - av_md5_final(c->md5, md5); - for (i = 0; i < sizeof(md5); i++) { + int len = av_hash_get_size(c->hash); + av_assert0(len > 0 && len <= sizeof(md5)); + av_hash_final(c->hash, md5); + for (i = 0; i < len; i++) { snprintf(buf + offset, 3, "%02"PRIx8, md5[i]); offset += 2; } @@ -44,32 +51,48 @@ static void md5_finish(struct AVFormatContext *s, char *buf) avio_flush(s->pb); } +#define OFFSET(x) offsetof(struct MD5Context, x) +#define ENC AV_OPT_FLAG_ENCODING_PARAM +static const AVOption hash_options[] = { + { "hash", "set hash to use", OFFSET(hash_name), AV_OPT_TYPE_STRING, {.str = "md5"}, 0, 0, ENC }, + { NULL }, +}; + +static const AVClass md5enc_class = { + .class_name = "hash encoder class", + .item_name = av_default_item_name, + .option = hash_options, + .version = LIBAVUTIL_VERSION_INT, +}; + #if CONFIG_MD5_MUXER static int write_header(struct AVFormatContext *s) { struct MD5Context *c = s->priv_data; - c->md5 = av_md5_alloc(); - if (!c->md5) - return AVERROR(ENOMEM); - av_md5_init(c->md5); + int res = av_hash_alloc(&c->hash, c->hash_name); + if (res < 0) + return res; + av_hash_init(c->hash); return 0; } static int write_packet(struct AVFormatContext *s, AVPacket *pkt) { struct MD5Context *c = s->priv_data; - av_md5_update(c->md5, pkt->data, pkt->size); + av_hash_update(c->hash, pkt->data, pkt->size); return 0; } static int write_trailer(struct AVFormatContext *s) { struct MD5Context *c = s->priv_data; - char buf[64] = "MD5="; + char buf[256]; + av_strlcpy(buf, av_hash_get_name(c->hash), sizeof(buf) - 200); + av_strlcat(buf, "=", sizeof(buf) - 200); md5_finish(s, buf); - av_freep(&c->md5); + av_hash_freep(&c->hash); return 0; } @@ -83,6 +106,7 @@ AVOutputFormat ff_md5_muxer = { .write_packet = write_packet, .write_trailer = write_trailer, .flags = AVFMT_NOTIMESTAMPS, + .priv_class = &md5enc_class, }; #endif @@ -90,9 +114,9 @@ AVOutputFormat ff_md5_muxer = { static int framemd5_write_header(struct AVFormatContext *s) { struct MD5Context *c = s->priv_data; - c->md5 = av_md5_alloc(); - if (!c->md5) - return AVERROR(ENOMEM); + int res = av_hash_alloc(&c->hash, c->hash_name); + if (res < 0) + return res; return ff_framehash_write_header(s); } @@ -100,8 +124,8 @@ static int framemd5_write_packet(struct AVFormatContext *s, AVPacket *pkt) { struct MD5Context *c = s->priv_data; char buf[256]; - av_md5_init(c->md5); - av_md5_update(c->md5, pkt->data, pkt->size); + av_hash_init(c->hash); + av_hash_update(c->hash, pkt->data, pkt->size); snprintf(buf, sizeof(buf) - 64, "%d, %10"PRId64", %10"PRId64", %8d, %8d, ", pkt->stream_index, pkt->dts, pkt->pts, pkt->duration, pkt->size); @@ -112,10 +136,17 @@ static int framemd5_write_packet(struct AVFormatContext *s, AVPacket *pkt) static int framemd5_write_trailer(struct AVFormatContext *s) { struct MD5Context *c = s->priv_data; - av_freep(&c->md5); + av_hash_freep(&c->hash); return 0; } +static const AVClass framemd5_class = { + .class_name = "frame hash encoder class", + .item_name = av_default_item_name, + .option = hash_options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVOutputFormat ff_framemd5_muxer = { .name = "framemd5", .long_name = NULL_IF_CONFIG_SMALL("Per-frame MD5 testing"), @@ -125,6 +156,8 @@ AVOutputFormat ff_framemd5_muxer = { .write_header = framemd5_write_header, .write_packet = framemd5_write_packet, .write_trailer = framemd5_write_trailer, - .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT, + .flags = AVFMT_VARIABLE_FPS | AVFMT_TS_NONSTRICT | + AVFMT_TS_NEGATIVE, + .priv_class = &framemd5_class, }; #endif diff --git a/chromium/third_party/ffmpeg/libavformat/mm.c b/chromium/third_party/ffmpeg/libavformat/mm.c index 12a11ac69d5..4315802f733 100644 --- a/chromium/third_party/ffmpeg/libavformat/mm.c +++ b/chromium/third_party/ffmpeg/libavformat/mm.c @@ -79,7 +79,7 @@ static int probe(AVProbeData *p) return 0; /* only return half certainty since this check is a bit sketchy */ - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; } static int read_header(AVFormatContext *s) diff --git a/chromium/third_party/ffmpeg/libavformat/mmf.c b/chromium/third_party/ffmpeg/libavformat/mmf.c index d074d7c57cb..cb87a6dddb9 100644 --- a/chromium/third_party/ffmpeg/libavformat/mmf.c +++ b/chromium/third_party/ffmpeg/libavformat/mmf.c @@ -21,8 +21,8 @@ #include "libavutil/channel_layout.h" #include "avformat.h" -#include "internal.h" #include "avio_internal.h" +#include "internal.h" #include "pcm.h" #include "rawenc.h" #include "riff.h" @@ -37,7 +37,7 @@ static const int mmf_rates[] = { 4000, 8000, 11025, 22050, 44100 }; static int mmf_rate(int code) { - if((code < 0) || (code > 4)) + if ((code < 0) || (code > 4)) return -1; return mmf_rates[code]; } @@ -46,8 +46,8 @@ static int mmf_rate(int code) static int mmf_rate_code(int rate) { int i; - for(i = 0; i < 5; i++) - if(mmf_rates[i] == rate) + for (i = 0; i < 5; i++) + if (mmf_rates[i] == rate) return i; return -1; } @@ -74,8 +74,9 @@ static int mmf_write_header(AVFormatContext *s) "VN:"LIBAVFORMAT_IDENT","; rate = mmf_rate_code(s->streams[0]->codec->sample_rate); - if(rate < 0) { - av_log(s, AV_LOG_ERROR, "Unsupported sample rate %d, supported are 4000, 8000, 11025, 22050 and 44100\n", s->streams[0]->codec->sample_rate); + if (rate < 0) { + av_log(s, AV_LOG_ERROR, "Unsupported sample rate %d, supported are 4000, 8000, 11025, 22050 and 44100\n", + s->streams[0]->codec->sample_rate); return AVERROR(EINVAL); } @@ -97,6 +98,7 @@ static int mmf_write_header(AVFormatContext *s) avio_w8(pb, 0); /* status */ avio_w8(pb, 0); /* counts */ end_tag_be(pb, pos); + pos = ff_start_tag(pb, "OPDA"); avio_write(pb, version, strlen(version)); /* metadata ("ST:songtitle,VN:version,...") */ end_tag_be(pb, pos); @@ -129,7 +131,7 @@ static int mmf_write_header(AVFormatContext *s) /* Write a variable-length symbol */ static void put_varlength(AVIOContext *pb, int val) { - if(val < 128) + if (val < 128) avio_w8(pb, val); else { val -= 128; @@ -151,7 +153,7 @@ static int mmf_write_trailer(AVFormatContext *s) end_tag_be(pb, mmf->atrpos); end_tag_be(pb, 8); - pos = avio_tell(pb); + pos = avio_tell(pb); size = pos - mmf->awapos; /* Fill Atsq chunk */ @@ -206,11 +208,13 @@ static int mmf_read_header(AVFormatContext *s) avio_skip(pb, 4); /* file_size */ /* Skip some unused chunks that may or may not be present */ - for(;; avio_skip(pb, size)) { - tag = avio_rl32(pb); + for (;; avio_skip(pb, size)) { + tag = avio_rl32(pb); size = avio_rb32(pb); - if(tag == MKTAG('C','N','T','I')) continue; - if(tag == MKTAG('O','P','D','A')) continue; + if (tag == MKTAG('C', 'N', 'T', 'I')) + continue; + if (tag == MKTAG('O', 'P', 'D', 'A')) + continue; break; } @@ -227,8 +231,8 @@ static int mmf_read_header(AVFormatContext *s) avio_r8(pb); /* format type */ avio_r8(pb); /* sequence type */ params = avio_r8(pb); /* (channel << 7) | (format << 4) | rate */ - rate = mmf_rate(params & 0x0f); - if(rate < 0) { + rate = mmf_rate(params & 0x0f); + if (rate < 0) { av_log(s, AV_LOG_ERROR, "Invalid sample rate\n"); return AVERROR_INVALIDDATA; } @@ -237,11 +241,13 @@ static int mmf_read_header(AVFormatContext *s) avio_r8(pb); /* time base g */ /* Skip some unused chunks that may or may not be present */ - for(;; avio_skip(pb, size)) { - tag = avio_rl32(pb); + for (;; avio_skip(pb, size)) { + tag = avio_rl32(pb); size = avio_rb32(pb); - if(tag == MKTAG('A','t','s','q')) continue; - if(tag == MKTAG('A','s','p','I')) continue; + if (tag == MKTAG('A', 't', 's', 'q')) + continue; + if (tag == MKTAG('A', 's', 'p', 'I')) + continue; break; } @@ -256,13 +262,14 @@ static int mmf_read_header(AVFormatContext *s) if (!st) return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_ADPCM_YAMAHA; - st->codec->sample_rate = rate; - st->codec->channels = (params >> 7) + 1; - st->codec->channel_layout = params >> 7 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_id = AV_CODEC_ID_ADPCM_YAMAHA; + st->codec->sample_rate = rate; + st->codec->channels = (params >> 7) + 1; + st->codec->channel_layout = params >> 7 ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO; st->codec->bits_per_coded_sample = 4; - st->codec->bit_rate = st->codec->sample_rate * st->codec->bits_per_coded_sample; + st->codec->bit_rate = st->codec->sample_rate * + st->codec->bits_per_coded_sample; avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); @@ -271,8 +278,7 @@ static int mmf_read_header(AVFormatContext *s) #define MAX_SIZE 4096 -static int mmf_read_packet(AVFormatContext *s, - AVPacket *pkt) +static int mmf_read_packet(AVFormatContext *s, AVPacket *pkt) { MMFContext *mmf = s->priv_data; int64_t left, size; @@ -303,17 +309,18 @@ AVInputFormat ff_mmf_demuxer = { .flags = AVFMT_GENERIC_INDEX, }; #endif + #if CONFIG_MMF_MUXER AVOutputFormat ff_mmf_muxer = { - .name = "mmf", - .long_name = NULL_IF_CONFIG_SMALL("Yamaha SMAF"), - .mime_type = "application/vnd.smaf", - .extensions = "mmf", - .priv_data_size = sizeof(MMFContext), - .audio_codec = AV_CODEC_ID_ADPCM_YAMAHA, - .video_codec = AV_CODEC_ID_NONE, - .write_header = mmf_write_header, - .write_packet = ff_raw_write_packet, - .write_trailer = mmf_write_trailer, + .name = "mmf", + .long_name = NULL_IF_CONFIG_SMALL("Yamaha SMAF"), + .mime_type = "application/vnd.smaf", + .extensions = "mmf", + .priv_data_size = sizeof(MMFContext), + .audio_codec = AV_CODEC_ID_ADPCM_YAMAHA, + .video_codec = AV_CODEC_ID_NONE, + .write_header = mmf_write_header, + .write_packet = ff_raw_write_packet, + .write_trailer = mmf_write_trailer, }; #endif diff --git a/chromium/third_party/ffmpeg/libavformat/mmsh.c b/chromium/third_party/ffmpeg/libavformat/mmsh.c index 86a0575e59d..482ece40316 100644 --- a/chromium/third_party/ffmpeg/libavformat/mmsh.c +++ b/chromium/third_party/ffmpeg/libavformat/mmsh.c @@ -66,9 +66,9 @@ static int mmsh_close(URLContext *h) MMSHContext *mmsh = (MMSHContext *)h->priv_data; MMSContext *mms = &mmsh->mms; if (mms->mms_hd) - ffurl_close(mms->mms_hd); - av_free(mms->streams); - av_free(mms->asf_header); + ffurl_closep(&mms->mms_hd); + av_freep(&mms->streams); + av_freep(&mms->asf_header); return 0; } @@ -368,23 +368,26 @@ static int mmsh_read(URLContext *h, uint8_t *buf, int size) static int64_t mmsh_read_seek(URLContext *h, int stream_index, int64_t timestamp, int flags) { - MMSHContext *mmsh = h->priv_data; - MMSContext *mms = &mmsh->mms; + MMSHContext *mmsh_old = h->priv_data; + MMSHContext *mmsh = av_mallocz(sizeof(*mmsh)); int ret; - ret= mmsh_open_internal(h, mmsh->location, 0, FFMAX(timestamp, 0), 0); + if (!mmsh) + return AVERROR(ENOMEM); + h->priv_data = mmsh; + ret= mmsh_open_internal(h, mmsh_old->location, 0, FFMAX(timestamp, 0), 0); if(ret>=0){ - if (mms->mms_hd) - ffurl_close(mms->mms_hd); - av_freep(&mms->streams); - av_freep(&mms->asf_header); + h->priv_data = mmsh_old; + mmsh_close(h); + h->priv_data = mmsh; + av_free(mmsh_old); + mmsh->mms.asf_header_read_size = mmsh->mms.asf_header_size; + }else { + h->priv_data = mmsh_old; av_free(mmsh); - mmsh = h->priv_data; - mms = &mmsh->mms; - mms->asf_header_read_size= mms->asf_header_size; - }else - h->priv_data= mmsh; + } + return ret; } diff --git a/chromium/third_party/ffmpeg/libavformat/mov.c b/chromium/third_party/ffmpeg/libavformat/mov.c index 3e48f15e20d..ed5fb9563f2 100644 --- a/chromium/third_party/ffmpeg/libavformat/mov.c +++ b/chromium/third_party/ffmpeg/libavformat/mov.c @@ -25,7 +25,6 @@ #include <limits.h> -//#define DEBUG //#define MOV_EXPORT_ALL_METADATA #include "libavutil/attributes.h" @@ -786,6 +785,12 @@ static int mov_read_moov(MOVContext *c, AVIOContext *pb, MOVAtom atom) { int ret; + if (c->found_moov) { + av_log(c->fc, AV_LOG_WARNING, "Found duplicated MOOV Atom. Skipped it\n"); + avio_skip(pb, atom.size); + return 0; + } + if ((ret = mov_read_default(c, pb, atom)) < 0) return ret; /* we parsed the 'moov' atom, we can terminate the parsing as soon as we find the 'mdat' */ @@ -831,6 +836,11 @@ static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) st = c->fc->streams[c->fc->nb_streams-1]; sc = st->priv_data; + if (sc->time_scale) { + av_log(c->fc, AV_LOG_ERROR, "Multiple mdhd?\n"); + return AVERROR_INVALIDDATA; + } + version = avio_r8(pb); if (version > 1) { avpriv_request_sample(c->fc, "Version %d", version); @@ -878,7 +888,7 @@ static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) c->duration = (version == 1) ? avio_rb64(pb) : avio_rb32(pb); /* duration */ // set the AVCodecContext duration because the duration of individual tracks // may be inaccurate - if (c->time_scale > 0) + if (c->time_scale > 0 && !c->trex_data) c->fc->duration = av_rescale(c->duration, AV_TIME_BASE, c->time_scale); avio_rb32(pb); /* preferred scale */ @@ -1015,6 +1025,36 @@ static int mov_read_avid(MOVContext *c, AVIOContext *pb, MOVAtom atom) return mov_read_extradata(c, pb, atom, AV_CODEC_ID_AVUI); } +static int mov_read_targa_y216(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int ret = mov_read_extradata(c, pb, atom, AV_CODEC_ID_TARGA_Y216); + + if (!ret && c->fc->nb_streams >= 1) { + AVCodecContext *avctx = c->fc->streams[c->fc->nb_streams-1]->codec; + if (avctx->extradata_size >= 40) { + avctx->height = AV_RB16(&avctx->extradata[36]); + avctx->width = AV_RB16(&avctx->extradata[38]); + } + } + return ret; +} + +static int mov_read_ares(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVCodecContext *codec = c->fc->streams[c->fc->nb_streams-1]->codec; + if (codec->codec_tag == MKTAG('A', 'V', 'i', 'n') && + codec->codec_id == AV_CODEC_ID_H264 && + atom.size > 11) { + avio_skip(pb, 10); + /* For AVID AVCI50, force width of 1440 to be able to select the correct SPS and PPS */ + if (avio_rb16(pb) == 0xd4d) + codec->width = 1440; + return 0; + } + + return mov_read_avid(c, pb, atom); +} + static int mov_read_svq3(MOVContext *c, AVIOContext *pb, MOVAtom atom) { return mov_read_extradata(c, pb, atom, AV_CODEC_ID_SVQ3); @@ -1550,6 +1590,9 @@ int ff_mov_read_stsd_entries(MOVContext *c, AVIOContext *pb, int entries) case AV_CODEC_ID_ADPCM_MS: case AV_CODEC_ID_ADPCM_IMA_WAV: case AV_CODEC_ID_ILBC: + case AV_CODEC_ID_MACE3: + case AV_CODEC_ID_MACE6: + case AV_CODEC_ID_QDM2: st->codec->block_align = sc->bytes_per_frame; break; case AV_CODEC_ID_ALAC: @@ -1720,7 +1763,7 @@ static int mov_read_stsz(MOVContext *c, AVIOContext *pb, MOVAtom atom) sample_size = avio_rb32(pb); if (!sc->sample_size) /* do not overwrite value computed in stsd */ sc->sample_size = sample_size; - sc->alt_sample_size = sample_size; + sc->stsz_sample_size = sample_size; field_size = 32; } else { sample_size = 0; @@ -1838,6 +1881,13 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static void mov_update_dts_shift(MOVStreamContext *sc, int duration) +{ + if (duration < 0) { + sc->dts_shift = FFMAX(sc->dts_shift, -duration); + } +} + static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) { AVStream *st; @@ -1880,8 +1930,8 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } - if (duration < 0 && i+2<entries) - sc->dts_shift = FFMAX(sc->dts_shift, -duration); + if (i+2<entries) + mov_update_dts_shift(sc, duration); } sc->ctts_count = i; @@ -1987,10 +2037,22 @@ static void mov_build_index(MOVContext *mov, AVStream *st) st->index_entries_allocated_size = (st->nb_index_entries + sc->sample_count) * sizeof(*st->index_entries); for (i = 0; i < sc->chunk_count; i++) { + int64_t next_offset = i+1 < sc->chunk_count ? sc->chunk_offsets[i+1] : INT64_MAX; current_offset = sc->chunk_offsets[i]; while (stsc_index + 1 < sc->stsc_count && i + 1 == sc->stsc_data[stsc_index + 1].first) stsc_index++; + + if (next_offset > current_offset && sc->sample_size>0 && sc->sample_size < sc->stsz_sample_size && + sc->stsc_data[stsc_index].count * (int64_t)sc->stsz_sample_size > next_offset - current_offset) { + av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too large), ignoring\n", sc->stsz_sample_size); + sc->stsz_sample_size = sc->sample_size; + } + if (sc->stsz_sample_size>0 && sc->stsz_sample_size < sc->sample_size) { + av_log(mov->fc, AV_LOG_WARNING, "STSZ sample size %d invalid (too small), ignoring\n", sc->stsz_sample_size); + sc->stsz_sample_size = sc->sample_size; + } + for (j = 0; j < sc->stsc_data[stsc_index].count; j++) { int keyframe = 0; if (current_sample >= sc->sample_count) { @@ -2017,7 +2079,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) } if (keyframe) distance = 0; - sample_size = sc->alt_sample_size > 0 ? sc->alt_sample_size : sc->sample_sizes[current_sample]; + sample_size = sc->stsz_sample_size > 0 ? sc->stsz_sample_size : sc->sample_sizes[current_sample]; if (sc->pseudo_stream_id == -1 || sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) { AVIndexEntry *e = &st->index_entries[st->nb_index_entries++]; @@ -2549,6 +2611,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->ctts_data[sc->ctts_count].count = 1; sc->ctts_data[sc->ctts_count].duration = (flags & MOV_TRUN_SAMPLE_CTS) ? avio_rb32(pb) : 0; + mov_update_dts_shift(sc, sc->ctts_data[sc->ctts_count].duration); sc->ctts_count++; if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) keyframe = 1; @@ -2709,11 +2772,77 @@ static int mov_read_tmcd(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_uuid(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + int ret; + uint8_t uuid[16]; + static const uint8_t uuid_isml_manifest[] = { + 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd, + 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 + }; + + if (atom.size < sizeof(uuid) || atom.size == INT64_MAX) + return AVERROR_INVALIDDATA; + + ret = avio_read(pb, uuid, sizeof(uuid)); + if (ret < 0) { + return ret; + } else if (ret != sizeof(uuid)) { + return AVERROR_INVALIDDATA; + } + if (!memcmp(uuid, uuid_isml_manifest, sizeof(uuid))) { + uint8_t *buffer, *ptr; + char *endptr; + size_t len = atom.size - sizeof(uuid); + + if (len < 4) { + return AVERROR_INVALIDDATA; + } + ret = avio_skip(pb, 4); // zeroes + len -= 4; + + buffer = av_mallocz(len + 1); + if (!buffer) { + return AVERROR(ENOMEM); + } + ret = avio_read(pb, buffer, len); + if (ret < 0) { + av_free(buffer); + return ret; + } else if (ret != len) { + av_free(buffer); + return AVERROR_INVALIDDATA; + } + + ptr = buffer; + while ((ptr = av_stristr(ptr, "systemBitrate=\"")) != NULL) { + ptr += sizeof("systemBitrate=\"") - 1; + c->bitrates_count++; + c->bitrates = av_realloc_f(c->bitrates, c->bitrates_count, sizeof(*c->bitrates)); + if (!c->bitrates) { + c->bitrates_count = 0; + av_free(buffer); + return AVERROR(ENOMEM); + } + errno = 0; + ret = strtol(ptr, &endptr, 10); + if (ret < 0 || errno || *endptr != '"') { + c->bitrates[c->bitrates_count - 1] = 0; + } else { + c->bitrates[c->bitrates_count - 1] = ret; + } + } + + av_free(buffer); + } + return 0; +} + static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('A','C','L','R'), mov_read_avid }, { MKTAG('A','P','R','G'), mov_read_avid }, { MKTAG('A','A','L','P'), mov_read_avid }, -{ MKTAG('A','R','E','S'), mov_read_avid }, +{ MKTAG('A','R','E','S'), mov_read_ares }, { MKTAG('a','v','s','s'), mov_read_avss }, { MKTAG('c','h','p','l'), mov_read_chpl }, { MKTAG('c','o','6','4'), mov_read_stco }, @@ -2772,6 +2901,8 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('c','h','a','n'), mov_read_chan }, /* channel layout */ { MKTAG('d','v','c','1'), mov_read_dvc1 }, { MKTAG('s','b','g','p'), mov_read_sbgp }, +{ MKTAG('u','u','i','d'), mov_read_uuid }, +{ MKTAG('C','i','n', 0x8e), mov_read_targa_y216 }, { 0, NULL } }; @@ -2845,8 +2976,10 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) left = a.size - avio_tell(pb) + start_pos; if (left > 0) /* skip garbage at atom end */ avio_skip(pb, left); - else if(left < 0) { - av_log(c->fc, AV_LOG_DEBUG, "undoing overread of %"PRId64" in '%.4s'\n", -left, (char*)&a.type); + else if (left < 0) { + av_log(c->fc, AV_LOG_WARNING, + "overread end of atom '%.4s' by %"PRId64" bytes\n", + (char*)&a.type, -left); avio_seek(pb, left, SEEK_CUR); } } @@ -2887,7 +3020,7 @@ static int mov_probe(AVProbeData *p) (AV_RB32(p->buf+offset) != 1 || offset + 12 > (unsigned int)p->buf_size || AV_RB64(p->buf+offset + 8) == 0)) { - score = FFMAX(score, AVPROBE_SCORE_MAX - 50); + score = FFMAX(score, AVPROBE_SCORE_EXTENSION); } else { score = AVPROBE_SCORE_MAX; } @@ -2907,7 +3040,7 @@ static int mov_probe(AVProbeData *p) case MKTAG('u','u','i','d'): case MKTAG('p','r','f','l'): /* if we only find those cause probedata is too small at least rate them */ - score = FFMAX(score, AVPROBE_SCORE_MAX - 50); + score = FFMAX(score, AVPROBE_SCORE_EXTENSION); offset = FFMAX(4, AV_RB32(p->buf+offset)) + offset; break; default: @@ -3088,6 +3221,7 @@ static int mov_read_close(AVFormatContext *s) } av_freep(&mov->trex_data); + av_freep(&mov->bitrates); return 0; } @@ -3200,6 +3334,12 @@ static int mov_read_header(AVFormatContext *s) } } + for (i = 0; i < mov->bitrates_count && i < s->nb_streams; i++) { + if (mov->bitrates[i]) { + s->streams[i]->codec->bit_rate = mov->bitrates[i]; + } + } + return 0; } @@ -3255,6 +3395,11 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) /* must be done just before reading, to avoid infinite loop on sample */ sc->current_sample++; + if (mov->next_root_atom) { + sample->pos = FFMIN(sample->pos, mov->next_root_atom); + sample->size = FFMIN(sample->size, (mov->next_root_atom - sample->pos)); + } + if (st->discard != AVDISCARD_ALL) { if (avio_seek(sc->pb, sample->pos, SEEK_SET) != sample->pos) { av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%"PRIx64": partial file\n", @@ -3387,7 +3532,7 @@ static const AVOption options[] = { {NULL} }; -static const AVClass class = { +static const AVClass mov_class = { .class_name = "mov,mp4,m4a,3gp,3g2,mj2", .item_name = av_default_item_name, .option = options, @@ -3403,6 +3548,6 @@ AVInputFormat ff_mov_demuxer = { .read_packet = mov_read_packet, .read_close = mov_read_close, .read_seek = mov_read_seek, - .priv_class = &class, + .priv_class = &mov_class, .flags = AVFMT_NO_BYTE_SEEK, }; diff --git a/chromium/third_party/ffmpeg/libavformat/movenc.c b/chromium/third_party/ffmpeg/libavformat/movenc.c index 8f3b1bc57a3..13ffa24c2cb 100644 --- a/chromium/third_party/ffmpeg/libavformat/movenc.c +++ b/chromium/third_party/ffmpeg/libavformat/movenc.c @@ -52,7 +52,7 @@ static const AVOption options[] = { { "separate_moof", "Write separate moof/mdat atoms for each track", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SEPARATE_MOOF}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "frag_custom", "Flush fragments on caller requests", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FRAG_CUSTOM}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "isml", "Create a live smooth streaming feed (for pushing to a publishing point)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_ISML}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, - { "faststart", "Run a second pass to put the moov at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "faststart", "Run a second pass to put the index (moov atom) at the beginning of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_FASTSTART}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags), { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM}, @@ -62,6 +62,7 @@ static const AVOption options[] = { { "frag_size", "Maximum fragment size", offsetof(MOVMuxContext, max_fragment_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "ism_lookahead", "Number of lookahead entries for ISM files", offsetof(MOVMuxContext, ism_lookahead), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { "use_editlist", "use edit list", offsetof(MOVMuxContext, use_editlist), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, + { "video_track_timescale", "set timescale of all video tracks", offsetof(MOVMuxContext, video_track_timescale), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { NULL }, }; @@ -73,6 +74,8 @@ static const AVClass flavor ## _muxer_class = {\ .version = LIBAVUTIL_VERSION_INT,\ }; +static int get_moov_size(AVFormatContext *s); + //FIXME support 64 bit variant with wide placeholders static int64_t update_size(AVIOContext *pb, int64_t pos) { @@ -86,20 +89,14 @@ static int64_t update_size(AVIOContext *pb, int64_t pos) static int supports_edts(MOVMuxContext *mov) { - // EDTS with fragments is tricky as we dont know the duration when its written + // EDTS with fragments is tricky as we don't know the duration when its written return (mov->use_editlist<0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) || mov->use_editlist>0; } -static int is_co64_required(const MOVTrack *track) +static int co64_required(const MOVTrack *track) { - int i; - - for (i = 0; i < track->entry; i++) { - if (!track->cluster[i].chunkNum) - continue; - if (track->cluster[i].pos + track->data_offset > UINT32_MAX) - return 1; - } + if (track->entry > 0 && track->cluster[track->entry - 1].pos + track->data_offset > UINT32_MAX) + return 1; return 0; } @@ -107,7 +104,7 @@ static int is_co64_required(const MOVTrack *track) static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track) { int i; - int mode64 = is_co64_required(track); // use 32 bit size variant if possible + int mode64 = co64_required(track); // use 32 bit size variant if possible int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ if (mode64) @@ -116,10 +113,10 @@ static int mov_write_stco_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "stco"); avio_wb32(pb, 0); /* version & flags */ avio_wb32(pb, track->chunkCount); /* entry count */ - for (i=0; i<track->entry; i++) { - if(!track->cluster[i].chunkNum) + for (i = 0; i < track->entry; i++) { + if (!track->cluster[i].chunkNum) continue; - if(mode64 == 1) + if (mode64 == 1) avio_wb64(pb, track->cluster[i].pos + track->data_offset); else avio_wb32(pb, track->cluster[i].pos + track->data_offset); @@ -138,27 +135,25 @@ static int mov_write_stsz_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "stsz"); avio_wb32(pb, 0); /* version & flags */ - for (i=0; i<track->entry; i++) { - tst = track->cluster[i].size/track->cluster[i].entries; - if(oldtst != -1 && tst != oldtst) { + for (i = 0; i < track->entry; i++) { + tst = track->cluster[i].size / track->cluster[i].entries; + if (oldtst != -1 && tst != oldtst) equalChunks = 0; - } oldtst = tst; entries += track->cluster[i].entries; } if (equalChunks && track->entry) { - int sSize = track->entry ? track->cluster[0].size/track->cluster[0].entries : 0; + int sSize = track->entry ? track->cluster[0].size / track->cluster[0].entries : 0; sSize = FFMAX(1, sSize); // adpcm mono case could make sSize == 0 avio_wb32(pb, sSize); // sample size avio_wb32(pb, entries); // sample count - } - else { + } else { avio_wb32(pb, 0); // sample size avio_wb32(pb, entries); // sample count - for (i=0; i<track->entry; i++) { - for (j=0; j<track->cluster[i].entries; j++) { + for (i = 0; i < track->entry; i++) { + for (j = 0; j < track->cluster[i].entries; j++) { avio_wb32(pb, track->cluster[i].size / - track->cluster[i].entries); + track->cluster[i].entries); } } } @@ -177,9 +172,8 @@ static int mov_write_stsc_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); // version & flags entryPos = avio_tell(pb); avio_wb32(pb, track->chunkCount); // entry count - for (i=0; i<track->entry; i++) { - if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) - { + for (i = 0; i < track->entry; i++) { + if (oldval != track->cluster[i].samples_in_chunk && track->cluster[i].chunkNum) { avio_wb32(pb, track->cluster[i].chunkNum); // first chunk avio_wb32(pb, track->cluster[i].samples_in_chunk); // samples per chunk avio_wb32(pb, 0x1); // sample description index @@ -206,9 +200,9 @@ static int mov_write_stss_tag(AVIOContext *pb, MOVTrack *track, uint32_t flag) avio_wb32(pb, 0); // version & flags entryPos = avio_tell(pb); avio_wb32(pb, track->entry); // entry count - for (i=0; i<track->entry; i++) { + for (i = 0; i < track->entry; i++) { if (track->cluster[i].flags & flag) { - avio_wb32(pb, i+1); + avio_wb32(pb, i + 1); index++; } } @@ -268,7 +262,7 @@ static int mov_write_ac3_tag(AVIOContext *pb, MOVTrack *track) put_bits(&pbc, 3, bsmod); put_bits(&pbc, 3, acmod); put_bits(&pbc, 1, lfeon); - put_bits(&pbc, 5, frmsizecod>>1); // bit_rate_code + put_bits(&pbc, 5, frmsizecod >> 1); // bit_rate_code put_bits(&pbc, 5, 0); // reserved flush_put_bits(&pbc); @@ -307,8 +301,8 @@ static void put_descr(AVIOContext *pb, int tag, unsigned int size) { int i = 3; avio_w8(pb, tag); - for(; i>0; i--) - avio_w8(pb, (size>>(7*i)) | 0x80); + for (; i > 0; i--) + avio_w8(pb, (size >> (7 * i)) | 0x80); avio_w8(pb, size & 0x7F); } @@ -351,7 +345,7 @@ static int mov_write_esds_tag(AVIOContext *pb, MOVTrack *track) // Basic // the following fields is made of 6 bits to identify the streamtype (4 for video, 5 for audio) // plus 1 bit to indicate upstream and 1 bit set to 1 (reserved) - if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO) + if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) avio_w8(pb, 0x15); // flags (= Audiostream) else avio_w8(pb, 0x11); // flags (= Visualstream) @@ -707,7 +701,7 @@ static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track) avio_wb16(pb, 0); /* Reserved */ } - if(version == 1) { /* SoundDescription V1 extended info */ + if (version == 1) { /* SoundDescription V1 extended info */ if (mov_pcm_le_gt16(track->enc->codec_id) || mov_pcm_be_gt16(track->enc->codec_id)) avio_wb32(pb, 1); /* must be 1 for uncompressed formats */ @@ -718,24 +712,24 @@ static int mov_write_audio_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 2); /* Bytes per sample */ } - if(track->mode == MODE_MOV && - (track->enc->codec_id == AV_CODEC_ID_AAC || - track->enc->codec_id == AV_CODEC_ID_AC3 || - track->enc->codec_id == AV_CODEC_ID_AMR_NB || - track->enc->codec_id == AV_CODEC_ID_ALAC || - track->enc->codec_id == AV_CODEC_ID_ADPCM_MS || - track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV || - track->enc->codec_id == AV_CODEC_ID_QDM2 || - (mov_pcm_le_gt16(track->enc->codec_id) && version==1) || - (mov_pcm_be_gt16(track->enc->codec_id) && version==1))) + if (track->mode == MODE_MOV && + (track->enc->codec_id == AV_CODEC_ID_AAC || + track->enc->codec_id == AV_CODEC_ID_AC3 || + track->enc->codec_id == AV_CODEC_ID_AMR_NB || + track->enc->codec_id == AV_CODEC_ID_ALAC || + track->enc->codec_id == AV_CODEC_ID_ADPCM_MS || + track->enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV || + track->enc->codec_id == AV_CODEC_ID_QDM2 || + (mov_pcm_le_gt16(track->enc->codec_id) && version==1) || + (mov_pcm_be_gt16(track->enc->codec_id) && version==1))) mov_write_wave_tag(pb, track); - else if(track->tag == MKTAG('m','p','4','a')) + else if (track->tag == MKTAG('m','p','4','a')) mov_write_esds_tag(pb, track); - else if(track->enc->codec_id == AV_CODEC_ID_AMR_NB) + else if (track->enc->codec_id == AV_CODEC_ID_AMR_NB) mov_write_amr_tag(pb, track); - else if(track->enc->codec_id == AV_CODEC_ID_AC3) + else if (track->enc->codec_id == AV_CODEC_ID_AC3) mov_write_ac3_tag(pb, track); - else if(track->enc->codec_id == AV_CODEC_ID_ALAC) + else if (track->enc->codec_id == AV_CODEC_ID_ALAC) mov_write_extradata_tag(pb, track); else if (track->enc->codec_id == AV_CODEC_ID_WMAPRO) mov_write_wfex_tag(pb, track); @@ -796,7 +790,7 @@ static int mov_write_avid_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, track->enc->width); /* values below are based on samples created with quicktime and avid codecs */ if (track->vos_data[5] & 2) { // interlaced - avio_wb32(pb, track->enc->height/2); + avio_wb32(pb, track->enc->height / 2); avio_wb32(pb, 2); /* unknown */ avio_wb32(pb, 0); /* unknown */ avio_wb32(pb, 4); /* unknown */ @@ -830,18 +824,18 @@ static int mp4_get_codec_tag(AVFormatContext *s, MOVTrack *track) else if (track->enc->codec_id == AV_CODEC_ID_DIRAC) tag = MKTAG('d','r','a','c'); else if (track->enc->codec_id == AV_CODEC_ID_MOV_TEXT) tag = MKTAG('t','x','3','g'); else if (track->enc->codec_id == AV_CODEC_ID_VC1) tag = MKTAG('v','c','-','1'); - else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); - else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); + else if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) tag = MKTAG('m','p','4','v'); + else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) tag = MKTAG('m','p','4','a'); return tag; } static const AVCodecTag codec_ipod_tags[] = { - { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, - { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, - { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, - { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') }, - { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') }, + { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, + { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, + { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, + { AV_CODEC_ID_ALAC, MKTAG('a','l','a','c') }, + { AV_CODEC_ID_AC3, MKTAG('a','c','-','3') }, { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, { AV_CODEC_ID_MOV_TEXT, MKTAG('t','e','x','t') }, { AV_CODEC_ID_NONE, 0 }, @@ -853,8 +847,8 @@ static int ipod_get_codec_tag(AVFormatContext *s, MOVTrack *track) // keep original tag for subs, ipod supports both formats if (!(track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE && - (tag == MKTAG('t','x','3','g') || - tag == MKTAG('t','e','x','t')))) + (tag == MKTAG('t', 'x', '3', 'g') || + tag == MKTAG('t', 'e', 'x', 't')))) tag = ff_codec_get_tag(codec_ipod_tags, track->enc->codec_id); if (!av_match_ext(s->filename, "m4a") && !av_match_ext(s->filename, "m4v")) @@ -871,16 +865,16 @@ static int mov_get_dv_codec_tag(AVFormatContext *s, MOVTrack *track) if (track->enc->width == 720) { /* SD */ if (track->enc->height == 480) { /* NTSC */ if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','n'); - else tag = MKTAG('d','v','c',' '); + else tag = MKTAG('d','v','c',' '); }else if (track->enc->pix_fmt == AV_PIX_FMT_YUV422P) tag = MKTAG('d','v','5','p'); else if (track->enc->pix_fmt == AV_PIX_FMT_YUV420P) tag = MKTAG('d','v','c','p'); - else tag = MKTAG('d','v','p','p'); + else tag = MKTAG('d','v','p','p'); } else if (track->enc->height == 720) { /* HD 720 line */ - if (track->enc->time_base.den == 50) tag = MKTAG('d','v','h','q'); - else tag = MKTAG('d','v','h','p'); + if (track->enc->time_base.den == 50) tag = MKTAG('d','v','h','q'); + else tag = MKTAG('d','v','h','p'); } else if (track->enc->height == 1080) { /* HD 1080 line */ - if (track->enc->time_base.den == 25) tag = MKTAG('d','v','h','5'); - else tag = MKTAG('d','v','h','6'); + if (track->enc->time_base.den == 25) tag = MKTAG('d','v','h','5'); + else tag = MKTAG('d','v','h','6'); } else { av_log(s, AV_LOG_ERROR, "unsupported height for dv codec\n"); return 0; @@ -967,12 +961,12 @@ static int mov_get_codec_tag(AVFormatContext *s, MOVTrack *track) } static const AVCodecTag codec_3gp_tags[] = { - { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, - { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, - { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, - { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, - { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, - { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') }, + { AV_CODEC_ID_H263, MKTAG('s','2','6','3') }, + { AV_CODEC_ID_H264, MKTAG('a','v','c','1') }, + { AV_CODEC_ID_MPEG4, MKTAG('m','p','4','v') }, + { AV_CODEC_ID_AAC, MKTAG('m','p','4','a') }, + { AV_CODEC_ID_AMR_NB, MKTAG('s','a','m','r') }, + { AV_CODEC_ID_AMR_WB, MKTAG('s','a','w','b') }, { AV_CODEC_ID_MOV_TEXT, MKTAG('t','x','3','g') }, { AV_CODEC_ID_NONE, 0 }, }; @@ -1083,7 +1077,7 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track) avio_wb16(pb, 0); /* Codec stream revision (=0) */ if (track->mode == MODE_MOV) { ffio_wfourcc(pb, "FFMP"); /* Vendor */ - if(track->enc->codec_id == AV_CODEC_ID_RAWVIDEO) { + if (track->enc->codec_id == AV_CODEC_ID_RAWVIDEO) { avio_wb32(pb, 0); /* Temporal Quality */ avio_wb32(pb, 0x400); /* Spatial Quality = lossless*/ } else { @@ -1104,7 +1098,7 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track) /* FIXME not sure, ISO 14496-1 draft where it shall be set to 0 */ if (track->mode == MODE_MOV && track->enc->codec && track->enc->codec->name) - av_strlcpy(compressor_name,track->enc->codec->name,32); + av_strlcpy(compressor_name, track->enc->codec->name, 32); avio_w8(pb, strlen(compressor_name)); avio_write(pb, compressor_name, 31); @@ -1113,19 +1107,19 @@ static int mov_write_video_tag(AVIOContext *pb, MOVTrack *track) else avio_wb16(pb, 0x18); /* Reserved */ avio_wb16(pb, 0xffff); /* Reserved */ - if(track->tag == MKTAG('m','p','4','v')) + if (track->tag == MKTAG('m','p','4','v')) mov_write_esds_tag(pb, track); - else if(track->enc->codec_id == AV_CODEC_ID_H263) + else if (track->enc->codec_id == AV_CODEC_ID_H263) mov_write_d263_tag(pb); - else if(track->enc->codec_id == AV_CODEC_ID_AVUI || + else if (track->enc->codec_id == AV_CODEC_ID_AVUI || track->enc->codec_id == AV_CODEC_ID_SVQ3) { mov_write_extradata_tag(pb, track); avio_wb32(pb, 0); - } else if(track->enc->codec_id == AV_CODEC_ID_DNXHD) + } else if (track->enc->codec_id == AV_CODEC_ID_DNXHD) mov_write_avid_tag(pb, track); - else if(track->enc->codec_id == AV_CODEC_ID_H264) { + else if (track->enc->codec_id == AV_CODEC_ID_H264) { mov_write_avcc_tag(pb, track); - if(track->mode == MODE_IPOD) + if (track->mode == MODE_IPOD) mov_write_uuid_tag_ipod(pb); } else if (track->enc->codec_id == AV_CODEC_ID_VC1 && track->vos_len > 0) mov_write_dvc1_tag(pb, track); @@ -1221,7 +1215,7 @@ static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) ctts_entries = av_malloc((track->entry + 1) * sizeof(*ctts_entries)); /* worst case */ ctts_entries[0].count = 1; ctts_entries[0].duration = track->cluster[0].cts; - for (i=1; i<track->entry; i++) { + for (i = 1; i < track->entry; i++) { if (track->cluster[i].cts == ctts_entries[entries].duration) { ctts_entries[entries].count++; /* compress */ } else { @@ -1236,7 +1230,7 @@ static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "ctts"); avio_wb32(pb, 0); /* version & flags */ avio_wb32(pb, entries); /* entry count */ - for (i=0; i<entries; i++) { + for (i = 0; i < entries; i++) { avio_wb32(pb, ctts_entries[i].count); avio_wb32(pb, ctts_entries[i].duration); } @@ -1261,7 +1255,7 @@ static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track) stts_entries = track->entry ? av_malloc(track->entry * sizeof(*stts_entries)) : /* worst case */ NULL; - for (i=0; i<track->entry; i++) { + for (i = 0; i < track->entry; i++) { int duration = get_cluster_duration(track, i); if (i && duration == stts_entries[entries].duration) { stts_entries[entries].count++; /* compress */ @@ -1278,7 +1272,7 @@ static int mov_write_stts_tag(AVIOContext *pb, MOVTrack *track) ffio_wfourcc(pb, "stts"); avio_wb32(pb, 0); /* version & flags */ avio_wb32(pb, entries); /* entry count */ - for (i=0; i<entries; i++) { + for (i = 0; i < entries; i++) { avio_wb32(pb, stts_entries[i].count); avio_wb32(pb, stts_entries[i].duration); } @@ -1432,18 +1426,18 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track) const char *hdlr, *descr = NULL, *hdlr_type = NULL; int64_t pos = avio_tell(pb); - if (!track) { /* no media --> data handler */ - hdlr = "dhlr"; - hdlr_type = "url "; - descr = "DataHandler"; - } else { + hdlr = "dhlr"; + hdlr_type = "url "; + descr = "DataHandler"; + + if (track) { hdlr = (track->mode == MODE_MOV) ? "mhlr" : "\0\0\0\0"; if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) { hdlr_type = "vide"; - descr = "VideoHandler"; + descr = "VideoHandler"; } else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) { hdlr_type = "soun"; - descr = "SoundHandler"; + descr = "SoundHandler"; } else if (track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE) { if (track->tag == MKTAG('c','6','0','8')) { hdlr_type = "clcp"; @@ -1453,16 +1447,20 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track) else hdlr_type = "text"; descr = "SubtitleHandler"; } + } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) { + hdlr_type = "hint"; + descr = "HintHandler"; } else if (track->enc->codec_tag == MKTAG('t','m','c','d')) { hdlr_type = "tmcd"; descr = "TimeCodeHandler"; - } else if (track->enc->codec_tag == MKTAG('r','t','p',' ')) { - hdlr_type = "hint"; - descr = "HintHandler"; } else { - hdlr = "dhlr"; - hdlr_type = "url "; - descr = "DataHandler"; + char tag_buf[32]; + av_get_codec_tag_string(tag_buf, sizeof(tag_buf), + track->enc->codec_tag); + + av_log(track->enc, AV_LOG_WARNING, + "Unknown hldr_type for %s / 0x%04X, writing dummy values\n", + tag_buf, track->enc->codec_tag); } } @@ -1471,9 +1469,9 @@ static int mov_write_hdlr_tag(AVIOContext *pb, MOVTrack *track) avio_wb32(pb, 0); /* Version & flags */ avio_write(pb, hdlr, 4); /* handler */ ffio_wfourcc(pb, hdlr_type); /* handler type */ - avio_wb32(pb ,0); /* reserved */ - avio_wb32(pb ,0); /* reserved */ - avio_wb32(pb ,0); /* reserved */ + avio_wb32(pb, 0); /* reserved */ + avio_wb32(pb, 0); /* reserved */ + avio_wb32(pb, 0); /* reserved */ if (!track || track->mode == MODE_MOV) avio_w8(pb, strlen(descr)); /* pascal string */ avio_write(pb, descr, strlen(descr)); /* handler description */ @@ -1502,7 +1500,7 @@ static int mov_write_minf_tag(AVIOContext *pb, MOVTrack *track) int64_t pos = avio_tell(pb); avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "minf"); - if(track->enc->codec_type == AVMEDIA_TYPE_VIDEO) + if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO) mov_write_vmhd_tag(pb); else if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) mov_write_smhd_tag(pb); @@ -1550,11 +1548,11 @@ static int mov_write_mdhd_tag(AVIOContext *pb, MOVTrack *track) avio_wb16(pb, track->language); /* language */ avio_wb16(pb, 0); /* reserved (quality) */ - if(version!=0 && track->mode == MODE_MOV){ + if (version != 0 && track->mode == MODE_MOV) { av_log(NULL, AV_LOG_ERROR, - "FATAL error, file duration too long for timebase, this file will not be\n" - "playable with quicktime. Choose a different timebase or a different\n" - "container format\n"); + "FATAL error, file duration too long for timebase, this file will not be\n" + "playable with quicktime. Choose a different timebase or a different\n" + "container format\n"); } return 32; @@ -1622,7 +1620,7 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st) avio_wb16(pb, 0); /* layer */ avio_wb16(pb, st ? st->codec->codec_type : 0); /* alternate group) */ /* Volume, only for audio */ - if(track->enc->codec_type == AVMEDIA_TYPE_AUDIO) + if (track->enc->codec_type == AVMEDIA_TYPE_AUDIO) avio_wb16(pb, 0x0100); else avio_wb16(pb, 0); @@ -1643,20 +1641,19 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVTrack *track, AVStream *st) write_matrix(pb, 1, 0, 0, 1, 0, 0); } /* Track width and height, for visual only */ - if(st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO || - track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) { - if(track->mode == MODE_MOV) { + if (st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO || + track->enc->codec_type == AVMEDIA_TYPE_SUBTITLE)) { + if (track->mode == MODE_MOV) { avio_wb32(pb, track->enc->width << 16); avio_wb32(pb, track->height << 16); } else { double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); - if(!sample_aspect_ratio || track->height != track->enc->height) + if (!sample_aspect_ratio || track->height != track->enc->height) sample_aspect_ratio = 1; - avio_wb32(pb, sample_aspect_ratio * track->enc->width*0x10000); - avio_wb32(pb, track->height*0x10000); + avio_wb32(pb, sample_aspect_ratio * track->enc->width * 0x10000); + avio_wb32(pb, track->height * 0x10000); } - } - else { + } else { avio_wb32(pb, 0); avio_wb32(pb, 0); } @@ -1777,7 +1774,6 @@ static int mov_write_uuid_tag_psp(AVIOContext *pb, MOVTrack *mov) static int mov_write_udta_sdp(AVIOContext *pb, MOVTrack *track) { - AVFormatContext *ctx = track->rtp_ctx; char buf[1000] = ""; int len; @@ -1810,14 +1806,14 @@ static int mov_write_trak_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_tref_tag(pb, track); mov_write_mdia_tag(pb, track); if (track->mode == MODE_PSP) - mov_write_uuid_tag_psp(pb,track); // PSP Movies require this uuid box + mov_write_uuid_tag_psp(pb, track); // PSP Movies require this uuid box if (track->tag == MKTAG('r','t','p',' ')) mov_write_udta_sdp(pb, track); if (track->enc->codec_type == AVMEDIA_TYPE_VIDEO && track->mode == MODE_MOV) { double sample_aspect_ratio = av_q2d(st->sample_aspect_ratio); if (st->sample_aspect_ratio.num && 1.0 != sample_aspect_ratio) mov_write_tapt_tag(pb, track); - }; + } return update_size(pb, pos); } @@ -1828,7 +1824,7 @@ static int mov_write_iods_tag(AVIOContext *pb, MOVMuxContext *mov) int audio_profile = mov->iods_audio_profile; int video_profile = mov->iods_video_profile; for (i = 0; i < mov->nb_streams; i++) { - if(mov->tracks[i].entry > 0) { + if (mov->tracks[i].entry > 0) { has_audio |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_AUDIO; has_video |= mov->tracks[i].enc->codec_type == AVMEDIA_TYPE_VIDEO; } @@ -1880,8 +1876,8 @@ static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov) int64_t max_track_len_temp, max_track_len = 0; int version; - for (i=0; i<mov->nb_streams; i++) { - if(mov->tracks[i].entry > 0) { + for (i = 0; i < mov->nb_streams; i++) { + if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) { max_track_len_temp = av_rescale_rnd(mov->tracks[i].track_duration, MOV_TIMESCALE, mov->tracks[i].timescale, @@ -1945,7 +1941,7 @@ static int mov_write_itunes_hdlr_tag(AVIOContext *pb, MOVMuxContext *mov, /* helper function to write a data tag with the specified string as data */ static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang, int long_style) { - if(long_style){ + if (long_style) { int size = 16 + strlen(data); avio_wb32(pb, size); /* size */ ffio_wfourcc(pb, "data"); @@ -1953,7 +1949,7 @@ static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang avio_wb32(pb, 0); avio_write(pb, data, strlen(data)); return size; - }else{ + } else { if (!lang) lang = ff_mov_iso639_to_lang("und", 1); avio_wb16(pb, strlen(data)); /* string length */ @@ -1963,7 +1959,9 @@ static int mov_write_string_data_tag(AVIOContext *pb, const char *data, int lang } } -static int mov_write_string_tag(AVIOContext *pb, const char *name, const char *value, int lang, int long_style){ +static int mov_write_string_tag(AVIOContext *pb, const char *name, + const char *value, int lang, int long_style) +{ int size = 0; if (value && value[0]) { int64_t pos = avio_tell(pb); @@ -1990,8 +1988,8 @@ static int mov_write_string_metadata(AVFormatContext *s, AVIOContext *pb, snprintf(tag2, sizeof(tag2), "%s-", tag); while ((t2 = av_dict_get(s->metadata, tag2, t2, AV_DICT_IGNORE_SUFFIX))) { len2 = strlen(t2->key); - if (len2 == len+4 && !strcmp(t->value, t2->value) - && (l=ff_mov_iso639_to_lang(&t2->key[len2-3], 1)) >= 0) { + if (len2 == len + 4 && !strcmp(t->value, t2->value) + && (l = ff_mov_iso639_to_lang(&t2->key[len2 - 3], 1)) >= 0) { lang = l; break; } @@ -2017,23 +2015,29 @@ static int mov_write_tmpo_tag(AVIOContext *pb, AVFormatContext *s) return size; } -/* iTunes track number */ +/* iTunes track or disc number */ static int mov_write_trkn_tag(AVIOContext *pb, MOVMuxContext *mov, - AVFormatContext *s) + AVFormatContext *s, int disc) { - AVDictionaryEntry *t = av_dict_get(s->metadata, "track", NULL, 0); + AVDictionaryEntry *t = av_dict_get(s->metadata, + disc ? "disc" : "track", + NULL, 0); int size = 0, track = t ? atoi(t->value) : 0; if (track) { + int tracks = 0; + char *slash = strchr(t->value, '/'); + if (slash) + tracks = atoi(slash + 1); avio_wb32(pb, 32); /* size */ - ffio_wfourcc(pb, "trkn"); - avio_wb32(pb, 24); /* size */ - ffio_wfourcc(pb, "data"); - avio_wb32(pb, 0); // 8 bytes empty - avio_wb32(pb, 0); - avio_wb16(pb, 0); // empty - avio_wb16(pb, track); // track number - avio_wb16(pb, 0); // total track number - avio_wb16(pb, 0); // empty + ffio_wfourcc(pb, disc ? "disk" : "trkn"); + avio_wb32(pb, 24); /* size */ + ffio_wfourcc(pb, "data"); + avio_wb32(pb, 0); // 8 bytes empty + avio_wb32(pb, 0); + avio_wb16(pb, 0); // empty + avio_wb16(pb, track); // track / disc number + avio_wb16(pb, tracks); // total track / disc number + avio_wb16(pb, 0); // empty size = 32; } return size; @@ -2045,16 +2049,25 @@ static int mov_write_int8_metadata(AVFormatContext *s, AVIOContext *pb, { AVDictionaryEntry *t = NULL; uint8_t num; + int size = 24 + len; + + if (len != 1 && len != 4) + return -1; if (!(t = av_dict_get(s->metadata, tag, NULL, 0))) return 0; num = atoi(t->value); - avio_wb32(pb, len+8); + avio_wb32(pb, size); ffio_wfourcc(pb, name); + avio_wb32(pb, size - 8); + ffio_wfourcc(pb, "data"); + avio_wb32(pb, 0x15); + avio_wb32(pb, 0); if (len==4) avio_wb32(pb, num); else avio_w8 (pb, num); - return len+8; + + return size; } /* iTunes meta data list */ @@ -2086,7 +2099,8 @@ static int mov_write_ilst_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_int8_metadata (s, pb, "stik", "media_type",1); mov_write_int8_metadata (s, pb, "hdvd", "hd_video", 1); mov_write_int8_metadata (s, pb, "pgap", "gapless_playback",1); - mov_write_trkn_tag(pb, mov, s); + mov_write_trkn_tag(pb, mov, s, 0); // track number + mov_write_trkn_tag(pb, mov, s, 1); // disc number mov_write_tmpo_tag(pb, s); return update_size(pb, pos); } @@ -2108,9 +2122,9 @@ static int mov_write_meta_tag(AVIOContext *pb, MOVMuxContext *mov, static int utf8len(const uint8_t *b) { - int len=0; + int len = 0; int val; - while(*b){ + while (*b) { GET_UTF8(val, *b++, return -1;) len++; } @@ -2120,7 +2134,7 @@ static int utf8len(const uint8_t *b) static int ascii_to_wc(AVIOContext *pb, const uint8_t *b) { int val; - while(*b){ + while (*b) { GET_UTF8(val, *b++, return -1;) avio_wb16(pb, val); } @@ -2130,7 +2144,9 @@ static int ascii_to_wc(AVIOContext *pb, const uint8_t *b) static uint16_t language_code(const char *str) { - return (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F); + return (((str[0] - 0x60) & 0x1F) << 10) + + (((str[1] - 0x60) & 0x1F) << 5) + + (( str[2] - 0x60) & 0x1F); } static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s, @@ -2147,7 +2163,7 @@ static int mov_write_3gp_udta_tag(AVIOContext *pb, AVFormatContext *s, avio_wb16(pb, atoi(t->value)); else { avio_wb16(pb, language_code("eng")); /* language */ - avio_write(pb, t->value, strlen(t->value)+1); /* UTF8 string value */ + avio_write(pb, t->value, strlen(t->value) + 1); /* UTF8 string value */ if (!strcmp(tag, "albm") && (t = av_dict_get(s->metadata, "track", NULL, 0))) avio_w8(pb, atoi(t->value)); @@ -2194,7 +2210,7 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, } ret = avio_open_dyn_buf(&pb_buf); - if(ret < 0) + if (ret < 0) return ret; if (mov->mode & MODE_3GP) { @@ -2207,18 +2223,18 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_3gp_udta_tag(pb_buf, s, "cprt", "copyright"); mov_write_3gp_udta_tag(pb_buf, s, "yrrc", "date"); } else if (mov->mode == MODE_MOV) { // the title field breaks gtkpod with mp4 and my suspicion is that stuff is not valid in mp4 - mov_write_string_metadata(s, pb_buf, "\251ART", "artist" , 0); - mov_write_string_metadata(s, pb_buf, "\251nam", "title" , 0); - mov_write_string_metadata(s, pb_buf, "\251aut", "author" , 0); - mov_write_string_metadata(s, pb_buf, "\251alb", "album" , 0); - mov_write_string_metadata(s, pb_buf, "\251day", "date" , 0); - mov_write_string_metadata(s, pb_buf, "\251swr", "encoder" , 0); + mov_write_string_metadata(s, pb_buf, "\251ART", "artist", 0); + mov_write_string_metadata(s, pb_buf, "\251nam", "title", 0); + mov_write_string_metadata(s, pb_buf, "\251aut", "author", 0); + mov_write_string_metadata(s, pb_buf, "\251alb", "album", 0); + mov_write_string_metadata(s, pb_buf, "\251day", "date", 0); + mov_write_string_metadata(s, pb_buf, "\251swr", "encoder", 0); // currently ignored by mov.c - mov_write_string_metadata(s, pb_buf, "\251des", "comment" , 0); + mov_write_string_metadata(s, pb_buf, "\251des", "comment", 0); // add support for libquicktime, this atom is also actually read by mov.c - mov_write_string_metadata(s, pb_buf, "\251cmt", "comment" , 0); - mov_write_string_metadata(s, pb_buf, "\251gen", "genre" , 0); - mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright" , 0); + mov_write_string_metadata(s, pb_buf, "\251cmt", "comment", 0); + mov_write_string_metadata(s, pb_buf, "\251gen", "genre", 0); + mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright", 0); } else { /* iTunes meta data */ mov_write_meta_tag(pb_buf, mov, s); @@ -2228,7 +2244,7 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_chpl_tag(pb_buf, s); if ((size = avio_close_dyn_buf(pb_buf, &buf)) > 0) { - avio_wb32(pb, size+8); + avio_wb32(pb, size + 8); ffio_wfourcc(pb, "udta"); avio_write(pb, buf, size); } @@ -2238,12 +2254,12 @@ static int mov_write_udta_tag(AVIOContext *pb, MOVMuxContext *mov, } static void mov_write_psp_udta_tag(AVIOContext *pb, - const char *str, const char *lang, int type) + const char *str, const char *lang, int type) { - int len = utf8len(str)+1; - if(len<=0) + int len = utf8len(str) + 1; + if (len <= 0) return; - avio_wb16(pb, len*2+10); /* size */ + avio_wb16(pb, len * 2 + 10); /* size */ avio_wb32(pb, type); /* type */ avio_wb16(pb, language_code(lang)); /* language */ avio_wb16(pb, 0x01); /* ? */ @@ -2290,18 +2306,18 @@ static int mov_write_uuidusmt_tag(AVIOContext *pb, AVFormatContext *s) static void build_chunks(MOVTrack *trk) { int i; - MOVIentry *chunk= &trk->cluster[0]; + MOVIentry *chunk = &trk->cluster[0]; uint64_t chunkSize = chunk->size; - chunk->chunkNum= 1; + chunk->chunkNum = 1; if (trk->chunkCount) return; - trk->chunkCount= 1; - for(i=1; i<trk->entry; i++){ - if(chunk->pos + chunkSize == trk->cluster[i].pos && + trk->chunkCount = 1; + for (i = 1; i<trk->entry; i++){ + if (chunk->pos + chunkSize == trk->cluster[i].pos && chunkSize + trk->cluster[i].size < (1<<20)){ chunkSize += trk->cluster[i].size; chunk->samples_in_chunk += trk->cluster[i].entries; - }else{ + } else { trk->cluster[i].chunkNum = chunk->chunkNum+1; chunk=&trk->cluster[i]; chunkSize = chunk->size; @@ -2319,21 +2335,21 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, avio_wb32(pb, 0); /* size placeholder*/ ffio_wfourcc(pb, "moov"); - for (i=0; i<mov->nb_streams; i++) { + for (i = 0; i < mov->nb_streams; i++) { if (mov->tracks[i].entry <= 0 && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) continue; - mov->tracks[i].time = mov->time; - mov->tracks[i].track_id = i+1; + mov->tracks[i].time = mov->time; + mov->tracks[i].track_id = i + 1; if (mov->tracks[i].entry) build_chunks(&mov->tracks[i]); } if (mov->chapter_track) - for (i=0; i<s->nb_streams; i++) { + for (i = 0; i < s->nb_streams; i++) { mov->tracks[i].tref_tag = MKTAG('c','h','a','p'); - mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].track_id; + mov->tracks[i].tref_id = mov->tracks[mov->chapter_track].track_id; } for (i = 0; i < mov->nb_streams; i++) { if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) { @@ -2354,11 +2370,11 @@ static int mov_write_moov_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_mvhd_tag(pb, mov); if (mov->mode != MODE_MOV && !mov->iods_skip) mov_write_iods_tag(pb, mov); - for (i=0; i<mov->nb_streams; i++) { + for (i = 0; i < mov->nb_streams; i++) { if (mov->tracks[i].entry > 0 || mov->flags & FF_MOV_FLAG_FRAGMENT) { - if(i < s->nb_streams){ + if (i < s->nb_streams){ int codec_type= s->streams[i]->codec->codec_type; - if(codec_type==AVMEDIA_TYPE_AUDIO || codec_type==AVMEDIA_TYPE_SUBTITLE){ + if (codec_type==AVMEDIA_TYPE_AUDIO || codec_type==AVMEDIA_TYPE_SUBTITLE){ mov->tracks[i].secondary= not_first[codec_type]; not_first[codec_type]= 1; } @@ -2390,9 +2406,9 @@ static void param_write_string(AVIOContext *pb, const char *name, const char *va static void param_write_hex(AVIOContext *pb, const char *name, const uint8_t *value, int len) { char buf[150]; - len = FFMIN(sizeof(buf)/2 - 1, len); + len = FFMIN(sizeof(buf) / 2 - 1, len); ff_data_to_hex(buf, value, len, 0); - buf[2*len] = '\0'; + buf[2 * len] = '\0'; avio_printf(pb, "<param name=\"%s\" value=\"%s\" valuetype=\"data\"/>\n", name, buf); } @@ -2400,7 +2416,7 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov) { int64_t pos = avio_tell(pb); int i; - const uint8_t uuid[] = { + static const uint8_t uuid[] = { 0xa5, 0xd4, 0x0b, 0x30, 0xe8, 0x14, 0x11, 0xdd, 0xba, 0x2f, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 }; @@ -2466,7 +2482,7 @@ static int mov_write_isml_manifest(AVIOContext *pb, MOVMuxContext *mov) param_write_hex(pb, "CodecPrivateData", track->enc->extradata, track->enc->extradata_size); param_write_int(pb, "AudioTag", ff_codec_get_tag(ff_codec_wav_tags, - track->enc->codec_id)); + track->enc->codec_id)); param_write_int(pb, "Channels", track->enc->channels); param_write_int(pb, "SamplingRate", track->enc->sample_rate); param_write_int(pb, "BitsPerSample", 16); @@ -2505,9 +2521,11 @@ static int mov_write_tfhd_tag(AVIOContext *pb, MOVTrack *track, /* Don't set a default sample size, the silverlight player refuses * to play files with that set. Don't set a default sample duration, - * WMP freaks out if it is set. */ + * WMP freaks out if it is set. Don't set a base data offset, PIFF + * file format says it MUST NOT be set. */ if (track->mode == MODE_ISM) - flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION); + flags &= ~(MOV_TFHD_DEFAULT_SIZE | MOV_TFHD_DEFAULT_DURATION | + MOV_TFHD_BASE_DATA_OFFSET); avio_wb32(pb, 0); /* size placeholder */ ffio_wfourcc(pb, "tfhd"); @@ -2591,7 +2609,7 @@ static int mov_write_trun_tag(AVIOContext *pb, MOVTrack *track) static int mov_write_tfxd_tag(AVIOContext *pb, MOVTrack *track) { int64_t pos = avio_tell(pb); - const uint8_t uuid[] = { + static const uint8_t uuid[] = { 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6, 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2 }; @@ -2613,7 +2631,7 @@ static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov, { int n = track->nb_frag_info - 1 - entry, i; int size = 8 + 16 + 4 + 1 + 16*n; - const uint8_t uuid[] = { + static const uint8_t uuid[] = { 0xd4, 0x80, 0x7e, 0xf2, 0xca, 0x39, 0x46, 0x95, 0x8e, 0x54, 0x26, 0xcb, 0x9e, 0x46, 0xa7, 0x9f }; @@ -2634,11 +2652,10 @@ static int mov_write_tfrf_tag(AVIOContext *pb, MOVMuxContext *mov, avio_wb64(pb, track->frag_info[index].duration); } if (n < mov->ism_lookahead) { - int free_size = 16*(mov->ism_lookahead - n); + int free_size = 16 * (mov->ism_lookahead - n); avio_wb32(pb, free_size); ffio_wfourcc(pb, "free"); - for (i = 0; i < free_size - 8; i++) - avio_w8(pb, 0); + ffio_fill(pb, 0, free_size - 8); } return 0; @@ -2671,7 +2688,7 @@ static int mov_write_traf_tag(AVIOContext *pb, MOVMuxContext *mov, mov_write_tfxd_tag(pb, track); if (mov->ism_lookahead) { - int i, size = 16 + 4 + 1 + 16*mov->ism_lookahead; + int i, size = 16 + 4 + 1 + 16 * mov->ism_lookahead; track->tfrf_offset = avio_tell(pb); avio_wb32(pb, 8 + size); @@ -2805,7 +2822,7 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) } else if (mov->mode & MODE_3G2) { ffio_wfourcc(pb, has_h264 ? "3g2b" : "3g2a"); minor = has_h264 ? 0x20000 : 0x10000; - }else if (mov->mode == MODE_PSP) + } else if (mov->mode == MODE_PSP) ffio_wfourcc(pb, "MSNV"); else if (mov->mode == MODE_MP4) ffio_wfourcc(pb, "isom"); @@ -2820,7 +2837,7 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) avio_wb32(pb, minor); - if(mov->mode == MODE_MOV) + if (mov->mode == MODE_MOV) ffio_wfourcc(pb, "qt "); else if (mov->mode == MODE_ISM) { ffio_wfourcc(pb, "piff"); @@ -2828,7 +2845,7 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) } else { ffio_wfourcc(pb, "isom"); ffio_wfourcc(pb, "iso2"); - if(has_h264) + if (has_h264) ffio_wfourcc(pb, "avc1"); } @@ -2848,7 +2865,7 @@ static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s) AVCodecContext *video_codec = s->streams[0]->codec; AVCodecContext *audio_codec = s->streams[1]->codec; int audio_rate = audio_codec->sample_rate; - int frame_rate = ((video_codec->time_base.den) * (0x10000))/ (video_codec->time_base.num); + int frame_rate = ((video_codec->time_base.den) * (0x10000)) / (video_codec->time_base.num); int audio_kbitrate = audio_codec->bit_rate / 1000; int video_kbitrate = FFMIN(video_codec->bit_rate / 1000, 800 - audio_kbitrate); @@ -2870,7 +2887,7 @@ static void mov_write_uuidprof_tag(AVIOContext *pb, AVFormatContext *s) avio_wb32(pb, 0x0); /* ? */ avio_wb32(pb, 0x2c); /* size */ - ffio_wfourcc(pb, "APRF");/* audio */ + ffio_wfourcc(pb, "APRF"); /* audio */ avio_wb32(pb, 0x0); avio_wb32(pb, 0x2); /* TrackID */ ffio_wfourcc(pb, "mp4a"); @@ -2910,11 +2927,11 @@ static int mov_parse_mpeg2_frame(AVPacket *pkt, uint32_t *flags) int i, closed_gop = 0; for (i = 0; i < pkt->size - 4; i++) { - c = (c<<8) + pkt->data[i]; + c = (c << 8) + pkt->data[i]; if (c == 0x1b8) { // gop - closed_gop = pkt->data[i+4]>>6 & 0x01; + closed_gop = pkt->data[i + 4] >> 6 & 0x01; } else if (c == 0x100) { // pic - int temp_ref = (pkt->data[i+1]<<2) | (pkt->data[i+2]>>6); + int temp_ref = (pkt->data[i + 1] << 2) | (pkt->data[i + 2] >> 6); if (!temp_ref || closed_gop) // I picture is not reordered *flags = MOV_SYNC_SAMPLE; else @@ -2982,21 +2999,6 @@ static void mov_parse_vc1_frame(AVPacket *pkt, MOVTrack *trk, int fragment) } } -static int get_moov_size(AVFormatContext *s) -{ - int ret; - uint8_t *buf; - AVIOContext *moov_buf; - MOVMuxContext *mov = s->priv_data; - - if ((ret = avio_open_dyn_buf(&moov_buf)) < 0) - return ret; - mov_write_moov_tag(moov_buf, mov, s); - ret = avio_close_dyn_buf(moov_buf, &buf); - av_free(buf); - return ret; -} - static int mov_flush_fragment(AVFormatContext *s) { MOVMuxContext *mov = s->priv_data; @@ -3082,9 +3084,14 @@ static int mov_flush_fragment(AVFormatContext *s) MOVFragmentInfo *info; avio_flush(s->pb); track->nb_frag_info++; - track->frag_info = av_realloc(track->frag_info, - sizeof(*track->frag_info) * - track->nb_frag_info); + if (track->nb_frag_info >= track->frag_info_capacity) { + unsigned new_capacity = track->nb_frag_info + MOV_FRAG_INFO_ALLOC_INCREMENT; + if (av_reallocp_array(&track->frag_info, + new_capacity, + sizeof(*track->frag_info))) + return AVERROR(ENOMEM); + track->frag_info_capacity = new_capacity; + } info = &track->frag_info[track->nb_frag_info - 1]; info->offset = avio_tell(s->pb); info->time = mov->tracks[i].frag_start; @@ -3124,7 +3131,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) MOVTrack *trk = &mov->tracks[pkt->stream_index]; AVCodecContext *enc = trk->enc; unsigned int samples_in_chunk = 0; - int size= pkt->size; + int size = pkt->size; uint8_t *reformatted_data = NULL; if (mov->flags & FF_MOV_FLAG_FRAGMENT) { @@ -3168,7 +3175,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) /* copy extradata if it exists */ if (trk->vos_len == 0 && enc->extradata_size > 0) { - trk->vos_len = enc->extradata_size; + trk->vos_len = enc->extradata_size; trk->vos_data = av_malloc(trk->vos_len); memcpy(trk->vos_data, enc->extradata, trk->vos_len); } @@ -3176,7 +3183,9 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) if (enc->codec_id == AV_CODEC_ID_AAC && pkt->size > 2 && (AV_RB16(pkt->data) & 0xfff0) == 0xfff0) { if (!s->streams[pkt->stream_index]->nb_frames) { - av_log(s, AV_LOG_ERROR, "malformated aac bitstream, use -absf aac_adtstoasc\n"); + av_log(s, AV_LOG_ERROR, "Malformed AAC bitstream detected: " + "use audio bitstream filter 'aac_adtstoasc' to fix it " + "('-bsf:a aac_adtstoasc' option with ffmpeg)\n"); return -1; } av_log(s, AV_LOG_WARNING, "aac bitstream error\n"); @@ -3198,25 +3207,27 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) if ((enc->codec_id == AV_CODEC_ID_DNXHD || enc->codec_id == AV_CODEC_ID_AC3) && !trk->vos_len) { /* copy frame to create needed atoms */ - trk->vos_len = size; + trk->vos_len = size; trk->vos_data = av_malloc(size); if (!trk->vos_data) return AVERROR(ENOMEM); memcpy(trk->vos_data, pkt->data, size); } - if (!(trk->entry % MOV_INDEX_CLUSTER_SIZE)) { - trk->cluster = av_realloc_f(trk->cluster, sizeof(*trk->cluster), (trk->entry + MOV_INDEX_CLUSTER_SIZE)); - if (!trk->cluster) - return -1; + if (trk->entry >= trk->cluster_capacity) { + unsigned new_capacity = 2 * (trk->entry + MOV_INDEX_CLUSTER_SIZE); + if (av_reallocp_array(&trk->cluster, new_capacity, + sizeof(*trk->cluster))) + return AVERROR(ENOMEM); + trk->cluster_capacity = new_capacity; } - trk->cluster[trk->entry].pos = avio_tell(pb) - size; + trk->cluster[trk->entry].pos = avio_tell(pb) - size; trk->cluster[trk->entry].samples_in_chunk = samples_in_chunk; - trk->cluster[trk->entry].chunkNum = 0; - trk->cluster[trk->entry].size = size; - trk->cluster[trk->entry].entries = samples_in_chunk; - trk->cluster[trk->entry].dts = pkt->dts; + trk->cluster[trk->entry].chunkNum = 0; + trk->cluster[trk->entry].size = size; + trk->cluster[trk->entry].entries = samples_in_chunk; + trk->cluster[trk->entry].dts = pkt->dts; if (!trk->entry && trk->start_dts != AV_NOPTS_VALUE) { /* First packet of a new fragment. We already wrote the duration * of the last packet of the previous fragment based on track_duration, @@ -3238,7 +3249,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) } if (pkt->dts != pkt->pts) trk->flags |= MOV_TRACK_CTTS; - trk->cluster[trk->entry].cts = pkt->pts - pkt->dts; + trk->cluster[trk->entry].cts = pkt->pts - pkt->dts; trk->cluster[trk->entry].flags = 0; if (enc->codec_id == AV_CODEC_ID_VC1) { mov_parse_vc1_frame(pkt, trk, mov->fragments); @@ -3256,7 +3267,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt) } trk->entry++; trk->sample_count += samples_in_chunk; - mov->mdat_size += size; + mov->mdat_size += size; avio_flush(pb); @@ -3275,7 +3286,8 @@ static int mov_write_single_packet(AVFormatContext *s, AVPacket *pkt) int64_t frag_duration = 0; int size = pkt->size; - if (!pkt->size) return 0; /* Discard 0 sized packets */ + if (!pkt->size) + return 0; /* Discard 0 sized packets */ if (trk->entry && pkt->stream_index < s->nb_streams) frag_duration = av_rescale_q(pkt->dts - trk->cluster[0].dts, @@ -3364,7 +3376,7 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) // QuickTime chapters involve an additional text track with the chapter names // as samples, and a tref pointing from the other tracks to the chapter one. -static void mov_create_chapter_track(AVFormatContext *s, int tracknum) +static int mov_create_chapter_track(AVFormatContext *s, int tracknum) { AVIOContext *pb; @@ -3372,13 +3384,21 @@ static void mov_create_chapter_track(AVFormatContext *s, int tracknum) MOVTrack *track = &mov->tracks[tracknum]; AVPacket pkt = { .stream_index = tracknum, .flags = AV_PKT_FLAG_KEY }; int i, len; + // These properties are required to make QT recognize the chapter track + uint8_t chapter_properties[43] = { 0, 0, 0, 0, 0, 0, 0, 1, }; track->mode = mov->mode; track->tag = MKTAG('t','e','x','t'); track->timescale = MOV_TIMESCALE; track->enc = avcodec_alloc_context3(NULL); track->enc->codec_type = AVMEDIA_TYPE_SUBTITLE; - +#if 0 + track->enc->extradata = av_malloc(sizeof(chapter_properties)); + if (track->enc->extradata == NULL) + return AVERROR(ENOMEM); + track->enc->extradata_size = sizeof(chapter_properties); + memcpy(track->enc->extradata, chapter_properties, sizeof(chapter_properties)); +#else if (avio_open_dyn_buf(&pb) >= 0) { int size; uint8_t *buf; @@ -3422,6 +3442,7 @@ static void mov_create_chapter_track(AVFormatContext *s, int tracknum) av_free(&buf); } } +#endif for (i = 0; i < s->nb_chapters; i++) { AVChapter *c = s->chapters[i]; @@ -3432,15 +3453,17 @@ static void mov_create_chapter_track(AVFormatContext *s, int tracknum) pkt.duration = end - pkt.dts; if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { - len = strlen(t->value); - pkt.size = len+2; + len = strlen(t->value); + pkt.size = len + 2; pkt.data = av_malloc(pkt.size); AV_WB16(pkt.data, len); - memcpy(pkt.data+2, t->value, len); + memcpy(pkt.data + 2, t->value, len); ff_mov_write_packet(s, &pkt); av_freep(&pkt.data); } } + + return 0; } static int mov_create_timecode_track(AVFormatContext *s, int index, int src_index, const char *tcstr) @@ -3504,7 +3527,8 @@ static int mov_write_header(AVFormatContext *s) /* faststart: moov at the beginning of the file, if supported */ if (mov->flags & FF_MOV_FLAG_FASTSTART) { - if (mov->flags & FF_MOV_FLAG_FRAGMENT) + if ((mov->flags & FF_MOV_FLAG_FRAGMENT) || + (s->flags & AVFMT_FLAG_CUSTOM_IO)) mov->flags &= ~FF_MOV_FLAG_FASTSTART; else mov->reserved_moov_size = -1; @@ -3518,7 +3542,7 @@ static int mov_write_header(AVFormatContext *s) * is enabled, we don't support non-seekable output at all. */ if (!s->pb->seekable && ((!(mov->flags & FF_MOV_FLAG_FRAGMENT) && - !(s->oformat && !strcmp(s->oformat->name, "ismv"))) + strcmp(s->oformat->name, "ismv")) || mov->ism_lookahead)) { av_log(s, AV_LOG_ERROR, "muxer does not support non seekable output\n"); return -1; @@ -3527,27 +3551,36 @@ static int mov_write_header(AVFormatContext *s) /* Default mode == MP4 */ mov->mode = MODE_MP4; - if (s->oformat != NULL) { - if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP; - else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2; - else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV; - else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP; - else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD; - else if (!strcmp("ismv",s->oformat->name)) mov->mode = MODE_ISM; - else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V; - - mov_write_ftyp_tag(pb,s); - if (mov->mode == MODE_PSP) { - if (s->nb_streams != 2) { - av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n"); - return -1; + if (!strcmp("3gp", s->oformat->name)) mov->mode = MODE_3GP; + else if (!strcmp("3g2", s->oformat->name)) mov->mode = MODE_3GP|MODE_3G2; + else if (!strcmp("mov", s->oformat->name)) mov->mode = MODE_MOV; + else if (!strcmp("psp", s->oformat->name)) mov->mode = MODE_PSP; + else if (!strcmp("ipod",s->oformat->name)) mov->mode = MODE_IPOD; + else if (!strcmp("ismv",s->oformat->name)) mov->mode = MODE_ISM; + else if (!strcmp("f4v", s->oformat->name)) mov->mode = MODE_F4V; + + mov_write_ftyp_tag(pb,s); + if (mov->mode == MODE_PSP) { + int video_streams_nb = 0, audio_streams_nb = 0, other_streams_nb = 0; + for (i = 0; i < s->nb_streams; i++) { + AVStream *st = s->streams[i]; + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) + video_streams_nb++; + else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + audio_streams_nb++; + else + other_streams_nb++; } - mov_write_uuidprof_tag(pb,s); + + if (video_streams_nb != 1 || audio_streams_nb != 1 || other_streams_nb) { + av_log(s, AV_LOG_ERROR, "PSP mode need one video and one audio stream\n"); + return -1; } + mov_write_uuidprof_tag(pb, s); } mov->nb_streams = s->nb_streams; - if (mov->mode & (MODE_MOV|MODE_IPOD) && s->nb_chapters) + if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) mov->chapter_track = mov->nb_streams++; if (mov->flags & FF_MOV_FLAG_RTP_HINT) { @@ -3588,11 +3621,13 @@ static int mov_write_header(AVFormatContext *s) mov->nb_streams += mov->nb_meta_tmcd; } - mov->tracks = av_mallocz(mov->nb_streams*sizeof(*mov->tracks)); + // Reserve an extra stream for chapters for the case where chapters + // are written in the trailer + mov->tracks = av_mallocz((mov->nb_streams + 1) * sizeof(*mov->tracks)); if (!mov->tracks) return AVERROR(ENOMEM); - for(i=0; i<s->nb_streams; i++){ + for (i = 0; i < s->nb_streams; i++) { AVStream *st= s->streams[i]; MOVTrack *track= &mov->tracks[i]; AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL,0); @@ -3602,7 +3637,7 @@ static int mov_write_header(AVFormatContext *s) if (track->language < 0) track->language = 0; track->mode = mov->mode; - track->tag = mov_find_codec_tag(s, track); + track->tag = mov_find_codec_tag(s, track); if (!track->tag) { av_log(s, AV_LOG_ERROR, "track %d: could not find tag, " "codec not currently supported in container\n", i); @@ -3611,8 +3646,8 @@ static int mov_write_header(AVFormatContext *s) /* If hinting of this track is enabled by a later hint track, * this is updated. */ track->hint_track = -1; - track->start_dts = AV_NOPTS_VALUE; - if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO){ + track->start_dts = AV_NOPTS_VALUE; + if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') || track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') || track->tag == MKTAG('m','x','5','p') || track->tag == MKTAG('m','x','5','n')) { @@ -3620,22 +3655,26 @@ static int mov_write_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "D-10/IMX must use 720x608 or 720x512 video resolution\n"); goto error; } - track->height = track->tag>>24 == 'n' ? 486 : 576; + track->height = track->tag >> 24 == 'n' ? 486 : 576; + } + if (mov->video_track_timescale) { + track->timescale = mov->video_track_timescale; + } else { + track->timescale = st->codec->time_base.den; + while(track->timescale < 10000) + track->timescale *= 2; } - track->timescale = st->codec->time_base.den; - while(track->timescale < 10000) - track->timescale *= 2; if (track->mode == MODE_MOV && track->timescale > 100000) av_log(s, AV_LOG_WARNING, "WARNING codec timebase is very high. If duration is too long,\n" "file may not be playable by quicktime. Specify a shorter timebase\n" "or choose different container.\n"); - }else if(st->codec->codec_type == AVMEDIA_TYPE_AUDIO){ + } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { track->timescale = st->codec->sample_rate; - if(!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) { + if (!st->codec->frame_size && !av_get_bits_per_sample(st->codec->codec_id)) { av_log(s, AV_LOG_WARNING, "track %d: codec frame size is not set\n", i); track->audio_vbr = 1; - }else if(st->codec->codec_id == AV_CODEC_ID_ADPCM_MS || + }else if (st->codec->codec_id == AV_CODEC_ID_ADPCM_MS || st->codec->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV || st->codec->codec_id == AV_CODEC_ID_ILBC){ if (!st->codec->block_align) { @@ -3643,20 +3682,25 @@ static int mov_write_header(AVFormatContext *s) goto error; } track->sample_size = st->codec->block_align; - }else if(st->codec->frame_size > 1){ /* assume compressed audio */ + }else if (st->codec->frame_size > 1){ /* assume compressed audio */ track->audio_vbr = 1; }else{ track->sample_size = (av_get_bits_per_sample(st->codec->codec_id) >> 3) * st->codec->channels; } + if (st->codec->codec_id == AV_CODEC_ID_ILBC) { + track->audio_vbr = 1; + } if (track->mode != MODE_MOV && track->enc->codec_id == AV_CODEC_ID_MP3 && track->timescale < 16000) { av_log(s, AV_LOG_ERROR, "track %d: muxing mp3 at %dhz is not supported\n", i, track->enc->sample_rate); goto error; } - }else if(st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE){ + } else if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) { track->timescale = st->codec->time_base.den; - }else{ + } else if (st->codec->codec_type == AVMEDIA_TYPE_DATA) { + track->timescale = st->codec->time_base.den; + } else { track->timescale = MOV_TIMESCALE; } if (!track->height) @@ -3686,14 +3730,17 @@ static int mov_write_header(AVFormatContext *s) FF_MOV_FLAG_FRAGMENT; } - if(mov->reserved_moov_size){ + if (mov->reserved_moov_size){ mov->reserved_moov_pos= avio_tell(pb); if (mov->reserved_moov_size > 0) avio_skip(pb, mov->reserved_moov_size); } - if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) + if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) { + if (mov->flags & FF_MOV_FLAG_FASTSTART) + mov->reserved_moov_pos = avio_tell(pb); mov_write_mdat_tag(pb, mov); + } if (t = av_dict_get(s->metadata, "creation_time", NULL, 0)) mov->time = ff_iso8601_to_unix_time(t->value); @@ -3709,7 +3756,8 @@ static int mov_write_header(AVFormatContext *s) AVStream *st = s->streams[i]; if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO || st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { - ff_mov_init_hinting(s, hint_track, i); + if (ff_mov_init_hinting(s, hint_track, i) < 0) + goto error; hint_track++; } } @@ -3749,11 +3797,26 @@ static int mov_write_header(AVFormatContext *s) return -1; } -/** +static int get_moov_size(AVFormatContext *s) +{ + int ret; + uint8_t *buf; + AVIOContext *moov_buf; + MOVMuxContext *mov = s->priv_data; + + if ((ret = avio_open_dyn_buf(&moov_buf)) < 0) + return ret; + mov_write_moov_tag(moov_buf, mov, s); + ret = avio_close_dyn_buf(moov_buf, &buf); + av_free(buf); + return ret; +} + +/* * This function gets the moov size if moved to the top of the file: the chunk * offset table can switch between stco (32-bit entries) to co64 (64-bit - * entries) when the moov is moved to the top, so the size of the moov would - * change. It also updates the chunk offset tables. + * entries) when the moov is moved to the beginning, so the size of the moov + * would change. It also updates the chunk offset tables. */ static int compute_moov_size(AVFormatContext *s) { @@ -3771,7 +3834,7 @@ static int compute_moov_size(AVFormatContext *s) if (moov_size2 < 0) return moov_size2; - /* if the size changed, we just switched from stco to co64 and needs to + /* if the size changed, we just switched from stco to co64 and need to * update the offsets */ if (moov_size2 != moov_size) for (i = 0; i < mov->nb_streams; i++) @@ -3847,9 +3910,9 @@ static int mov_write_trailer(AVFormatContext *s) { MOVMuxContext *mov = s->priv_data; AVIOContext *pb = s->pb; - int64_t moov_pos; int res = 0; int i; + int64_t moov_pos; /* * Before actually writing the trailer, make sure that there are no @@ -3864,9 +3927,19 @@ static int mov_write_trailer(AVFormatContext *s) } } - moov_pos = avio_tell(pb); + // If there were no chapters when the header was written, but there + // are chapters now, write them in the trailer. This only works + // when we are not doing fragments. + if (!mov->chapter_track && !(mov->flags & FF_MOV_FLAG_FRAGMENT)) { + if (mov->mode & (MODE_MP4|MODE_MOV|MODE_IPOD) && s->nb_chapters) { + mov->chapter_track = mov->nb_streams++; + mov_create_chapter_track(s, mov->chapter_track); + } + } if (!(mov->flags & FF_MOV_FLAG_FRAGMENT)) { + moov_pos = avio_tell(pb); + /* Write size of mdat tag */ if (mov->mdat_size + 8 <= UINT32_MAX) { avio_seek(pb, mov->mdat_pos, SEEK_SET); @@ -3882,8 +3955,8 @@ static int mov_write_trailer(AVFormatContext *s) } avio_seek(pb, mov->reserved_moov_size > 0 ? mov->reserved_moov_pos : moov_pos, SEEK_SET); - if (mov->reserved_moov_size == -1) { - av_log(s, AV_LOG_INFO, "Starting second pass: moving header on top of the file\n"); + if (mov->flags & FF_MOV_FLAG_FASTSTART) { + av_log(s, AV_LOG_INFO, "Starting second pass: moving the moov atom to the beginning of the file\n"); res = shift_data(s); if (res == 0) { avio_seek(s->pb, mov->reserved_moov_pos, SEEK_SET); @@ -3893,13 +3966,13 @@ static int mov_write_trailer(AVFormatContext *s) int64_t size; mov_write_moov_tag(pb, mov, s); size = mov->reserved_moov_size - (avio_tell(pb) - mov->reserved_moov_pos); - if(size < 8){ + if (size < 8){ av_log(s, AV_LOG_ERROR, "reserved_moov_size is too small, needed %"PRId64" additional\n", 8-size); return -1; } avio_wb32(pb, size); ffio_wfourcc(pb, "free"); - for(i=0; i<size; i++) + for (i = 0; i < size; i++) avio_w8(pb, 0); avio_seek(pb, moov_pos, SEEK_SET); } else { @@ -3910,10 +3983,12 @@ static int mov_write_trailer(AVFormatContext *s) mov_write_mfra_tag(pb, mov); } - if (mov->chapter_track) + if (mov->chapter_track) { + av_free(mov->tracks[mov->chapter_track].enc->extradata); av_freep(&mov->tracks[mov->chapter_track].enc); + } - for (i=0; i<mov->nb_streams; i++) { + for (i = 0; i < mov->nb_streams; i++) { if (mov->tracks[i].tag == MKTAG('r','t','p',' ')) ff_mov_close_hinting(&mov->tracks[i]); else if (mov->tracks[i].tag == MKTAG('t','m','c','d') && mov->nb_meta_tmcd) @@ -3933,7 +4008,6 @@ static int mov_write_trailer(AVFormatContext *s) if (mov->tracks[i].vos_len) av_free(mov->tracks[i].vos_data); - } av_freep(&mov->tracks); @@ -3954,7 +4028,7 @@ AVOutputFormat ff_mov_muxer = { .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ ff_codec_movvideo_tags, ff_codec_movaudio_tags, 0 }, @@ -3973,7 +4047,7 @@ AVOutputFormat ff_tgp_muxer = { .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 }, .priv_class = &tgp_muxer_class, }; @@ -3992,7 +4066,7 @@ AVOutputFormat ff_mp4_muxer = { .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, .priv_class = &mp4_muxer_class, }; @@ -4010,7 +4084,7 @@ AVOutputFormat ff_psp_muxer = { .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, .priv_class = &psp_muxer_class, }; @@ -4027,7 +4101,7 @@ AVOutputFormat ff_tg2_muxer = { .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ codec_3gp_tags, 0 }, .priv_class = &tg2_muxer_class, }; @@ -4045,7 +4119,7 @@ AVOutputFormat ff_ipod_muxer = { .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ codec_ipod_tags, 0 }, .priv_class = &ipod_muxer_class, }; @@ -4063,7 +4137,7 @@ AVOutputFormat ff_ismv_muxer = { .write_header = mov_write_header, .write_packet = mov_write_packet, .write_trailer = mov_write_trailer, - .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH, + .flags = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE, .codec_tag = (const AVCodecTag* const []){ ff_mp4_obj_type, 0 }, .priv_class = &ismv_muxer_class, }; diff --git a/chromium/third_party/ffmpeg/libavformat/movenc.h b/chromium/third_party/ffmpeg/libavformat/movenc.h index a5db8950ab9..79d8fa2d21d 100644 --- a/chromium/third_party/ffmpeg/libavformat/movenc.h +++ b/chromium/third_party/ffmpeg/libavformat/movenc.h @@ -26,7 +26,8 @@ #include "avformat.h" -#define MOV_INDEX_CLUSTER_SIZE 16384 +#define MOV_FRAG_INFO_ALLOC_INCREMENT 64 +#define MOV_INDEX_CLUSTER_SIZE 1024 #define MOV_TIMESCALE 1000 #define RTP_MAX_PACKET_SIZE 1450 @@ -75,7 +76,7 @@ typedef struct MOVFragmentInfo { int64_t tfrf_offset; } MOVFragmentInfo; -typedef struct MOVIndex { +typedef struct MOVTrack { int mode; int entry; unsigned timescale; @@ -102,6 +103,7 @@ typedef struct MOVIndex { int vos_len; uint8_t *vos_data; MOVIentry *cluster; + unsigned cluster_capacity; int audio_vbr; int height; ///< active picture (w/o VBI) height for D-10/IMX uint32_t tref_tag; @@ -129,6 +131,7 @@ typedef struct MOVIndex { int nb_frag_info; MOVFragmentInfo *frag_info; + unsigned frag_info_capacity; struct { int64_t struct_offset; @@ -153,8 +156,6 @@ typedef struct MOVMuxContext { int flags; int rtp_flags; - int reserved_moov_size; ///< 0 for disabled, -1 for automatic, size otherwise - int64_t reserved_moov_pos; int iods_skip; int iods_video_profile; @@ -168,6 +169,10 @@ typedef struct MOVMuxContext { AVIOContext *mdat_buf; int use_editlist; + int video_track_timescale; + + int reserved_moov_size; ///< 0 for disabled, -1 for automatic, size otherwise + int64_t reserved_moov_pos; } MOVMuxContext; #define FF_MOV_FLAG_RTP_HINT 1 diff --git a/chromium/third_party/ffmpeg/libavformat/movenchint.c b/chromium/third_party/ffmpeg/libavformat/movenchint.c index cc90f0b45ac..943680e9ad0 100644 --- a/chromium/third_party/ffmpeg/libavformat/movenchint.c +++ b/chromium/third_party/ffmpeg/libavformat/movenchint.c @@ -87,7 +87,7 @@ static void sample_queue_free(HintSampleQueue *queue) if (queue->samples[i].own_data) av_free(queue->samples[i].data); av_freep(&queue->samples); - queue->len = 0; + queue->len = 0; queue->size = 0; } @@ -104,7 +104,7 @@ static void sample_queue_push(HintSampleQueue *queue, uint8_t *data, int size, if (size <= 14) return; if (!queue->samples || queue->len >= queue->size) { - HintSample* samples; + HintSample *samples; queue->size += 10; samples = av_realloc(queue->samples, sizeof(HintSample)*queue->size); if (!samples) @@ -114,7 +114,7 @@ static void sample_queue_push(HintSampleQueue *queue, uint8_t *data, int size, queue->samples[queue->len].data = data; queue->samples[queue->len].size = size; queue->samples[queue->len].sample_number = sample; - queue->samples[queue->len].offset = 0; + queue->samples[queue->len].offset = 0; queue->samples[queue->len].own_data = 0; queue->len++; } @@ -128,7 +128,7 @@ static void sample_queue_retain(HintSampleQueue *queue) for (i = 0; i < queue->len; ) { HintSample *sample = &queue->samples[i]; if (!sample->own_data) { - uint8_t* ptr = av_malloc(sample->size); + uint8_t *ptr = av_malloc(sample->size); if (!ptr) { /* Unable to allocate memory for this one, remove it */ memmove(queue->samples + i, queue->samples + i + 1, @@ -309,11 +309,11 @@ static void describe_payload(const uint8_t *data, int size, * @param data buffer containing RTP packets * @param size the size of the data buffer * @param trk the MOVTrack for the hint track - * @param pts pointer where the timestamp for the written RTP hint is stored + * @param dts pointer where the timestamp for the written RTP hint is stored * @return the number of RTP packets in the written hint */ static int write_hint_packets(AVIOContext *out, const uint8_t *data, - int size, MOVTrack *trk, int64_t *pts) + int size, MOVTrack *trk, int64_t *dts) { int64_t curpos; int64_t count_pos, entries_pos; @@ -328,6 +328,7 @@ static int write_hint_packets(AVIOContext *out, const uint8_t *data, uint32_t packet_len = AV_RB32(data); uint16_t seq; uint32_t ts; + int32_t ts_diff; data += 4; size -= 4; @@ -344,25 +345,35 @@ static int write_hint_packets(AVIOContext *out, const uint8_t *data, trk->max_packet_size = packet_len; seq = AV_RB16(&data[2]); - ts = AV_RB32(&data[4]); + ts = AV_RB32(&data[4]); if (trk->prev_rtp_ts == 0) trk->prev_rtp_ts = ts; /* Unwrap the 32-bit RTP timestamp that wraps around often * into a not (as often) wrapping 64-bit timestamp. */ - trk->cur_rtp_ts_unwrapped += (int32_t) (ts - trk->prev_rtp_ts); - trk->prev_rtp_ts = ts; - if (*pts == AV_NOPTS_VALUE) - *pts = trk->cur_rtp_ts_unwrapped; + ts_diff = ts - trk->prev_rtp_ts; + if (ts_diff > 0) { + trk->cur_rtp_ts_unwrapped += ts_diff; + trk->prev_rtp_ts = ts; + ts_diff = 0; + } + if (*dts == AV_NOPTS_VALUE) + *dts = trk->cur_rtp_ts_unwrapped; count++; /* RTPpacket header */ avio_wb32(out, 0); /* relative_time */ avio_write(out, data, 2); /* RTP header */ avio_wb16(out, seq); /* RTPsequenceseed */ - avio_wb16(out, 0); /* reserved + flags */ + avio_wb16(out, ts_diff ? 4 : 0); /* reserved + flags (extra_flag) */ entries_pos = avio_tell(out); avio_wb16(out, 0); /* entry count */ + if (ts_diff) { /* if extra_flag is set */ + avio_wb32(out, 16); /* extra_information_length */ + avio_wb32(out, 12); /* rtpoffsetTLV box */ + avio_write(out, "rtpo", 4); + avio_wb32(out, ts_diff); + } data += 12; size -= 12; @@ -417,7 +428,7 @@ int ff_mov_add_hinted_packet(AVFormatContext *s, AVPacket *pkt, * for next time. */ size = avio_close_dyn_buf(rtp_ctx->pb, &buf); if ((ret = ffio_open_dyn_packet_buf(&rtp_ctx->pb, - RTP_MAX_PACKET_SIZE)) < 0) + RTP_MAX_PACKET_SIZE)) < 0) goto done; if (size <= 0) @@ -445,8 +456,9 @@ done: return ret; } -void ff_mov_close_hinting(MOVTrack *track) { - AVFormatContext* rtp_ctx = track->rtp_ctx; +void ff_mov_close_hinting(MOVTrack *track) +{ + AVFormatContext *rtp_ctx = track->rtp_ctx; uint8_t *ptr; av_freep(&track->enc); diff --git a/chromium/third_party/ffmpeg/libavformat/mp3dec.c b/chromium/third_party/ffmpeg/libavformat/mp3dec.c index d599c9c489c..472bad9b6ae 100644 --- a/chromium/third_party/ffmpeg/libavformat/mp3dec.c +++ b/chromium/third_party/ffmpeg/libavformat/mp3dec.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/opt.h" #include "libavutil/avstring.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" @@ -36,10 +37,14 @@ #define XING_TOC_COUNT 100 typedef struct { + AVClass *class; int64_t filesize; + int64_t header_filesize; int xing_toc; int start_pad; int end_pad; + int usetoc; + int is_cbr; } MP3DecContext; /* mp3 read */ @@ -76,11 +81,11 @@ static int mp3_read_probe(AVProbeData *p) } // keep this in sync with ac3 probe, both need to avoid // issues with MPEG-files! - if (first_frames>=4) return AVPROBE_SCORE_MAX/2+1; - else if(max_frames>200)return AVPROBE_SCORE_MAX/2; - else if(max_frames>=4) return AVPROBE_SCORE_MAX/4; + if (first_frames>=4) return AVPROBE_SCORE_EXTENSION + 1; + else if(max_frames>200)return AVPROBE_SCORE_EXTENSION; + else if(max_frames>=4) return AVPROBE_SCORE_EXTENSION / 2; else if(ff_id3v2_match(buf0, ID3v2_DEFAULT_MAGIC) && 2*ff_id3v2_tag_len(buf0) >= p->buf_size) - return AVPROBE_SCORE_MAX/8; + return AVPROBE_SCORE_EXTENSION / 4; else if(max_frames>=1) return 1; else return 0; //mpegps_mp3_unrecognized_format.mpg has max_frames=3 @@ -90,22 +95,24 @@ static void read_xing_toc(AVFormatContext *s, int64_t filesize, int64_t duration { int i; MP3DecContext *mp3 = s->priv_data; + int fill_index = mp3->usetoc && duration > 0; if (!filesize && !(filesize = avio_size(s->pb))) { av_log(s, AV_LOG_WARNING, "Cannot determine file size, skipping TOC table.\n"); - return; + fill_index = 0; } for (i = 0; i < XING_TOC_COUNT; i++) { uint8_t b = avio_r8(s->pb); - - av_add_index_entry(s->streams[0], + if (fill_index) + av_add_index_entry(s->streams[0], av_rescale(b, filesize, 256), av_rescale(i, duration, XING_TOC_COUNT), 0, 0, AVINDEX_KEYFRAME); } - mp3->xing_toc = 1; + if (fill_index) + mp3->xing_toc = 1; } /** @@ -117,7 +124,7 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) uint32_t v, spf; unsigned frames = 0; /* Total number of frames in file */ unsigned size = 0; /* Total number of bytes in the stream */ - const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}}; + static const int64_t xing_offtbl[2][2] = {{32, 17}, {17,9}}; MPADecodeHeader c; int vbrtag_size = 0; int is_cbr; @@ -143,7 +150,7 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) frames = avio_rb32(s->pb); if(v & XING_FLAG_SIZE) size = avio_rb32(s->pb); - if (v & XING_FLAG_TOC && frames) + if (v & XING_FLAG_TOC) read_xing_toc(s, size, av_rescale_q(frames, (AVRational){spf, c.sample_rate}, st->time_base)); if(v & 8) @@ -185,6 +192,9 @@ static int mp3_parse_vbr_tags(AVFormatContext *s, AVStream *st, int64_t base) if (size && frames && !is_cbr) st->codec->bit_rate = av_rescale(size, 8 * c.sample_rate, frames * (int64_t)spf); + mp3->is_cbr = is_cbr; + mp3->header_filesize = size; + return 0; } @@ -274,21 +284,33 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { MP3DecContext *mp3 = s->priv_data; - AVIndexEntry *ie; + AVIndexEntry *ie, ie1; AVStream *st = s->streams[0]; int64_t ret = av_index_search_timestamp(st, timestamp, flags); int i, j; - if (!mp3->xing_toc) { + if (mp3->is_cbr && st->duration > 0 && mp3->header_filesize > s->data_offset) { + int64_t filesize = avio_size(s->pb); + int64_t duration; + if (filesize <= s->data_offset) + filesize = mp3->header_filesize; + filesize -= s->data_offset; + duration = av_rescale(st->duration, filesize, mp3->header_filesize - s->data_offset); + ie = &ie1; + timestamp = av_clip64(timestamp, 0, duration); + ie->timestamp = timestamp; + ie->pos = av_rescale(timestamp, filesize, duration) + s->data_offset; + } else if (mp3->xing_toc) { + if (ret < 0) + return ret; + + ie = &st->index_entries[ret]; + } else { st->skip_samples = timestamp <= 0 ? mp3->start_pad + 528 + 1 : 0; return -1; } - if (ret < 0) - return ret; - - ie = &st->index_entries[ret]; ret = avio_seek(s->pb, ie->pos, SEEK_SET); if (ret < 0) return ret; @@ -316,6 +338,19 @@ static int mp3_seek(AVFormatContext *s, int stream_index, int64_t timestamp, return 0; } +static const AVOption options[] = { + { "usetoc", "use table of contents", offsetof(MP3DecContext, usetoc), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, AV_OPT_FLAG_DECODING_PARAM}, + { NULL }, +}; + +static const AVClass demuxer_class = { + .class_name = "mp3", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_DEMUXER, +}; + AVInputFormat ff_mp3_demuxer = { .name = "mp3", .long_name = NULL_IF_CONFIG_SMALL("MP2/3 (MPEG audio layer 2/3)"), @@ -326,4 +361,5 @@ AVInputFormat ff_mp3_demuxer = { .priv_data_size = sizeof(MP3DecContext), .flags = AVFMT_GENERIC_INDEX, .extensions = "mp2,mp3,m2a", /* XXX: use probe */ + .priv_class = &demuxer_class, }; diff --git a/chromium/third_party/ffmpeg/libavformat/mpc8.c b/chromium/third_party/ffmpeg/libavformat/mpc8.c index 73f805711d2..73b7eb739c7 100644 --- a/chromium/third_party/ffmpeg/libavformat/mpc8.c +++ b/chromium/third_party/ffmpeg/libavformat/mpc8.c @@ -92,7 +92,7 @@ static int mpc8_probe(AVProbeData *p) if (size < 2) return 0; if (bs + size - 2 >= bs_end) - return AVPROBE_SCORE_MAX / 4 - 1; //seems to be valid MPC but no header yet + return AVPROBE_SCORE_EXTENSION - 1; // seems to be valid MPC but no header yet if (header_found) { if (size < 11 || size > 28) return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/mpeg.c b/chromium/third_party/ffmpeg/libavformat/mpeg.c index 8f835ad0568..5d5b09fc079 100644 --- a/chromium/third_party/ffmpeg/libavformat/mpeg.c +++ b/chromium/third_party/ffmpeg/libavformat/mpeg.c @@ -89,14 +89,14 @@ static int mpegps_probe(AVProbeData *p) } if(vid+audio > invalid+1) /* invalid VDR files nd short PES streams */ - score= AVPROBE_SCORE_MAX/4; + score = AVPROBE_SCORE_EXTENSION / 2; if(sys>invalid && sys*9 <= pspack*10) - return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_MAX/2+2 : AVPROBE_SCORE_MAX/4; // +1 for .mpg + return (audio > 12 || vid > 3 || pspack > 2) ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg if(pspack > invalid && (priv1+vid+audio)*10 >= pspack*9) - return pspack > 2 ? AVPROBE_SCORE_MAX/2+2 : AVPROBE_SCORE_MAX/4; // +1 for .mpg + return pspack > 2 ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2; // 1 more than .mpg if((!!vid ^ !!audio) && (audio > 4 || vid > 1) && !sys && !pspack && p->buf_size>2048 && vid + audio > invalid) /* PES stream */ - return (audio > 12 || vid > 3 + 2*invalid) ? AVPROBE_SCORE_MAX/2+2 : AVPROBE_SCORE_MAX/4; + return (audio > 12 || vid > 3 + 2*invalid) ? AVPROBE_SCORE_EXTENSION + 2 : AVPROBE_SCORE_EXTENSION / 2; //02-Penguin.flac has sys:0 priv1:0 pspack:0 vid:0 audio:1 //mp3_misidentified_2.mp3 has sys:0 priv1:0 pspack:0 vid:0 audio:6 diff --git a/chromium/third_party/ffmpeg/libavformat/mpegenc.c b/chromium/third_party/ffmpeg/libavformat/mpegenc.c index b467bb5de5f..6f6da5c83de 100644 --- a/chromium/third_party/ffmpeg/libavformat/mpegenc.c +++ b/chromium/third_party/ffmpeg/libavformat/mpegenc.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/attributes.h" #include "libavutil/fifo.h" #include "libavutil/log.h" #include "libavutil/mathematics.h" @@ -293,7 +294,7 @@ static int get_system_header_size(AVFormatContext *ctx) return buf_index; } -static int mpeg_mux_init(AVFormatContext *ctx) +static av_cold int mpeg_mux_init(AVFormatContext *ctx) { MpegMuxContext *s = ctx->priv_data; int bitrate, i, mpa_id, mpv_id, mps_id, ac3_id, dts_id, lpcm_id, j; diff --git a/chromium/third_party/ffmpeg/libavformat/mpegts.c b/chromium/third_party/ffmpeg/libavformat/mpegts.c index 85b5146255f..c6417945560 100644 --- a/chromium/third_party/ffmpeg/libavformat/mpegts.c +++ b/chromium/third_party/ffmpeg/libavformat/mpegts.c @@ -29,6 +29,7 @@ #include "libavutil/avassert.h" #include "libavcodec/bytestream.h" #include "libavcodec/get_bits.h" +#include "libavcodec/mathops.h" #include "avformat.h" #include "mpegts.h" #include "internal.h" @@ -52,7 +53,7 @@ enum MpegTSFilterType { typedef struct MpegTSFilter MpegTSFilter; -typedef int PESCallback(MpegTSFilter *f, const uint8_t *buf, int len, int is_start, int64_t pos); +typedef int PESCallback(MpegTSFilter *f, const uint8_t *buf, int len, int is_start, int64_t pos, int64_t cur_pcr); typedef struct MpegTSPESFilter { PESCallback *pes_cb; @@ -98,7 +99,11 @@ struct MpegTSContext { /** raw packet size, including FEC if present */ int raw_packet_size; - int pos47; + int size_stat[3]; + int size_stat_count; +#define SIZE_STAT_THRESHOLD 10 + + int64_t pos47_full; /** if true, all pids are analyzed to find streams */ int auto_guess; @@ -106,6 +111,9 @@ struct MpegTSContext { /** compute exact PCR for each transport stream packet */ int mpeg2ts_compute_pcr; + /** fix dvb teletext pts */ + int fix_teletext_pts; + int64_t cur_pcr; /**< used to estimate the exact PCR */ int pcr_incr; /**< used to estimate the exact PCR */ @@ -131,7 +139,7 @@ struct MpegTSContext { int current_pid; }; -static const AVOption options[] = { +static const AVOption mpegtsraw_options[] = { {"compute_pcr", "Compute exact PCR for each transport stream packet.", offsetof(MpegTSContext, mpeg2ts_compute_pcr), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, { NULL }, @@ -140,7 +148,20 @@ static const AVOption options[] = { static const AVClass mpegtsraw_class = { .class_name = "mpegtsraw demuxer", .item_name = av_default_item_name, - .option = options, + .option = mpegtsraw_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static const AVOption mpegts_options[] = { + {"fix_teletext_pts", "Try to fix pts values of dvb teletext streams.", offsetof(MpegTSContext, fix_teletext_pts), AV_OPT_TYPE_INT, + {.i64 = 1}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, + { NULL }, +}; + +static const AVClass mpegts_class = { + .class_name = "mpegts demuxer", + .item_name = av_default_item_name, + .option = mpegts_options, .version = LIBAVUTIL_VERSION_INT, }; @@ -179,6 +200,7 @@ typedef struct PESContext { uint8_t header[MAX_PES_HEADER_SIZE]; AVBufferRef *buffer; SLConfigDescr sl; + int64_t last_pcr; } PESContext; extern AVInputFormat ff_mpegts_demuxer; @@ -268,6 +290,17 @@ static int discard_pid(MpegTSContext *ts, unsigned int pid) int i, j, k; int used = 0, discarded = 0; struct Program *p; + + /* If none of the programs have .discard=AVDISCARD_ALL then there's + * no way we have to discard this packet + */ + for (k = 0; k < ts->stream->nb_programs; k++) { + if (ts->stream->programs[k]->discard == AVDISCARD_ALL) + break; + } + if (k == ts->stream->nb_programs) + return 0; + for(i=0; i<ts->nb_prg; i++) { p = &ts->prg[i]; for(j=0; j<p->nb_pids; j++) { @@ -808,7 +841,7 @@ static int read_sl_header(PESContext *pes, SLConfigDescr *sl, const uint8_t *buf /* return non zero if a packet could be constructed */ static int mpegts_push_data(MpegTSFilter *filter, const uint8_t *buf, int buf_size, int is_start, - int64_t pos) + int64_t pos, int64_t pcr) { PESContext *pes = filter->u.pes_filter.opaque; MpegTSContext *ts = pes->ts; @@ -818,6 +851,9 @@ static int mpegts_push_data(MpegTSFilter *filter, if(!ts->pkt) return 0; + if (pcr != -1) + pes->last_pcr = pcr; + if (is_start) { if (pes->state == MPEGTS_PAYLOAD && pes->data_index > 0) { new_pes_packet(pes, ts->pkt); @@ -964,6 +1000,32 @@ static int mpegts_push_data(MpegTSFilter *filter, p += sl_header_bytes; buf_size -= sl_header_bytes; } + if (pes->ts->fix_teletext_pts && pes->st->codec->codec_id == AV_CODEC_ID_DVB_TELETEXT) { + AVProgram *p = NULL; + while ((p = av_find_program_from_stream(pes->stream, p, pes->st->index))) { + if (p->pcr_pid != -1 && p->discard != AVDISCARD_ALL) { + MpegTSFilter *f = pes->ts->pids[p->pcr_pid]; + if (f && f->type == MPEGTS_PES) { + PESContext *pcrpes = f->u.pes_filter.opaque; + if (pcrpes && pcrpes->last_pcr != -1 && pcrpes->st && pcrpes->st->discard != AVDISCARD_ALL) { + // teletext packets do not always have correct timestamps, + // the standard says they should be handled after 40.6 ms at most, + // and the pcr error to this packet should be no more than 100 ms. + // TODO: we should interpolate the PCR, not just use the last one + int64_t pcr = pcrpes->last_pcr / 300; + pes->st->pts_wrap_reference = pcrpes->st->pts_wrap_reference; + pes->st->pts_wrap_behavior = pcrpes->st->pts_wrap_behavior; + if (pes->dts == AV_NOPTS_VALUE || pes->dts < pcr) { + pes->pts = pes->dts = pcr; + } else if (pes->dts > pcr + 3654 + 9000) { + pes->pts = pes->dts = pcr + 3654 + 9000; + } + break; + } + } + } + } + } } break; case MPEGTS_PAYLOAD: @@ -1020,6 +1082,7 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid) pes->state = MPEGTS_SKIP; pes->pts = AV_NOPTS_VALUE; pes->dts = AV_NOPTS_VALUE; + pes->last_pcr = -1; tss = mpegts_open_pes_filter(ts, pid, mpegts_push_data, pes); if (!tss) { av_free(pes); @@ -1625,12 +1688,18 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len if (sid == 0x0000) { /* NIT info */ } else { + MpegTSFilter *fil = ts->pids[pmt_pid]; program = av_new_program(ts->stream, sid); program->program_num = sid; program->pmt_pid = pmt_pid; - if (ts->pids[pmt_pid]) - mpegts_close_filter(ts, ts->pids[pmt_pid]); - mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1); + if (fil) + if ( fil->type != MPEGTS_SECTION + || fil->pid != pmt_pid + || fil->u.section_filter.section_cb != pmt_cb) + mpegts_close_filter(ts, ts->pids[pmt_pid]); + + if (!ts->pids[pmt_pid]) + mpegts_open_section_filter(ts, pmt_pid, pmt_cb, ts, 1); add_pat_entry(ts, sid); add_pid_to_pmt(ts, sid, 0); //add pat pid to program add_pid_to_pmt(ts, sid, pmt_pid); @@ -1726,6 +1795,9 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len } } +static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, + const uint8_t *packet); + /* handle one TS packet */ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) { @@ -1790,7 +1862,8 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) return 0; pos = avio_tell(ts->stream->pb); - ts->pos47= pos % ts->raw_packet_size; + av_assert0(pos >= TS_PACKET_SIZE); + ts->pos47_full = pos - TS_PACKET_SIZE; if (tss->type == MPEGTS_SECTION) { if (is_start) { @@ -1819,15 +1892,53 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet) } } else { int ret; + int64_t pcr = -1; + int64_t pcr_h; + int pcr_l; + if (parse_pcr(&pcr_h, &pcr_l, packet) == 0) + pcr = pcr_h * 300 + pcr_l; // Note: The position here points actually behind the current packet. if ((ret = tss->u.pes_filter.pes_cb(tss, p, p_end - p, is_start, - pos - ts->raw_packet_size)) < 0) + pos - ts->raw_packet_size, pcr)) < 0) return ret; } return 0; } +static void reanalyze(MpegTSContext *ts) { + AVIOContext *pb = ts->stream->pb; + int64_t pos = avio_tell(pb); + if(pos < 0) + return; + pos -= ts->pos47_full; + if (pos == TS_PACKET_SIZE) { + ts->size_stat[0] ++; + } else if (pos == TS_DVHS_PACKET_SIZE) { + ts->size_stat[1] ++; + } else if (pos == TS_FEC_PACKET_SIZE) { + ts->size_stat[2] ++; + } + + ts->size_stat_count ++; + if(ts->size_stat_count > SIZE_STAT_THRESHOLD) { + int newsize = 0; + if (ts->size_stat[0] > SIZE_STAT_THRESHOLD) { + newsize = TS_PACKET_SIZE; + } else if (ts->size_stat[1] > SIZE_STAT_THRESHOLD) { + newsize = TS_DVHS_PACKET_SIZE; + } else if (ts->size_stat[2] > SIZE_STAT_THRESHOLD) { + newsize = TS_FEC_PACKET_SIZE; + } + if (newsize && newsize != ts->raw_packet_size) { + av_log(ts->stream, AV_LOG_WARNING, "changing packet size to %d\n", newsize); + ts->raw_packet_size = newsize; + } + ts->size_stat_count = 0; + memset(ts->size_stat, 0, sizeof(ts->size_stat)); + } +} + /* XXX: try to find a better synchro over several packets (use get_packet_size() ?) */ static int mpegts_resync(AVFormatContext *s) @@ -1841,6 +1952,7 @@ static int mpegts_resync(AVFormatContext *s) return -1; if (c == 0x47) { avio_seek(pb, -1, SEEK_CUR); + reanalyze(s->priv_data); return 0; } } @@ -1850,37 +1962,43 @@ static int mpegts_resync(AVFormatContext *s) } /* return -1 if error or EOF. Return 0 if OK. */ -static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size) +static int read_packet(AVFormatContext *s, uint8_t *buf, int raw_packet_size, const uint8_t **data) { AVIOContext *pb = s->pb; - int skip, len; + int len; for(;;) { - len = avio_read(pb, buf, TS_PACKET_SIZE); + len = ffio_read_indirect(pb, buf, TS_PACKET_SIZE, data); if (len != TS_PACKET_SIZE) return len < 0 ? len : AVERROR_EOF; /* check packet sync byte */ - if (buf[0] != 0x47) { + if ((*data)[0] != 0x47) { /* find a new packet start */ - avio_seek(pb, -TS_PACKET_SIZE, SEEK_CUR); + avio_seek(pb, -raw_packet_size, SEEK_CUR); if (mpegts_resync(s) < 0) return AVERROR(EAGAIN); else continue; } else { - skip = raw_packet_size - TS_PACKET_SIZE; - if (skip > 0) - avio_skip(pb, skip); break; } } return 0; } +static void finished_reading_packet(AVFormatContext *s, int raw_packet_size) +{ + AVIOContext *pb = s->pb; + int skip = raw_packet_size - TS_PACKET_SIZE; + if (skip > 0) + avio_skip(pb, skip); +} + static int handle_packets(MpegTSContext *ts, int nb_packets) { AVFormatContext *s = ts->stream; uint8_t packet[TS_PACKET_SIZE + FF_INPUT_BUFFER_PADDING_SIZE]; + const uint8_t *data; int packet_num, ret = 0; if (avio_tell(s->pb) != ts->last_pos) { @@ -1894,6 +2012,7 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) av_buffer_unref(&pes->buffer); pes->data_index = 0; pes->state = MPEGTS_SKIP; /* skip until pes header */ + pes->last_pcr = -1; } ts->pids[i]->last_cc = -1; } @@ -1913,10 +2032,11 @@ static int handle_packets(MpegTSContext *ts, int nb_packets) if (ts->stop_parse > 0) break; - ret = read_packet(s, packet, ts->raw_packet_size); + ret = read_packet(s, packet, ts->raw_packet_size, &data); if (ret != 0) break; - ret = handle_packet(ts, packet); + ret = handle_packet(ts, data); + finished_reading_packet(s, ts->raw_packet_size); if (ret != 0) break; } @@ -1986,6 +2106,15 @@ static int parse_pcr(int64_t *ppcr_high, int *ppcr_low, return 0; } +static void seek_back(AVFormatContext *s, AVIOContext *pb, int64_t pos) { + + /* NOTE: We attempt to seek on non-seekable files as well, as the + * probe buffer usually is big enough. Only warn if the seek failed + * on files where the seek should work. */ + if (avio_seek(pb, pos, SEEK_SET) < 0) + av_log(s, pb->seekable ? AV_LOG_ERROR : AV_LOG_INFO, "Unable to seek back to the start\n"); +} + static int mpegts_read_header(AVFormatContext *s) { MpegTSContext *ts = s->priv_data; @@ -1994,6 +2123,8 @@ static int mpegts_read_header(AVFormatContext *s) int len; int64_t pos; + ffio_ensure_seekback(pb, s->probesize); + /* read the first 8192 bytes to get packet size */ pos = avio_tell(pb); len = avio_read(pb, buf, sizeof(buf)); @@ -2009,11 +2140,7 @@ static int mpegts_read_header(AVFormatContext *s) /* normal demux */ /* first do a scan to get all the services */ - /* NOTE: We attempt to seek on non-seekable files as well, as the - * probe buffer usually is big enough. Only warn if the seek failed - * on files where the seek should work. */ - if (avio_seek(pb, pos, SEEK_SET) < 0) - av_log(s, pb->seekable ? AV_LOG_ERROR : AV_LOG_INFO, "Unable to seek back to the start\n"); + seek_back(s, pb, pos); mpegts_open_section_filter(ts, SDT_PID, sdt_cb, ts, 1); @@ -2033,6 +2160,7 @@ static int mpegts_read_header(AVFormatContext *s) int64_t pcrs[2], pcr_h; int packet_count[2]; uint8_t packet[TS_PACKET_SIZE]; + const uint8_t *data; /* only read packets */ @@ -2048,18 +2176,21 @@ static int mpegts_read_header(AVFormatContext *s) nb_pcrs = 0; nb_packets = 0; for(;;) { - ret = read_packet(s, packet, ts->raw_packet_size); + ret = read_packet(s, packet, ts->raw_packet_size, &data); if (ret < 0) - return -1; - pid = AV_RB16(packet + 1) & 0x1fff; + goto fail; + pid = AV_RB16(data + 1) & 0x1fff; if ((pcr_pid == -1 || pcr_pid == pid) && - parse_pcr(&pcr_h, &pcr_l, packet) == 0) { + parse_pcr(&pcr_h, &pcr_l, data) == 0) { + finished_reading_packet(s, ts->raw_packet_size); pcr_pid = pid; packet_count[nb_pcrs] = nb_packets; pcrs[nb_pcrs] = pcr_h * 300 + pcr_l; nb_pcrs++; if (nb_pcrs >= 2) break; + } else { + finished_reading_packet(s, ts->raw_packet_size); } nb_packets++; } @@ -2075,7 +2206,7 @@ static int mpegts_read_header(AVFormatContext *s) st->start_time / 1000000.0, pcrs[0] / 27e6, ts->pcr_incr); } - avio_seek(pb, pos, SEEK_SET); + seek_back(s, pb, pos); return 0; fail: return -1; @@ -2091,15 +2222,19 @@ static int mpegts_raw_read_packet(AVFormatContext *s, int64_t pcr_h, next_pcr_h, pos; int pcr_l, next_pcr_l; uint8_t pcr_buf[12]; + const uint8_t *data; if (av_new_packet(pkt, TS_PACKET_SIZE) < 0) return AVERROR(ENOMEM); pkt->pos= avio_tell(s->pb); - ret = read_packet(s, pkt->data, ts->raw_packet_size); + ret = read_packet(s, pkt->data, ts->raw_packet_size, &data); if (ret < 0) { av_free_packet(pkt); return ret; } + if (data != pkt->data) + memcpy(pkt->data, data, ts->raw_packet_size); + finished_reading_packet(s, ts->raw_packet_size); if (ts->mpeg2ts_compute_pcr) { /* compute exact PCR for each packet */ if (parse_pcr(&pcr_h, &pcr_l, pkt->data) == 0) { @@ -2181,13 +2316,15 @@ static av_unused int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index, int64_t pos, timestamp; uint8_t buf[TS_PACKET_SIZE]; int pcr_l, pcr_pid = ((PESContext*)s->streams[stream_index]->priv_data)->pcr_pid; - pos = ((*ppos + ts->raw_packet_size - 1 - ts->pos47) / ts->raw_packet_size) * ts->raw_packet_size + ts->pos47; + int pos47 = ts->pos47_full % ts->raw_packet_size; + pos = ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) * ts->raw_packet_size + pos47; while(pos < pos_limit) { if (avio_seek(s->pb, pos, SEEK_SET) < 0) return AV_NOPTS_VALUE; if (avio_read(s->pb, buf, TS_PACKET_SIZE) != TS_PACKET_SIZE) return AV_NOPTS_VALUE; if (buf[0] != 0x47) { + avio_seek(s->pb, -TS_PACKET_SIZE, SEEK_CUR); if (mpegts_resync(s) < 0) return AV_NOPTS_VALUE; pos = avio_tell(s->pb); @@ -2209,7 +2346,8 @@ static int64_t mpegts_get_dts(AVFormatContext *s, int stream_index, { MpegTSContext *ts = s->priv_data; int64_t pos; - pos = ((*ppos + ts->raw_packet_size - 1 - ts->pos47) / ts->raw_packet_size) * ts->raw_packet_size + ts->pos47; + int pos47 = ts->pos47_full % ts->raw_packet_size; + pos = ((*ppos + ts->raw_packet_size - 1 - pos47) / ts->raw_packet_size) * ts->raw_packet_size + pos47; ff_read_frame_flush(s); if (avio_seek(s->pb, pos, SEEK_SET) < 0) return AV_NOPTS_VALUE; @@ -2298,6 +2436,7 @@ AVInputFormat ff_mpegts_demuxer = { .read_close = mpegts_read_close, .read_timestamp = mpegts_get_dts, .flags = AVFMT_SHOW_IDS | AVFMT_TS_DISCONT, + .priv_class = &mpegts_class, }; AVInputFormat ff_mpegtsraw_demuxer = { diff --git a/chromium/third_party/ffmpeg/libavformat/mpegtsenc.c b/chromium/third_party/ffmpeg/libavformat/mpegtsenc.c index 0ddae651de0..1d51b97bdf0 100644 --- a/chromium/third_party/ffmpeg/libavformat/mpegtsenc.c +++ b/chromium/third_party/ffmpeg/libavformat/mpegtsenc.c @@ -85,6 +85,7 @@ typedef struct MpegTSWrite { #define MPEGTS_FLAG_AAC_LATM 0x02 int flags; int copyts; + int tables_version; } MpegTSWrite; /* a PES packet header is generated every DEFAULT_PES_HEADER_FREQ packets */ @@ -119,8 +120,10 @@ static const AVOption options[] = { // backward compatibility { "resend_headers", "Reemit PAT/PMT before writing the next packet", offsetof(MpegTSWrite, reemit_pat_pmt), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, - { "mpegts_copyts", "dont offset dts/pts", + { "mpegts_copyts", "don't offset dts/pts", offsetof(MpegTSWrite, copyts), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, AV_OPT_FLAG_ENCODING_PARAM}, + { "tables_version", "set PAT, PMT and SDT version", + offsetof(MpegTSWrite, tables_version), AV_OPT_TYPE_INT, {.i64=0}, 0, 31, AV_OPT_FLAG_ENCODING_PARAM}, { NULL }, }; @@ -252,7 +255,7 @@ static void mpegts_write_pat(AVFormatContext *s) put16(&q, service->sid); put16(&q, 0xe000 | service->pmt.pid); } - mpegts_write_section1(&ts->pat, PAT_TID, ts->tsid, 0, 0, 0, + mpegts_write_section1(&ts->pat, PAT_TID, ts->tsid, ts->tables_version, 0, 0, data, q - data); } @@ -397,13 +400,23 @@ static void mpegts_write_pmt(AVFormatContext *s, MpegTSService *service) *q++ = 'c'; } break; + case AVMEDIA_TYPE_DATA: + if (st->codec->codec_id == AV_CODEC_ID_SMPTE_KLV) { + *q++ = 0x05; /* MPEG-2 registration descriptor */ + *q++ = 4; + *q++ = 'K'; + *q++ = 'L'; + *q++ = 'V'; + *q++ = 'A'; + } + break; } val = 0xf000 | (q - desc_length_ptr - 2); desc_length_ptr[0] = val >> 8; desc_length_ptr[1] = val; } - mpegts_write_section1(&service->pmt, PMT_TID, service->sid, 0, 0, 0, + mpegts_write_section1(&service->pmt, PMT_TID, service->sid, ts->tables_version, 0, 0, data, q - data); } @@ -458,7 +471,7 @@ static void mpegts_write_sdt(AVFormatContext *s) desc_list_len_ptr[0] = val >> 8; desc_list_len_ptr[1] = val; } - mpegts_write_section1(&ts->sdt, SDT_TID, ts->tsid, 0, 0, 0, + mpegts_write_section1(&ts->sdt, SDT_TID, ts->tsid, ts->tables_version, 0, 0, data, q - data); } @@ -977,8 +990,8 @@ static void mpegts_write_pes(AVFormatContext *s, AVStream *st, *q++ = len >> 8; *q++ = len; val = 0x80; - /* data alignment indicator is required for subtitle data */ - if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE) + /* data alignment indicator is required for subtitle and data streams */ + if (st->codec->codec_type == AVMEDIA_TYPE_SUBTITLE || st->codec->codec_type == AVMEDIA_TYPE_DATA) val |= 0x04; *q++ = val; *q++ = flags; diff --git a/chromium/third_party/ffmpeg/libavformat/mpegvideodec.c b/chromium/third_party/ffmpeg/libavformat/mpegvideodec.c index 471d2f4d943..a400978d024 100644 --- a/chromium/third_party/ffmpeg/libavformat/mpegvideodec.c +++ b/chromium/third_party/ffmpeg/libavformat/mpegvideodec.c @@ -63,8 +63,8 @@ static int mpegvideo_probe(AVProbeData *p) } } if(seq && seq*9<=pic*10 && pic*9<=slice*10 && !pspack && !apes && !res && slice > sicle) { - if(vpes) return AVPROBE_SCORE_MAX/8; - else return pic>1 ? AVPROBE_SCORE_MAX/2+1 : AVPROBE_SCORE_MAX/4; // +1 for .mpg + if(vpes) return AVPROBE_SCORE_EXTENSION / 4; + else return pic>1 ? AVPROBE_SCORE_EXTENSION + 1 : AVPROBE_SCORE_EXTENSION / 2; // +1 for .mpg } return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/mpsubdec.c b/chromium/third_party/ffmpeg/libavformat/mpsubdec.c index 2acafaa81b4..6a0cefbeb68 100644 --- a/chromium/third_party/ffmpeg/libavformat/mpsubdec.c +++ b/chromium/third_party/ffmpeg/libavformat/mpsubdec.c @@ -37,11 +37,10 @@ static int mpsub_probe(AVProbeData *p) const char *ptr_end = p->buf + p->buf_size; while (ptr < ptr_end) { - int n; - - if (!memcmp(ptr, "FORMAT=TIME", 11) || - sscanf(ptr, "FORMAT=%d", &n) == 1) - return AVPROBE_SCORE_MAX/2; + if (!memcmp(ptr, "FORMAT=TIME", 11)) + return AVPROBE_SCORE_EXTENSION; + if (!memcmp(ptr, "FORMAT=", 7)) + return AVPROBE_SCORE_EXTENSION / 3; ptr += strcspn(ptr, "\n") + 1; } return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/mtv.c b/chromium/third_party/ffmpeg/libavformat/mtv.c index 6ffbb51ff2c..29c26c6811d 100644 --- a/chromium/third_party/ffmpeg/libavformat/mtv.c +++ b/chromium/third_party/ffmpeg/libavformat/mtv.c @@ -42,10 +42,10 @@ typedef struct MTVDemuxContext { unsigned int audio_br; ///< bitrate of audio channel (mp3) unsigned int img_colorfmt; ///< frame colorfmt rgb 565/555 unsigned int img_bpp; ///< frame bits per pixel - unsigned int img_width; // - unsigned int img_height; // + unsigned int img_width; + unsigned int img_height; unsigned int img_segment_size; ///< size of image segment - unsigned int video_fps; // + unsigned int video_fps; unsigned int full_segment_size; } MTVDemuxContext; @@ -64,13 +64,13 @@ static int mtv_probe(AVProbeData *p) if(!AV_RL16(&p->buf[52]) || !AV_RL16(&p->buf[54])) { if(!!AV_RL16(&p->buf[56])) - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; else return 0; } if(p->buf[51] != 16) - return AVPROBE_SCORE_MAX/4; // But we are going to assume 16bpp anyway .. + return AVPROBE_SCORE_EXTENSION / 2; // But we are going to assume 16bpp anyway .. return AVPROBE_SCORE_MAX; } diff --git a/chromium/third_party/ffmpeg/libavformat/mux.c b/chromium/third_party/ffmpeg/libavformat/mux.c index 1153ab69a84..aa5d5edebc9 100644 --- a/chromium/third_party/ffmpeg/libavformat/mux.c +++ b/chromium/third_party/ffmpeg/libavformat/mux.c @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* #define DEBUG */ - #include "avformat.h" #include "avio_internal.h" #include "internal.h" @@ -34,6 +32,7 @@ #include "id3v2.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/internal.h" #include "libavutil/mathematics.h" #include "libavutil/parseutils.h" #include "libavutil/time.h" @@ -275,13 +274,18 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) if (av_cmp_q(st->sample_aspect_ratio, codec->sample_aspect_ratio) && FFABS(av_q2d(st->sample_aspect_ratio) - av_q2d(codec->sample_aspect_ratio)) > 0.004*av_q2d(st->sample_aspect_ratio) ) { - av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between muxer " - "(%d/%d) and encoder layer (%d/%d)\n", - st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, - codec->sample_aspect_ratio.num, - codec->sample_aspect_ratio.den); - ret = AVERROR(EINVAL); - goto fail; + if (st->sample_aspect_ratio.num != 0 && + st->sample_aspect_ratio.den != 0 && + codec->sample_aspect_ratio.den != 0 && + codec->sample_aspect_ratio.den != 0) { + av_log(s, AV_LOG_ERROR, "Aspect ratio mismatch between muxer " + "(%d/%d) and encoder layer (%d/%d)\n", + st->sample_aspect_ratio.num, st->sample_aspect_ratio.den, + codec->sample_aspect_ratio.num, + codec->sample_aspect_ratio.den); + ret = AVERROR(EINVAL); + goto fail; + } } break; } @@ -298,12 +302,12 @@ static int init_muxer(AVFormatContext *s, AVDictionary **options) } if (codec->codec_tag) { if (!validate_codec_tag(s, st)) { - char tagbuf[32], cortag[32]; + char tagbuf[32], tagbuf2[32]; av_get_codec_tag_string(tagbuf, sizeof(tagbuf), codec->codec_tag); - av_get_codec_tag_string(cortag, sizeof(cortag), av_codec_get_tag(s->oformat->codec_tag, codec->codec_id)); + av_get_codec_tag_string(tagbuf2, sizeof(tagbuf2), av_codec_get_tag(s->oformat->codec_tag, codec->codec_id)); av_log(s, AV_LOG_ERROR, "Tag %s/0x%08x incompatible with output codec id '%d' (%s)\n", - tagbuf, codec->codec_tag, codec->codec_id, cortag); + tagbuf, codec->codec_tag, codec->codec_id, tagbuf2); ret = AVERROR_INVALIDDATA; goto fail; } @@ -398,6 +402,13 @@ int avformat_write_header(AVFormatContext *s, AVDictionary **options) if ((ret = init_pts(s)) < 0) return ret; + if (s->avoid_negative_ts < 0) { + if (s->oformat->flags & (AVFMT_TS_NEGATIVE | AVFMT_NOTIMESTAMPS)) { + s->avoid_negative_ts = 0; + } else + s->avoid_negative_ts = 1; + } + return 0; } @@ -485,13 +496,43 @@ static int compute_pkt_fields2(AVFormatContext *s, AVStream *st, AVPacket *pkt) } /** - * Move side data from payload to internal struct, call muxer, and restore - * original packet. + * Make timestamps non negative, move side data from payload to internal struct, call muxer, and restore + * sidedata. + * + * FIXME: this function should NEVER get undefined pts/dts beside when the + * AVFMT_NOTIMESTAMPS is set. + * Those additional safety checks should be dropped once the correct checks + * are set in the callers. */ -static inline int split_write_packet(AVFormatContext *s, AVPacket *pkt) +static int write_packet(AVFormatContext *s, AVPacket *pkt) { int ret, did_split; + if (s->avoid_negative_ts > 0) { + AVStream *st = s->streams[pkt->stream_index]; + int64_t offset = st->mux_ts_offset; + + if (pkt->dts < 0 && pkt->dts != AV_NOPTS_VALUE && !s->offset) { + s->offset = -pkt->dts; + s->offset_timebase = st->time_base; + } + + if (s->offset && !offset) { + offset = st->mux_ts_offset = + av_rescale_q_rnd(s->offset, + s->offset_timebase, + st->time_base, + AV_ROUND_UP); + } + + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += offset; + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts += offset; + + av_assert2(pkt->dts == AV_NOPTS_VALUE || pkt->dts >= 0); + } + did_split = av_packet_split_side_data(pkt); ret = s->oformat->write_packet(s, pkt); if (s->flush_packets && s->pb && s->pb->error >= 0) @@ -522,7 +563,7 @@ int av_write_frame(AVFormatContext *s, AVPacket *pkt) if (ret < 0 && !(s->oformat->flags & AVFMT_NOTIMESTAMPS)) return ret; - ret = split_write_packet(s, pkt); + ret = write_packet(s, pkt); if (ret >= 0 && s->pb && s->pb->error < 0) ret = s->pb->error; @@ -545,10 +586,13 @@ int ff_interleave_add_packet(AVFormatContext *s, AVPacket *pkt, return AVERROR(ENOMEM); this_pktl->pkt = *pkt; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS pkt->destruct = NULL; // do not free original but only the copy +FF_ENABLE_DEPRECATION_WARNINGS #endif pkt->buf = NULL; av_dup_packet(&this_pktl->pkt); // duplicate the packet if it uses non-allocated memory + av_copy_packet_side_data(&this_pktl->pkt, &this_pktl->pkt); // copy side data if (s->streams[pkt->stream_index]->last_in_packet_buffer) { next_point = &(st->last_in_packet_buffer->next); @@ -600,7 +644,8 @@ next_non_null: return 0; } -static int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacket *pkt) +static int interleave_compare_dts(AVFormatContext *s, AVPacket *next, + AVPacket *pkt) { AVStream *st = s->streams[pkt->stream_index]; AVStream *st2 = s->streams[next->stream_index]; @@ -631,7 +676,7 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, int i, ret; if (pkt) { - ret = ff_interleave_add_packet(s, pkt, ff_interleave_compare_dts); + ret = ff_interleave_add_packet(s, pkt, interleave_compare_dts); if (ret < 0) return ret; } @@ -679,23 +724,6 @@ int ff_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, st->last_in_packet_buffer = NULL; av_freep(&pktl); - if (s->avoid_negative_ts > 0) { - if (out->dts != AV_NOPTS_VALUE) { - if (!st->mux_ts_offset && out->dts < 0) { - for (i = 0; i < s->nb_streams; i++) { - s->streams[i]->mux_ts_offset = - av_rescale_q_rnd(-out->dts, - st->time_base, - s->streams[i]->time_base, - AV_ROUND_UP); - } - } - out->dts += st->mux_ts_offset; - } - if (out->pts != AV_NOPTS_VALUE) - out->pts += st->mux_ts_offset; - } - return 1; } else { av_init_packet(out); @@ -752,7 +780,7 @@ int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt) if (ret <= 0) //FIXME cleanup needed for ret<0 ? return ret; - ret = split_write_packet(s, &opkt); + ret = write_packet(s, &opkt); if (ret >= 0) s->streams[opkt.stream_index]->nb_frames++; @@ -778,7 +806,7 @@ int av_write_trailer(AVFormatContext *s) if (!ret) break; - ret = split_write_packet(s, &pkt); + ret = write_packet(s, &pkt); if (ret >= 0) s->streams[pkt.stream_index]->nb_frames++; @@ -816,3 +844,25 @@ int av_get_output_timestamp(struct AVFormatContext *s, int stream, s->oformat->get_output_timestamp(s, stream, dts, wall); return 0; } + +int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, + AVFormatContext *src) +{ + AVPacket local_pkt; + + local_pkt = *pkt; + local_pkt.stream_index = dst_stream; + if (pkt->pts != AV_NOPTS_VALUE) + local_pkt.pts = av_rescale_q(pkt->pts, + src->streams[pkt->stream_index]->time_base, + dst->streams[dst_stream]->time_base); + if (pkt->dts != AV_NOPTS_VALUE) + local_pkt.dts = av_rescale_q(pkt->dts, + src->streams[pkt->stream_index]->time_base, + dst->streams[dst_stream]->time_base); + if (pkt->duration) + local_pkt.duration = av_rescale_q(pkt->duration, + src->streams[pkt->stream_index]->time_base, + dst->streams[dst_stream]->time_base); + return av_write_frame(dst, &local_pkt); +} diff --git a/chromium/third_party/ffmpeg/libavformat/mxfdec.c b/chromium/third_party/ffmpeg/libavformat/mxfdec.c index 286a884cc7e..29a2f563e6c 100644 --- a/chromium/third_party/ffmpeg/libavformat/mxfdec.c +++ b/chromium/third_party/ffmpeg/libavformat/mxfdec.c @@ -43,8 +43,6 @@ * Only tracks with associated descriptors will be decoded. "Highly Desirable" SMPTE 377M D.1 */ -//#define DEBUG - #include "libavutil/aes.h" #include "libavutil/avassert.h" #include "libavutil/mathematics.h" @@ -1603,8 +1601,10 @@ static int mxf_parse_structural_metadata(MXFContext *mxf) } if (descriptor->extradata) { st->codec->extradata = av_mallocz(descriptor->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); - if (st->codec->extradata) + if (st->codec->extradata) { memcpy(st->codec->extradata, descriptor->extradata, descriptor->extradata_size); + st->codec->extradata_size = descriptor->extradata_size; + } } else if(st->codec->codec_id == AV_CODEC_ID_H264) { ff_generate_avci_extradata(st); } @@ -2210,10 +2210,8 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) KLVPacket klv; MXFContext *mxf = s->priv_data; - while (!url_feof(s->pb)) { + while (klv_read_packet(&klv, s->pb) == 0) { int ret; - if (klv_read_packet(&klv, s->pb) < 0) - return -1; PRINT_KEY(s, "read packet", klv.key); av_dlog(s, "size %"PRIu64" offset %#"PRIx64"\n", klv.length, klv.offset); if (IS_KLV_KEY(klv.key, mxf_encrypted_triplet_key)) { @@ -2298,7 +2296,7 @@ static int mxf_read_packet_old(AVFormatContext *s, AVPacket *pkt) skip: avio_skip(s->pb, klv.length); } - return AVERROR_EOF; + return url_feof(s->pb) ? AVERROR_EOF : -1; } static int mxf_read_packet(AVFormatContext *s, AVPacket *pkt) diff --git a/chromium/third_party/ffmpeg/libavformat/mxfenc.c b/chromium/third_party/ffmpeg/libavformat/mxfenc.c index ea13ee06503..52cb2826b8f 100644 --- a/chromium/third_party/ffmpeg/libavformat/mxfenc.c +++ b/chromium/third_party/ffmpeg/libavformat/mxfenc.c @@ -30,8 +30,6 @@ * SMPTE RP224: Registry of SMPTE Universal Labels */ -//#define DEBUG - #include <inttypes.h> #include <math.h> #include <time.h> @@ -44,6 +42,7 @@ #include "libavcodec/dnxhddata.h" #include "audiointerleave.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #include "mxf.h" #include "config.h" @@ -1296,13 +1295,12 @@ static void mxf_write_klv_fill(AVFormatContext *s) avio_write(s->pb, klv_fill_key, 16); pad -= 16 + 4; klv_encode_ber4_length(s->pb, pad); - for (; pad; pad--) - avio_w8(s->pb, 0); + ffio_fill(s->pb, 0, pad); av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1))); } } -static void mxf_write_partition(AVFormatContext *s, int bodysid, +static int mxf_write_partition(AVFormatContext *s, int bodysid, int indexsid, const uint8_t *key, int write_metadata) { @@ -1311,6 +1309,7 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid, int64_t header_byte_count_offset; unsigned index_byte_count = 0; uint64_t partition_offset = avio_tell(pb); + int err; if (!mxf->edit_unit_byte_count && mxf->edit_units_count) index_byte_count = 85 + 12+(s->nb_streams+1)*6 + @@ -1325,10 +1324,11 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid, } if (!memcmp(key, body_partition_key, 16)) { - mxf->body_partition_offset = - av_realloc(mxf->body_partition_offset, - (mxf->body_partitions_count+1)* - sizeof(*mxf->body_partition_offset)); + if ((err = av_reallocp_array(&mxf->body_partition_offset, mxf->body_partitions_count + 1, + sizeof(*mxf->body_partition_offset))) < 0) { + mxf->body_partitions_count = 0; + return err; + } mxf->body_partition_offset[mxf->body_partitions_count++] = partition_offset; } @@ -1393,6 +1393,8 @@ static void mxf_write_partition(AVFormatContext *s, int bodysid, } avio_flush(pb); + + return 0; } static int mxf_parse_dnxhd_frame(AVFormatContext *s, AVStream *st, @@ -1872,13 +1874,11 @@ static void mxf_write_d10_video_packet(AVFormatContext *s, AVStream *st, AVPacke avio_write(s->pb, klv_fill_key, 16); pad -= 16 + 4; klv_encode_ber4_length(s->pb, pad); - for (; pad; pad--) - avio_w8(s->pb, 0); + ffio_fill(s->pb, 0, pad); av_assert1(!(avio_tell(s->pb) & (KAG_SIZE-1))); } else { av_log(s, AV_LOG_WARNING, "cannot fill d-10 video packet\n"); - for (; pad > 0; pad--) - avio_w8(s->pb, 0); + ffio_fill(s->pb, 0, pad); } } @@ -1921,13 +1921,14 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) AVStream *st = s->streams[pkt->stream_index]; MXFStreamContext *sc = st->priv_data; MXFIndexEntry ie = {0}; + int err; if (!mxf->edit_unit_byte_count && !(mxf->edit_units_count % EDIT_UNITS_PER_BODY)) { - mxf->index_entries = av_realloc(mxf->index_entries, - (mxf->edit_units_count + EDIT_UNITS_PER_BODY)*sizeof(*mxf->index_entries)); - if (!mxf->index_entries) { + if ((err = av_reallocp_array(&mxf->index_entries, mxf->edit_units_count + + EDIT_UNITS_PER_BODY, sizeof(*mxf->index_entries))) < 0) { + mxf->edit_units_count = 0; av_log(s, AV_LOG_ERROR, "could not allocate index entries\n"); - return -1; + return err; } } @@ -1950,11 +1951,13 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) if (!mxf->header_written) { if (mxf->edit_unit_byte_count) { - mxf_write_partition(s, 1, 2, header_open_partition_key, 1); + if ((err = mxf_write_partition(s, 1, 2, header_open_partition_key, 1)) < 0) + return err; mxf_write_klv_fill(s); mxf_write_index_table_segment(s); } else { - mxf_write_partition(s, 0, 0, header_open_partition_key, 1); + if ((err = mxf_write_partition(s, 0, 0, header_open_partition_key, 1)) < 0) + return err; } mxf->header_written = 1; } @@ -1964,8 +1967,8 @@ static int mxf_write_packet(AVFormatContext *s, AVPacket *pkt) (!mxf->edit_units_count || mxf->edit_units_count > EDIT_UNITS_PER_BODY) && !(ie.flags & 0x33)) { // I frame, Gop start mxf_write_klv_fill(s); - mxf_write_partition(s, 1, 2, body_partition_key, 0); - + if ((err = mxf_write_partition(s, 1, 2, body_partition_key, 0)) < 0) + return err; mxf_write_klv_fill(s); mxf_write_index_table_segment(s); } @@ -2034,16 +2037,18 @@ static int mxf_write_footer(AVFormatContext *s) { MXFContext *mxf = s->priv_data; AVIOContext *pb = s->pb; + int err; mxf->duration = mxf->last_indexed_edit_unit + mxf->edit_units_count; mxf_write_klv_fill(s); mxf->footer_partition_offset = avio_tell(pb); if (mxf->edit_unit_byte_count) { // no need to repeat index - mxf_write_partition(s, 0, 0, footer_partition_key, 0); + if ((err = mxf_write_partition(s, 0, 0, footer_partition_key, 0)) < 0) + return err; } else { - mxf_write_partition(s, 0, 2, footer_partition_key, 0); - + if ((err = mxf_write_partition(s, 0, 2, footer_partition_key, 0)) < 0) + return err; mxf_write_klv_fill(s); mxf_write_index_table_segment(s); } @@ -2054,11 +2059,13 @@ static int mxf_write_footer(AVFormatContext *s) if (s->pb->seekable) { avio_seek(pb, 0, SEEK_SET); if (mxf->edit_unit_byte_count) { - mxf_write_partition(s, 1, 2, header_closed_partition_key, 1); + if ((err = mxf_write_partition(s, 1, 2, header_closed_partition_key, 1)) < 0) + return err; mxf_write_klv_fill(s); mxf_write_index_table_segment(s); } else { - mxf_write_partition(s, 0, 0, header_closed_partition_key, 1); + if ((err = mxf_write_partition(s, 0, 0, header_closed_partition_key, 1)) < 0) + return err; } } diff --git a/chromium/third_party/ffmpeg/libavformat/mxg.c b/chromium/third_party/ffmpeg/libavformat/mxg.c index 604be785bcf..b2b5b86c6f7 100644 --- a/chromium/third_party/ffmpeg/libavformat/mxg.c +++ b/chromium/third_party/ffmpeg/libavformat/mxg.c @@ -20,6 +20,7 @@ */ #include "libavutil/channel_layout.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavcodec/mjpeg.h" #include "avformat.h" @@ -74,7 +75,7 @@ static int mxg_read_header(AVFormatContext *s) static uint8_t* mxg_find_startmarker(uint8_t *p, uint8_t *end) { for (; p < end - 3; p += 4) { - uint32_t x = *(uint32_t*)p; + uint32_t x = AV_RN32(p); if (x & (~(x+0x01010101)) & 0x80808080) { if (p[0] == 0xff) { @@ -171,7 +172,9 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->pts = pkt->dts = mxg->dts; pkt->stream_index = 0; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS pkt->destruct = NULL; +FF_ENABLE_DEPRECATION_WARNINGS #endif pkt->buf = NULL; pkt->size = mxg->buffer_ptr - mxg->soi_ptr; @@ -212,7 +215,9 @@ static int mxg_read_packet(AVFormatContext *s, AVPacket *pkt) pkt->pts = pkt->dts = AV_RL64(startmarker_ptr + 8); pkt->stream_index = 1; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS pkt->destruct = NULL; +FF_ENABLE_DEPRECATION_WARNINGS #endif pkt->buf = NULL; pkt->size = size - 14; diff --git a/chromium/third_party/ffmpeg/libavformat/network.c b/chromium/third_party/ffmpeg/libavformat/network.c index ceed719356d..73409616cdd 100644 --- a/chromium/third_party/ffmpeg/libavformat/network.c +++ b/chromium/third_party/ffmpeg/libavformat/network.c @@ -18,9 +18,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/avutil.h" +#include <fcntl.h> #include "network.h" +#include "url.h" #include "libavcodec/internal.h" +#include "libavutil/avutil.h" #include "libavutil/mem.h" #include "url.h" #include "libavutil/time.h" @@ -29,9 +31,9 @@ #if HAVE_PTHREADS #include <pthread.h> #elif HAVE_OS2THREADS -#include "libavcodec/os2threads.h" +#include "compat/os2threads.h" #else -#include "libavcodec/w32pthreads.h" +#include "compat/w32pthreads.h" #endif #endif @@ -156,12 +158,12 @@ int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterrupt int64_t wait_start = 0; while (1) { + if (ff_check_interrupt(int_cb)) + return AVERROR_EXIT; ret = ff_network_wait_fd(fd, write); if (ret != AVERROR(EAGAIN)) return ret; - if (ff_check_interrupt(int_cb)) - return AVERROR_EXIT; - if (timeout) { + if (timeout > 0) { if (!wait_start) wait_start = av_gettime(); else if (av_gettime() - wait_start > timeout) @@ -212,3 +214,171 @@ int ff_is_multicast_address(struct sockaddr *addr) return 0; } + +static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout, + AVIOInterruptCB *cb) +{ + int runs = timeout / POLLING_TIME; + int ret = 0; + + do { + if (ff_check_interrupt(cb)) + return AVERROR_EXIT; + ret = poll(p, nfds, POLLING_TIME); + if (ret != 0) + break; + } while (timeout <= 0 || runs-- > 0); + + if (!ret) + return AVERROR(ETIMEDOUT); + if (ret < 0) + return AVERROR(errno); + return ret; +} + +int ff_socket(int af, int type, int proto) +{ + int fd; + +#ifdef SOCK_CLOEXEC + fd = socket(af, type | SOCK_CLOEXEC, proto); + if (fd == -1 && errno == EINVAL) +#endif + { + fd = socket(af, type, proto); +#if HAVE_FCNTL + if (fd != -1) + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif + } + return fd; +} + +int ff_listen_bind(int fd, const struct sockaddr *addr, + socklen_t addrlen, int timeout, URLContext *h) +{ + int ret; + int reuse = 1; + struct pollfd lp = { fd, POLLIN, 0 }; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) { + av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_REUSEADDR) failed\n"); + } + ret = bind(fd, addr, addrlen); + if (ret) + return ff_neterrno(); + + ret = listen(fd, 1); + if (ret) + return ff_neterrno(); + + ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback); + if (ret < 0) + return ret; + + ret = accept(fd, NULL, NULL); + if (ret < 0) + return ff_neterrno(); + + closesocket(fd); + + ff_socket_nonblock(ret, 1); + return ret; +} + +int ff_listen_connect(int fd, const struct sockaddr *addr, + socklen_t addrlen, int timeout, URLContext *h, + int will_try_next) +{ + struct pollfd p = {fd, POLLOUT, 0}; + int ret; + socklen_t optlen; + + ff_socket_nonblock(fd, 1); + + while ((ret = connect(fd, addr, addrlen))) { + ret = ff_neterrno(); + switch (ret) { + case AVERROR(EINTR): + if (ff_check_interrupt(&h->interrupt_callback)) + return AVERROR_EXIT; + continue; + case AVERROR(EINPROGRESS): + case AVERROR(EAGAIN): + ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback); + if (ret < 0) + return ret; + optlen = sizeof(ret); + if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) + ret = AVUNERROR(ff_neterrno()); + if (ret != 0) { + char errbuf[100]; + ret = AVERROR(ret); + av_strerror(ret, errbuf, sizeof(errbuf)); + if (will_try_next) + av_log(h, AV_LOG_WARNING, + "Connection to %s failed (%s), trying next address\n", + h->filename, errbuf); + else + av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n", + h->filename, errbuf); + } + default: + return ret; + } + } + return ret; +} + +static int match_host_pattern(const char *pattern, const char *hostname) +{ + int len_p, len_h; + if (!strcmp(pattern, "*")) + return 1; + // Skip a possible *. at the start of the pattern + if (pattern[0] == '*') + pattern++; + if (pattern[0] == '.') + pattern++; + len_p = strlen(pattern); + len_h = strlen(hostname); + if (len_p > len_h) + return 0; + // Simply check if the end of hostname is equal to 'pattern' + if (!strcmp(pattern, &hostname[len_h - len_p])) { + if (len_h == len_p) + return 1; // Exact match + if (hostname[len_h - len_p - 1] == '.') + return 1; // The matched substring is a domain and not just a substring of a domain + } + return 0; +} + +int ff_http_match_no_proxy(const char *no_proxy, const char *hostname) +{ + char *buf, *start; + int ret = 0; + if (!no_proxy) + return 0; + if (!hostname) + return 0; + buf = av_strdup(no_proxy); + if (!buf) + return 0; + start = buf; + while (start) { + char *sep, *next = NULL; + start += strspn(start, " ,"); + sep = start + strcspn(start, " ,"); + if (*sep) { + next = sep + 1; + *sep = '\0'; + } + if (match_host_pattern(start, hostname)) { + ret = 1; + break; + } + start = next; + } + av_free(buf); + return ret; +} diff --git a/chromium/third_party/ffmpeg/libavformat/network.h b/chromium/third_party/ffmpeg/libavformat/network.h index f8b4dee50e7..c60e1424a1c 100644 --- a/chromium/third_party/ffmpeg/libavformat/network.h +++ b/chromium/third_party/ffmpeg/libavformat/network.h @@ -28,6 +28,7 @@ #include "libavutil/error.h" #include "os_support.h" #include "avio.h" +#include "url.h" #if HAVE_UNISTD_H #include <unistd.h> @@ -89,7 +90,7 @@ int ff_network_wait_fd(int fd, int write); * @fd Socket descriptor * @write Set 1 to wait for socket able to be read, 0 to be written * @timeout Timeout interval, in microseconds. Actual precision is 100000 mcs, due to ff_network_wait_fd usage - * @param int_cb Interrupt callback, is checked after each ff_network_wait_fd call + * @param int_cb Interrupt callback, is checked before each ff_network_wait_fd call * @return 0 if data can be read/written, AVERROR(ETIMEDOUT) if timeout expired, or negative error code */ int ff_network_wait_fd_timeout(int fd, int write, int64_t timeout, AVIOInterruptCB *int_cb); @@ -222,4 +223,45 @@ const char *ff_gai_strerror(int ecode); int ff_is_multicast_address(struct sockaddr *addr); +#define POLLING_TIME 100 /// Time in milliseconds between interrupt check + +/** + * Bind to a file descriptor and poll for a connection. + * + * @param fd First argument of bind(). + * @param addr Second argument of bind(). + * @param addrlen Third argument of bind(). + * @param timeout Polling timeout in milliseconds. + * @param h URLContext providing interrupt check + * callback and logging context. + * @return A non-blocking file descriptor on success + * or an AVERROR on failure. + */ +int ff_listen_bind(int fd, const struct sockaddr *addr, + socklen_t addrlen, int timeout, + URLContext *h); + +/** + * Connect to a file descriptor and poll for result. + * + * @param fd First argument of connect(), + * will be set as non-blocking. + * @param addr Second argument of connect(). + * @param addrlen Third argument of connect(). + * @param timeout Polling timeout in milliseconds. + * @param h URLContext providing interrupt check + * callback and logging context. + * @param will_try_next Whether the caller will try to connect to another + * address for the same host name, affecting the form of + * logged errors. + * @return 0 on success, AVERROR on failure. + */ +int ff_listen_connect(int fd, const struct sockaddr *addr, + socklen_t addrlen, int timeout, + URLContext *h, int will_try_next); + +int ff_http_match_no_proxy(const char *no_proxy, const char *hostname); + +int ff_socket(int domain, int type, int protocol); + #endif /* AVFORMAT_NETWORK_H */ diff --git a/chromium/third_party/ffmpeg/libavformat/noproxy-test.c b/chromium/third_party/ffmpeg/libavformat/noproxy-test.c index a156620271a..4524764cbf0 100644 --- a/chromium/third_party/ffmpeg/libavformat/noproxy-test.c +++ b/chromium/third_party/ffmpeg/libavformat/noproxy-test.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "internal.h" +#include "network.h" static void test(const char *pattern, const char *host) { diff --git a/chromium/third_party/ffmpeg/libavformat/nsvdec.c b/chromium/third_party/ffmpeg/libavformat/nsvdec.c index e582f0f6cca..4a749a2feb3 100644 --- a/chromium/third_party/ffmpeg/libavformat/nsvdec.c +++ b/chromium/third_party/ffmpeg/libavformat/nsvdec.c @@ -28,10 +28,6 @@ #include "libavutil/dict.h" #include "libavutil/intreadwrite.h" -//#define DEBUG_DUMP_INDEX // XXX dumbdriving-271.nsv breaks with it commented!! -#define CHECK_SUBSEQUENT_NSVS -//#define DISABLE_AUDIO - /* max bytes to crawl for trying to resync * stupid streaming servers don't start at chunk boundaries... */ @@ -370,25 +366,6 @@ static int nsv_parse_NSVf_header(AVFormatContext *s) av_dlog(s, "NSV got index; filepos %"PRId64"\n", avio_tell(pb)); -#ifdef DEBUG_DUMP_INDEX -#define V(v) ((v<0x20 || v > 127)?'.':v) - /* dump index */ - av_dlog(s, "NSV %d INDEX ENTRIES:\n", table_entries); - av_dlog(s, "NSV [dataoffset][fileoffset]\n", table_entries); - for (i = 0; i < table_entries; i++) { - unsigned char b[8]; - avio_seek(pb, size + nsv->nsvs_file_offset[i], SEEK_SET); - avio_read(pb, b, 8); - av_dlog(s, "NSV [0x%08lx][0x%08lx]: %02x %02x %02x %02x %02x %02x %02x %02x" - "%c%c%c%c%c%c%c%c\n", - nsv->nsvs_file_offset[i], size + nsv->nsvs_file_offset[i], - b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7], - V(b[0]), V(b[1]), V(b[2]), V(b[3]), V(b[4]), V(b[5]), V(b[6]), V(b[7]) ); - } - //avio_seek(pb, size, SEEK_SET); /* go back to end of header */ -#undef V -#endif - avio_seek(pb, nsv->base_offset + size, SEEK_SET); /* required for dumbdriving-271.nsv (2 extra bytes) */ if (url_feof(pb)) @@ -479,7 +456,6 @@ static int nsv_parse_NSVs_header(AVFormatContext *s) } } if (atag != T_NONE) { -#ifndef DISABLE_AUDIO st = avformat_new_stream(s, NULL); if (!st) goto fail; @@ -499,15 +475,12 @@ static int nsv_parse_NSVs_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, framerate.num*1000); st->start_time = 0; st->duration = (int64_t)nsv->duration * framerate.num; -#endif } -#ifdef CHECK_SUBSEQUENT_NSVS } else { if (nsv->vtag != vtag || nsv->atag != atag || nsv->vwidth != vwidth || nsv->vheight != vwidth) { av_dlog(s, "NSV NSVs header values differ from the first one!!!\n"); //return -1; } -#endif /* CHECK_SUBSEQUENT_NSVS */ } nsv->state = NSV_HAS_READ_NSVS; @@ -786,7 +759,7 @@ static int nsv_probe(AVProbeData *p) } /* so we'll have more luck on extension... */ if (av_match_ext(p->filename, "nsv")) - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; /* FIXME: add mime-type check */ return score; } diff --git a/chromium/third_party/ffmpeg/libavformat/nut.c b/chromium/third_party/ffmpeg/libavformat/nut.c index 2abe9693080..7e7997998f9 100644 --- a/chromium/third_party/ffmpeg/libavformat/nut.c +++ b/chromium/third_party/ffmpeg/libavformat/nut.c @@ -26,125 +26,138 @@ #include "internal.h" const AVCodecTag ff_nut_subtitle_tags[] = { - { AV_CODEC_ID_TEXT , MKTAG('U', 'T', 'F', '8') }, - { AV_CODEC_ID_SSA , MKTAG('S', 'S', 'A', 0 ) }, - { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('D', 'V', 'D', 'S') }, - { AV_CODEC_ID_DVB_SUBTITLE, MKTAG('D', 'V', 'B', 'S') }, - { AV_CODEC_ID_DVB_TELETEXT, MKTAG('D', 'V', 'B', 'T') }, - { AV_CODEC_ID_NONE , 0 } + { AV_CODEC_ID_TEXT, MKTAG('U', 'T', 'F', '8') }, + { AV_CODEC_ID_SSA, MKTAG('S', 'S', 'A', 0 ) }, + { AV_CODEC_ID_DVD_SUBTITLE, MKTAG('D', 'V', 'D', 'S') }, + { AV_CODEC_ID_DVB_SUBTITLE, MKTAG('D', 'V', 'B', 'S') }, + { AV_CODEC_ID_DVB_TELETEXT, MKTAG('D', 'V', 'B', 'T') }, + { AV_CODEC_ID_NONE, 0 } }; const AVCodecTag ff_nut_data_tags[] = { - { AV_CODEC_ID_TEXT , MKTAG('U', 'T', 'F', '8') }, - { AV_CODEC_ID_NONE , 0 } + { AV_CODEC_ID_TEXT, MKTAG('U', 'T', 'F', '8') }, + { AV_CODEC_ID_NONE, 0 } }; const AVCodecTag ff_nut_video_tags[] = { - { AV_CODEC_ID_VP9, MKTAG('V', 'P', '9', '0') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 15 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 15 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(15 , 'B', 'G', 'R') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(15 , 'R', 'G', 'B') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 'B', 'G', 'R') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 'R', 'G', 'B') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 12 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 12 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 'B', 'G', 'R') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 'R', 'G', 'B') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 'A') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 0 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 'A') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 0 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'B', 'G', 'R') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG( 0 , 'B', 'G', 'R') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'R', 'G', 'B') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG( 0 , 'R', 'G', 'B') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 24 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 24 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '1', '1', 'P') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '2', '2', 'P') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '2', '2', 'P') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '4', '0', 'P') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '4', '0', 'P') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '4', '4', 'P') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '4', '4', 'P') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', '1', 'W', '0') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', '0', 'W', '1') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 8 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 8 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 4 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 4 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', '4', 'B', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', 'B', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 48 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 48 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(48 , 'B', 'G', 'R') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(48 , 'R', 'G', 'B') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'R', 'A', 64 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'B', 'A', 64 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'B', 'R', 'A') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'R', 'B', 'A') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 10 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 11 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 10 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 10 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 0 , 10 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 0 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 12 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 11 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 12 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 10 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 0 , 12 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 0 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 14 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(14 , 11 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 14 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(14 , 10 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 0 , 14 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(14 , 0 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '1', 0 , 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 0 , '1', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 11 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 10 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 0 , 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 0 , '3', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 11 , 8 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 10 , 8 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 0 , 8 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '2', 0 , 8 ) }, + { AV_CODEC_ID_VP9, MKTAG('V', 'P', '9', '0') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 15 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 15 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 16 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 16 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(15 , 'B', 'G', 'R') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(15 , 'R', 'G', 'B') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 'B', 'G', 'R') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 'R', 'G', 'B') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 12 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 12 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 'B', 'G', 'R') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 'R', 'G', 'B') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 'A') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 0 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 'A') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 0 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'B', 'G', 'R') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG( 0 , 'B', 'G', 'R') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('A', 'R', 'G', 'B') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG( 0 , 'R', 'G', 'B') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 24 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 24 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '1', '1', 'P') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '2', '2', 'P') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '2', '2', 'P') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '4', '0', 'P') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '4', '0', 'P') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '4', '4', 'P') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('4', '4', '4', 'P') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', '1', 'W', '0') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', '0', 'W', '1') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 8 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 8 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 4 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 4 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', '4', 'B', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', '4', 'B', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'G', 'R', 48 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'G', 'B', 48 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(48 , 'B', 'G', 'R') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(48 , 'R', 'G', 'B') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('B', 'R', 'A', 64 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('R', 'B', 'A', 64 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'B', 'R', 'A') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(64 , 'R', 'B', 'A') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 10 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 11 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 10 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 10 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 0 , 10 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 0 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 12 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 11 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 12 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 10 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 0 , 12 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(12 , 0 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 14 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(14 , 11 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 14 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(14 , 10 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 0 , 14 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(14 , 0 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '1', 0 , 16 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 0 , '1', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 11 , 16 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 11 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 10 , 16 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 10 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '3', 0 , 16 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 0 , '3', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 11 , 8 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 10 , 8 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 0 , 8 ) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '2', 0 , 8 ) }, + + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '1', 0, 9) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(9, 0, '1', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 11, 9) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(9, 11, '4', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 10, 9) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(9, 10, '4', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 0, 9) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(9, 0, '4', 'Y') }, + + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '1', 0, 10) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(10, 0, '1', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 11, 10) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(10, 11, '4', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 10, 10) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(10, 10, '4', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 0, 10) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(10, 0, '4', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '1', 0 , 9 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG( 9 , 0 , '1', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 11 , 9 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG( 9 , 11 , '4', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 10 , 9 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG( 9 , 10 , '4', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 0 , 9 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG( 9 , 0 , '4', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '1', 0, 16) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16, 0, '1', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 11, 16) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16, 11, '4', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 10, 16) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16, 10, '4', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 0, 16) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16, 0, '4', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '1', 0 , 10 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 0 , '1', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 11 , 10 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 11 , '4', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 10 , 10 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 10 , '4', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 0 , 10 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(10 , 0 , '4', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('G', '3', 0, 8) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '1', 0 , 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 0 , '1', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 11 , 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 11 , '4', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 10 , 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 10 , '4', 'Y') }, - { AV_CODEC_ID_RAWVIDEO, MKTAG('Y', '4', 0 , 16 ) }, - { AV_CODEC_ID_RAWVIDEO, MKTAG(16 , 0 , '4', 'Y') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('G', '3', 0, 9) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG( 9, 0, '3', 'G') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('G', '3', 0, 10) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(10, 0, '3', 'G') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('G', '3', 0, 12) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(12, 0, '3', 'G') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('G', '3', 0, 14) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(14, 0, '3', 'G') }, + { AV_CODEC_ID_RAWVIDEO, MKTAG('G', '3', 0, 16) }, + { AV_CODEC_ID_RAWVIDEO, MKTAG(16, 0, '3', 'G') }, - { AV_CODEC_ID_NONE , 0 } + { AV_CODEC_ID_NONE, 0 } }; static const AVCodecTag nut_audio_extra_tags[] = { @@ -186,42 +199,46 @@ const AVCodecTag * const ff_nut_codec_tags[] = { ff_codec_bmp_tags, ff_codec_wav_tags, nut_audio_extra_tags, ff_nut_data_tags, 0 }; -void ff_nut_reset_ts(NUTContext *nut, AVRational time_base, int64_t val){ +void ff_nut_reset_ts(NUTContext *nut, AVRational time_base, int64_t val) +{ int i; - for(i=0; i<nut->avf->nb_streams; i++){ - nut->stream[i].last_pts= av_rescale_rnd( - val, - time_base.num * (int64_t)nut->stream[i].time_base->den, - time_base.den * (int64_t)nut->stream[i].time_base->num, - AV_ROUND_DOWN); - } + for (i = 0; i < nut->avf->nb_streams; i++) + nut->stream[i].last_pts = + av_rescale_rnd(val, + time_base.num * (int64_t)nut->stream[i].time_base->den, + time_base.den * (int64_t)nut->stream[i].time_base->num, + AV_ROUND_DOWN); } -int64_t ff_lsb2full(StreamContext *stream, int64_t lsb){ - int64_t mask = (1ULL<<stream->msb_pts_shift)-1; - int64_t delta= stream->last_pts - mask/2; - return ((lsb - delta)&mask) + delta; +int64_t ff_lsb2full(StreamContext *stream, int64_t lsb) +{ + int64_t mask = (1ULL << stream->msb_pts_shift) - 1; + int64_t delta = stream->last_pts - mask / 2; + return ((lsb - delta) & mask) + delta; } -int ff_nut_sp_pos_cmp(const Syncpoint *a, const Syncpoint *b){ +int ff_nut_sp_pos_cmp(const Syncpoint *a, const Syncpoint *b) +{ return ((a->pos - b->pos) >> 32) - ((b->pos - a->pos) >> 32); } -int ff_nut_sp_pts_cmp(const Syncpoint *a, const Syncpoint *b){ +int ff_nut_sp_pts_cmp(const Syncpoint *a, const Syncpoint *b) +{ return ((a->ts - b->ts) >> 32) - ((b->ts - a->ts) >> 32); } -void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts){ - Syncpoint *sp= av_mallocz(sizeof(Syncpoint)); +void ff_nut_add_sp(NUTContext *nut, int64_t pos, int64_t back_ptr, int64_t ts) +{ + Syncpoint *sp = av_mallocz(sizeof(Syncpoint)); struct AVTreeNode *node = av_tree_node_alloc(); nut->sp_count++; - sp->pos= pos; - sp->back_ptr= back_ptr; - sp->ts= ts; + sp->pos = pos; + sp->back_ptr = back_ptr; + sp->ts = ts; av_tree_insert(&nut->syncpoints, sp, (void *) ff_nut_sp_pos_cmp, &node); - if(node){ + if (node) { av_free(sp); av_free(node); } @@ -240,13 +257,13 @@ void ff_nut_free_sp(NUTContext *nut) } const Dispositions ff_nut_dispositions[] = { - {"default" , AV_DISPOSITION_DEFAULT}, - {"dub" , AV_DISPOSITION_DUB}, - {"original" , AV_DISPOSITION_ORIGINAL}, - {"comment" , AV_DISPOSITION_COMMENT}, - {"lyrics" , AV_DISPOSITION_LYRICS}, - {"karaoke" , AV_DISPOSITION_KARAOKE}, - {"" , 0} + { "default", AV_DISPOSITION_DEFAULT }, + { "dub", AV_DISPOSITION_DUB }, + { "original", AV_DISPOSITION_ORIGINAL }, + { "comment", AV_DISPOSITION_COMMENT }, + { "lyrics", AV_DISPOSITION_LYRICS }, + { "karaoke", AV_DISPOSITION_KARAOKE }, + { "", 0 } }; const AVMetadataConv ff_nut_metadata_conv[] = { diff --git a/chromium/third_party/ffmpeg/libavformat/nut.h b/chromium/third_party/ffmpeg/libavformat/nut.h index ab31c274291..dc5af15a572 100644 --- a/chromium/third_party/ffmpeg/libavformat/nut.h +++ b/chromium/third_party/ffmpeg/libavformat/nut.h @@ -22,9 +22,6 @@ #ifndef AVFORMAT_NUT_H #define AVFORMAT_NUT_H -//#include <limits.h> -//#include "libavutil/adler32.h" -//#include "libavcodec/mpegaudio.h" #include "avformat.h" #include "internal.h" #include "metadata.h" @@ -39,6 +36,8 @@ #define MAX_DISTANCE (1024*32-1) +#define NUT_VERSION 3 + typedef enum{ FLAG_KEY = 1, ///<if set, frame is keyframe FLAG_EOR = 2, ///<if set, stream has no relevance on presentation. (EOR) diff --git a/chromium/third_party/ffmpeg/libavformat/nutdec.c b/chromium/third_party/ffmpeg/libavformat/nutdec.c index 88965181424..13048fba970 100644 --- a/chromium/third_party/ffmpeg/libavformat/nutdec.c +++ b/chromium/third_party/ffmpeg/libavformat/nutdec.c @@ -196,7 +196,7 @@ static int nut_probe(AVProbeData *p) tmp = ffio_read_varlen(bc); \ if (!(check)) { \ av_log(s, AV_LOG_ERROR, "Error " #dst " is (%"PRId64")\n", tmp); \ - return -1; \ + return AVERROR_INVALIDDATA; \ } \ dst = tmp; \ } while (0) @@ -206,7 +206,7 @@ static int skip_reserved(AVIOContext *bc, int64_t pos) pos -= avio_tell(bc); if (pos < 0) { avio_seek(bc, pos, SEEK_CUR); - return -1; + return AVERROR_INVALIDDATA; } else { while (pos--) avio_r8(bc); @@ -226,7 +226,13 @@ static int decode_main_header(NUTContext *nut) end = get_packetheader(nut, bc, 1, MAIN_STARTCODE); end += avio_tell(bc); - GET_V(tmp, tmp >= 2 && tmp <= 3); + tmp = ffio_read_varlen(bc); + if (tmp < 2 && tmp > NUT_VERSION) { + av_log(s, AV_LOG_ERROR, "Version %"PRId64" not supported.\n", + tmp); + return AVERROR(ENOSYS); + } + GET_V(stream_count, tmp > 0 && tmp <= NUT_MAX_STREAMS); nut->max_distance = ffio_read_varlen(bc); @@ -389,7 +395,7 @@ static int decode_stream_header(NUTContext *nut) break; default: av_log(s, AV_LOG_ERROR, "unknown stream class (%d)\n", class); - return -1; + return AVERROR(ENOSYS); } if (class < 3 && st->codec->codec_id == AV_CODEC_ID_NONE) av_log(s, AV_LOG_ERROR, @@ -418,7 +424,7 @@ static int decode_stream_header(NUTContext *nut) if ((!st->sample_aspect_ratio.num) != (!st->sample_aspect_ratio.den)) { av_log(s, AV_LOG_ERROR, "invalid aspect ratio %d/%d\n", st->sample_aspect_ratio.num, st->sample_aspect_ratio.den); - return -1; + return AVERROR_INVALIDDATA; } ffio_read_varlen(bc); /* csp type */ } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -429,7 +435,7 @@ static int decode_stream_header(NUTContext *nut) if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, "stream header %d checksum mismatch\n", stream_id); - return -1; + return AVERROR_INVALIDDATA; } stc->time_base = &nut->time_base[stc->time_base_id]; avpriv_set_pts_info(s->streams[stream_id], 63, stc->time_base->num, @@ -537,7 +543,7 @@ static int decode_info_header(NUTContext *nut) if (skip_reserved(bc, end) || ffio_get_checksum(bc)) { av_log(s, AV_LOG_ERROR, "info header checksum mismatch\n"); - return -1; + return AVERROR_INVALIDDATA; } return 0; } @@ -580,14 +586,8 @@ static int64_t find_duration(NUTContext *nut, int64_t filesize) AVFormatContext *s = nut->avf; int64_t duration = 0; - int64_t pos = FFMAX(0, filesize - 2*nut->max_distance); - for(;;){ - int64_t ts = nut_read_timestamp(s, -1, &pos, INT64_MAX); - if(ts < 0) - break; - duration = FFMAX(duration, ts); - pos++; - } + ff_find_last_ts(s, -1, &duration, NULL, nut_read_timestamp); + if(duration > 0) s->duration_estimation_method = AVFMT_DURATION_FROM_PTS; return duration; @@ -601,8 +601,9 @@ static int find_and_decode_index(NUTContext *nut) int i, j, syncpoint_count; int64_t filesize = avio_size(bc); int64_t *syncpoints; + uint64_t max_pts; int8_t *has_keyframe; - int ret = -1; + int ret = AVERROR_INVALIDDATA; if(filesize <= 0) return -1; @@ -614,13 +615,18 @@ static int find_and_decode_index(NUTContext *nut) if(s->duration<=0) s->duration = find_duration(nut, filesize); - return -1; + return ret; } end = get_packetheader(nut, bc, 1, INDEX_STARTCODE); end += avio_tell(bc); - ffio_read_varlen(bc); // max_pts + max_pts = ffio_read_varlen(bc); + s->duration = av_rescale_q(max_pts / nut->time_base_count, + nut->time_base[max_pts % nut->time_base_count], + AV_TIME_BASE_Q); + s->duration_estimation_method = AVFMT_DURATION_FROM_PTS; + GET_V(syncpoint_count, tmp < INT_MAX / 8 && tmp > 0); syncpoints = av_malloc(sizeof(int64_t) * syncpoint_count); has_keyframe = av_malloc(sizeof(int8_t) * (syncpoint_count + 1)); @@ -891,7 +897,7 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt) } else { frame_code = avio_r8(bc); if (url_feof(bc)) - return -1; + return AVERROR_EOF; if (frame_code == 'N') { tmp = frame_code; for (i = 1; i < 8; i++) diff --git a/chromium/third_party/ffmpeg/libavformat/nutenc.c b/chromium/third_party/ffmpeg/libavformat/nutenc.c index 2d8d2652ee5..9b7f41af8da 100644 --- a/chromium/third_party/ffmpeg/libavformat/nutenc.c +++ b/chromium/third_party/ffmpeg/libavformat/nutenc.c @@ -91,7 +91,7 @@ static int find_expected_header(AVCodecContext *c, int size, int key_frame, header |= (bitrate_index & 1) << 9; return 2; //FIXME actually put the needed ones in build_elision_headers() - return 3; //we guess that the private bit is not set + //return 3; //we guess that the private bit is not set //FIXME the above assumptions should be checked, if these turn out false too often something should be done } return 0; @@ -335,7 +335,7 @@ static void write_mainheader(NUTContext *nut, AVIOContext *bc) tmp_head_idx; int64_t tmp_match; - ff_put_v(bc, 3); /* version */ + ff_put_v(bc, NUT_VERSION); ff_put_v(bc, nut->avf->nb_streams); ff_put_v(bc, nut->max_distance); ff_put_v(bc, nut->time_base_count); diff --git a/chromium/third_party/ffmpeg/libavformat/oggdec.c b/chromium/third_party/ffmpeg/libavformat/oggdec.c index fd954b805b8..03a2618bec6 100644 --- a/chromium/third_party/ffmpeg/libavformat/oggdec.c +++ b/chromium/third_party/ffmpeg/libavformat/oggdec.c @@ -671,7 +671,12 @@ static int ogg_read_header(AVFormatContext *s) av_log(s, AV_LOG_ERROR, "Header parsing failed for stream %d\n", i); ogg->streams[i].codec = NULL; } else if (os->codec && os->nb_header < os->codec->nb_header) { - av_log(s, AV_LOG_WARNING, "Number of headers (%d) mismatch for stream %d\n", os->nb_header, i); + av_log(s, AV_LOG_WARNING, + "Headers mismatch for stream %d: " + "expected %d received %d.\n", + i, os->codec->nb_header, os->nb_header); + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; } if (os->start_granule != OGG_NOGRANULE_VALUE) os->lastpts = s->streams[i]->start_time = @@ -854,5 +859,5 @@ AVInputFormat ff_ogg_demuxer = { .read_seek = ogg_read_seek, .read_timestamp = ogg_read_timestamp, .extensions = "ogg", - .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT, + .flags = AVFMT_GENERIC_INDEX | AVFMT_TS_DISCONT | AVFMT_NOBINSEARCH, }; diff --git a/chromium/third_party/ffmpeg/libavformat/oggenc.c b/chromium/third_party/ffmpeg/libavformat/oggenc.c index 9a815d14a2e..3135de67767 100644 --- a/chromium/third_party/ffmpeg/libavformat/oggenc.c +++ b/chromium/third_party/ffmpeg/libavformat/oggenc.c @@ -447,11 +447,13 @@ static int ogg_write_header(AVFormatContext *s) } while (j < i); oggstream->serial_num = serial_num; + av_dict_copy(&st->metadata, s->metadata, AV_DICT_DONT_OVERWRITE); + st->priv_data = oggstream; if (st->codec->codec_id == AV_CODEC_ID_FLAC) { int err = ogg_build_flac_headers(st->codec, oggstream, st->codec->flags & CODEC_FLAG_BITEXACT, - &s->metadata); + &st->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing FLAC headers\n"); av_freep(&st->priv_data); @@ -460,7 +462,7 @@ static int ogg_write_header(AVFormatContext *s) } else if (st->codec->codec_id == AV_CODEC_ID_SPEEX) { int err = ogg_build_speex_headers(st->codec, oggstream, st->codec->flags & CODEC_FLAG_BITEXACT, - &s->metadata); + &st->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing Speex headers\n"); av_freep(&st->priv_data); @@ -469,7 +471,7 @@ static int ogg_write_header(AVFormatContext *s) } else if (st->codec->codec_id == AV_CODEC_ID_OPUS) { int err = ogg_build_opus_headers(st->codec, oggstream, st->codec->flags & CODEC_FLAG_BITEXACT, - &s->metadata); + &st->metadata); if (err) { av_log(s, AV_LOG_ERROR, "Error writing Opus headers\n"); av_freep(&st->priv_data); @@ -490,7 +492,7 @@ static int ogg_write_header(AVFormatContext *s) } p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT, - &oggstream->header_len[1], &s->metadata, + &oggstream->header_len[1], &st->metadata, framing_bit); oggstream->header[1] = p; if (!p) @@ -632,5 +634,6 @@ AVOutputFormat ff_ogg_muxer = { .write_header = ogg_write_header, .write_packet = ogg_write_packet, .write_trailer = ogg_write_trailer, + .flags = AVFMT_TS_NEGATIVE, .priv_class = &ogg_muxer_class, }; diff --git a/chromium/third_party/ffmpeg/libavformat/oggparseskeleton.c b/chromium/third_party/ffmpeg/libavformat/oggparseskeleton.c index 307387d065a..d94b0c2e07b 100644 --- a/chromium/third_party/ffmpeg/libavformat/oggparseskeleton.c +++ b/chromium/third_party/ffmpeg/libavformat/oggparseskeleton.c @@ -37,6 +37,9 @@ static int skeleton_header(AVFormatContext *s, int idx) strcpy(st->codec->codec_name, "skeleton"); st->codec->codec_type = AVMEDIA_TYPE_DATA; + if ((os->flags & OGG_FLAG_EOS) && os->psize == 0) + return 1; + if (os->psize < 8) return -1; @@ -74,12 +77,16 @@ 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 (target_idx < 0) { + av_log(s, AV_LOG_WARNING, "Serial number in fisbone doesn't match any stream\n"); + return 1; + } + os = ogg->streams + target_idx; if (os->start_granule != OGG_NOGRANULE_VALUE) { - avpriv_report_missing_feature(s, - "Multiple fisbone for the same stream"); + av_log(s, AV_LOG_WARNING, "Multiple fisbone for the same stream\n"); return 1; } - if (target_idx >= 0 && start_granule != OGG_NOGRANULE_VALUE) { + if (start_granule != OGG_NOGRANULE_VALUE) { os->start_granule = start_granule; } } diff --git a/chromium/third_party/ffmpeg/libavformat/oggparsevorbis.c b/chromium/third_party/ffmpeg/libavformat/oggparsevorbis.c index da029a47df8..7d525f43dcf 100644 --- a/chromium/third_party/ffmpeg/libavformat/oggparsevorbis.c +++ b/chromium/third_party/ffmpeg/libavformat/oggparsevorbis.c @@ -24,12 +24,14 @@ #include <stdlib.h> #include "libavutil/avstring.h" +#include "libavutil/base64.h" #include "libavutil/bswap.h" #include "libavutil/dict.h" #include "libavcodec/get_bits.h" #include "libavcodec/bytestream.h" #include "libavcodec/vorbis_parser.h" #include "avformat.h" +#include "flacdec.h" #include "internal.h" #include "oggdec.h" #include "vorbiscomment.h" @@ -39,10 +41,10 @@ static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val) int i, cnum, h, m, s, ms, keylen = strlen(key); AVChapter *chapter = NULL; - if (keylen < 9 || sscanf(key, "CHAPTER%02d", &cnum) != 1) + if (keylen < 9 || sscanf(key, "CHAPTER%03d", &cnum) != 1) return 0; - if (keylen == 9) { + if (keylen <= 10) { if (sscanf(val, "%02d:%02d:%02d.%03d", &h, &m, &s, &ms) < 4) return 0; @@ -50,7 +52,7 @@ static int ogm_chapter(AVFormatContext *as, uint8_t *key, uint8_t *val) ms + 1000*(s + 60*(m + 60*h)), AV_NOPTS_VALUE, NULL); av_free(val); - } else if (!strcmp(key+9, "NAME")) { + } else if (!strcmp(key+(keylen-4), "NAME")) { for(i = 0; i < as->nb_chapters; i++) if (as->chapters[i]->id == cnum) { chapter = as->chapters[i]; @@ -128,7 +130,26 @@ ff_vorbis_comment(AVFormatContext * as, AVDictionary **m, const uint8_t *buf, in memcpy(ct, v, vl); ct[vl] = 0; - if (!ogm_chapter(as, tt, ct)) + if (!strcmp(tt, "METADATA_BLOCK_PICTURE")) { + int ret; + char *pict = av_malloc(vl); + + if (!pict) { + av_log(as, AV_LOG_WARNING, "out-of-memory error. Skipping cover art block.\n"); + av_freep(&tt); + av_freep(&ct); + continue; + } + if ((ret = av_base64_decode(pict, ct, vl)) > 0) + ret = ff_flac_parse_picture(as, pict, ret); + av_freep(&pict); + av_freep(&tt); + av_freep(&ct); + if (ret < 0) { + av_log(as, AV_LOG_WARNING, "Failed to parse cover art block.\n"); + continue; + } + } else if (!ogm_chapter(as, tt, ct)) av_dict_set(m, tt, ct, AV_DICT_DONT_STRDUP_KEY | AV_DICT_DONT_STRDUP_VAL); @@ -216,15 +237,15 @@ vorbis_header (AVFormatContext * s, int idx) struct oggvorbis_private *priv; int pkt_type = os->buf[os->pstart]; - if (!(pkt_type & 1)) - return os->private ? 0 : -1; - if (!os->private) { os->private = av_mallocz(sizeof(struct oggvorbis_private)); if (!os->private) return -1; } + if (!(pkt_type & 1)) + return 0; + if (os->psize < 1 || pkt_type > 5) return -1; diff --git a/chromium/third_party/ffmpeg/libavformat/omadec.c b/chromium/third_party/ffmpeg/libavformat/omadec.c index ae359074f9d..d05795494c8 100644 --- a/chromium/third_party/ffmpeg/libavformat/omadec.c +++ b/chromium/third_party/ffmpeg/libavformat/omadec.c @@ -73,18 +73,20 @@ typedef struct OMAContext { struct AVDES av_des; } OMAContext; -static void hex_log(AVFormatContext *s, int level, const char *name, const uint8_t *value, int len) +static void hex_log(AVFormatContext *s, int level, + const char *name, const uint8_t *value, int len) { char buf[33]; len = FFMIN(len, 16); if (av_log_get_level() < level) return; ff_data_to_hex(buf, value, len, 1); - buf[len<<1] = '\0'; + buf[len << 1] = '\0'; av_log(s, level, "%s: %s\n", name, buf); } -static int kset(AVFormatContext *s, const uint8_t *r_val, const uint8_t *n_val, int len) +static int kset(AVFormatContext *s, const uint8_t *r_val, const uint8_t *n_val, + int len) { OMAContext *oc = s->priv_data; @@ -112,13 +114,18 @@ static int kset(AVFormatContext *s, const uint8_t *r_val, const uint8_t *n_val, return 0; } -static int rprobe(AVFormatContext *s, uint8_t *enc_header, const uint8_t *r_val) +#define OMA_RPROBE_M_VAL 48 + 1 + +static int rprobe(AVFormatContext *s, uint8_t *enc_header, unsigned size, + const uint8_t *r_val) { OMAContext *oc = s->priv_data; unsigned int pos; struct AVDES av_des; - if (!enc_header || !r_val) + if (!enc_header || !r_val || + size < OMA_ENC_HEADER_SIZE + oc->k_size + oc->e_size + oc->i_size || + size < OMA_RPROBE_M_VAL) return -1; /* m_val */ @@ -139,35 +146,41 @@ static int rprobe(AVFormatContext *s, uint8_t *enc_header, const uint8_t *r_val) return memcmp(&enc_header[pos], oc->sm_val, 8) ? -1 : 0; } -static int nprobe(AVFormatContext *s, uint8_t *enc_header, int size, const uint8_t *n_val) +static int nprobe(AVFormatContext *s, uint8_t *enc_header, unsigned size, + const uint8_t *n_val) { OMAContext *oc = s->priv_data; - uint32_t pos, taglen, datalen; + uint64_t pos; + uint32_t taglen, datalen; struct AVDES av_des; - if (!enc_header || !n_val) + if (!enc_header || !n_val || + size < OMA_ENC_HEADER_SIZE + oc->k_size + 4) return -1; pos = OMA_ENC_HEADER_SIZE + oc->k_size; if (!memcmp(&enc_header[pos], "EKB ", 4)) pos += 32; + if (size < pos + 44) + return -1; + if (AV_RB32(&enc_header[pos]) != oc->rid) av_log(s, AV_LOG_DEBUG, "Mismatching RID\n"); - taglen = AV_RB32(&enc_header[pos+32]); - datalen = AV_RB32(&enc_header[pos+36]) >> 4; - - if(pos + (uint64_t)taglen + (((uint64_t)datalen)<<4) + 44 > size) - return -1; + taglen = AV_RB32(&enc_header[pos + 32]); + datalen = AV_RB32(&enc_header[pos + 36]) >> 4; pos += 44 + taglen; + if (pos + (((uint64_t)datalen) << 4) > size) + return -1; + av_des_init(&av_des, n_val, 192, 1); while (datalen-- > 0) { av_des_crypt(&av_des, oc->r_val, &enc_header[pos], 2, NULL, 1); kset(s, oc->r_val, NULL, 16); - if (!rprobe(s, enc_header, oc->r_val)) + if (!rprobe(s, enc_header, size, oc->r_val)) return 0; pos += 16; } @@ -196,12 +209,13 @@ static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header) } if (!em) { av_log(s, AV_LOG_ERROR, "No encryption header found\n"); - return -1; + return AVERROR_INVALIDDATA; } if (geob->datasize < 64) { - av_log(s, AV_LOG_ERROR, "Invalid GEOB data size: %u\n", geob->datasize); - return -1; + av_log(s, AV_LOG_ERROR, + "Invalid GEOB data size: %u\n", geob->datasize); + return AVERROR_INVALIDDATA; } gdata = geob->data; @@ -216,7 +230,7 @@ static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header) if (memcmp(&gdata[OMA_ENC_HEADER_SIZE], "KEYRING ", 12)) { av_log(s, AV_LOG_ERROR, "Invalid encryption header\n"); - return -1; + return AVERROR_INVALIDDATA; } if ( OMA_ENC_HEADER_SIZE + oc->k_size + oc->e_size + oc->i_size + 8 > geob->datasize || OMA_ENC_HEADER_SIZE + 48 > geob->datasize @@ -230,32 +244,36 @@ static int decrypt_init(AVFormatContext *s, ID3v2ExtraMeta *em, uint8_t *header) memcpy(oc->iv, &header[0x58], 8); hex_log(s, AV_LOG_DEBUG, "IV", oc->iv, 8); - hex_log(s, AV_LOG_DEBUG, "CBC-MAC", &gdata[OMA_ENC_HEADER_SIZE+oc->k_size+oc->e_size+oc->i_size], 8); + hex_log(s, AV_LOG_DEBUG, "CBC-MAC", + &gdata[OMA_ENC_HEADER_SIZE + oc->k_size + oc->e_size + oc->i_size], + 8); if (s->keylen > 0) { kset(s, s->key, s->key, s->keylen); } if (!memcmp(oc->r_val, (const uint8_t[8]){0}, 8) || - rprobe(s, gdata, oc->r_val) < 0 && + rprobe(s, gdata, geob->datasize, oc->r_val) < 0 && nprobe(s, gdata, geob->datasize, oc->n_val) < 0) { int i; for (i = 0; i < FF_ARRAY_ELEMS(leaf_table); i += 2) { uint8_t buf[16]; - AV_WL64(buf, leaf_table[i]); - AV_WL64(&buf[8], leaf_table[i+1]); + AV_WL64(buf, leaf_table[i]); + AV_WL64(&buf[8], leaf_table[i + 1]); kset(s, buf, buf, 16); - if (!rprobe(s, gdata, oc->r_val) || !nprobe(s, gdata, geob->datasize, oc->n_val)) + if (!rprobe(s, gdata, geob->datasize, oc->r_val) || + !nprobe(s, gdata, geob->datasize, oc->n_val)) break; } if (i >= FF_ARRAY_ELEMS(leaf_table)) { av_log(s, AV_LOG_ERROR, "Invalid key\n"); - return -1; + return AVERROR_INVALIDDATA; } } /* e_val */ av_des_init(&oc->av_des, oc->m_val, 64, 0); - av_des_crypt(&oc->av_des, oc->e_val, &gdata[OMA_ENC_HEADER_SIZE + 40], 1, NULL, 0); + av_des_crypt(&oc->av_des, oc->e_val, + &gdata[OMA_ENC_HEADER_SIZE + 40], 1, NULL, 0); hex_log(s, AV_LOG_DEBUG, "EK", oc->e_val, 8); /* init e_val */ @@ -280,9 +298,10 @@ static int oma_read_header(AVFormatContext *s) if (ret < EA3_HEADER_SIZE) return -1; - if (memcmp(buf, ((const uint8_t[]){'E', 'A', '3'}),3) || buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) { + if (memcmp(buf, ((const uint8_t[]){'E', 'A', '3'}), 3) || + buf[4] != 0 || buf[5] != EA3_HEADER_SIZE) { av_log(s, AV_LOG_ERROR, "Couldn't find the EA3 header !\n"); - return -1; + return AVERROR_INVALIDDATA; } oc->content_start = avio_tell(s->pb); @@ -303,74 +322,80 @@ static int oma_read_header(AVFormatContext *s) return AVERROR(ENOMEM); st->start_time = 0; - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_tag = buf[32]; - st->codec->codec_id = ff_codec_get_id(ff_oma_codec_tags, st->codec->codec_tag); + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_tag = buf[32]; + st->codec->codec_id = ff_codec_get_id(ff_oma_codec_tags, + st->codec->codec_tag); switch (buf[32]) { - case OMA_CODECID_ATRAC3: - samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100; - if (!samplerate) { - av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); - return AVERROR_INVALIDDATA; - } - if (samplerate != 44100) - avpriv_request_sample(s, "Sample rate %d", samplerate); - - framesize = (codec_params & 0x3FF) * 8; - jsflag = (codec_params >> 17) & 1; /* get stereo coding mode, 1 for joint-stereo */ - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; - st->codec->sample_rate = samplerate; - st->codec->bit_rate = st->codec->sample_rate * framesize * 8 / 1024; - - /* fake the atrac3 extradata (wav format, makes stream copy to wav work) */ - st->codec->extradata_size = 14; - edata = av_mallocz(14 + FF_INPUT_BUFFER_PADDING_SIZE); - if (!edata) - return AVERROR(ENOMEM); - - st->codec->extradata = edata; - AV_WL16(&edata[0], 1); // always 1 - AV_WL32(&edata[2], samplerate); // samples rate - AV_WL16(&edata[6], jsflag); // coding mode - AV_WL16(&edata[8], jsflag); // coding mode - AV_WL16(&edata[10], 1); // always 1 - // AV_WL16(&edata[12], 0); // always 0 - - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); - break; - case OMA_CODECID_ATRAC3P: - st->codec->channels = (codec_params >> 10) & 7; - framesize = ((codec_params & 0x3FF) * 8) + 8; - samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100; - if (!samplerate) { - av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); - return AVERROR_INVALIDDATA; - } - st->codec->sample_rate = samplerate; - st->codec->bit_rate = samplerate * framesize * 8 / 1024; - avpriv_set_pts_info(st, 64, 1, samplerate); - av_log(s, AV_LOG_ERROR, "Unsupported codec ATRAC3+!\n"); - break; - case OMA_CODECID_MP3: - st->need_parsing = AVSTREAM_PARSE_FULL_RAW; - framesize = 1024; - break; - case OMA_CODECID_LPCM: - /* PCM 44.1 kHz 16 bit stereo big-endian */ - st->codec->channels = 2; - st->codec->channel_layout = AV_CH_LAYOUT_STEREO; - st->codec->sample_rate = 44100; - framesize = 1024; - /* bit rate = sample rate x PCM block align (= 4) x 8 */ - st->codec->bit_rate = st->codec->sample_rate * 32; - st->codec->bits_per_coded_sample = av_get_bits_per_sample(st->codec->codec_id); - avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); - break; - default: - av_log(s, AV_LOG_ERROR, "Unsupported codec %d!\n",buf[32]); - return -1; + case OMA_CODECID_ATRAC3: + samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100; + if (!samplerate) { + av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); + return AVERROR_INVALIDDATA; + } + if (samplerate != 44100) + avpriv_request_sample(s, "Sample rate %d", samplerate); + + framesize = (codec_params & 0x3FF) * 8; + + /* get stereo coding mode, 1 for joint-stereo */ + jsflag = (codec_params >> 17) & 1; + + st->codec->channels = 2; + st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codec->sample_rate = samplerate; + st->codec->bit_rate = st->codec->sample_rate * framesize * 8 / 1024; + + /* fake the atrac3 extradata + * (wav format, makes stream copy to wav work) */ + st->codec->extradata_size = 14; + edata = av_mallocz(14 + FF_INPUT_BUFFER_PADDING_SIZE); + if (!edata) + return AVERROR(ENOMEM); + + st->codec->extradata = edata; + AV_WL16(&edata[0], 1); // always 1 + AV_WL32(&edata[2], samplerate); // samples rate + AV_WL16(&edata[6], jsflag); // coding mode + AV_WL16(&edata[8], jsflag); // coding mode + AV_WL16(&edata[10], 1); // always 1 + // AV_WL16(&edata[12], 0); // always 0 + + avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + break; + case OMA_CODECID_ATRAC3P: + st->codec->channels = (codec_params >> 10) & 7; + framesize = ((codec_params & 0x3FF) * 8) + 8; + samplerate = ff_oma_srate_tab[(codec_params >> 13) & 7] * 100; + if (!samplerate) { + av_log(s, AV_LOG_ERROR, "Unsupported sample rate\n"); + return AVERROR_INVALIDDATA; + } + st->codec->sample_rate = samplerate; + st->codec->bit_rate = samplerate * framesize * 8 / 1024; + avpriv_set_pts_info(st, 64, 1, samplerate); + av_log(s, AV_LOG_ERROR, "Unsupported codec ATRAC3+!\n"); + break; + case OMA_CODECID_MP3: + st->need_parsing = AVSTREAM_PARSE_FULL_RAW; + framesize = 1024; + break; + case OMA_CODECID_LPCM: + /* PCM 44.1 kHz 16 bit stereo big-endian */ + st->codec->channels = 2; + st->codec->channel_layout = AV_CH_LAYOUT_STEREO; + st->codec->sample_rate = 44100; + framesize = 1024; + /* bit rate = sample rate x PCM block align (= 4) x 8 */ + st->codec->bit_rate = st->codec->sample_rate * 32; + st->codec->bits_per_coded_sample = + av_get_bits_per_sample(st->codec->codec_id); + avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); + break; + default: + av_log(s, AV_LOG_ERROR, "Unsupported codec %d!\n", buf[32]); + return AVERROR(ENOSYS); } st->codec->block_align = framesize; @@ -385,14 +410,24 @@ static int oma_read_packet(AVFormatContext *s, AVPacket *pkt) int packet_size = s->streams[0]->codec->block_align; int ret = av_get_packet(s->pb, pkt, packet_size); - if (ret <= 0) - return AVERROR(EIO); + if (ret < packet_size) + pkt->flags |= AV_PKT_FLAG_CORRUPT; + + if (ret < 0) + return ret; + if (!ret) + return AVERROR_EOF; pkt->stream_index = 0; if (oc->encrypted) { - /* previous unencrypted block saved in IV for the next packet (CBC mode) */ - av_des_crypt(&oc->av_des, pkt->data, pkt->data, (ret >> 3), oc->iv, 1); + /* previous unencrypted block saved in IV for + * the next packet (CBC mode) */ + if (ret == packet_size) + av_des_crypt(&oc->av_des, pkt->data, pkt->data, + (packet_size >> 3), oc->iv, 1); + else + memset(oc->iv, 0, 8); } return ret; @@ -416,7 +451,7 @@ static int oma_read_probe(AVProbeData *p) /* This check cannot overflow as tag_len has at most 28 bits */ if (p->buf_size < tag_len + 5) /* EA3 header comes late, might be outside of the probe buffer */ - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; buf += tag_len; @@ -426,26 +461,30 @@ static int oma_read_probe(AVProbeData *p) return 0; } -static int oma_read_seek(struct AVFormatContext *s, int stream_index, int64_t timestamp, int flags) +static int oma_read_seek(struct AVFormatContext *s, + int stream_index, int64_t timestamp, int flags) { OMAContext *oc = s->priv_data; - - ff_pcm_read_seek(s, stream_index, timestamp, flags); - - if (oc->encrypted) { - /* readjust IV for CBC */ - int64_t pos = avio_tell(s->pb); - if (pos < oc->content_start) - memset(oc->iv, 0, 8); - else { - if (avio_seek(s->pb, -8, SEEK_CUR) < 0 || avio_read(s->pb, oc->iv, 8) < 8) { - memset(oc->iv, 0, 8); - return -1; - } - } + int err = ff_pcm_read_seek(s, stream_index, timestamp, flags); + + if (!oc->encrypted) + return err; + + /* readjust IV for CBC */ + if (err || avio_tell(s->pb) < oc->content_start) + goto wipe; + if ((err = avio_seek(s->pb, -8, SEEK_CUR)) < 0) + goto wipe; + if ((err = avio_read(s->pb, oc->iv, 8)) < 8) { + if (err >= 0) + err = AVERROR_EOF; + goto wipe; } return 0; +wipe: + memset(oc->iv, 0, 8); + return err; } AVInputFormat ff_oma_demuxer = { diff --git a/chromium/third_party/ffmpeg/libavformat/options.c b/chromium/third_party/ffmpeg/libavformat/options.c index 42307d170f6..5218e5b92a4 100644 --- a/chromium/third_party/ffmpeg/libavformat/options.c +++ b/chromium/third_party/ffmpeg/libavformat/options.c @@ -86,7 +86,7 @@ static AVClassCategory get_category(void *ptr) static const AVClass av_format_context_class = { .class_name = "AVFormatContext", .item_name = format_to_name, - .option = options, + .option = avformat_options, .version = LIBAVUTIL_VERSION_INT, .child_next = format_child_next, .child_class_next = format_child_class_next, diff --git a/chromium/third_party/ffmpeg/libavformat/options_table.h b/chromium/third_party/ffmpeg/libavformat/options_table.h index 9f8613764c5..a87868e162f 100644 --- a/chromium/third_party/ffmpeg/libavformat/options_table.h +++ b/chromium/third_party/ffmpeg/libavformat/options_table.h @@ -32,7 +32,7 @@ #define E AV_OPT_FLAG_ENCODING_PARAM #define D AV_OPT_FLAG_DECODING_PARAM -static const AVOption options[]={ +static const AVOption avformat_options[] = { {"avioflags", NULL, OFFSET(avio_flags), AV_OPT_TYPE_FLAGS, {.i64 = DEFAULT }, INT_MIN, INT_MAX, D|E, "avioflags"}, {"direct", "reduce buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVIO_FLAG_DIRECT }, INT_MIN, INT_MAX, D|E, "avioflags"}, {"probesize", "set probing size", OFFSET(probesize), AV_OPT_TYPE_INT, {.i64 = 5000000 }, 32, INT_MAX, D}, @@ -45,7 +45,7 @@ static const AVOption options[]={ {"igndts", "ignore dts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_IGNDTS }, INT_MIN, INT_MAX, D, "fflags"}, {"discardcorrupt", "discard corrupted frames", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_DISCARD_CORRUPT }, INT_MIN, INT_MAX, D, "fflags"}, {"sortdts", "try to interleave outputted packets by dts", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_SORT_DTS }, INT_MIN, INT_MAX, D, "fflags"}, -{"keepside", "dont merge side data", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_KEEP_SIDE_DATA }, INT_MIN, INT_MAX, D, "fflags"}, +{"keepside", "don't merge side data", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_KEEP_SIDE_DATA }, INT_MIN, INT_MAX, D, "fflags"}, {"latm", "enable RTP MP4A-LATM payload", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_MP4A_LATM }, INT_MIN, INT_MAX, E, "fflags"}, {"nobuffer", "reduce the latency introduced by optional buffering", 0, AV_OPT_TYPE_CONST, {.i64 = AVFMT_FLAG_NOBUFFER }, 0, INT_MAX, D, "fflags"}, {"seek2any", "forces seeking to enable seek to any mode", OFFSET(seek2any), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, 1, D}, @@ -70,9 +70,9 @@ static const AVOption options[]={ {"explode", "abort decoding on minor error detection", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_EXPLODE }, INT_MIN, INT_MAX, D, "err_detect"}, {"careful", "consider things that violate the spec and have not been seen in the wild as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_CAREFUL }, INT_MIN, INT_MAX, D, "err_detect"}, {"compliant", "consider all spec non compliancies as errors", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_COMPLIANT }, INT_MIN, INT_MAX, D, "err_detect"}, -{"aggressive", "consider things that a sane encoder shouldnt do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, D, "err_detect"}, +{"aggressive", "consider things that a sane encoder shouldn't do as an error", 0, AV_OPT_TYPE_CONST, {.i64 = AV_EF_AGGRESSIVE }, INT_MIN, INT_MAX, D, "err_detect"}, {"use_wallclock_as_timestamps", "use wallclock as timestamps", OFFSET(use_wallclock_as_timestamps), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, D}, -{"avoid_negative_ts", "shift timestamps to make them positive. 1 enables, 0 disables, default of -1 enables when required by target format.", OFFSET(avoid_negative_ts), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, E}, +{"avoid_negative_ts", "shift timestamps to make them non-negative. 1 enables, 0 disables, default of -1 enables when required by target format.", OFFSET(avoid_negative_ts), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 1, E}, {"skip_initial_bytes", "skip initial bytes", OFFSET(skip_initial_bytes), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX-1, D}, {"correct_ts_overflow", "correct single timestamp overflows", OFFSET(correct_ts_overflow), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, D}, {"flush_packets", "enable flushing of the I/O context after each packet", OFFSET(flush_packets), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E}, diff --git a/chromium/third_party/ffmpeg/libavformat/os_support.c b/chromium/third_party/ffmpeg/libavformat/os_support.c index dc88834bf33..3218956df5e 100644 --- a/chromium/third_party/ffmpeg/libavformat/os_support.c +++ b/chromium/third_party/ffmpeg/libavformat/os_support.c @@ -27,46 +27,6 @@ #include "avformat.h" #include "os_support.h" -#if defined(_WIN32) && !defined(__MINGW32CE__) -#undef open -#undef lseek -#undef stat -#undef fstat -#include <fcntl.h> -#include <io.h> -#include <windows.h> -#include <share.h> -#include <errno.h> - -int ff_win32_open(const char *filename_utf8, int oflag, int pmode) -{ - int fd; - int num_chars; - wchar_t *filename_w; - - /* convert UTF-8 to wide chars */ - num_chars = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename_utf8, -1, NULL, 0); - if (num_chars <= 0) - goto fallback; - filename_w = av_mallocz(sizeof(wchar_t) * num_chars); - if (!filename_w) { - errno = ENOMEM; - return -1; - } - MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, filename_w, num_chars); - - fd = _wsopen(filename_w, oflag, SH_DENYNO, pmode); - av_freep(&filename_w); - - if (fd != -1 || (oflag & O_CREAT)) - return fd; - -fallback: - /* filename may be be in CP_ACP */ - return _sopen(filename_utf8, oflag, SH_DENYNO, pmode); -} -#endif - #if CONFIG_NETWORK #include <fcntl.h> #if !HAVE_POLL_H diff --git a/chromium/third_party/ffmpeg/libavformat/os_support.h b/chromium/third_party/ffmpeg/libavformat/os_support.h index e5f31e05a4c..b0f02c11f14 100644 --- a/chromium/third_party/ffmpeg/libavformat/os_support.h +++ b/chromium/third_party/ffmpeg/libavformat/os_support.h @@ -86,11 +86,6 @@ static inline int is_dos_path(const char *path) #endif #endif -#if defined(_WIN32) && !defined(__MINGW32CE__) -int ff_win32_open(const char *filename, int oflag, int pmode); -#define open ff_win32_open -#endif - #if CONFIG_NETWORK #if !HAVE_SOCKLEN_T typedef int socklen_t; diff --git a/chromium/third_party/ffmpeg/libavformat/paf.c b/chromium/third_party/ffmpeg/libavformat/paf.c index 09786eb34f1..09aefe6770b 100644 --- a/chromium/third_party/ffmpeg/libavformat/paf.c +++ b/chromium/third_party/ffmpeg/libavformat/paf.c @@ -233,10 +233,11 @@ static int read_packet(AVFormatContext *s, AVPacket *pkt) p->current_frame_block++; } - size = p->video_size - p->frames_offset_table[p->current_frame]; - if (size < 1) + if (p->frames_offset_table[p->current_frame] >= p->video_size) return AVERROR_INVALIDDATA; + size = p->video_size - p->frames_offset_table[p->current_frame]; + if (av_new_packet(pkt, size) < 0) return AVERROR(ENOMEM); diff --git a/chromium/third_party/ffmpeg/libavformat/pmpdec.c b/chromium/third_party/ffmpeg/libavformat/pmpdec.c index 2fe6c46e13d..71f450e9d37 100644 --- a/chromium/third_party/ffmpeg/libavformat/pmpdec.c +++ b/chromium/third_party/ffmpeg/libavformat/pmpdec.c @@ -174,7 +174,7 @@ static int pmp_seek(AVFormatContext *s, int stream_index, int64_t ts, int flags) { PMPContext *pmp = s->priv_data; pmp->cur_stream = 0; - // fallback to default seek now + // fall back on default seek now return -1; } diff --git a/chromium/third_party/ffmpeg/libavformat/psxstr.c b/chromium/third_party/ffmpeg/libavformat/psxstr.c index 90c933ecd62..3409d6a5af8 100644 --- a/chromium/third_party/ffmpeg/libavformat/psxstr.c +++ b/chromium/third_party/ffmpeg/libavformat/psxstr.c @@ -30,6 +30,7 @@ */ #include "libavutil/channel_layout.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "avformat.h" #include "internal.h" @@ -126,7 +127,7 @@ static int str_probe(AVProbeData *p) } /* MPEG files (like those ripped from VCDs) can also look like this; * only return half certainty */ - if(vid+aud > 3) return 50; + if(vid+aud > 3) return AVPROBE_SCORE_EXTENSION; else if(vid+aud) return 1; else return 0; } @@ -237,7 +238,9 @@ static int str_read_packet(AVFormatContext *s, pkt->size= -1; pkt->buf = NULL; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS pkt->destruct = NULL; +FF_ENABLE_DEPRECATION_WARNINGS #endif return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/pva.c b/chromium/third_party/ffmpeg/libavformat/pva.c index ae42c8363d2..9b7a40a0682 100644 --- a/chromium/third_party/ffmpeg/libavformat/pva.c +++ b/chromium/third_party/ffmpeg/libavformat/pva.c @@ -49,7 +49,7 @@ static int pva_probe(AVProbeData * pd) { if (pd->buf_size >= len + 8 && pva_check(buf + len) >= 0) - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; return AVPROBE_SCORE_MAX / 4; } diff --git a/chromium/third_party/ffmpeg/libavformat/r3d.c b/chromium/third_party/ffmpeg/libavformat/r3d.c index 3b3ecce3d93..8459cddc705 100644 --- a/chromium/third_party/ffmpeg/libavformat/r3d.c +++ b/chromium/third_party/ffmpeg/libavformat/r3d.c @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -//#define DEBUG - #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "libavutil/mathematics.h" diff --git a/chromium/third_party/ffmpeg/libavformat/rawdec.c b/chromium/third_party/ffmpeg/libavformat/rawdec.c index 153cc7b04ea..a9ff22ae182 100644 --- a/chromium/third_party/ffmpeg/libavformat/rawdec.c +++ b/chromium/third_party/ffmpeg/libavformat/rawdec.c @@ -90,6 +90,17 @@ fail: return ret; } +static int ff_raw_data_read_header(AVFormatContext *s) +{ + AVStream *st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codec->codec_type = AVMEDIA_TYPE_DATA; + st->codec->codec_id = s->iformat->raw_codec_id; + st->start_time = 0; + return 0; +} + /* Note: Do not forget to add new entries to the Makefile as well. */ #define OFFSET(x) offsetof(FFRawVideoDemuxerContext, x) @@ -99,6 +110,16 @@ const AVOption ff_rawvideo_options[] = { { NULL }, }; +#if CONFIG_DATA_DEMUXER +AVInputFormat ff_data_demuxer = { + .name = "data", + .long_name = NULL_IF_CONFIG_SMALL("raw data"), + .read_header = ff_raw_data_read_header, + .read_packet = ff_raw_read_partial_packet, + .raw_codec_id = AV_CODEC_ID_NONE, +}; +#endif + #if CONFIG_LATM_DEMUXER AVInputFormat ff_latm_demuxer = { .name = "latm", diff --git a/chromium/third_party/ffmpeg/libavformat/rawenc.c b/chromium/third_party/ffmpeg/libavformat/rawenc.c index 7894c8e0c5d..7a1fa93e8ba 100644 --- a/chromium/third_party/ffmpeg/libavformat/rawenc.c +++ b/chromium/third_party/ffmpeg/libavformat/rawenc.c @@ -68,6 +68,15 @@ AVOutputFormat ff_cavsvideo_muxer = { }; #endif +#if CONFIG_DATA_MUXER +AVOutputFormat ff_data_muxer = { + .name = "data", + .long_name = NULL_IF_CONFIG_SMALL("raw data"), + .write_packet = ff_raw_write_packet, + .flags = AVFMT_NOTIMESTAMPS, +}; +#endif + #if CONFIG_DIRAC_MUXER AVOutputFormat ff_dirac_muxer = { .name = "dirac", diff --git a/chromium/third_party/ffmpeg/libavformat/rdt.c b/chromium/third_party/ffmpeg/libavformat/rdt.c index 695323ab0fe..54111a5adad 100644 --- a/chromium/third_party/ffmpeg/libavformat/rdt.c +++ b/chromium/third_party/ffmpeg/libavformat/rdt.c @@ -98,7 +98,7 @@ ff_rdt_calc_response_and_checksum(char response[41], char chksum[9], unsigned char zres[16], buf[64] = { 0xa1, 0xe9, 0x14, 0x9d, 0x0e, 0x6b, 0x3b, 0x59 }; #define XOR_TABLE_SIZE 37 - const unsigned char xor_table[XOR_TABLE_SIZE] = { + static const unsigned char xor_table[XOR_TABLE_SIZE] = { 0x05, 0x18, 0x74, 0xd0, 0x0d, 0x09, 0x02, 0x53, 0xc0, 0x01, 0x05, 0x05, 0x67, 0x03, 0x19, 0x70, 0x08, 0x27, 0x66, 0x10, 0x10, 0x72, 0x08, 0x09, @@ -548,7 +548,7 @@ rdt_free_context (PayloadContext *rdt) } #define RDT_HANDLER(n, s, t) \ -static RTPDynamicProtocolHandler ff_rdt_ ## n ## _handler = { \ +static RTPDynamicProtocolHandler rdt_ ## n ## _handler = { \ .enc_name = s, \ .codec_type = t, \ .codec_id = AV_CODEC_ID_NONE, \ @@ -565,8 +565,8 @@ RDT_HANDLER(audio, "x-pn-realaudio", AVMEDIA_TYPE_AUDIO); void av_register_rdt_dynamic_payload_handlers(void) { - ff_register_dynamic_payload_handler(&ff_rdt_video_handler); - ff_register_dynamic_payload_handler(&ff_rdt_audio_handler); - ff_register_dynamic_payload_handler(&ff_rdt_live_video_handler); - ff_register_dynamic_payload_handler(&ff_rdt_live_audio_handler); + ff_register_dynamic_payload_handler(&rdt_video_handler); + ff_register_dynamic_payload_handler(&rdt_audio_handler); + ff_register_dynamic_payload_handler(&rdt_live_video_handler); + ff_register_dynamic_payload_handler(&rdt_live_audio_handler); } diff --git a/chromium/third_party/ffmpeg/libavformat/realtextdec.c b/chromium/third_party/ffmpeg/libavformat/realtextdec.c index 67bc33983a5..5e4981a40b5 100644 --- a/chromium/third_party/ffmpeg/libavformat/realtextdec.c +++ b/chromium/third_party/ffmpeg/libavformat/realtextdec.c @@ -41,7 +41,7 @@ static int realtext_probe(AVProbeData *p) if (AV_RB24(ptr) == 0xEFBBBF) ptr += 3; /* skip UTF-8 BOM */ - return !av_strncasecmp(ptr, "<window", 7) ? AVPROBE_SCORE_MAX/2 : 0; + return !av_strncasecmp(ptr, "<window", 7) ? AVPROBE_SCORE_EXTENSION : 0; } static int read_ts(const char *s) diff --git a/chromium/third_party/ffmpeg/libavformat/redspark.c b/chromium/third_party/ffmpeg/libavformat/redspark.c new file mode 100644 index 00000000000..44d5da77fb3 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/redspark.c @@ -0,0 +1,167 @@ +/* + * RedSpark demuxer + * Copyright (c) 2013 James Almer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/bytestream.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "avio.h" +#include "internal.h" + +#define HEADER_SIZE 4096 + +typedef struct RedSparkContext { + int samples_count; +} RedSparkContext; + +static int redspark_probe(AVProbeData *p) +{ + uint32_t key, data; + uint8_t header[8]; + + /* Decrypt first 8 bytes of the header */ + data = AV_RB32(p->buf); + data = data ^ (key = data ^ 0x52656453); + AV_WB32(header, data); + key = (key << 11) | (key >> 21); + + data = AV_RB32(p->buf + 4) ^ (((key << 3) | (key >> 29)) + key); + AV_WB32(header + 4, data); + + if (AV_RB64(header) == AV_RB64("RedSpark")) + return AVPROBE_SCORE_MAX; + + return 0; +} + +static int redspark_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + RedSparkContext *redspark = s->priv_data; + AVCodecContext *codec; + GetByteContext gbc; + int i, coef_off, ret = 0; + uint32_t key, data; + uint8_t *header, *pbc; + AVStream *st; + + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + codec = st->codec; + + header = av_malloc(HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + if (!header) + return AVERROR(ENOMEM); + pbc = header; + + /* Decrypt header */ + data = avio_rb32(pb); + data = data ^ (key = data ^ 0x52656453); + bytestream_put_be32(&pbc, data); + key = (key << 11) | (key >> 21); + + for (i = 4; i < HEADER_SIZE; i += 4) { + data = avio_rb32(pb) ^ (key = ((key << 3) | (key >> 29)) + key); + bytestream_put_be32(&pbc, data); + } + + codec->codec_id = AV_CODEC_ID_ADPCM_THP; + codec->codec_type = AVMEDIA_TYPE_AUDIO; + + bytestream2_init(&gbc, header, HEADER_SIZE); + bytestream2_seek(&gbc, 0x3c, SEEK_SET); + codec->sample_rate = bytestream2_get_be32u(&gbc); + if (codec->sample_rate <= 0 || codec->sample_rate > 96000) { + av_log(s, AV_LOG_ERROR, "Invalid sample rate: %d\n", codec->sample_rate); + ret = AVERROR_INVALIDDATA; + goto fail; + } + + st->duration = bytestream2_get_be32u(&gbc) * 14; + redspark->samples_count = 0; + bytestream2_skipu(&gbc, 10); + codec->channels = bytestream2_get_byteu(&gbc); + if (!codec->channels) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + + coef_off = 0x54 + codec->channels * 8; + if (bytestream2_get_byteu(&gbc)) // Loop flag + coef_off += 16; + + codec->extradata_size = 32 * codec->channels; + codec->extradata = av_malloc(codec->extradata_size); + if (!codec->extradata) { + ret = AVERROR(ENOMEM); + goto fail; + } + + /* Get the ADPCM table */ + bytestream2_seek(&gbc, coef_off, SEEK_SET); + for (i = 0; i < codec->channels; i++) { + if (bytestream2_get_bufferu(&gbc, codec->extradata + i * 32, 32) != 32) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + bytestream2_skipu(&gbc, 14); + } + + avpriv_set_pts_info(st, 64, 1, codec->sample_rate); + +fail: + av_free(header); + + return ret; +} + +static int redspark_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVCodecContext *codec = s->streams[0]->codec; + RedSparkContext *redspark = s->priv_data; + uint32_t size = 8 * codec->channels; + int ret; + + if (url_feof(s->pb) || redspark->samples_count == s->streams[0]->duration) + return AVERROR_EOF; + + ret = av_get_packet(s->pb, pkt, size); + if (ret != size) { + av_free_packet(pkt); + return AVERROR(EIO); + } + + pkt->duration = 14; + redspark->samples_count += pkt->duration; + pkt->stream_index = 0; + + return ret; +} + +AVInputFormat ff_redspark_demuxer = { + .name = "redspark", + .long_name = NULL_IF_CONFIG_SMALL("RedSpark"), + .priv_data_size = sizeof(RedSparkContext), + .read_probe = redspark_probe, + .read_header = redspark_read_header, + .read_packet = redspark_read_packet, + .extensions = "rsd", +}; diff --git a/chromium/third_party/ffmpeg/libavformat/riff.c b/chromium/third_party/ffmpeg/libavformat/riff.c index 7ad96a8a76c..38d12fd64fe 100644 --- a/chromium/third_party/ffmpeg/libavformat/riff.c +++ b/chromium/third_party/ffmpeg/libavformat/riff.c @@ -19,13 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/mathematics.h" +#include "libavutil/error.h" #include "libavcodec/avcodec.h" #include "avformat.h" -#include "avio_internal.h" #include "riff.h" -#include "libavcodec/bytestream.h" -#include "libavutil/avassert.h" /* Note: When encoding, the first matching tag is used, so order is * important if multiple tags are possible for a given codec. @@ -87,6 +84,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_MPEG4, MKTAG('G', 'E', 'O', 'X') }, /* flipped video */ { AV_CODEC_ID_MPEG4, MKTAG('H', 'D', 'X', '4') }, + { AV_CODEC_ID_MPEG4, MKTAG('D', 'M', '4', 'V') }, { AV_CODEC_ID_MPEG4, MKTAG('D', 'M', 'K', '2') }, { AV_CODEC_ID_MPEG4, MKTAG('D', 'I', 'G', 'I') }, { AV_CODEC_ID_MPEG4, MKTAG('I', 'N', 'M', 'C') }, @@ -325,21 +323,20 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_DPX, MKTAG('d', 'p', 'x', ' ') }, { AV_CODEC_ID_KGV1, MKTAG('K', 'G', 'V', '1') }, { AV_CODEC_ID_LAGARITH, MKTAG('L', 'A', 'G', 'S') }, - { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '2') }, - { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '3') }, - { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '4') }, { AV_CODEC_ID_AMV, MKTAG('A', 'M', 'V', 'F') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'R', 'A') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'R', 'G') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'Y', '0') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'Y', '2') }, + /* Ut Video version 13.0.1 BT.709 codecs */ + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '0') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'L', 'H', '2') }, { AV_CODEC_ID_VBLE, MKTAG('V', 'B', 'L', 'E') }, { AV_CODEC_ID_ESCAPE130, MKTAG('E', '1', '3', '0') }, { AV_CODEC_ID_DXTORY, MKTAG('x', 't', 'o', 'r') }, { AV_CODEC_ID_ZEROCODEC, MKTAG('Z', 'E', 'C', 'O') }, { AV_CODEC_ID_Y41P, MKTAG('Y', '4', '1', 'P') }, { AV_CODEC_ID_FLIC, MKTAG('A', 'F', 'L', 'C') }, - { AV_CODEC_ID_EXR, MKTAG('e', 'x', 'r', ' ') }, { AV_CODEC_ID_MSS1, MKTAG('M', 'S', 'S', '1') }, { AV_CODEC_ID_MSA1, MKTAG('M', 'S', 'A', '1') }, { AV_CODEC_ID_TSCC2, MKTAG('T', 'S', 'C', '2') }, @@ -349,6 +346,9 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_SVQ3, MKTAG('S', 'V', 'Q', '3') }, { AV_CODEC_ID_012V, MKTAG('0', '1', '2', 'v') }, { AV_CODEC_ID_012V, MKTAG('a', '1', '2', 'v') }, + { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '2') }, + { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '3') }, + { AV_CODEC_ID_G2M, MKTAG('G', '2', 'M', '4') }, { AV_CODEC_ID_NONE, 0 } }; @@ -373,6 +373,7 @@ const AVCodecTag ff_codec_wav_tags[] = { { AV_CODEC_ID_ADPCM_YAMAHA, 0x0020 }, { AV_CODEC_ID_TRUESPEECH, 0x0022 }, { AV_CODEC_ID_GSM_MS, 0x0031 }, + { AV_CODEC_ID_GSM_MS, 0x0032 }, /* msn audio */ { AV_CODEC_ID_AMR_NB, 0x0038 }, /* rogue format number */ { AV_CODEC_ID_G723_1, 0x0042 }, { AV_CODEC_ID_ADPCM_G726, 0x0045 }, @@ -385,7 +386,7 @@ const AVCodecTag ff_codec_wav_tags[] = { /* rogue format number */ { AV_CODEC_ID_ADPCM_IMA_DK3, 0x0062 }, { AV_CODEC_ID_ADPCM_IMA_WAV, 0x0069 }, - { AV_CODEC_ID_VOXWARE, 0x0075 }, + { AV_CODEC_ID_METASOUND, 0x0075 }, { AV_CODEC_ID_AAC, 0x00ff }, { AV_CODEC_ID_SIPR, 0x0130 }, { AV_CODEC_ID_WMAV1, 0x0160 }, @@ -419,14 +420,6 @@ const AVCodecTag ff_codec_wav_tags[] = { { AV_CODEC_ID_NONE, 0 }, }; -const AVCodecGuid ff_codec_wav_guids[] = { - { AV_CODEC_ID_AC3, { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, - { AV_CODEC_ID_ATRAC3P, { 0xBF, 0xAA, 0x23, 0xE9, 0x58, 0xCB, 0x71, 0x44, 0xA1, 0x19, 0xFF, 0xFA, 0x01, 0xE4, 0xCE, 0x62 } }, - { AV_CODEC_ID_EAC3, { 0xAF, 0x87, 0xFB, 0xA7, 0x02, 0x2D, 0xFB, 0x42, 0xA4, 0xD4, 0x05, 0xCD, 0x93, 0x84, 0x3B, 0xDD } }, - { AV_CODEC_ID_MP2, { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, - { AV_CODEC_ID_NONE } -}; - const AVMetadataConv ff_riff_info_conv[] = { { "IART", "artist" }, { "ICMT", "comment" }, @@ -437,504 +430,19 @@ const AVMetadataConv ff_riff_info_conv[] = { { "INAM", "title" }, { "IPRD", "album" }, { "IPRT", "track" }, + { "ITRK", "track" }, { "ISFT", "encoder" }, { "ISMP", "timecode" }, { "ITCH", "encoded_by" }, { 0 }, }; -void ff_get_guid(AVIOContext *s, ff_asf_guid *g) -{ - av_assert0(sizeof(*g) == 16); //compiler will optimize this out - if (avio_read(s, *g, sizeof(*g)) < (int)sizeof(*g)) - memset(*g, 0, sizeof(*g)); -} - -enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid) -{ - int i; - for (i = 0; guids[i].id != AV_CODEC_ID_NONE; i++) - if (!ff_guidcmp(guids[i].guid, guid)) - return guids[i].id; - return AV_CODEC_ID_NONE; -} - -#if CONFIG_MUXERS -int64_t ff_start_tag(AVIOContext *pb, const char *tag) -{ - ffio_wfourcc(pb, tag); - avio_wl32(pb, 0); - return avio_tell(pb); -} - -void ff_end_tag(AVIOContext *pb, int64_t start) -{ - int64_t pos; - - av_assert0((start&1) == 0); - - pos = avio_tell(pb); - if (pos & 1) - avio_w8(pb, 0); - avio_seek(pb, start - 4, SEEK_SET); - avio_wl32(pb, (uint32_t)(pos - start)); - avio_seek(pb, FFALIGN(pos, 2), SEEK_SET); -} - -/* WAVEFORMATEX header */ -/* returns the size or -1 on error */ -int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) -{ - int bps, blkalign, bytespersec, frame_size; - int hdrsize = 18; - int waveformatextensible; - uint8_t temp[256]; - uint8_t *riff_extradata = temp; - uint8_t *riff_extradata_start = temp; - - if (!enc->codec_tag || enc->codec_tag > 0xffff) - return -1; - - /* We use the known constant frame size for the codec if known, otherwise - * fall back on using AVCodecContext.frame_size, which is not as reliable - * for indicating packet duration. */ - frame_size = av_get_audio_frame_duration(enc, 0); - if (!frame_size) - frame_size = enc->frame_size; - - waveformatextensible = (enc->channels > 2 && enc->channel_layout) || - enc->sample_rate > 48000 || - av_get_bits_per_sample(enc->codec_id) > 16; - - if (waveformatextensible) - avio_wl16(pb, 0xfffe); - else - avio_wl16(pb, enc->codec_tag); - - avio_wl16(pb, enc->channels); - avio_wl32(pb, enc->sample_rate); - if (enc->codec_id == AV_CODEC_ID_ATRAC3 || - enc->codec_id == AV_CODEC_ID_G723_1 || - enc->codec_id == AV_CODEC_ID_MP2 || - enc->codec_id == AV_CODEC_ID_MP3 || - enc->codec_id == AV_CODEC_ID_GSM_MS) { - bps = 0; - } else { - if (!(bps = av_get_bits_per_sample(enc->codec_id))) { - if (enc->bits_per_coded_sample) - bps = enc->bits_per_coded_sample; - else - bps = 16; // default to 16 - } - } - if (bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample) { - av_log(enc, AV_LOG_WARNING, - "requested bits_per_coded_sample (%d) " - "and actually stored (%d) differ\n", - enc->bits_per_coded_sample, bps); - } - - if (enc->codec_id == AV_CODEC_ID_MP2 || - enc->codec_id == AV_CODEC_ID_MP3) { - /* This is wrong, but it seems many demuxers do not work if this - * is set correctly. */ - blkalign = frame_size; - // blkalign = 144 * enc->bit_rate/enc->sample_rate; - } else if (enc->codec_id == AV_CODEC_ID_AC3) { - blkalign = 3840; /* maximum bytes per frame */ - } else if (enc->codec_id == AV_CODEC_ID_AAC) { - blkalign = 768 * enc->channels; /* maximum bytes per frame */ - } else if (enc->codec_id == AV_CODEC_ID_G723_1) { - blkalign = 24; - } else if (enc->block_align != 0) { /* specified by the codec */ - blkalign = enc->block_align; - } else - blkalign = bps * enc->channels / av_gcd(8, bps); - if (enc->codec_id == AV_CODEC_ID_PCM_U8 || - enc->codec_id == AV_CODEC_ID_PCM_S24LE || - enc->codec_id == AV_CODEC_ID_PCM_S32LE || - enc->codec_id == AV_CODEC_ID_PCM_F32LE || - enc->codec_id == AV_CODEC_ID_PCM_F64LE || - enc->codec_id == AV_CODEC_ID_PCM_S16LE) { - bytespersec = enc->sample_rate * blkalign; - } else if (enc->codec_id == AV_CODEC_ID_G723_1) { - bytespersec = 800; - } else { - bytespersec = enc->bit_rate / 8; - } - avio_wl32(pb, bytespersec); /* bytes per second */ - avio_wl16(pb, blkalign); /* block align */ - avio_wl16(pb, bps); /* bits per sample */ - if (enc->codec_id == AV_CODEC_ID_MP3) { - hdrsize += 12; - bytestream_put_le16(&riff_extradata, 1); /* wID */ - bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ - bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ - bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ - bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ - } else if (enc->codec_id == AV_CODEC_ID_MP2) { - hdrsize += 22; - /* fwHeadLayer */ - bytestream_put_le16(&riff_extradata, 2); - /* dwHeadBitrate */ - bytestream_put_le32(&riff_extradata, enc->bit_rate); - /* fwHeadMode */ - bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); - /* fwHeadModeExt */ - bytestream_put_le16(&riff_extradata, 0); - /* wHeadEmphasis */ - bytestream_put_le16(&riff_extradata, 1); - /* fwHeadFlags */ - bytestream_put_le16(&riff_extradata, 16); - /* dwPTSLow */ - bytestream_put_le32(&riff_extradata, 0); - /* dwPTSHigh */ - bytestream_put_le32(&riff_extradata, 0); - } else if (enc->codec_id == AV_CODEC_ID_G723_1) { - hdrsize += 20; - bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */ - bytestream_put_le32(&riff_extradata, 0xaea2f732); - bytestream_put_le16(&riff_extradata, 0xacde); - } else if (enc->codec_id == AV_CODEC_ID_GSM_MS || - enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { - hdrsize += 2; - /* wSamplesPerBlock */ - bytestream_put_le16(&riff_extradata, frame_size); - } else if (enc->extradata_size) { - riff_extradata_start = enc->extradata; - riff_extradata = enc->extradata + enc->extradata_size; - hdrsize += enc->extradata_size; - } - /* write WAVEFORMATEXTENSIBLE extensions */ - if (waveformatextensible) { - hdrsize += 22; - /* 22 is WAVEFORMATEXTENSIBLE size */ - avio_wl16(pb, riff_extradata - riff_extradata_start + 22); - /* ValidBitsPerSample || SamplesPerBlock || Reserved */ - avio_wl16(pb, bps); - /* dwChannelMask */ - avio_wl32(pb, enc->channel_layout); - /* GUID + next 3 */ - avio_wl32(pb, enc->codec_tag); - avio_wl32(pb, 0x00100000); - avio_wl32(pb, 0xAA000080); - avio_wl32(pb, 0x719B3800); - } else { - avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */ - } - avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start); - if (hdrsize & 1) { - hdrsize++; - avio_w8(pb, 0); - } - - return hdrsize; -} - -/* BITMAPINFOHEADER header */ -void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, - const AVCodecTag *tags, int for_asf) -{ - /* size */ - avio_wl32(pb, 40 + enc->extradata_size); - avio_wl32(pb, enc->width); - //We always store RGB TopDown - avio_wl32(pb, enc->codec_tag ? enc->height : -enc->height); - /* planes */ - avio_wl16(pb, 1); - /* depth */ - avio_wl16(pb, enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24); - /* compression type */ - avio_wl32(pb, enc->codec_tag); - avio_wl32(pb, (enc->width * enc->height * (enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24)+7) / 8); - avio_wl32(pb, 0); - avio_wl32(pb, 0); - avio_wl32(pb, 0); - avio_wl32(pb, 0); - - avio_write(pb, enc->extradata, enc->extradata_size); - - if (!for_asf && enc->extradata_size & 1) - avio_w8(pb, 0); -} - -void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, - int *au_ssize, int *au_scale) -{ - int gcd; - int audio_frame_size; - - /* We use the known constant frame size for the codec if known, otherwise - * fall back on using AVCodecContext.frame_size, which is not as reliable - * for indicating packet duration. */ - audio_frame_size = av_get_audio_frame_duration(stream, 0); - if (!audio_frame_size) - audio_frame_size = stream->frame_size; - - *au_ssize = stream->block_align; - if (audio_frame_size && stream->sample_rate) { - *au_scale = audio_frame_size; - *au_rate = stream->sample_rate; - } else if (stream->codec_type == AVMEDIA_TYPE_VIDEO || - stream->codec_type == AVMEDIA_TYPE_DATA || - stream->codec_type == AVMEDIA_TYPE_SUBTITLE) { - *au_scale = stream->time_base.num; - *au_rate = stream->time_base.den; - } else { - *au_scale = stream->block_align ? stream->block_align * 8 : 8; - *au_rate = stream->bit_rate ? stream->bit_rate : - 8 * stream->sample_rate; - } - gcd = av_gcd(*au_scale, *au_rate); - *au_scale /= gcd; - *au_rate /= gcd; -} - -void ff_riff_write_info_tag(AVIOContext *pb, const char *tag, const char *str) -{ - int len = strlen(str); - if (len > 0) { - len++; - ffio_wfourcc(pb, tag); - avio_wl32(pb, len); - avio_put_str(pb, str); - if (len & 1) - avio_w8(pb, 0); - } -} - -static const char riff_tags[][5] = { - "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI", - "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD", - "IPRT", "ISBJ", "ISFT", "ISHP", "ISMP", "ISRC", "ISRF", "ITCH", - { 0 } -}; - -static int riff_has_valid_tags(AVFormatContext *s) -{ - int i; - - for (i = 0; *riff_tags[i]; i++) - if (av_dict_get(s->metadata, riff_tags[i], NULL, AV_DICT_MATCH_CASE)) - return 1; - - return 0; -} - -void ff_riff_write_info(AVFormatContext *s) -{ - AVIOContext *pb = s->pb; - int i; - int64_t list_pos; - AVDictionaryEntry *t = NULL; - - ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL); - - /* writing empty LIST is not nice and may cause problems */ - if (!riff_has_valid_tags(s)) - return; - - list_pos = ff_start_tag(pb, "LIST"); - ffio_wfourcc(pb, "INFO"); - for (i = 0; *riff_tags[i]; i++) - if ((t = av_dict_get(s->metadata, riff_tags[i], - NULL, AV_DICT_MATCH_CASE))) - ff_riff_write_info_tag(s->pb, t->key, t->value); - ff_end_tag(pb, list_pos); -} -#endif /* CONFIG_MUXERS */ - -#if CONFIG_DEMUXERS -/* We could be given one of the three possible structures here: - * WAVEFORMAT, PCMWAVEFORMAT or WAVEFORMATEX. Each structure - * is an expansion of the previous one with the fields added - * at the bottom. PCMWAVEFORMAT adds 'WORD wBitsPerSample' and - * WAVEFORMATEX adds 'WORD cbSize' and basically makes itself - * an openended structure. - */ - -static void parse_waveformatex(AVIOContext *pb, AVCodecContext *c) +const struct AVCodecTag *avformat_get_riff_video_tags(void) { - ff_asf_guid subformat; - int bps = avio_rl16(pb); - if (bps) - c->bits_per_coded_sample = bps; - - c->channel_layout = avio_rl32(pb); /* dwChannelMask */ - - ff_get_guid(pb, &subformat); - if (!memcmp(subformat + 4, - (const uint8_t[]){ FF_MEDIASUBTYPE_BASE_GUID }, 12)) { - c->codec_tag = AV_RL32(subformat); - c->codec_id = ff_wav_codec_get_id(c->codec_tag, - c->bits_per_coded_sample); - } else { - c->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat); - if (!c->codec_id) - av_log(c, AV_LOG_WARNING, - "unknown subformat:"FF_PRI_GUID"\n", - FF_ARG_GUID(subformat)); - } + return ff_codec_bmp_tags; } -int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) +const struct AVCodecTag *avformat_get_riff_audio_tags(void) { - int id; - - id = avio_rl16(pb); - codec->codec_type = AVMEDIA_TYPE_AUDIO; - codec->channels = avio_rl16(pb); - codec->sample_rate = avio_rl32(pb); - codec->bit_rate = avio_rl32(pb) * 8; - codec->block_align = avio_rl16(pb); - if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */ - codec->bits_per_coded_sample = 8; - } else - codec->bits_per_coded_sample = avio_rl16(pb); - if (id == 0xFFFE) { - codec->codec_tag = 0; - } else { - codec->codec_tag = id; - codec->codec_id = ff_wav_codec_get_id(id, - codec->bits_per_coded_sample); - } - if (size >= 18) { /* We're obviously dealing with WAVEFORMATEX */ - int cbSize = avio_rl16(pb); /* cbSize */ - size -= 18; - cbSize = FFMIN(size, cbSize); - if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */ - parse_waveformatex(pb, codec); - cbSize -= 22; - size -= 22; - } - codec->extradata_size = cbSize; - if (cbSize > 0) { - av_free(codec->extradata); - codec->extradata = av_mallocz(codec->extradata_size + - FF_INPUT_BUFFER_PADDING_SIZE); - if (!codec->extradata) - return AVERROR(ENOMEM); - avio_read(pb, codec->extradata, codec->extradata_size); - size -= cbSize; - } - - /* It is possible for the chunk to contain garbage at the end */ - if (size > 0) - avio_skip(pb, size); - } - if (codec->codec_id == AV_CODEC_ID_AAC_LATM) { - /* Channels and sample_rate values are those prior to applying SBR - * and/or PS. */ - codec->channels = 0; - codec->sample_rate = 0; - } - /* override bits_per_coded_sample for G.726 */ - if (codec->codec_id == AV_CODEC_ID_ADPCM_G726 && codec->sample_rate) - codec->bits_per_coded_sample = codec->bit_rate / codec->sample_rate; - - return 0; -} - -enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps) -{ - enum AVCodecID id; - id = ff_codec_get_id(ff_codec_wav_tags, tag); - if (id <= 0) - return id; - - if (id == AV_CODEC_ID_PCM_S16LE) - id = ff_get_pcm_codec_id(bps, 0, 0, ~1); - else if (id == AV_CODEC_ID_PCM_F32LE) - id = ff_get_pcm_codec_id(bps, 1, 0, 0); - - if (id == AV_CODEC_ID_ADPCM_IMA_WAV && bps == 8) - id = AV_CODEC_ID_PCM_ZORK; - return id; -} - -int ff_get_bmp_header(AVIOContext *pb, AVStream *st, unsigned *esize) -{ - int tag1; - if(esize) *esize = avio_rl32(pb); - else avio_rl32(pb); - st->codec->width = avio_rl32(pb); - st->codec->height = (int32_t)avio_rl32(pb); - avio_rl16(pb); /* planes */ - st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */ - tag1 = avio_rl32(pb); - avio_rl32(pb); /* ImageSize */ - avio_rl32(pb); /* XPelsPerMeter */ - avio_rl32(pb); /* YPelsPerMeter */ - avio_rl32(pb); /* ClrUsed */ - avio_rl32(pb); /* ClrImportant */ - return tag1; -} - -int ff_read_riff_info(AVFormatContext *s, int64_t size) -{ - int64_t start, end, cur; - AVIOContext *pb = s->pb; - - start = avio_tell(pb); - end = start + size; - - while ((cur = avio_tell(pb)) >= 0 && - cur <= end - 8 /* = tag + size */) { - uint32_t chunk_code; - int64_t chunk_size; - char key[5] = { 0 }; - char *value; - - chunk_code = avio_rl32(pb); - chunk_size = avio_rl32(pb); - if (url_feof(pb)) { - if (chunk_code || chunk_size) { - av_log(s, AV_LOG_WARNING, "INFO subchunk truncated\n"); - return AVERROR_INVALIDDATA; - } - return AVERROR_EOF; - } - if (chunk_size > end || - end - chunk_size < cur || - chunk_size == UINT_MAX) { - avio_seek(pb, -9, SEEK_CUR); - chunk_code = avio_rl32(pb); - chunk_size = avio_rl32(pb); - if (chunk_size > end || end - chunk_size < cur || chunk_size == UINT_MAX) { - av_log(s, AV_LOG_WARNING, "too big INFO subchunk\n"); - return AVERROR_INVALIDDATA; - } - } - - chunk_size += (chunk_size & 1); - - if (!chunk_code) { - if (chunk_size) - avio_skip(pb, chunk_size); - else if (pb->eof_reached) { - av_log(s, AV_LOG_WARNING, "truncated file\n"); - return AVERROR_EOF; - } - continue; - } - - value = av_mallocz(chunk_size + 1); - if (!value) { - av_log(s, AV_LOG_ERROR, - "out of memory, unable to read INFO tag\n"); - return AVERROR(ENOMEM); - } - - AV_WL32(key, chunk_code); - - if (avio_read(pb, value, chunk_size) != chunk_size) { - av_log(s, AV_LOG_WARNING, - "premature end of file while reading INFO tag\n"); - } - - av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); - } - - return 0; + return ff_codec_wav_tags; } -#endif /* CONFIG_DEMUXERS */ diff --git a/chromium/third_party/ffmpeg/libavformat/riff.h b/chromium/third_party/ffmpeg/libavformat/riff.h index cb8378922f6..1bf437e06c8 100644 --- a/chromium/third_party/ffmpeg/libavformat/riff.h +++ b/chromium/third_party/ffmpeg/libavformat/riff.h @@ -34,7 +34,6 @@ #include "metadata.h" extern const AVMetadataConv ff_riff_info_conv[]; -extern const char ff_riff_tags[][5]; int64_t ff_start_tag(AVIOContext *pb, const char *tag); void ff_end_tag(AVIOContext *pb, int64_t start); diff --git a/chromium/third_party/ffmpeg/libavformat/riffdec.c b/chromium/third_party/ffmpeg/libavformat/riffdec.c new file mode 100644 index 00000000000..973f3fada9c --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/riffdec.c @@ -0,0 +1,247 @@ +/* + * RIFF demuxing functions and data + * Copyright (c) 2000 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/dict.h" +#include "libavutil/error.h" +#include "libavutil/log.h" +#include "libavutil/mathematics.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/bytestream.h" +#include "avformat.h" +#include "avio_internal.h" +#include "riff.h" + +const AVCodecGuid ff_codec_wav_guids[] = { + { AV_CODEC_ID_AC3, { 0x2C, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, + { AV_CODEC_ID_ATRAC3P, { 0xBF, 0xAA, 0x23, 0xE9, 0x58, 0xCB, 0x71, 0x44, 0xA1, 0x19, 0xFF, 0xFA, 0x01, 0xE4, 0xCE, 0x62 } }, + { AV_CODEC_ID_EAC3, { 0xAF, 0x87, 0xFB, 0xA7, 0x02, 0x2D, 0xFB, 0x42, 0xA4, 0xD4, 0x05, 0xCD, 0x93, 0x84, 0x3B, 0xDD } }, + { AV_CODEC_ID_MP2, { 0x2B, 0x80, 0x6D, 0xE0, 0x46, 0xDB, 0xCF, 0x11, 0xB4, 0xD1, 0x00, 0x80, 0x5F, 0x6C, 0xBB, 0xEA } }, + { AV_CODEC_ID_NONE } +}; + +void ff_get_guid(AVIOContext *s, ff_asf_guid *g) +{ + av_assert0(sizeof(*g) == 16); //compiler will optimize this out + if (avio_read(s, *g, sizeof(*g)) < (int)sizeof(*g)) + memset(*g, 0, sizeof(*g)); +} + +enum AVCodecID ff_codec_guid_get_id(const AVCodecGuid *guids, ff_asf_guid guid) +{ + int i; + for (i = 0; guids[i].id != AV_CODEC_ID_NONE; i++) + if (!ff_guidcmp(guids[i].guid, guid)) + return guids[i].id; + return AV_CODEC_ID_NONE; +} + +/* We could be given one of the three possible structures here: + * WAVEFORMAT, PCMWAVEFORMAT or WAVEFORMATEX. Each structure + * is an expansion of the previous one with the fields added + * at the bottom. PCMWAVEFORMAT adds 'WORD wBitsPerSample' and + * WAVEFORMATEX adds 'WORD cbSize' and basically makes itself + * an openended structure. + */ + +static void parse_waveformatex(AVIOContext *pb, AVCodecContext *c) +{ + ff_asf_guid subformat; + int bps = avio_rl16(pb); + if (bps) + c->bits_per_coded_sample = bps; + + c->channel_layout = avio_rl32(pb); /* dwChannelMask */ + + ff_get_guid(pb, &subformat); + if (!memcmp(subformat + 4, + (const uint8_t[]){ FF_MEDIASUBTYPE_BASE_GUID }, 12)) { + c->codec_tag = AV_RL32(subformat); + c->codec_id = ff_wav_codec_get_id(c->codec_tag, + c->bits_per_coded_sample); + } else { + c->codec_id = ff_codec_guid_get_id(ff_codec_wav_guids, subformat); + if (!c->codec_id) + av_log(c, AV_LOG_WARNING, + "unknown subformat:"FF_PRI_GUID"\n", + FF_ARG_GUID(subformat)); + } +} + +int ff_get_wav_header(AVIOContext *pb, AVCodecContext *codec, int size) +{ + int id; + + id = avio_rl16(pb); + codec->codec_type = AVMEDIA_TYPE_AUDIO; + codec->channels = avio_rl16(pb); + codec->sample_rate = avio_rl32(pb); + codec->bit_rate = avio_rl32(pb) * 8; + codec->block_align = avio_rl16(pb); + if (size == 14) { /* We're dealing with plain vanilla WAVEFORMAT */ + codec->bits_per_coded_sample = 8; + } else + codec->bits_per_coded_sample = avio_rl16(pb); + if (id == 0xFFFE) { + codec->codec_tag = 0; + } else { + codec->codec_tag = id; + codec->codec_id = ff_wav_codec_get_id(id, + codec->bits_per_coded_sample); + } + if (size >= 18) { /* We're obviously dealing with WAVEFORMATEX */ + int cbSize = avio_rl16(pb); /* cbSize */ + size -= 18; + cbSize = FFMIN(size, cbSize); + if (cbSize >= 22 && id == 0xfffe) { /* WAVEFORMATEXTENSIBLE */ + parse_waveformatex(pb, codec); + cbSize -= 22; + size -= 22; + } + codec->extradata_size = cbSize; + if (cbSize > 0) { + av_free(codec->extradata); + codec->extradata = av_mallocz(codec->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (!codec->extradata) + return AVERROR(ENOMEM); + avio_read(pb, codec->extradata, codec->extradata_size); + size -= cbSize; + } + + /* It is possible for the chunk to contain garbage at the end */ + if (size > 0) + avio_skip(pb, size); + } + if (codec->codec_id == AV_CODEC_ID_AAC_LATM) { + /* Channels and sample_rate values are those prior to applying SBR + * and/or PS. */ + codec->channels = 0; + codec->sample_rate = 0; + } + /* override bits_per_coded_sample for G.726 */ + if (codec->codec_id == AV_CODEC_ID_ADPCM_G726 && codec->sample_rate) + codec->bits_per_coded_sample = codec->bit_rate / codec->sample_rate; + + return 0; +} + +enum AVCodecID ff_wav_codec_get_id(unsigned int tag, int bps) +{ + enum AVCodecID id; + id = ff_codec_get_id(ff_codec_wav_tags, tag); + if (id <= 0) + return id; + + if (id == AV_CODEC_ID_PCM_S16LE) + id = ff_get_pcm_codec_id(bps, 0, 0, ~1); + else if (id == AV_CODEC_ID_PCM_F32LE) + id = ff_get_pcm_codec_id(bps, 1, 0, 0); + + if (id == AV_CODEC_ID_ADPCM_IMA_WAV && bps == 8) + id = AV_CODEC_ID_PCM_ZORK; + return id; +} + +int ff_get_bmp_header(AVIOContext *pb, AVStream *st, unsigned *esize) +{ + int tag1; + if(esize) *esize = avio_rl32(pb); + else avio_rl32(pb); + st->codec->width = avio_rl32(pb); + st->codec->height = (int32_t)avio_rl32(pb); + avio_rl16(pb); /* planes */ + st->codec->bits_per_coded_sample = avio_rl16(pb); /* depth */ + tag1 = avio_rl32(pb); + avio_rl32(pb); /* ImageSize */ + avio_rl32(pb); /* XPelsPerMeter */ + avio_rl32(pb); /* YPelsPerMeter */ + avio_rl32(pb); /* ClrUsed */ + avio_rl32(pb); /* ClrImportant */ + return tag1; +} + +int ff_read_riff_info(AVFormatContext *s, int64_t size) +{ + int64_t start, end, cur; + AVIOContext *pb = s->pb; + + start = avio_tell(pb); + end = start + size; + + while ((cur = avio_tell(pb)) >= 0 && + cur <= end - 8 /* = tag + size */) { + uint32_t chunk_code; + int64_t chunk_size; + char key[5] = { 0 }; + char *value; + + chunk_code = avio_rl32(pb); + chunk_size = avio_rl32(pb); + if (url_feof(pb)) { + if (chunk_code || chunk_size) { + av_log(s, AV_LOG_WARNING, "INFO subchunk truncated\n"); + return AVERROR_INVALIDDATA; + } + return AVERROR_EOF; + } + if (chunk_size > end || + end - chunk_size < cur || + chunk_size == UINT_MAX) { + avio_seek(pb, -9, SEEK_CUR); + chunk_code = avio_rl32(pb); + chunk_size = avio_rl32(pb); + if (chunk_size > end || end - chunk_size < cur || chunk_size == UINT_MAX) { + av_log(s, AV_LOG_WARNING, "too big INFO subchunk\n"); + return AVERROR_INVALIDDATA; + } + } + + chunk_size += (chunk_size & 1); + + if (!chunk_code) { + if (chunk_size) + avio_skip(pb, chunk_size); + else if (pb->eof_reached) { + av_log(s, AV_LOG_WARNING, "truncated file\n"); + return AVERROR_EOF; + } + continue; + } + + value = av_mallocz(chunk_size + 1); + if (!value) { + av_log(s, AV_LOG_ERROR, + "out of memory, unable to read INFO tag\n"); + return AVERROR(ENOMEM); + } + + AV_WL32(key, chunk_code); + + if (avio_read(pb, value, chunk_size) != chunk_size) { + av_log(s, AV_LOG_WARNING, + "premature end of file while reading INFO tag\n"); + } + + av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); + } + + return 0; +} diff --git a/chromium/third_party/ffmpeg/libavformat/riffenc.c b/chromium/third_party/ffmpeg/libavformat/riffenc.c new file mode 100644 index 00000000000..bcfe018f74e --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/riffenc.c @@ -0,0 +1,312 @@ +/* + * RIFF muxing functions + * Copyright (c) 2000 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/dict.h" +#include "libavutil/log.h" +#include "libavutil/mathematics.h" +#include "libavcodec/avcodec.h" +#include "libavcodec/bytestream.h" +#include "avformat.h" +#include "avio_internal.h" +#include "riff.h" + +int64_t ff_start_tag(AVIOContext *pb, const char *tag) +{ + ffio_wfourcc(pb, tag); + avio_wl32(pb, 0); + return avio_tell(pb); +} + +void ff_end_tag(AVIOContext *pb, int64_t start) +{ + int64_t pos; + + av_assert0((start&1) == 0); + + pos = avio_tell(pb); + if (pos & 1) + avio_w8(pb, 0); + avio_seek(pb, start - 4, SEEK_SET); + avio_wl32(pb, (uint32_t)(pos - start)); + avio_seek(pb, FFALIGN(pos, 2), SEEK_SET); +} + +/* WAVEFORMATEX header */ +/* returns the size or -1 on error */ +int ff_put_wav_header(AVIOContext *pb, AVCodecContext *enc) +{ + int bps, blkalign, bytespersec, frame_size; + int hdrsize = 18; + int waveformatextensible; + uint8_t temp[256]; + uint8_t *riff_extradata = temp; + uint8_t *riff_extradata_start = temp; + + if (!enc->codec_tag || enc->codec_tag > 0xffff) + return -1; + + /* We use the known constant frame size for the codec if known, otherwise + * fall back on using AVCodecContext.frame_size, which is not as reliable + * for indicating packet duration. */ + frame_size = av_get_audio_frame_duration(enc, 0); + if (!frame_size) + frame_size = enc->frame_size; + + waveformatextensible = (enc->channels > 2 && enc->channel_layout) || + enc->sample_rate > 48000 || + av_get_bits_per_sample(enc->codec_id) > 16; + + if (waveformatextensible) + avio_wl16(pb, 0xfffe); + else + avio_wl16(pb, enc->codec_tag); + + avio_wl16(pb, enc->channels); + avio_wl32(pb, enc->sample_rate); + if (enc->codec_id == AV_CODEC_ID_ATRAC3 || + enc->codec_id == AV_CODEC_ID_G723_1 || + enc->codec_id == AV_CODEC_ID_MP2 || + enc->codec_id == AV_CODEC_ID_MP3 || + enc->codec_id == AV_CODEC_ID_GSM_MS) { + bps = 0; + } else { + if (!(bps = av_get_bits_per_sample(enc->codec_id))) { + if (enc->bits_per_coded_sample) + bps = enc->bits_per_coded_sample; + else + bps = 16; // default to 16 + } + } + if (bps != enc->bits_per_coded_sample && enc->bits_per_coded_sample) { + av_log(enc, AV_LOG_WARNING, + "requested bits_per_coded_sample (%d) " + "and actually stored (%d) differ\n", + enc->bits_per_coded_sample, bps); + } + + if (enc->codec_id == AV_CODEC_ID_MP2 || + enc->codec_id == AV_CODEC_ID_MP3) { + /* This is wrong, but it seems many demuxers do not work if this + * is set correctly. */ + blkalign = frame_size; + // blkalign = 144 * enc->bit_rate/enc->sample_rate; + } else if (enc->codec_id == AV_CODEC_ID_AC3) { + blkalign = 3840; /* maximum bytes per frame */ + } else if (enc->codec_id == AV_CODEC_ID_AAC) { + blkalign = 768 * enc->channels; /* maximum bytes per frame */ + } else if (enc->codec_id == AV_CODEC_ID_G723_1) { + blkalign = 24; + } else if (enc->block_align != 0) { /* specified by the codec */ + blkalign = enc->block_align; + } else + blkalign = bps * enc->channels / av_gcd(8, bps); + if (enc->codec_id == AV_CODEC_ID_PCM_U8 || + enc->codec_id == AV_CODEC_ID_PCM_S24LE || + enc->codec_id == AV_CODEC_ID_PCM_S32LE || + enc->codec_id == AV_CODEC_ID_PCM_F32LE || + enc->codec_id == AV_CODEC_ID_PCM_F64LE || + enc->codec_id == AV_CODEC_ID_PCM_S16LE) { + bytespersec = enc->sample_rate * blkalign; + } else if (enc->codec_id == AV_CODEC_ID_G723_1) { + bytespersec = 800; + } else { + bytespersec = enc->bit_rate / 8; + } + avio_wl32(pb, bytespersec); /* bytes per second */ + avio_wl16(pb, blkalign); /* block align */ + avio_wl16(pb, bps); /* bits per sample */ + if (enc->codec_id == AV_CODEC_ID_MP3) { + hdrsize += 12; + bytestream_put_le16(&riff_extradata, 1); /* wID */ + bytestream_put_le32(&riff_extradata, 2); /* fdwFlags */ + bytestream_put_le16(&riff_extradata, 1152); /* nBlockSize */ + bytestream_put_le16(&riff_extradata, 1); /* nFramesPerBlock */ + bytestream_put_le16(&riff_extradata, 1393); /* nCodecDelay */ + } else if (enc->codec_id == AV_CODEC_ID_MP2) { + hdrsize += 22; + /* fwHeadLayer */ + bytestream_put_le16(&riff_extradata, 2); + /* dwHeadBitrate */ + bytestream_put_le32(&riff_extradata, enc->bit_rate); + /* fwHeadMode */ + bytestream_put_le16(&riff_extradata, enc->channels == 2 ? 1 : 8); + /* fwHeadModeExt */ + bytestream_put_le16(&riff_extradata, 0); + /* wHeadEmphasis */ + bytestream_put_le16(&riff_extradata, 1); + /* fwHeadFlags */ + bytestream_put_le16(&riff_extradata, 16); + /* dwPTSLow */ + bytestream_put_le32(&riff_extradata, 0); + /* dwPTSHigh */ + bytestream_put_le32(&riff_extradata, 0); + } else if (enc->codec_id == AV_CODEC_ID_G723_1) { + hdrsize += 20; + bytestream_put_le32(&riff_extradata, 0x9ace0002); /* extradata needed for msacm g723.1 codec */ + bytestream_put_le32(&riff_extradata, 0xaea2f732); + bytestream_put_le16(&riff_extradata, 0xacde); + } else if (enc->codec_id == AV_CODEC_ID_GSM_MS || + enc->codec_id == AV_CODEC_ID_ADPCM_IMA_WAV) { + hdrsize += 2; + /* wSamplesPerBlock */ + bytestream_put_le16(&riff_extradata, frame_size); + } else if (enc->extradata_size) { + riff_extradata_start = enc->extradata; + riff_extradata = enc->extradata + enc->extradata_size; + hdrsize += enc->extradata_size; + } + /* write WAVEFORMATEXTENSIBLE extensions */ + if (waveformatextensible) { + hdrsize += 22; + /* 22 is WAVEFORMATEXTENSIBLE size */ + avio_wl16(pb, riff_extradata - riff_extradata_start + 22); + /* ValidBitsPerSample || SamplesPerBlock || Reserved */ + avio_wl16(pb, bps); + /* dwChannelMask */ + avio_wl32(pb, enc->channel_layout); + /* GUID + next 3 */ + avio_wl32(pb, enc->codec_tag); + avio_wl32(pb, 0x00100000); + avio_wl32(pb, 0xAA000080); + avio_wl32(pb, 0x719B3800); + } else { + avio_wl16(pb, riff_extradata - riff_extradata_start); /* cbSize */ + } + avio_write(pb, riff_extradata_start, riff_extradata - riff_extradata_start); + if (hdrsize & 1) { + hdrsize++; + avio_w8(pb, 0); + } + + return hdrsize; +} + +/* BITMAPINFOHEADER header */ +void ff_put_bmp_header(AVIOContext *pb, AVCodecContext *enc, + const AVCodecTag *tags, int for_asf) +{ + /* size */ + avio_wl32(pb, 40 + enc->extradata_size); + avio_wl32(pb, enc->width); + //We always store RGB TopDown + avio_wl32(pb, enc->codec_tag ? enc->height : -enc->height); + /* planes */ + avio_wl16(pb, 1); + /* depth */ + avio_wl16(pb, enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24); + /* compression type */ + avio_wl32(pb, enc->codec_tag); + avio_wl32(pb, (enc->width * enc->height * (enc->bits_per_coded_sample ? enc->bits_per_coded_sample : 24)+7) / 8); + avio_wl32(pb, 0); + avio_wl32(pb, 0); + avio_wl32(pb, 0); + avio_wl32(pb, 0); + + avio_write(pb, enc->extradata, enc->extradata_size); + + if (!for_asf && enc->extradata_size & 1) + avio_w8(pb, 0); +} + +void ff_parse_specific_params(AVCodecContext *stream, int *au_rate, + int *au_ssize, int *au_scale) +{ + int gcd; + int audio_frame_size; + + /* We use the known constant frame size for the codec if known, otherwise + * fall back on using AVCodecContext.frame_size, which is not as reliable + * for indicating packet duration. */ + audio_frame_size = av_get_audio_frame_duration(stream, 0); + if (!audio_frame_size) + audio_frame_size = stream->frame_size; + + *au_ssize = stream->block_align; + if (audio_frame_size && stream->sample_rate) { + *au_scale = audio_frame_size; + *au_rate = stream->sample_rate; + } else if (stream->codec_type == AVMEDIA_TYPE_VIDEO || + stream->codec_type == AVMEDIA_TYPE_DATA || + stream->codec_type == AVMEDIA_TYPE_SUBTITLE) { + *au_scale = stream->time_base.num; + *au_rate = stream->time_base.den; + } else { + *au_scale = stream->block_align ? stream->block_align * 8 : 8; + *au_rate = stream->bit_rate ? stream->bit_rate : + 8 * stream->sample_rate; + } + gcd = av_gcd(*au_scale, *au_rate); + *au_scale /= gcd; + *au_rate /= gcd; +} + +void ff_riff_write_info_tag(AVIOContext *pb, const char *tag, const char *str) +{ + int len = strlen(str); + if (len > 0) { + len++; + ffio_wfourcc(pb, tag); + avio_wl32(pb, len); + avio_put_str(pb, str); + if (len & 1) + avio_w8(pb, 0); + } +} + +static const char riff_tags[][5] = { + "IARL", "IART", "ICMS", "ICMT", "ICOP", "ICRD", "ICRP", "IDIM", "IDPI", + "IENG", "IGNR", "IKEY", "ILGT", "ILNG", "IMED", "INAM", "IPLT", "IPRD", + "IPRT", "ITRK", "ISBJ", "ISFT", "ISHP", "ISMP", "ISRC", "ISRF", "ITCH", + { 0 } +}; + +static int riff_has_valid_tags(AVFormatContext *s) +{ + int i; + + for (i = 0; *riff_tags[i]; i++) + if (av_dict_get(s->metadata, riff_tags[i], NULL, AV_DICT_MATCH_CASE)) + return 1; + + return 0; +} + +void ff_riff_write_info(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + int i; + int64_t list_pos; + AVDictionaryEntry *t = NULL; + + ff_metadata_conv(&s->metadata, ff_riff_info_conv, NULL); + + /* writing empty LIST is not nice and may cause problems */ + if (!riff_has_valid_tags(s)) + return; + + list_pos = ff_start_tag(pb, "LIST"); + ffio_wfourcc(pb, "INFO"); + for (i = 0; *riff_tags[i]; i++) + if ((t = av_dict_get(s->metadata, riff_tags[i], + NULL, AV_DICT_MATCH_CASE))) + ff_riff_write_info_tag(s->pb, t->key, t->value); + ff_end_tag(pb, list_pos); +} diff --git a/chromium/third_party/ffmpeg/libavformat/rmdec.c b/chromium/third_party/ffmpeg/libavformat/rmdec.c index 13d1d25758d..38bddc37600 100644 --- a/chromium/third_party/ffmpeg/libavformat/rmdec.c +++ b/chromium/third_party/ffmpeg/libavformat/rmdec.c @@ -22,6 +22,7 @@ #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/channel_layout.h" +#include "libavutil/internal.h" #include "libavutil/intreadwrite.h" #include "libavutil/dict.h" #include "avformat.h" @@ -95,13 +96,14 @@ static int rm_read_extradata(AVIOContext *pb, AVCodecContext *avctx, unsigned si return 0; } -static void rm_read_metadata(AVFormatContext *s, int wide) +static void rm_read_metadata(AVFormatContext *s, AVIOContext *pb, int wide) { char buf[1024]; int i; + for (i=0; i<FF_ARRAY_ELEMS(ff_rm_metadata); i++) { - int len = wide ? avio_rb16(s->pb) : avio_r8(s->pb); - get_strl(s->pb, buf, sizeof(buf), len); + int len = wide ? avio_rb16(pb) : avio_r8(pb); + get_strl(pb, buf, sizeof(buf), len); av_dict_set(&s->metadata, ff_rm_metadata[i], buf, 0); } } @@ -134,7 +136,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, avio_skip(pb, 8); bytes_per_minute = avio_rb16(pb); avio_skip(pb, 4); - rm_read_metadata(s, 0); + rm_read_metadata(s, pb, 0); if ((startpos + header_size) >= avio_tell(pb) + 2) { // fourcc (should always be "lpcJ") avio_r8(pb); @@ -293,7 +295,7 @@ static int rm_read_audio_stream_info(AVFormatContext *s, AVIOContext *pb, avio_r8(pb); avio_r8(pb); avio_r8(pb); - rm_read_metadata(s, 0); + rm_read_metadata(s, pb, 0); } } return 0; @@ -516,7 +518,7 @@ static int rm_read_header(AVFormatContext *s) flags = avio_rb16(pb); /* flags */ break; case MKTAG('C', 'O', 'N', 'T'): - rm_read_metadata(s, 1); + rm_read_metadata(s, pb, 1); break; case MKTAG('M', 'D', 'P', 'R'): st = avformat_new_stream(s, NULL); @@ -721,6 +723,8 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, if(++vst->cur_slice > vst->slices) return 1; + if(!vst->pkt.data) + return AVERROR(ENOMEM); AV_WL32(vst->pkt.data - 7 + 8*vst->cur_slice, 1); AV_WL32(vst->pkt.data - 3 + 8*vst->cur_slice, vst->videobufpos - 8*vst->slices - 1); if(vst->videobufpos + len > vst->videobufsize) @@ -737,7 +741,9 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, vst->pkt.size= 0; vst->pkt.buf = NULL; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS vst->pkt.destruct = NULL; +FF_ENABLE_DEPRECATION_WARNINGS #endif if(vst->slices != vst->cur_slice) //FIXME find out how to set slices correct from the begin memmove(pkt->data + 1 + 8*vst->cur_slice, pkt->data + 1 + 8*vst->slices, @@ -773,11 +779,13 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, int *seq, int flags, int64_t timestamp) { RMDemuxContext *rm = s->priv_data; + int ret; if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { rm->current_stream= st->id; - if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, ×tamp)) - return -1; //got partial frame + ret = rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, ×tamp); + if(ret) + return ret; //got partial frame or error } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { if ((ast->deint_id == DEINT_ID_GENR) || (ast->deint_id == DEINT_ID_INT4) || @@ -924,6 +932,8 @@ static int rm_read_packet(AVFormatContext *s, AVPacket *pkt) res = ff_rm_parse_packet (s, s->pb, st, st->priv_data, len, pkt, &seq, flags, timestamp); + if (res < -1) + return res; if((flags&2) && (seq&0x7F) == 1) av_add_index_entry(st, pos, timestamp, 0, 0, AVINDEX_KEYFRAME); if (res) diff --git a/chromium/third_party/ffmpeg/libavformat/rsd.c b/chromium/third_party/ffmpeg/libavformat/rsd.c new file mode 100644 index 00000000000..5b53cef9c09 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/rsd.c @@ -0,0 +1,170 @@ +/* + * RSD demuxer + * Copyright (c) 2013 James Almer + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavcodec/bytestream.h" +#include "libavutil/intreadwrite.h" +#include "avformat.h" +#include "avio.h" +#include "internal.h" + +static const AVCodecTag rsd_tags[] = { + { AV_CODEC_ID_ADPCM_THP, MKTAG('G','A','D','P') }, + { AV_CODEC_ID_ADPCM_IMA_RAD, MKTAG('R','A','D','P') }, + { AV_CODEC_ID_PCM_S16BE, MKTAG('P','C','M','B') }, + { AV_CODEC_ID_PCM_S16LE, MKTAG('P','C','M',' ') }, + { AV_CODEC_ID_NONE, 0 }, +}; + +static const uint32_t rsd_unsupported_tags[] = { + MKTAG('O','G','G',' '), + MKTAG('V','A','G',' '), + MKTAG('W','A','D','P'), + MKTAG('X','A','D','P'), + MKTAG('X','M','A',' '), +}; + +static int rsd_probe(AVProbeData *p) +{ + if (!memcmp(p->buf, "RSD", 3) && + p->buf[3] - '0' >= 2 && p->buf[3] - '0' <= 6) + return AVPROBE_SCORE_EXTENSION; + return 0; +} + +static int rsd_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + int i, version, start = 0x800; + AVCodecContext *codec; + AVStream *st = avformat_new_stream(s, NULL); + + if (!st) + return AVERROR(ENOMEM); + + avio_skip(pb, 3); // "RSD" + version = avio_r8(pb) - '0'; + + codec = st->codec; + codec->codec_type = AVMEDIA_TYPE_AUDIO; + codec->codec_tag = avio_rl32(pb); + codec->codec_id = ff_codec_get_id(rsd_tags, codec->codec_tag); + if (!codec->codec_id) { + char tag_buf[5]; + + av_get_codec_tag_string(tag_buf, sizeof(tag_buf), codec->codec_tag); + for (i=0; i < FF_ARRAY_ELEMS(rsd_unsupported_tags); i++) { + if (codec->codec_tag == rsd_unsupported_tags[i]) { + avpriv_request_sample(s, "Codec tag: %s", tag_buf); + return AVERROR_PATCHWELCOME; + } + } + av_log(s, AV_LOG_ERROR, "Unknown codec tag: %s\n", tag_buf); + return AVERROR_INVALIDDATA; + } + + codec->channels = avio_rl32(pb); + if (!codec->channels) + return AVERROR_INVALIDDATA; + + avio_skip(pb, 4); // Bit depth + codec->sample_rate = avio_rl32(pb); + if (!codec->sample_rate) + return AVERROR_INVALIDDATA; + + avio_skip(pb, 4); // Unknown + + switch (codec->codec_id) { + case AV_CODEC_ID_ADPCM_IMA_RAD: + codec->block_align = 20 * codec->channels; + if (pb->seekable) + st->duration = av_get_audio_frame_duration(codec, avio_size(pb) - start); + break; + case AV_CODEC_ID_ADPCM_THP: + /* RSD3GADP is mono, so only alloc enough memory + to store the coeff table for a single channel. */ + + codec->extradata_size = 32; + codec->extradata = av_malloc(codec->extradata_size); + if (!codec->extradata) + return AVERROR(ENOMEM); + + start = avio_rl32(pb); + + if (avio_read(s->pb, codec->extradata, 32) != 32) + return AVERROR_INVALIDDATA; + + for (i = 0; i < 16; i++) + AV_WB16(codec->extradata + i * 2, AV_RL16(codec->extradata + i * 2)); + + if (pb->seekable) + st->duration = (avio_size(pb) - start) / 8 * 14; + break; + case AV_CODEC_ID_PCM_S16LE: + case AV_CODEC_ID_PCM_S16BE: + if (version != 4) + start = avio_rl32(pb); + + if (pb->seekable) + st->duration = (avio_size(pb) - start) / 2 / codec->channels; + break; + } + + avio_skip(pb, start - avio_tell(pb)); + + avpriv_set_pts_info(st, 64, 1, codec->sample_rate); + + return 0; +} + +static int rsd_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + AVCodecContext *codec = s->streams[0]->codec; + int ret, size = 1024; + + if (url_feof(s->pb)) + return AVERROR_EOF; + + if (codec->codec_id == AV_CODEC_ID_ADPCM_IMA_RAD) + ret = av_get_packet(s->pb, pkt, codec->block_align); + else + ret = av_get_packet(s->pb, pkt, size); + + if (ret != size) { + if (ret < 0) { + av_free_packet(pkt); + return ret; + } + av_shrink_packet(pkt, ret); + } + pkt->stream_index = 0; + + return ret; +} + +AVInputFormat ff_rsd_demuxer = { + .name = "rsd", + .long_name = NULL_IF_CONFIG_SMALL("GameCube RSD"), + .read_probe = rsd_probe, + .read_header = rsd_read_header, + .read_packet = rsd_read_packet, + .extensions = "rsd", + .codec_tag = (const AVCodecTag* const []){rsd_tags, 0}, +}; diff --git a/chromium/third_party/ffmpeg/libavformat/rtmp.h b/chromium/third_party/ffmpeg/libavformat/rtmp.h index 7c9bb6d766c..8fc8040d89e 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtmp.h +++ b/chromium/third_party/ffmpeg/libavformat/rtmp.h @@ -1,6 +1,6 @@ /* * RTMP definitions - * Copyright (c) 2009 Kostya Shishkov + * Copyright (c) 2009 Konstantin Shishkov * * This file is part of FFmpeg. * diff --git a/chromium/third_party/ffmpeg/libavformat/rtmppkt.c b/chromium/third_party/ffmpeg/libavformat/rtmppkt.c index 3bd28eb6147..0982775135f 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtmppkt.c +++ b/chromium/third_party/ffmpeg/libavformat/rtmppkt.c @@ -1,6 +1,6 @@ /* * RTMP input format - * Copyright (c) 2009 Kostya Shishkov + * Copyright (c) 2009 Konstantin Shishkov * * This file is part of FFmpeg. * @@ -145,25 +145,25 @@ int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, { uint8_t t, buf[16]; - int channel_id, timestamp, data_size, offset = 0; + int channel_id, timestamp, size, offset = 0; uint32_t extra = 0; enum RTMPPacketType type; - int size = 0; + int written = 0; int ret; - size++; + written++; channel_id = hdr & 0x3F; if (channel_id < 2) { //special case for channel number >= 64 buf[1] = 0; if (ffurl_read_complete(h, buf, channel_id + 1) != channel_id + 1) return AVERROR(EIO); - size += channel_id + 1; + written += channel_id + 1; channel_id = AV_RL16(buf) + 64; } - data_size = prev_pkt[channel_id].data_size; - type = prev_pkt[channel_id].type; - extra = prev_pkt[channel_id].extra; + size = prev_pkt[channel_id].size; + type = prev_pkt[channel_id].type; + extra = prev_pkt[channel_id].extra; hdr >>= 6; if (hdr == RTMP_PS_ONEBYTE) { @@ -171,21 +171,21 @@ int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, } else { if (ffurl_read_complete(h, buf, 3) != 3) return AVERROR(EIO); - size += 3; + written += 3; timestamp = AV_RB24(buf); if (hdr != RTMP_PS_FOURBYTES) { if (ffurl_read_complete(h, buf, 3) != 3) return AVERROR(EIO); - size += 3; - data_size = AV_RB24(buf); + written += 3; + size = AV_RB24(buf); if (ffurl_read_complete(h, buf, 1) != 1) return AVERROR(EIO); - size++; + written++; type = buf[0]; if (hdr == RTMP_PS_TWELVEBYTES) { if (ffurl_read_complete(h, buf, 4) != 4) return AVERROR(EIO); - size += 4; + written += 4; extra = AV_RL32(buf); } } @@ -199,36 +199,36 @@ int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, timestamp += prev_pkt[channel_id].timestamp; if ((ret = ff_rtmp_packet_create(p, channel_id, type, timestamp, - data_size)) < 0) + size)) < 0) return ret; p->extra = extra; // save history prev_pkt[channel_id].channel_id = channel_id; prev_pkt[channel_id].type = type; - prev_pkt[channel_id].data_size = data_size; + prev_pkt[channel_id].size = size; prev_pkt[channel_id].ts_delta = timestamp - prev_pkt[channel_id].timestamp; prev_pkt[channel_id].timestamp = timestamp; prev_pkt[channel_id].extra = extra; - while (data_size > 0) { - int toread = FFMIN(data_size, chunk_size); + while (size > 0) { + int toread = FFMIN(size, chunk_size); if (ffurl_read_complete(h, p->data + offset, toread) != toread) { ff_rtmp_packet_destroy(p); return AVERROR(EIO); } - data_size -= chunk_size; - offset += chunk_size; - size += chunk_size; - if (data_size > 0) { + size -= chunk_size; + offset += chunk_size; + written += chunk_size; + if (size > 0) { if ((ret = ffurl_read_complete(h, &t, 1)) < 0) { // marker ff_rtmp_packet_destroy(p); return ret; } - size++; + written++; if (t != (0xC0 + channel_id)) return -1; } } - return size; + return written; } int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, @@ -237,7 +237,7 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, uint8_t pkt_hdr[16], *p = pkt_hdr; int mode = RTMP_PS_TWELVEBYTES; int off = 0; - int size = 0; + int written = 0; int ret; pkt->ts_delta = pkt->timestamp - prev_pkt[pkt->channel_id].timestamp; @@ -246,7 +246,7 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, if (prev_pkt[pkt->channel_id].channel_id && pkt->extra == prev_pkt[pkt->channel_id].extra) { if (pkt->type == prev_pkt[pkt->channel_id].type && - pkt->data_size == prev_pkt[pkt->channel_id].data_size) { + pkt->size == prev_pkt[pkt->channel_id].size) { mode = RTMP_PS_FOURBYTES; if (pkt->ts_delta == prev_pkt[pkt->channel_id].ts_delta) mode = RTMP_PS_ONEBYTE; @@ -270,7 +270,7 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, timestamp = pkt->ts_delta; bytestream_put_be24(&p, timestamp >= 0xFFFFFF ? 0xFFFFFF : timestamp); if (mode != RTMP_PS_FOURBYTES) { - bytestream_put_be24(&p, pkt->data_size); + bytestream_put_be24(&p, pkt->size); bytestream_put_byte(&p, pkt->type); if (mode == RTMP_PS_TWELVEBYTES) bytestream_put_le32(&p, pkt->extra); @@ -281,7 +281,7 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, // save history prev_pkt[pkt->channel_id].channel_id = pkt->channel_id; prev_pkt[pkt->channel_id].type = pkt->type; - prev_pkt[pkt->channel_id].data_size = pkt->data_size; + prev_pkt[pkt->channel_id].size = pkt->size; prev_pkt[pkt->channel_id].timestamp = pkt->timestamp; if (mode != RTMP_PS_TWELVEBYTES) { prev_pkt[pkt->channel_id].ts_delta = pkt->ts_delta; @@ -292,20 +292,20 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, if ((ret = ffurl_write(h, pkt_hdr, p - pkt_hdr)) < 0) return ret; - size = p - pkt_hdr + pkt->data_size; - while (off < pkt->data_size) { - int towrite = FFMIN(chunk_size, pkt->data_size - off); + written = p - pkt_hdr + pkt->size; + while (off < pkt->size) { + int towrite = FFMIN(chunk_size, pkt->size - off); if ((ret = ffurl_write(h, pkt->data + off, towrite)) < 0) return ret; off += towrite; - if (off < pkt->data_size) { + if (off < pkt->size) { uint8_t marker = 0xC0 | pkt->channel_id; if ((ret = ffurl_write(h, &marker, 1)) < 0) return ret; - size++; + written++; } } - return size; + return written; } int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, @@ -316,7 +316,7 @@ int ff_rtmp_packet_create(RTMPPacket *pkt, int channel_id, RTMPPacketType type, if (!pkt->data) return AVERROR(ENOMEM); } - pkt->data_size = size; + pkt->size = size; pkt->channel_id = channel_id; pkt->type = type; pkt->timestamp = timestamp; @@ -331,7 +331,7 @@ void ff_rtmp_packet_destroy(RTMPPacket *pkt) if (!pkt) return; av_freep(&pkt->data); - pkt->data_size = 0; + pkt->size = 0; } int ff_amf_tag_size(const uint8_t *data, const uint8_t *data_end) @@ -438,7 +438,8 @@ static const char* rtmp_packet_type(int type) } } -static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *data_end) +static void amf_tag_contents(void *ctx, const uint8_t *data, + const uint8_t *data_end) { unsigned int size; char buf[1024]; @@ -484,7 +485,7 @@ static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *d return; data += size; av_log(ctx, AV_LOG_DEBUG, " %s: ", buf); - ff_amf_tag_contents(ctx, data, data_end); + amf_tag_contents(ctx, data, data_end); t = ff_amf_tag_size(data, data_end); if (t < 0 || t >= data_end - data) return; @@ -502,12 +503,12 @@ static void ff_amf_tag_contents(void *ctx, const uint8_t *data, const uint8_t *d void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p) { av_log(ctx, AV_LOG_DEBUG, "RTMP packet type '%s'(%d) for channel %d, timestamp %d, extra field %d size %d\n", - rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->data_size); + rtmp_packet_type(p->type), p->type, p->channel_id, p->timestamp, p->extra, p->size); if (p->type == RTMP_PT_INVOKE || p->type == RTMP_PT_NOTIFY) { - uint8_t *src = p->data, *src_end = p->data + p->data_size; + uint8_t *src = p->data, *src_end = p->data + p->size; while (src < src_end) { int sz; - ff_amf_tag_contents(ctx, src, src_end); + amf_tag_contents(ctx, src, src_end); sz = ff_amf_tag_size(src, src_end); if (sz < 0) break; @@ -519,8 +520,41 @@ void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p) av_log(ctx, AV_LOG_DEBUG, "Client BW = %d\n", AV_RB32(p->data)); } else if (p->type != RTMP_PT_AUDIO && p->type != RTMP_PT_VIDEO && p->type != RTMP_PT_METADATA) { int i; - for (i = 0; i < p->data_size; i++) + for (i = 0; i < p->size; i++) av_log(ctx, AV_LOG_DEBUG, " %02X", p->data[i]); av_log(ctx, AV_LOG_DEBUG, "\n"); } } + +int ff_amf_match_string(const uint8_t *data, int size, const char *str) +{ + int len = strlen(str); + int amf_len, type; + + if (size < 1) + return 0; + + type = *data++; + + if (type != AMF_DATA_TYPE_LONG_STRING && + type != AMF_DATA_TYPE_STRING) + return 0; + + if (type == AMF_DATA_TYPE_LONG_STRING) { + if ((size -= 4 + 1) < 0) + return 0; + amf_len = bytestream_get_be32(&data); + } else { + if ((size -= 2 + 1) < 0) + return 0; + amf_len = bytestream_get_be16(&data); + } + + if (amf_len > size) + return 0; + + if (amf_len != len) + return 0; + + return !memcmp(data, str, len); +} diff --git a/chromium/third_party/ffmpeg/libavformat/rtmppkt.h b/chromium/third_party/ffmpeg/libavformat/rtmppkt.h index a9422954f56..9ca6382a17a 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtmppkt.h +++ b/chromium/third_party/ffmpeg/libavformat/rtmppkt.h @@ -1,6 +1,6 @@ /* * RTMP packet utilities - * Copyright (c) 2009 Kostya Shishkov + * Copyright (c) 2009 Konstantin Shishkov * * This file is part of FFmpeg. * @@ -81,7 +81,7 @@ typedef struct RTMPPacket { uint32_t ts_delta; ///< timestamp increment to the previous one in milliseconds (latter only for media packets) uint32_t extra; ///< probably an additional channel ID used during streaming data uint8_t *data; ///< packet payload - int data_size; ///< packet payload size + int size; ///< packet payload size } RTMPPacket; /** @@ -282,6 +282,13 @@ int ff_amf_read_string(GetByteContext *gbc, uint8_t *str, */ int ff_amf_read_null(GetByteContext *gbc); +/** + * Match AMF string with a NULL-terminated string. + * + * @return 0 if the strings do not match. + */ + +int ff_amf_match_string(const uint8_t *data, int size, const char *str); /** @} */ // AMF funcs diff --git a/chromium/third_party/ffmpeg/libavformat/rtmpproto.c b/chromium/third_party/ffmpeg/libavformat/rtmpproto.c index d73e015d55a..f230f9eca1b 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtmpproto.c +++ b/chromium/third_party/ffmpeg/libavformat/rtmpproto.c @@ -1,6 +1,6 @@ /* * RTMP network protocol - * Copyright (c) 2009 Kostya Shishkov + * Copyright (c) 2009 Konstantin Shishkov * * This file is part of FFmpeg. * @@ -48,8 +48,6 @@ #include <zlib.h> #endif -//#define DEBUG - #define APP_MAX_LENGTH 1024 #define PLAYPATH_MAX_LENGTH 256 #define TCURL_MAX_LENGTH 512 @@ -62,6 +60,7 @@ typedef enum { STATE_HANDSHAKED, ///< client has performed handshake STATE_FCPUBLISH, ///< client FCPublishing stream (for output) STATE_PLAYING, ///< client has started receiving multimedia data from server + STATE_SEEKING, ///< client has started the seek operation. Back on STATE_PLAYING when the time comes STATE_PUBLISHING, ///< client has started sending multimedia data to server (for output) STATE_RECEIVING, ///< received a publish command (for input) STATE_STOPPED, ///< the broadcast has been stopped @@ -186,7 +185,7 @@ static int find_tracked_method(URLContext *s, RTMPPacket *pkt, int offset, int ret; int i; - bytestream2_init(&gbc, pkt->data + offset, pkt->data_size - offset); + bytestream2_init(&gbc, pkt->data + offset, pkt->size - offset); if ((ret = ff_amf_read_number(&gbc, &pkt_id)) < 0) return ret; @@ -224,7 +223,7 @@ static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track) double pkt_id; int len; - bytestream2_init(&gbc, pkt->data, pkt->data_size); + bytestream2_init(&gbc, pkt->data, pkt->size); if ((ret = ff_amf_read_string(&gbc, name, sizeof(name), &len)) < 0) goto fail; @@ -385,7 +384,7 @@ static int gen_connect(URLContext *s, RTMPContext *rt) } } - pkt.data_size = p - pkt.data; + pkt.size = p - pkt.data; return rtmp_send_packet(rt, &pkt, 1); } @@ -406,7 +405,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) rt->prev_pkt[1])) < 0) return ret; cp = pkt.data; - bytestream2_init(&gbc, cp, pkt.data_size); + bytestream2_init(&gbc, cp, pkt.size); if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) { av_log(s, AV_LOG_ERROR, "Unable to read command string\n"); ff_rtmp_packet_destroy(&pkt); @@ -437,7 +436,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) return ret; p = pkt.data; bytestream_put_be32(&p, rt->server_bw); - pkt.data_size = p - pkt.data; + pkt.size = p - pkt.data; ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, rt->prev_pkt[1]); ff_rtmp_packet_destroy(&pkt); @@ -450,7 +449,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) p = pkt.data; bytestream_put_be32(&p, rt->server_bw); bytestream_put_byte(&p, 2); // dynamic - pkt.data_size = p - pkt.data; + pkt.size = p - pkt.data; ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, rt->prev_pkt[1]); ff_rtmp_packet_destroy(&pkt); @@ -512,7 +511,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) ff_amf_write_number(&p, 0); ff_amf_write_object_end(&p); - pkt.data_size = p - pkt.data; + pkt.size = p - pkt.data; ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, rt->prev_pkt[1]); ff_rtmp_packet_destroy(&pkt); @@ -527,7 +526,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) ff_amf_write_number(&p, 0); ff_amf_write_null(&p); ff_amf_write_number(&p, 8192); - pkt.data_size = p - pkt.data; + pkt.size = p - pkt.data; ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, rt->prev_pkt[1]); ff_rtmp_packet_destroy(&pkt); @@ -706,6 +705,29 @@ static int gen_play(URLContext *s, RTMPContext *rt) return rtmp_send_packet(rt, &pkt, 1); } +static int gen_seek(URLContext *s, RTMPContext *rt, int64_t timestamp) +{ + RTMPPacket pkt; + uint8_t *p; + int ret; + + av_log(s, AV_LOG_DEBUG, "Sending seek command for timestamp %"PRId64"\n", + timestamp); + + if ((ret = ff_rtmp_packet_create(&pkt, 3, RTMP_PT_INVOKE, 0, 26)) < 0) + return ret; + + pkt.extra = rt->main_channel_id; + + p = pkt.data; + ff_amf_write_string(&p, "seek"); + ff_amf_write_number(&p, 0); //no tracking back responses + ff_amf_write_null(&p); //as usual, the first null param + ff_amf_write_number(&p, timestamp); //where we want to jump + + return rtmp_send_packet(rt, &pkt, 1); +} + /** * Generate 'publish' call and send it to the server. */ @@ -742,9 +764,9 @@ static int gen_pong(URLContext *s, RTMPContext *rt, RTMPPacket *ppkt) uint8_t *p; int ret; - if (ppkt->data_size < 6) { + if (ppkt->size < 6) { av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n", - ppkt->data_size); + ppkt->size); return AVERROR_INVALIDDATA; } @@ -1418,10 +1440,10 @@ static int handle_chunk_size(URLContext *s, RTMPPacket *pkt) RTMPContext *rt = s->priv_data; int ret; - if (pkt->data_size < 4) { + if (pkt->size < 4) { av_log(s, AV_LOG_ERROR, "Too short chunk size change packet (%d)\n", - pkt->data_size); + pkt->size); return AVERROR_INVALIDDATA; } @@ -1451,9 +1473,9 @@ static int handle_ping(URLContext *s, RTMPPacket *pkt) RTMPContext *rt = s->priv_data; int t, ret; - if (pkt->data_size < 2) { + if (pkt->size < 2) { av_log(s, AV_LOG_ERROR, "Too short ping packet (%d)\n", - pkt->data_size); + pkt->size); return AVERROR_INVALIDDATA; } @@ -1477,10 +1499,10 @@ static int handle_client_bw(URLContext *s, RTMPPacket *pkt) { RTMPContext *rt = s->priv_data; - if (pkt->data_size < 4) { + if (pkt->size < 4) { av_log(s, AV_LOG_ERROR, "Client bandwidth report packet is less than 4 bytes long (%d)\n", - pkt->data_size); + pkt->size); return AVERROR_INVALIDDATA; } @@ -1501,10 +1523,10 @@ static int handle_server_bw(URLContext *s, RTMPPacket *pkt) { RTMPContext *rt = s->priv_data; - if (pkt->data_size < 4) { + if (pkt->size < 4) { av_log(s, AV_LOG_ERROR, "Too short server bandwidth report packet (%d)\n", - pkt->data_size); + pkt->size); return AVERROR_INVALIDDATA; } @@ -1704,7 +1726,7 @@ static int handle_connect_error(URLContext *s, const char *desc) static int handle_invoke_error(URLContext *s, RTMPPacket *pkt) { RTMPContext *rt = s->priv_data; - const uint8_t *data_end = pkt->data + pkt->data_size; + const uint8_t *data_end = pkt->data + pkt->size; char *tracked_method = NULL; int level = AV_LOG_ERROR; uint8_t tmpstr[256]; @@ -1752,7 +1774,7 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt) GetByteContext gbc; int ret; - bytestream2_init(&gbc, p, pkt->data_size); + bytestream2_init(&gbc, p, pkt->size); if (ff_amf_read_string(&gbc, command, sizeof(command), &stringlen)) { av_log(s, AV_LOG_ERROR, "Error in PT_INVOKE\n"); @@ -1804,7 +1826,7 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt) return ret; } pp = spkt.data; - bytestream2_init_writer(&pbc, pp, spkt.data_size); + bytestream2_init_writer(&pbc, pp, spkt.size); bytestream2_put_be16(&pbc, 0); // 0 -> Stream Begin bytestream2_put_be32(&pbc, rt->nb_streamid); ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size, @@ -1863,7 +1885,7 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt) * if a client creates more than 2^32 - 2 streams. */ } } - spkt.data_size = pp - spkt.data; + spkt.size = pp - spkt.data; ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size, rt->prev_pkt[1]); ff_rtmp_packet_destroy(&spkt); @@ -1884,7 +1906,7 @@ static int handle_invoke_result(URLContext *s, RTMPPacket *pkt) return ret; } - if (!memcmp(tracked_method, "connect", 7)) { + if (!strcmp(tracked_method, "connect")) { if (!rt->is_input) { if ((ret = gen_release_stream(s, rt)) < 0) goto fail; @@ -1910,7 +1932,7 @@ static int handle_invoke_result(URLContext *s, RTMPPacket *pkt) goto fail; } } - } else if (!memcmp(tracked_method, "createStream", 12)) { + } else if (!strcmp(tracked_method, "createStream")) { //extract a number from the result if (pkt->data[10] || pkt->data[19] != 5 || pkt->data[20]) { av_log(s, AV_LOG_WARNING, "Unexpected reply on connect()\n"); @@ -1937,7 +1959,7 @@ fail: static int handle_invoke_status(URLContext *s, RTMPPacket *pkt) { RTMPContext *rt = s->priv_data; - const uint8_t *data_end = pkt->data + pkt->data_size; + const uint8_t *data_end = pkt->data + pkt->size; const uint8_t *ptr = pkt->data + 11; uint8_t tmpstr[256]; int i, t; @@ -1962,6 +1984,7 @@ static int handle_invoke_status(URLContext *s, RTMPPacket *pkt) if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED; if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED; if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING; + if (!t && !strcmp(tmpstr, "NetStream.Seek.Notify")) rt->state = STATE_PLAYING; return 0; } @@ -1972,23 +1995,23 @@ static int handle_invoke(URLContext *s, RTMPPacket *pkt) int ret = 0; //TODO: check for the messages sent for wrong state? - if (!memcmp(pkt->data, "\002\000\006_error", 9)) { + if (ff_amf_match_string(pkt->data, pkt->size, "_error")) { if ((ret = handle_invoke_error(s, pkt)) < 0) return ret; - } else if (!memcmp(pkt->data, "\002\000\007_result", 10)) { + } else if (ff_amf_match_string(pkt->data, pkt->size, "_result")) { if ((ret = handle_invoke_result(s, pkt)) < 0) return ret; - } else if (!memcmp(pkt->data, "\002\000\010onStatus", 11)) { + } else if (ff_amf_match_string(pkt->data, pkt->size, "onStatus")) { if ((ret = handle_invoke_status(s, pkt)) < 0) return ret; - } else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) { + } else if (ff_amf_match_string(pkt->data, pkt->size, "onBWDone")) { if ((ret = gen_check_bw(s, rt)) < 0) return ret; - } else if (!memcmp(pkt->data, "\002\000\015releaseStream", 16) || - !memcmp(pkt->data, "\002\000\011FCPublish", 12) || - !memcmp(pkt->data, "\002\000\007publish", 10) || - !memcmp(pkt->data, "\002\000\010_checkbw", 11) || - !memcmp(pkt->data, "\002\000\014createStream", 15)) { + } else if (ff_amf_match_string(pkt->data, pkt->size, "releaseStream") || + ff_amf_match_string(pkt->data, pkt->size, "FCPublish") || + ff_amf_match_string(pkt->data, pkt->size, "publish") || + ff_amf_match_string(pkt->data, pkt->size, "_checkbw") || + ff_amf_match_string(pkt->data, pkt->size, "createStream")) { if ((ret = send_invoke_response(s, pkt)) < 0) return ret; } @@ -2011,7 +2034,7 @@ static int handle_notify(URLContext *s, RTMPPacket *pkt) { unsigned datatowritelength; p = pkt->data; - bytestream2_init(&gbc, p, pkt->data_size); + bytestream2_init(&gbc, p, pkt->size); if (ff_amf_read_string(&gbc, commandbuffer, sizeof(commandbuffer), &stringlen)) return AVERROR_INVALIDDATA; @@ -2125,7 +2148,7 @@ static int get_packet(URLContext *s, int for_header) int ret; uint8_t *p; const uint8_t *next; - uint32_t data_size; + uint32_t size; uint32_t ts, cts, pts=0; if (rt->state == STATE_STOPPED) @@ -2150,6 +2173,17 @@ static int get_packet(URLContext *s, int for_header) } ret = rtmp_parse_result(s, rt, &rpkt); + + // At this point we must check if we are in the seek state and continue + // with the next packet. handle_invoke will get us out of this state + // when the right message is encountered + if (rt->state == STATE_SEEKING) { + ff_rtmp_packet_destroy(&rpkt); + // We continue, let the natural flow of things happen: + // AVERROR(EAGAIN) or handle_invoke gets us out of here + continue; + } + if (ret < 0) {//serious error in current packet ff_rtmp_packet_destroy(&rpkt); return ret; @@ -2168,24 +2202,25 @@ static int get_packet(URLContext *s, int for_header) ff_rtmp_packet_destroy(&rpkt); return 0; } - if (!rpkt.data_size || !rt->is_input) { + if (!rpkt.size || !rt->is_input) { ff_rtmp_packet_destroy(&rpkt); continue; } if (rpkt.type == RTMP_PT_VIDEO || rpkt.type == RTMP_PT_AUDIO || - (rpkt.type == RTMP_PT_NOTIFY && !memcmp("\002\000\012onMetaData", rpkt.data, 13))) { + (rpkt.type == RTMP_PT_NOTIFY && + ff_amf_match_string(rpkt.data, rpkt.size, "onMetaData"))) { ts = rpkt.timestamp; // generate packet header and put data into buffer for FLV demuxer rt->flv_off = 0; - rt->flv_size = rpkt.data_size + 15; + rt->flv_size = rpkt.size + 15; rt->flv_data = p = av_realloc(rt->flv_data, rt->flv_size); bytestream_put_byte(&p, rpkt.type); - bytestream_put_be24(&p, rpkt.data_size); + bytestream_put_be24(&p, rpkt.size); bytestream_put_be24(&p, ts); bytestream_put_byte(&p, ts >> 24); bytestream_put_be24(&p, 0); - bytestream_put_buffer(&p, rpkt.data, rpkt.data_size); + bytestream_put_buffer(&p, rpkt.data, rpkt.size); bytestream_put_be32(&p, 0); ff_rtmp_packet_destroy(&rpkt); return 0; @@ -2200,14 +2235,14 @@ static int get_packet(URLContext *s, int for_header) } else if (rpkt.type == RTMP_PT_METADATA) { // we got raw FLV data, make it available for FLV demuxer rt->flv_off = 0; - rt->flv_size = rpkt.data_size; + rt->flv_size = rpkt.size; rt->flv_data = av_realloc(rt->flv_data, rt->flv_size); /* rewrite timestamps */ next = rpkt.data; ts = rpkt.timestamp; - while (next - rpkt.data < rpkt.data_size - 11) { + while (next - rpkt.data < rpkt.size - 11) { next++; - data_size = bytestream_get_be24(&next); + size = bytestream_get_be24(&next); p=next; cts = bytestream_get_be24(&next); cts |= bytestream_get_byte(&next) << 24; @@ -2217,9 +2252,9 @@ static int get_packet(URLContext *s, int for_header) pts = cts; bytestream_put_be24(&p, ts); bytestream_put_byte(&p, ts >> 24); - next += data_size + 3 + 4; + next += size + 3 + 4; } - memcpy(rt->flv_data, rpkt.data, rpkt.data_size); + memcpy(rt->flv_data, rpkt.data, rpkt.size); ff_rtmp_packet_destroy(&rpkt); return 0; } @@ -2234,7 +2269,7 @@ static int rtmp_close(URLContext *h) if (!rt->is_input) { rt->flv_data = NULL; - if (rt->out_pkt.data_size) + if (rt->out_pkt.size) ff_rtmp_packet_destroy(&rt->out_pkt); if (rt->state > STATE_FCPUBLISH) ret = gen_fcunpublish_stream(h, rt); @@ -2276,6 +2311,13 @@ static int rtmp_open(URLContext *s, const char *uri, int flags) hostname, sizeof(hostname), &port, path, sizeof(path), s->filename); + if (strchr(path, ' ')) { + av_log(s, AV_LOG_WARNING, + "Detected librtmp style URL parameters, these aren't supported " + "by the libavformat internal RTMP handler currently enabled. " + "See the documentation for the correct way to pass parameters.\n"); + } + if (auth[0]) { char *ptr = strchr(auth, ':'); if (ptr) { @@ -2514,6 +2556,26 @@ static int rtmp_read(URLContext *s, uint8_t *buf, int size) return orig_size; } +static int64_t rtmp_seek(URLContext *s, int stream_index, int64_t timestamp, + int flags) +{ + RTMPContext *rt = s->priv_data; + int ret; + av_log(s, AV_LOG_DEBUG, + "Seek on stream index %d at timestamp %"PRId64" with flags %08x\n", + stream_index, timestamp, flags); + if ((ret = gen_seek(s, rt, timestamp)) < 0) { + av_log(s, AV_LOG_ERROR, + "Unable to send seek command on stream index %d at timestamp " + "%"PRId64" with flags %08x\n", + stream_index, timestamp, flags); + return ret; + } + rt->flv_off = rt->flv_size; + rt->state = STATE_SEEKING; + return timestamp; +} + static int rtmp_write(URLContext *s, const uint8_t *buf, int size) { RTMPContext *rt = s->priv_data; @@ -2665,6 +2727,7 @@ URLProtocol ff_##flavor##_protocol = { \ .name = #flavor, \ .url_open = rtmp_open, \ .url_read = rtmp_read, \ + .url_read_seek = rtmp_seek, \ .url_write = rtmp_write, \ .url_close = rtmp_close, \ .priv_data_size = sizeof(RTMPContext), \ diff --git a/chromium/third_party/ffmpeg/libavformat/rtp.c b/chromium/third_party/ffmpeg/libavformat/rtp.c index c4dcf6ae8d4..4d41350f3cd 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtp.c +++ b/chromium/third_party/ffmpeg/libavformat/rtp.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avstring.h" #include "libavutil/opt.h" #include "avformat.h" @@ -144,7 +145,7 @@ enum AVCodecID ff_rtp_codec_id(const char *buf, enum AVMediaType codec_type) int i; for (i = 0; rtp_payload_types[i].pt >= 0; i++) - if (!strcmp(buf, rtp_payload_types[i].enc_name) && (codec_type == rtp_payload_types[i].codec_type)) + if (!av_strcasecmp(buf, rtp_payload_types[i].enc_name) && (codec_type == rtp_payload_types[i].codec_type)) return rtp_payload_types[i].codec_id; return AV_CODEC_ID_NONE; diff --git a/chromium/third_party/ffmpeg/libavformat/rtp.h b/chromium/third_party/ffmpeg/libavformat/rtp.h index 1732af8a918..66a4f3afbd9 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtp.h +++ b/chromium/third_party/ffmpeg/libavformat/rtp.h @@ -23,6 +23,7 @@ #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" +#include "libavutil/mathematics.h" /** * Return the payload type for a given stream used in the given format context. @@ -109,4 +110,6 @@ enum RTCPType { #define RTP_PT_IS_RTCP(x) (((x) >= RTCP_FIR && (x) <= RTCP_IJ) || \ ((x) >= RTCP_SR && (x) <= RTCP_TOKEN)) +#define NTP_TO_RTP_FORMAT(x) av_rescale((x), INT64_C(1) << 32, 1000000) + #endif /* AVFORMAT_RTP_H */ diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec.c b/chromium/third_party/ffmpeg/libavformat/rtpdec.c index b512b8975ff..b2342f18249 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec.c @@ -78,8 +78,8 @@ void av_register_rtp_dynamic_payload_handlers(void) ff_register_dynamic_payload_handler(&ff_mpeg_video_dynamic_handler); ff_register_dynamic_payload_handler(&ff_mpeg4_generic_dynamic_handler); ff_register_dynamic_payload_handler(&ff_mpegts_dynamic_handler); - ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler); ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfa_handler); + ff_register_dynamic_payload_handler(&ff_ms_rtp_asf_pfv_handler); ff_register_dynamic_payload_handler(&ff_qcelp_dynamic_handler); ff_register_dynamic_payload_handler(&ff_qdm2_dynamic_handler); ff_register_dynamic_payload_handler(&ff_qt_rtp_aud_handler); diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec.h b/chromium/third_party/ffmpeg/libavformat/rtpdec.h index 623d911b997..2a191ec762d 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec.h +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec.h @@ -51,10 +51,6 @@ int ff_rtp_parse_packet(RTPDemuxContext *s, AVPacket *pkt, void ff_rtp_parse_close(RTPDemuxContext *s); int64_t ff_rtp_queued_packet_time(RTPDemuxContext *s); void ff_rtp_reset_packet_queue(RTPDemuxContext *s); -int ff_rtp_get_local_rtp_port(URLContext *h); -int ff_rtp_get_local_rtcp_port(URLContext *h); - -int ff_rtp_set_remote_url(URLContext *h, const char *uri); /** * Send a dummy packet on both port pairs to set up the connection diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_g726.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_g726.c index ec37f09155d..7e9ef56e066 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec_g726.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_g726.c @@ -18,11 +18,13 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/attributes.h" #include "avformat.h" #include "rtpdec_formats.h" #define RTP_G726_HANDLER(bitrate) \ -static int g726_ ## bitrate ##_init(AVFormatContext *s, int st_index, PayloadContext *data) \ +static av_cold int g726_ ## bitrate ##_init(AVFormatContext *s, int st_index, \ + PayloadContext *data) \ { \ AVStream *stream = s->streams[st_index]; \ AVCodecContext *codec = stream->codec; \ diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_h263.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_h263.c index dd7aa60fd51..ae4cc270407 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec_h263.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_h263.c @@ -21,9 +21,11 @@ #include "avformat.h" #include "rtpdec_formats.h" +#include "libavutil/attributes.h" #include "libavutil/intreadwrite.h" -static int h263_init(AVFormatContext *ctx, int st_index, PayloadContext *data) +static av_cold int h263_init(AVFormatContext *ctx, int st_index, + PayloadContext *data) { if (st_index < 0) return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_h263_rfc2190.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_h263_rfc2190.c index 4b6e9967701..116db750658 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec_h263_rfc2190.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_h263_rfc2190.c @@ -27,6 +27,7 @@ #include "avformat.h" #include "rtpdec_formats.h" +#include "libavutil/attributes.h" #include "libavutil/intreadwrite.h" #include "libavcodec/get_bits.h" @@ -55,7 +56,7 @@ static void h263_free_context(PayloadContext *data) av_free(data); } -static int h263_init(AVFormatContext *ctx, int st_index, PayloadContext *data) +static av_cold int h263_init(AVFormatContext *ctx, int st_index, PayloadContext *data) { if (st_index < 0) return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_h264.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_h264.c index d1133b78e1b..be657c0ccc7 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec_h264.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_h264.c @@ -33,6 +33,7 @@ * FU-B packet types) */ +#include "libavutil/attributes.h" #include "libavutil/base64.h" #include "libavutil/avstring.h" #include "libavcodec/get_bits.h" @@ -338,7 +339,8 @@ static void h264_free_context(PayloadContext *data) av_free(data); } -static int h264_init(AVFormatContext *s, int st_index, PayloadContext *data) +static av_cold int h264_init(AVFormatContext *s, int st_index, + PayloadContext *data) { if (st_index < 0) return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_mpeg12.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_mpeg12.c index 82e58a097ab..d73ff1e1441 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec_mpeg12.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_mpeg12.c @@ -19,10 +19,11 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "rtpdec_formats.h" +#include "libavutil/attributes.h" #include "libavutil/intreadwrite.h" +#include "rtpdec_formats.h" -static int mpeg_init(AVFormatContext *ctx, int st_index, PayloadContext *data) +static av_cold int mpeg_init(AVFormatContext *ctx, int st_index, PayloadContext *data) { if (st_index < 0) return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_mpeg4.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_mpeg4.c index 3f1f244b83d..571b7392e09 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec_mpeg4.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_mpeg4.c @@ -29,6 +29,7 @@ #include "rtpdec_formats.h" #include "internal.h" +#include "libavutil/attributes.h" #include "libavutil/avstring.h" #include "libavcodec/get_bits.h" @@ -252,7 +253,8 @@ static int parse_sdp_line(AVFormatContext *s, int st_index, return 0; } -static int init_video(AVFormatContext *s, int st_index, PayloadContext *data) +static av_cold int init_video(AVFormatContext *s, int st_index, + PayloadContext *data) { if (st_index < 0) return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_mpegts.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_mpegts.c index cbb8eb49f7e..5b851c4fd77 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec_mpegts.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_mpegts.c @@ -19,6 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/attributes.h" #include "mpegts.h" #include "rtpdec_formats.h" @@ -43,7 +44,8 @@ static void mpegts_free_context(PayloadContext *data) av_free(data); } -static int mpegts_init(AVFormatContext *ctx, int st_index, PayloadContext *data) +static av_cold int mpegts_init(AVFormatContext *ctx, int st_index, + PayloadContext *data) { data->ts = ff_mpegts_parse_open(ctx); if (!data->ts) diff --git a/chromium/third_party/ffmpeg/libavformat/rtpdec_xiph.c b/chromium/third_party/ffmpeg/libavformat/rtpdec_xiph.c index eddb781ddb8..52a94b31598 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpdec_xiph.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpdec_xiph.c @@ -27,6 +27,7 @@ * @author Josh Allmann <joshua.allmann@gmail.com> */ +#include "libavutil/attributes.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" #include "libavutil/base64.h" @@ -69,8 +70,8 @@ static void xiph_free_context(PayloadContext * data) av_free(data); } -static int xiph_vorbis_init(AVFormatContext *ctx, int st_index, - PayloadContext *data) +static av_cold int xiph_vorbis_init(AVFormatContext *ctx, int st_index, + PayloadContext *data) { if (st_index < 0) return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/rtpenc.c b/chromium/third_party/ffmpeg/libavformat/rtpenc.c index 7adf687c7f9..9fd361d3036 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpenc.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpenc.c @@ -28,8 +28,6 @@ #include "rtpenc.h" -//#define DEBUG - static const AVOption options[] = { FF_RTP_FLAG_OPTS(RTPMuxContext, flags), { "payload_type", "Specify RTP payload type", offsetof(RTPMuxContext, payload_type), AV_OPT_TYPE_INT, {.i64 = -1 }, -1, 127, AV_OPT_FLAG_ENCODING_PARAM }, @@ -278,8 +276,7 @@ static void rtcp_send_sr(AVFormatContext *s1, int64_t ntp_time) avio_w8(s1->pb, RTCP_SR); avio_wb16(s1->pb, 6); /* length in words - 1 */ avio_wb32(s1->pb, s->ssrc); - avio_wb32(s1->pb, ntp_time / 1000000); - avio_wb32(s1->pb, ((ntp_time % 1000000) << 32) / 1000000); + avio_wb64(s1->pb, NTP_TO_RTP_FORMAT(ntp_time)); avio_wb32(s1->pb, rtp_ts); avio_wb32(s1->pb, s->packet_count); avio_wb32(s1->pb, s->octet_count); diff --git a/chromium/third_party/ffmpeg/libavformat/rtpenc.h b/chromium/third_party/ffmpeg/libavformat/rtpenc.h index 72a5fa4c8f4..b0c9630ee91 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpenc.h +++ b/chromium/third_party/ffmpeg/libavformat/rtpenc.h @@ -38,11 +38,9 @@ struct RTPMuxContext { int max_payload_size; int num_frames; - /* rtcp sender statistics receive */ + /* rtcp sender statistics */ int64_t last_rtcp_ntp_time; int64_t first_rtcp_ntp_time; - - /* rtcp sender statistics */ unsigned int packet_count; unsigned int octet_count; unsigned int last_octet_count; diff --git a/chromium/third_party/ffmpeg/libavformat/rtpenc_chain.c b/chromium/third_party/ffmpeg/libavformat/rtpenc_chain.c index 70d68ce5341..9379d94697b 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpenc_chain.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpenc_chain.c @@ -78,16 +78,19 @@ int ff_rtp_chain_mux_open(AVFormatContext **out, AVFormatContext *s, avcodec_copy_context(rtpctx->streams[0]->codec, st->codec); if (handle) { - ffio_fdopen(&rtpctx->pb, handle); + ret = ffio_fdopen(&rtpctx->pb, handle); + if (ret < 0) + ffurl_close(handle); } else - ffio_open_dyn_packet_buf(&rtpctx->pb, packet_size); - ret = avformat_write_header(rtpctx, &opts); + ret = ffio_open_dyn_packet_buf(&rtpctx->pb, packet_size); + if (!ret) + ret = avformat_write_header(rtpctx, &opts); av_dict_free(&opts); if (ret) { - if (handle) { + if (handle && rtpctx->pb) { avio_close(rtpctx->pb); - } else { + } else if (rtpctx->pb) { uint8_t *ptr; avio_close_dyn_buf(rtpctx->pb, &ptr); av_free(ptr); diff --git a/chromium/third_party/ffmpeg/libavformat/rtpproto.c b/chromium/third_party/ffmpeg/libavformat/rtpproto.c index 62ec4c9d7de..bf9c60d9998 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtpproto.c +++ b/chromium/third_party/ffmpeg/libavformat/rtpproto.c @@ -28,7 +28,8 @@ #include "libavutil/avstring.h" #include "avformat.h" #include "avio_internal.h" -#include "rtpdec.h" +#include "rtp.h" +#include "rtpproto.h" #include "url.h" #include <stdarg.h> @@ -42,7 +43,11 @@ typedef struct RTPContext { URLContext *rtp_hd, *rtcp_hd; - int rtp_fd, rtcp_fd; + int rtp_fd, rtcp_fd, nb_ssm_include_addrs, nb_ssm_exclude_addrs; + struct sockaddr_storage **ssm_include_addrs, **ssm_exclude_addrs; + int write_to_source; + struct sockaddr_storage last_rtp_source, last_rtcp_source; + socklen_t last_rtp_source_len, last_rtcp_source_len; } RTPContext; /** @@ -59,22 +64,109 @@ int ff_rtp_set_remote_url(URLContext *h, const char *uri) { RTPContext *s = h->priv_data; char hostname[256]; - int port; + int port, rtcp_port; + const char *p; char buf[1024]; char path[1024]; av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); + rtcp_port = port + 1; + + p = strchr(uri, '?'); + if (p) { + if (av_find_info_tag(buf, sizeof(buf), "rtcpport", p)) { + rtcp_port = strtol(buf, NULL, 10); + } + } ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port, "%s", path); ff_udp_set_remote_url(s->rtp_hd, buf); - ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, port + 1, "%s", path); + ff_url_join(buf, sizeof(buf), "udp", NULL, hostname, rtcp_port, "%s", path); ff_udp_set_remote_url(s->rtcp_hd, buf); return 0; } +static struct addrinfo* rtp_resolve_host(const char *hostname, int port, + int type, int family, int flags) +{ + struct addrinfo hints = { 0 }, *res = 0; + int error; + char service[16]; + + snprintf(service, sizeof(service), "%d", port); + hints.ai_socktype = type; + hints.ai_family = family; + hints.ai_flags = flags; + if ((error = getaddrinfo(hostname, service, &hints, &res))) { + res = NULL; + av_log(NULL, AV_LOG_ERROR, "rtp_resolve_host: %s\n", gai_strerror(error)); + } + + return res; +} + +static int compare_addr(const struct sockaddr_storage *a, + const struct sockaddr_storage *b) +{ + if (a->ss_family != b->ss_family) + return 1; + if (a->ss_family == AF_INET) { + return (((const struct sockaddr_in *)a)->sin_addr.s_addr != + ((const struct sockaddr_in *)b)->sin_addr.s_addr); + } + +#if HAVE_STRUCT_SOCKADDR_IN6 + if (a->ss_family == AF_INET6) { + const uint8_t *s6_addr_a = ((const struct sockaddr_in6 *)a)->sin6_addr.s6_addr; + const uint8_t *s6_addr_b = ((const struct sockaddr_in6 *)b)->sin6_addr.s6_addr; + return memcmp(s6_addr_a, s6_addr_b, 16); + } +#endif + return 1; +} + +static int get_port(const struct sockaddr_storage *ss) +{ + if (ss->ss_family == AF_INET) + return ntohs(((const struct sockaddr_in *)ss)->sin_port); +#if HAVE_STRUCT_SOCKADDR_IN6 + if (ss->ss_family == AF_INET6) + return ntohs(((const struct sockaddr_in6 *)ss)->sin6_port); +#endif + return 0; +} + +static void set_port(struct sockaddr_storage *ss, int port) +{ + if (ss->ss_family == AF_INET) + ((struct sockaddr_in *)ss)->sin_port = htons(port); +#if HAVE_STRUCT_SOCKADDR_IN6 + else if (ss->ss_family == AF_INET6) + ((struct sockaddr_in6 *)ss)->sin6_port = htons(port); +#endif +} + +static int rtp_check_source_lists(RTPContext *s, struct sockaddr_storage *source_addr_ptr) +{ + int i; + if (s->nb_ssm_exclude_addrs) { + for (i = 0; i < s->nb_ssm_exclude_addrs; i++) { + if (!compare_addr(source_addr_ptr, s->ssm_exclude_addrs[i])) + return 1; + } + } + if (s->nb_ssm_include_addrs) { + for (i = 0; i < s->nb_ssm_include_addrs; i++) { + if (!compare_addr(source_addr_ptr, s->ssm_include_addrs[i])) + return 0; + } + return 1; + } + return 0; +} /** * add option to url of the form: @@ -99,7 +191,9 @@ static av_printf_format(3, 4) void url_add_option(char *buf, int buf_size, const static void build_udp_url(char *buf, int buf_size, const char *hostname, int port, int local_port, int ttl, - int max_packet_size, int connect) + int max_packet_size, int connect, + const char *include_sources, + const char *exclude_sources) { ff_url_join(buf, buf_size, "udp", NULL, hostname, port, NULL); if (local_port >= 0) @@ -111,6 +205,50 @@ static void build_udp_url(char *buf, int buf_size, if (connect) url_add_option(buf, buf_size, "connect=1"); url_add_option(buf, buf_size, "fifo_size=0"); + if (include_sources && include_sources[0]) + url_add_option(buf, buf_size, "sources=%s", include_sources); + if (exclude_sources && exclude_sources[0]) + url_add_option(buf, buf_size, "block=%s", exclude_sources); +} + +static void rtp_parse_addr_list(URLContext *h, char *buf, + struct sockaddr_storage ***address_list_ptr, + int *address_list_size_ptr) +{ + struct addrinfo *ai = NULL; + struct sockaddr_storage *source_addr; + char tmp = '\0', *p = buf, *next; + + /* Resolve all of the IPs */ + + while (p && p[0]) { + next = strchr(p, ','); + + if (next) { + tmp = *next; + *next = '\0'; + } + + ai = rtp_resolve_host(p, 0, SOCK_DGRAM, AF_UNSPEC, 0); + if (ai) { + source_addr = av_mallocz(sizeof(struct sockaddr_storage)); + if (!source_addr) + break; + + memcpy(source_addr, ai->ai_addr, ai->ai_addrlen); + freeaddrinfo(ai); + dynarray_add(address_list_ptr, address_list_size_ptr, source_addr); + } else { + av_log(h, AV_LOG_WARNING, "Unable to resolve %s\n", p); + } + + if (next) { + *next = tmp; + p = next + 1; + } else { + p = NULL; + } + } } /** @@ -121,6 +259,9 @@ static void build_udp_url(char *buf, int buf_size, * 'localrtcpport=n' : set the local rtcp port to n * 'pkt_size=n' : set max packet size * 'connect=0/1' : do a connect() on the UDP socket + * 'sources=ip[,ip]' : list allowed source IP addresses + * 'block=ip[,ip]' : list disallowed source IP addresses + * 'write_to_source=0/1' : send packets to the source address of the latest received packet * deprecated option: * 'localport=n' : set the local port to n * @@ -136,7 +277,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) int rtp_port, rtcp_port, ttl, connect, local_rtp_port, local_rtcp_port, max_packet_size; - char hostname[256]; + char hostname[256], include_sources[1024] = "", exclude_sources[1024] = ""; char buf[1024]; char path[1024]; const char *p; @@ -174,11 +315,22 @@ static int rtp_open(URLContext *h, const char *uri, int flags) if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { connect = strtol(buf, NULL, 10); } + if (av_find_info_tag(buf, sizeof(buf), "write_to_source", p)) { + s->write_to_source = strtol(buf, NULL, 10); + } + if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { + av_strlcpy(include_sources, buf, sizeof(include_sources)); + rtp_parse_addr_list(h, buf, &s->ssm_include_addrs, &s->nb_ssm_include_addrs); + } + if (av_find_info_tag(buf, sizeof(buf), "block", p)) { + av_strlcpy(exclude_sources, buf, sizeof(exclude_sources)); + rtp_parse_addr_list(h, buf, &s->ssm_exclude_addrs, &s->nb_ssm_exclude_addrs); + } } build_udp_url(buf, sizeof(buf), hostname, rtp_port, local_rtp_port, ttl, max_packet_size, - connect); + connect, include_sources, exclude_sources); if (ffurl_open(&s->rtp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) goto fail; if (local_rtp_port>=0 && local_rtcp_port<0) @@ -186,7 +338,7 @@ static int rtp_open(URLContext *h, const char *uri, int flags) build_udp_url(buf, sizeof(buf), hostname, rtcp_port, local_rtcp_port, ttl, max_packet_size, - connect); + connect, include_sources, exclude_sources); if (ffurl_open(&s->rtcp_hd, buf, flags, &h->interrupt_callback, NULL) < 0) goto fail; @@ -210,48 +362,41 @@ static int rtp_open(URLContext *h, const char *uri, int flags) static int rtp_read(URLContext *h, uint8_t *buf, int size) { RTPContext *s = h->priv_data; - struct sockaddr_storage from; - socklen_t from_len; - int len, n; + int len, n, i; struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}}; + int poll_delay = h->flags & AVIO_FLAG_NONBLOCK ? 0 : 100; + struct sockaddr_storage *addrs[2] = { &s->last_rtp_source, &s->last_rtcp_source }; + socklen_t *addr_lens[2] = { &s->last_rtp_source_len, &s->last_rtcp_source_len }; for(;;) { if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; - /* build fdset to listen to RTP and RTCP packets */ - n = poll(p, 2, 100); + n = poll(p, 2, poll_delay); if (n > 0) { - /* first try RTCP */ - if (p[1].revents & POLLIN) { - from_len = sizeof(from); - len = recvfrom (s->rtcp_fd, buf, size, 0, - (struct sockaddr *)&from, &from_len); - if (len < 0) { - if (ff_neterrno() == AVERROR(EAGAIN) || - ff_neterrno() == AVERROR(EINTR)) - continue; - return AVERROR(EIO); - } - break; - } - /* then RTP */ - if (p[0].revents & POLLIN) { - from_len = sizeof(from); - len = recvfrom (s->rtp_fd, buf, size, 0, - (struct sockaddr *)&from, &from_len); + /* first try RTCP, then RTP */ + for (i = 1; i >= 0; i--) { + if (!(p[i].revents & POLLIN)) + continue; + *addr_lens[i] = sizeof(*addrs[i]); + len = recvfrom(p[i].fd, buf, size, 0, + (struct sockaddr *)addrs[i], addr_lens[i]); if (len < 0) { if (ff_neterrno() == AVERROR(EAGAIN) || ff_neterrno() == AVERROR(EINTR)) continue; return AVERROR(EIO); } - break; + if (rtp_check_source_lists(s, addrs[i])) + continue; + return len; } } else if (n < 0) { if (ff_neterrno() == AVERROR(EINTR)) continue; return AVERROR(EIO); } + if (h->flags & AVIO_FLAG_NONBLOCK) + return AVERROR(EAGAIN); } return len; } @@ -262,6 +407,60 @@ static int rtp_write(URLContext *h, const uint8_t *buf, int size) int ret; URLContext *hd; + if (size < 2) + return AVERROR(EINVAL); + + if (s->write_to_source) { + int fd; + struct sockaddr_storage *source, temp_source; + socklen_t *source_len, temp_len; + if (!s->last_rtp_source.ss_family && !s->last_rtcp_source.ss_family) { + av_log(h, AV_LOG_ERROR, + "Unable to send packet to source, no packets received yet\n"); + // Intentionally not returning an error here + return size; + } + + if (RTP_PT_IS_RTCP(buf[1])) { + fd = s->rtcp_fd; + source = &s->last_rtcp_source; + source_len = &s->last_rtcp_source_len; + } else { + fd = s->rtp_fd; + source = &s->last_rtp_source; + source_len = &s->last_rtp_source_len; + } + if (!source->ss_family) { + source = &temp_source; + source_len = &temp_len; + if (RTP_PT_IS_RTCP(buf[1])) { + temp_source = s->last_rtp_source; + temp_len = s->last_rtp_source_len; + set_port(source, get_port(source) + 1); + av_log(h, AV_LOG_INFO, + "Not received any RTCP packets yet, inferring peer port " + "from the RTP port\n"); + } else { + temp_source = s->last_rtcp_source; + temp_len = s->last_rtcp_source_len; + set_port(source, get_port(source) - 1); + av_log(h, AV_LOG_INFO, + "Not received any RTP packets yet, inferring peer port " + "from the RTCP port\n"); + } + } + + if (!(h->flags & AVIO_FLAG_NONBLOCK)) { + ret = ff_network_wait_fd(fd, 1); + if (ret < 0) + return ret; + } + ret = sendto(fd, buf, size, 0, (struct sockaddr *) source, + *source_len); + + return ret < 0 ? ff_neterrno() : ret; + } + if (RTP_PT_IS_RTCP(buf[1])) { /* RTCP payload type */ hd = s->rtcp_hd; @@ -277,6 +476,14 @@ static int rtp_write(URLContext *h, const uint8_t *buf, int size) static int rtp_close(URLContext *h) { RTPContext *s = h->priv_data; + int i; + + for (i = 0; i < s->nb_ssm_include_addrs; i++) + av_free(s->ssm_include_addrs[i]); + av_freep(&s->ssm_include_addrs); + for (i = 0; i < s->nb_ssm_exclude_addrs; i++) + av_free(s->ssm_exclude_addrs[i]); + av_freep(&s->ssm_exclude_addrs); ffurl_close(s->rtp_hd); ffurl_close(s->rtcp_hd); diff --git a/chromium/third_party/ffmpeg/libavformat/rtpproto.h b/chromium/third_party/ffmpeg/libavformat/rtpproto.h new file mode 100644 index 00000000000..5b243fb2486 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/rtpproto.h @@ -0,0 +1,31 @@ +/* + * RTP network protocol + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_RTPPROTO_H +#define AVFORMAT_RTPPROTO_H + +#include "url.h" + +int ff_rtp_set_remote_url(URLContext *h, const char *uri); + +int ff_rtp_get_local_rtp_port(URLContext *h); +int ff_rtp_get_local_rtcp_port(URLContext *h); + +#endif /* AVFORMAT_RTPPROTO_H */ diff --git a/chromium/third_party/ffmpeg/libavformat/rtsp.c b/chromium/third_party/ffmpeg/libavformat/rtsp.c index dc94f0f795c..2abb36b4a5d 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtsp.c +++ b/chromium/third_party/ffmpeg/libavformat/rtsp.c @@ -42,6 +42,7 @@ #include "rtsp.h" #include "rtpdec.h" +#include "rtpproto.h" #include "rdt.h" #include "rtpdec_formats.h" #include "rtpenc_chain.h" @@ -49,8 +50,6 @@ #include "rtpenc.h" #include "mpegts.h" -//#define DEBUG - /* Timeout values for socket poll, in ms, * and read_packet(), in seconds */ #define POLL_TIMEOUT_MS 100 @@ -66,8 +65,7 @@ #define RTSP_FLAG_OPTS(name, longname) \ { name, longname, OFFSET(rtsp_flags), AV_OPT_TYPE_FLAGS, {.i64 = 0}, INT_MIN, INT_MAX, DEC, "rtsp_flags" }, \ - { "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" }, \ - { "listen", "Wait for incoming connections", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" } + { "filter_src", "Only receive packets from the negotiated peer IP", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_FILTER_SRC}, 0, 0, DEC, "rtsp_flags" } #define RTSP_MEDIATYPE_OPTS(name, longname) \ { name, longname, OFFSET(media_type_mask), AV_OPT_TYPE_FLAGS, { .i64 = (1 << (AVMEDIA_TYPE_DATA+1)) - 1 }, INT_MIN, INT_MAX, DEC, "allowed_media_types" }, \ @@ -87,18 +85,21 @@ const AVOption ff_rtsp_options[] = { { "udp_multicast", "UDP multicast", 0, AV_OPT_TYPE_CONST, {.i64 = 1 << RTSP_LOWER_TRANSPORT_UDP_MULTICAST}, 0, 0, DEC, "rtsp_transport" }, { "http", "HTTP tunneling", 0, AV_OPT_TYPE_CONST, {.i64 = (1 << RTSP_LOWER_TRANSPORT_HTTP)}, 0, 0, DEC, "rtsp_transport" }, RTSP_FLAG_OPTS("rtsp_flags", "RTSP flags"), + { "listen", "Wait for incoming connections", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_LISTEN}, 0, 0, DEC, "rtsp_flags" }, RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"), { "min_port", "Minimum local UDP port", OFFSET(rtp_port_min), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MIN}, 0, 65535, DEC|ENC }, { "max_port", "Maximum local UDP port", OFFSET(rtp_port_max), AV_OPT_TYPE_INT, {.i64 = RTSP_RTP_PORT_MAX}, 0, 65535, DEC|ENC }, { "timeout", "Maximum timeout (in seconds) to wait for incoming connections. -1 is infinite. Implies flag listen", OFFSET(initial_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, INT_MIN, INT_MAX, DEC }, { "stimeout", "timeout (in micro seconds) of socket i/o operations.", OFFSET(stimeout), AV_OPT_TYPE_INT, {.i64 = 0}, INT_MIN, INT_MAX, DEC }, RTSP_REORDERING_OPTS(), + { "user-agent", "override User-Agent header", OFFSET(user_agent), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, DEC }, { NULL }, }; static const AVOption sdp_options[] = { RTSP_FLAG_OPTS("sdp_flags", "SDP flags"), { "custom_io", "Use custom IO", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_CUSTOM_IO}, 0, 0, DEC, "rtsp_flags" }, + { "rtcp_to_source", "Send RTCP packets to the source address of received packets", 0, AV_OPT_TYPE_CONST, {.i64 = RTSP_FLAG_RTCP_TO_SOURCE}, 0, 0, DEC, "rtsp_flags" }, RTSP_MEDIATYPE_OPTS("allowed_media_types", "Media types to accept from the server"), RTSP_REORDERING_OPTS(), { NULL }, @@ -290,8 +291,27 @@ typedef struct SDPParseState { struct sockaddr_storage default_ip; int default_ttl; int skip_media; ///< set if an unknown m= line occurs + int nb_default_include_source_addrs; /**< Number of source-specific multicast include source IP address (from SDP content) */ + struct RTSPSource **default_include_source_addrs; /**< Source-specific multicast include source IP address (from SDP content) */ + int nb_default_exclude_source_addrs; /**< Number of source-specific multicast exclude source IP address (from SDP content) */ + struct RTSPSource **default_exclude_source_addrs; /**< Source-specific multicast exclude source IP address (from SDP content) */ } SDPParseState; +static void copy_default_source_addrs(struct RTSPSource **addrs, int count, + struct RTSPSource ***dest, int *dest_count) +{ + RTSPSource *rtsp_src, *rtsp_src2; + int i; + for (i = 0; i < count; i++) { + rtsp_src = addrs[i]; + rtsp_src2 = av_malloc(sizeof(*rtsp_src2)); + if (!rtsp_src2) + continue; + memcpy(rtsp_src2, rtsp_src, sizeof(*rtsp_src)); + dynarray_add(dest, dest_count, rtsp_src2); + } +} + static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, int letter, const char *buf) { @@ -302,6 +322,7 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, int payload_type, i; AVStream *st; RTSPStream *rtsp_st; + RTSPSource *rtsp_src; struct sockaddr_storage sdp_ip; int ttl; @@ -370,6 +391,15 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, rtsp_st->sdp_ip = s1->default_ip; rtsp_st->sdp_ttl = s1->default_ttl; + copy_default_source_addrs(s1->default_include_source_addrs, + s1->nb_default_include_source_addrs, + &rtsp_st->include_source_addrs, + &rtsp_st->nb_include_source_addrs); + copy_default_source_addrs(s1->default_exclude_source_addrs, + s1->nb_default_exclude_source_addrs, + &rtsp_st->exclude_source_addrs, + &rtsp_st->nb_exclude_source_addrs); + get_word(buf1, sizeof(buf1), &p); /* port */ rtsp_st->sdp_port = atoi(buf1); @@ -499,6 +529,43 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, p += strspn(p, SPACE_CHARS); if (av_strstart(p, "inline:", &p)) get_word(rtsp_st->crypto_params, sizeof(rtsp_st->crypto_params), &p); + } else if (av_strstart(p, "source-filter:", &p)) { + int exclude = 0; + get_word(buf1, sizeof(buf1), &p); + if (strcmp(buf1, "incl") && strcmp(buf1, "excl")) + return; + exclude = !strcmp(buf1, "excl"); + + get_word(buf1, sizeof(buf1), &p); + if (strcmp(buf1, "IN") != 0) + return; + get_word(buf1, sizeof(buf1), &p); + if (strcmp(buf1, "IP4") && strcmp(buf1, "IP6") && strcmp(buf1, "*")) + return; + // not checking that the destination address actually matches or is wildcard + get_word(buf1, sizeof(buf1), &p); + + while (*p != '\0') { + rtsp_src = av_mallocz(sizeof(*rtsp_src)); + if (!rtsp_src) + return; + get_word(rtsp_src->addr, sizeof(rtsp_src->addr), &p); + if (exclude) { + if (s->nb_streams == 0) { + dynarray_add(&s1->default_exclude_source_addrs, &s1->nb_default_exclude_source_addrs, rtsp_src); + } else { + rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; + dynarray_add(&rtsp_st->exclude_source_addrs, &rtsp_st->nb_exclude_source_addrs, rtsp_src); + } + } else { + if (s->nb_streams == 0) { + dynarray_add(&s1->default_include_source_addrs, &s1->nb_default_include_source_addrs, rtsp_src); + } else { + rtsp_st = rt->rtsp_streams[rt->nb_rtsp_streams - 1]; + dynarray_add(&rtsp_st->include_source_addrs, &rtsp_st->nb_include_source_addrs, rtsp_src); + } + } + } } else { if (rt->server_type == RTSP_SERVER_WMS) ff_wms_parse_sdp_a_line(s, p); @@ -523,7 +590,7 @@ int ff_sdp_parse(AVFormatContext *s, const char *content) { RTSPState *rt = s->priv_data; const char *p; - int letter; + int letter, i; /* Some SDP lines, particularly for Realmedia or ASF RTSP streams, * contain long SDP lines containing complete ASF Headers (several * kB) or arrays of MDPR (RM stream descriptor) headers plus @@ -560,6 +627,14 @@ int ff_sdp_parse(AVFormatContext *s, const char *content) if (*p == '\n') p++; } + + for (i = 0; i < s1->nb_default_include_source_addrs; i++) + av_free(s1->default_include_source_addrs[i]); + av_freep(&s1->default_include_source_addrs); + for (i = 0; i < s1->nb_default_exclude_source_addrs; i++) + av_free(s1->default_exclude_source_addrs[i]); + av_freep(&s1->default_exclude_source_addrs); + rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1)); if (!rt->p) return AVERROR(ENOMEM); return 0; @@ -603,7 +678,7 @@ void ff_rtsp_undo_setup(AVFormatContext *s) void ff_rtsp_close_streams(AVFormatContext *s) { RTSPState *rt = s->priv_data; - int i; + int i, j; RTSPStream *rtsp_st; ff_rtsp_undo_setup(s); @@ -613,6 +688,13 @@ void ff_rtsp_close_streams(AVFormatContext *s) if (rtsp_st->dynamic_handler && rtsp_st->dynamic_protocol_context) rtsp_st->dynamic_handler->free( rtsp_st->dynamic_protocol_context); + for (j = 0; j < rtsp_st->nb_include_source_addrs; j++) + av_free(rtsp_st->include_source_addrs[j]); + av_freep(&rtsp_st->include_source_addrs); + for (j = 0; j < rtsp_st->nb_exclude_source_addrs; j++) + av_free(rtsp_st->exclude_source_addrs[j]); + av_freep(&rtsp_st->exclude_source_addrs); + av_free(rtsp_st); } } @@ -1120,11 +1202,11 @@ start: * * @return zero if success, nonzero otherwise */ -static int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s, - const char *method, const char *url, - const char *headers, - const unsigned char *send_content, - int send_content_length) +static int rtsp_send_cmd_with_content_async(AVFormatContext *s, + const char *method, const char *url, + const char *headers, + const unsigned char *send_content, + int send_content_length) { RTSPState *rt = s->priv_data; char buf[4096], *out_buf; @@ -1137,6 +1219,7 @@ static int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s, if (headers) av_strlcat(buf, headers, sizeof(buf)); av_strlcatf(buf, sizeof(buf), "CSeq: %d\r\n", rt->seq); + av_strlcatf(buf, sizeof(buf), "User-Agent: %s\r\n", rt->user_agent); if (rt->session_id[0] != '\0' && (!headers || !strstr(headers, "\nIf-Match:"))) { av_strlcatf(buf, sizeof(buf), "Session: %s\r\n", rt->session_id); @@ -1177,7 +1260,7 @@ static int ff_rtsp_send_cmd_with_content_async(AVFormatContext *s, int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method, const char *url, const char *headers) { - return ff_rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0); + return rtsp_send_cmd_with_content_async(s, method, url, headers, NULL, 0); } int ff_rtsp_send_cmd(AVFormatContext *s, const char *method, const char *url, @@ -1202,9 +1285,9 @@ int ff_rtsp_send_cmd_with_content(AVFormatContext *s, retry: cur_auth_type = rt->auth_state.auth_type; - if ((ret = ff_rtsp_send_cmd_with_content_async(s, method, url, header, - send_content, - send_content_length))) + if ((ret = rtsp_send_cmd_with_content_async(s, method, url, header, + send_content, + send_content_length))) return ret; if ((ret = ff_rtsp_read_reply(s, reply, content_ptr, 0, method) ) < 0) @@ -1399,18 +1482,15 @@ int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port, case RTSP_LOWER_TRANSPORT_UDP: { char url[1024], options[30] = ""; + const char *peer = host; if (rt->rtsp_flags & RTSP_FLAG_FILTER_SRC) av_strlcpy(options, "?connect=1", sizeof(options)); /* Use source address if specified */ - if (reply->transports[0].source[0]) { - ff_url_join(url, sizeof(url), "rtp", NULL, - reply->transports[0].source, - reply->transports[0].server_port_min, "%s", options); - } else { - ff_url_join(url, sizeof(url), "rtp", NULL, host, - reply->transports[0].server_port_min, "%s", options); - } + if (reply->transports[0].source[0]) + peer = reply->transports[0].source; + ff_url_join(url, sizeof(url), "rtp", NULL, peer, + reply->transports[0].server_port_min, "%s", options); if (!(rt->server_type == RTSP_SERVER_WMS && i > 1) && ff_rtp_set_remote_url(rtsp_st->rtp_handle, url) < 0) { err = AVERROR_INVALIDDATA; @@ -2030,7 +2110,7 @@ static int sdp_probe(AVProbeData *p1) while (p < p_end && *p != '\0') { if (p + sizeof("c=IN IP") - 1 < p_end && av_strstart(p, "c=IN IP", NULL)) - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; while (p < p_end - 1 && *p != '\n') p++; if (++p >= p_end) @@ -2041,6 +2121,17 @@ static int sdp_probe(AVProbeData *p1) return 0; } +static void append_source_addrs(char *buf, int size, const char *name, + int count, struct RTSPSource **addrs) +{ + int i; + if (!count) + return; + av_strlcatf(buf, size, "&%s=%s", name, addrs[0]->addr); + for (i = 1; i < count; i++) + av_strlcatf(buf, size, ",%s", addrs[i]->addr); +} + static int sdp_read_header(AVFormatContext *s) { RTSPState *rt = s->priv_data; @@ -2081,9 +2172,17 @@ static int sdp_read_header(AVFormatContext *s) namebuf, sizeof(namebuf), NULL, 0, NI_NUMERICHOST); ff_url_join(url, sizeof(url), "rtp", NULL, namebuf, rtsp_st->sdp_port, - "?localport=%d&ttl=%d&connect=%d", rtsp_st->sdp_port, - rtsp_st->sdp_ttl, - rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0); + "?localport=%d&ttl=%d&connect=%d&write_to_source=%d", + rtsp_st->sdp_port, rtsp_st->sdp_ttl, + rt->rtsp_flags & RTSP_FLAG_FILTER_SRC ? 1 : 0, + rt->rtsp_flags & RTSP_FLAG_RTCP_TO_SOURCE ? 1 : 0); + + append_source_addrs(url, sizeof(url), "sources", + rtsp_st->nb_include_source_addrs, + rtsp_st->include_source_addrs); + append_source_addrs(url, sizeof(url), "block", + rtsp_st->nb_exclude_source_addrs, + rtsp_st->exclude_source_addrs); if (ffurl_open(&rtsp_st->rtp_handle, url, AVIO_FLAG_READ_WRITE, &s->interrupt_callback, NULL) < 0) { err = AVERROR_INVALIDDATA; diff --git a/chromium/third_party/ffmpeg/libavformat/rtsp.h b/chromium/third_party/ffmpeg/libavformat/rtsp.h index 4af3507d733..2dc4b6cbae6 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtsp.h +++ b/chromium/third_party/ffmpeg/libavformat/rtsp.h @@ -399,6 +399,11 @@ typedef struct RTSPState { * Size of RTP packet reordering queue. */ int reordering_queue_size; + + /** + * User-Agent string + */ + char *user_agent; } RTSPState; #define RTSP_FLAG_FILTER_SRC 0x1 /**< Filter incoming UDP packets - @@ -406,6 +411,12 @@ typedef struct RTSPState { source address and port. */ #define RTSP_FLAG_LISTEN 0x2 /**< Wait for incoming connections. */ #define RTSP_FLAG_CUSTOM_IO 0x4 /**< Do all IO via the AVIOContext. */ +#define RTSP_FLAG_RTCP_TO_SOURCE 0x8 /**< Send RTCP packets to the source + address of received packets. */ + +typedef struct RTSPSource { + char addr[128]; /**< Source-specific multicast include source IP address (from SDP content) */ +} RTSPSource; /** * Describe a single stream, as identified by a single m= line block in the @@ -430,6 +441,10 @@ typedef struct RTSPStream { //@{ int sdp_port; /**< port (from SDP content) */ struct sockaddr_storage sdp_ip; /**< IP address (from SDP content) */ + int nb_include_source_addrs; /**< Number of source-specific multicast include source IP addresses (from SDP content) */ + struct RTSPSource **include_source_addrs; /**< Source-specific multicast include source IP addresses (from SDP content) */ + int nb_exclude_source_addrs; /**< Number of source-specific multicast exclude source IP addresses (from SDP content) */ + struct RTSPSource **exclude_source_addrs; /**< Source-specific multicast exclude source IP addresses (from SDP content) */ int sdp_ttl; /**< IP Time-To-Live (from SDP content) */ int sdp_payload_type; /**< payload type */ //@} diff --git a/chromium/third_party/ffmpeg/libavformat/rtspdec.c b/chromium/third_party/ffmpeg/libavformat/rtspdec.c index da571a8ee8e..3615226ac00 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtspdec.c +++ b/chromium/third_party/ffmpeg/libavformat/rtspdec.c @@ -29,6 +29,7 @@ #include "internal.h" #include "network.h" #include "os_support.h" +#include "rtpproto.h" #include "rtsp.h" #include "rdt.h" #include "url.h" diff --git a/chromium/third_party/ffmpeg/libavformat/rtspenc.c b/chromium/third_party/ffmpeg/libavformat/rtspenc.c index bad6fbd3a29..bea18317fd1 100644 --- a/chromium/third_party/ffmpeg/libavformat/rtspenc.c +++ b/chromium/third_party/ffmpeg/libavformat/rtspenc.c @@ -145,6 +145,7 @@ static int tcp_write_packet(AVFormatContext *s, RTSPStream *rtsp_st) uint8_t *interleave_header, *interleaved_packet; size = avio_close_dyn_buf(rtpctx->pb, &buf); + rtpctx->pb = NULL; ptr = buf; while (size > 4) { uint32_t packet_len = AV_RB32(ptr); @@ -171,8 +172,7 @@ static int tcp_write_packet(AVFormatContext *s, RTSPStream *rtsp_st) size -= packet_len; } av_free(buf); - ffio_open_dyn_packet_buf(&rtpctx->pb, RTSP_TCP_MAX_PACKET_SIZE); - return 0; + return ffio_open_dyn_packet_buf(&rtpctx->pb, RTSP_TCP_MAX_PACKET_SIZE); } static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt) diff --git a/chromium/third_party/ffmpeg/libavformat/sctp.c b/chromium/third_party/ffmpeg/libavformat/sctp.c index 2fd5400ae5d..e3585b44b57 100644 --- a/chromium/third_party/ffmpeg/libavformat/sctp.c +++ b/chromium/third_party/ffmpeg/libavformat/sctp.c @@ -56,10 +56,10 @@ /* * The sctp_recvmsg and sctp_sendmsg functions are part of the user - * library that offers support - * for the SCTP kernel Implementation. The main purpose of this - * code is to provide the SCTP Socket API mappings for user - * application to interface with the SCTP in kernel. + * library that offers support for the SCTP kernel Implementation. + * To avoid build-time clashes the functions sport an ff_-prefix here. + * The main purpose of this code is to provide the SCTP Socket API + * mappings for user applications to interface with SCTP in the kernel. * * This implementation is based on the Socket API Extensions for SCTP * defined in <draft-ietf-tsvwg-sctpsocket-10.txt> @@ -198,7 +198,7 @@ static int sctp_open(URLContext *h, const char *uri, int flags) cur_ai = ai; - fd = socket(cur_ai->ai_family, SOCK_STREAM, IPPROTO_SCTP); + fd = ff_socket(cur_ai->ai_family, SOCK_STREAM, IPPROTO_SCTP); if (fd < 0) goto fail; diff --git a/chromium/third_party/ffmpeg/libavformat/seek-test.c b/chromium/third_party/ffmpeg/libavformat/seek-test.c index 34ac4deff26..8b0611db71a 100644 --- a/chromium/third_party/ffmpeg/libavformat/seek-test.c +++ b/chromium/third_party/ffmpeg/libavformat/seek-test.c @@ -64,6 +64,7 @@ int main(int argc, char **argv) int64_t seekfirst = AV_NOPTS_VALUE; int firstback=0; int frame_count = 1; + int duration = 4; for(i=2; i<argc; i+=2){ if (!strcmp(argv[i], "-seekforw")){ @@ -73,6 +74,8 @@ int main(int argc, char **argv) firstback = 1; } else if(!strcmp(argv[i], "-frames")){ frame_count = atoi(argv[i+1]); + } else if(!strcmp(argv[i], "-duration")){ + duration = atoi(argv[i+1]); } else { argc = 1; } @@ -133,7 +136,7 @@ int main(int argc, char **argv) if(i>25) break; stream_id= (i>>1)%(ic->nb_streams+1) - 1; - timestamp= (i*19362894167LL) % (4*AV_TIME_BASE) - AV_TIME_BASE; + timestamp= (i*19362894167LL) % (duration*AV_TIME_BASE) - AV_TIME_BASE; if(stream_id>=0){ st= ic->streams[stream_id]; timestamp= av_rescale_q(timestamp, AV_TIME_BASE_Q, st->time_base); diff --git a/chromium/third_party/ffmpeg/libavformat/segafilm.c b/chromium/third_party/ffmpeg/libavformat/segafilm.c index a33ad858f57..232a93117fa 100644 --- a/chromium/third_party/ffmpeg/libavformat/segafilm.c +++ b/chromium/third_party/ffmpeg/libavformat/segafilm.c @@ -215,6 +215,8 @@ static int film_read_header(AVFormatContext *s) film->sample_table[i].sample_offset = data_offset + AV_RB32(&scratch[0]); film->sample_table[i].sample_size = AV_RB32(&scratch[4]); + if (film->sample_table[i].sample_size > INT_MAX / 4) + return AVERROR_INVALIDDATA; if (AV_RB32(&scratch[8]) == 0xFFFFFFFF) { film->sample_table[i].stream = film->audio_stream_index; film->sample_table[i].pts = audio_frame_counter; diff --git a/chromium/third_party/ffmpeg/libavformat/segment.c b/chromium/third_party/ffmpeg/libavformat/segment.c index dbcfe898cf1..95984bd1160 100644 --- a/chromium/third_party/ffmpeg/libavformat/segment.c +++ b/chromium/third_party/ffmpeg/libavformat/segment.c @@ -43,6 +43,7 @@ typedef struct SegmentListEntry { int index; double start_time, end_time; int64_t start_pts; + int64_t offset_pts; char filename[1024]; struct SegmentListEntry *next; } SegmentListEntry; @@ -85,12 +86,12 @@ typedef struct { int nb_frames; ///< number of elments in the frames array int frame_count; - char *time_delta_str; ///< approximation value duration used for the segment times int64_t time_delta; int individual_header_trailer; /**< Set by a private option. */ int write_header_trailer; /**< Set by a private option. */ int reset_timestamps; ///< reset timestamps at the begin of each segment + int64_t initial_offset; ///< initial timestamps offset, expressed in microseconds char *reference_stream_specifier; ///< reference stream specifier int reference_stream_index; @@ -554,15 +555,6 @@ static int seg_write_header(AVFormatContext *s) } } - if (seg->time_delta_str) { - if ((ret = av_parse_time(&seg->time_delta, seg->time_delta_str, 1)) < 0) { - av_log(s, AV_LOG_ERROR, - "Invalid time duration specification '%s' for delta option\n", - seg->time_delta_str); - return ret; - } - } - if (seg->list) { if (seg->list_type == LIST_TYPE_UNDEFINED) { if (av_match_ext(seg->list, "csv" )) seg->list_type = LIST_TYPE_CSV; @@ -644,7 +636,7 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) SegmentContext *seg = s->priv_data; AVFormatContext *oc = seg->avf; AVStream *st = s->streams[pkt->stream_index]; - int64_t end_pts = INT64_MAX; + int64_t end_pts = INT64_MAX, offset; int start_frame = INT_MAX; int ret; @@ -694,23 +686,23 @@ static int seg_write_packet(AVFormatContext *s, AVPacket *pkt) seg->is_first_pkt = 0; } - if (seg->reset_timestamps) { - av_log(s, AV_LOG_DEBUG, "stream:%d start_pts_time:%s pts:%s pts_time:%s dts:%s dts_time:%s", - pkt->stream_index, - av_ts2timestr(seg->cur_entry.start_pts, &AV_TIME_BASE_Q), - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); - - /* compute new timestamps */ - if (pkt->pts != AV_NOPTS_VALUE) - pkt->pts -= av_rescale_q(seg->cur_entry.start_pts, AV_TIME_BASE_Q, st->time_base); - if (pkt->dts != AV_NOPTS_VALUE) - pkt->dts -= av_rescale_q(seg->cur_entry.start_pts, AV_TIME_BASE_Q, st->time_base); - - av_log(s, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n", - av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), - av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); - } + av_log(s, AV_LOG_DEBUG, "stream:%d start_pts_time:%s pts:%s pts_time:%s dts:%s dts_time:%s", + pkt->stream_index, + av_ts2timestr(seg->cur_entry.start_pts, &AV_TIME_BASE_Q), + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); + + /* compute new timestamps */ + offset = av_rescale_q(seg->initial_offset - (seg->reset_timestamps ? seg->cur_entry.start_pts : 0), + AV_TIME_BASE_Q, st->time_base); + if (pkt->pts != AV_NOPTS_VALUE) + pkt->pts += offset; + if (pkt->dts != AV_NOPTS_VALUE) + pkt->dts += offset; + + av_log(s, AV_LOG_DEBUG, " -> pts:%s pts_time:%s dts:%s dts_time:%s\n", + av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, &st->time_base), + av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, &st->time_base)); ret = ff_write_chained(oc, pkt->stream_index, pkt, s); @@ -784,7 +776,7 @@ static const AVOption options[] = { { "hls", "Apple HTTP Live Streaming compatible", 0, AV_OPT_TYPE_CONST, {.i64=LIST_TYPE_M3U8 }, INT_MIN, INT_MAX, E, "list_type" }, { "segment_time", "set segment duration", OFFSET(time_str),AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, - { "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta_str), AV_OPT_TYPE_STRING, {.str = "0"}, 0, 0, E }, + { "segment_time_delta","set approximation value used for the segment times", OFFSET(time_delta), AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, 0, E }, { "segment_times", "set segment split time points", OFFSET(times_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E }, { "segment_frames", "set segment split frame numbers", OFFSET(frames_str),AV_OPT_TYPE_STRING,{.str = NULL}, 0, 0, E }, { "segment_wrap", "set number after which the index wraps", OFFSET(segment_idx_wrap), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, @@ -793,6 +785,7 @@ static const AVOption options[] = { { "individual_header_trailer", "write header/trailer to each segment", OFFSET(individual_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E }, { "write_header_trailer", "write a header to the first segment and a trailer to the last one", OFFSET(write_header_trailer), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, E }, { "reset_timestamps", "reset timestamps at the begin of each segment", OFFSET(reset_timestamps), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E }, + { "initial_offset", "set initial timestamp offset", OFFSET(initial_offset), AV_OPT_TYPE_DURATION, {.i64 = 0}, -INT64_MAX, INT64_MAX, E }, { NULL }, }; diff --git a/chromium/third_party/ffmpeg/libavformat/sierravmd.c b/chromium/third_party/ffmpeg/libavformat/sierravmd.c index b0b582d719e..b2d1e5dd590 100644 --- a/chromium/third_party/ffmpeg/libavformat/sierravmd.c +++ b/chromium/third_party/ffmpeg/libavformat/sierravmd.c @@ -64,8 +64,8 @@ typedef struct VmdDemuxContext { static int vmd_probe(AVProbeData *p) { - int w, h; - if (p->buf_size < 16) + int w, h, sample_rate; + if (p->buf_size < 806) return 0; /* check if the first 2 bytes of the file contain the appropriate size * of a VMD header chunk */ @@ -73,23 +73,25 @@ static int vmd_probe(AVProbeData *p) return 0; w = AV_RL16(&p->buf[12]); h = AV_RL16(&p->buf[14]); - if (!w || w > 2048 || !h || h > 2048) + sample_rate = AV_RL16(&p->buf[804]); + if ((!w || w > 2048 || !h || h > 2048) && + sample_rate != 22050) return 0; /* only return half certainty since this check is a bit sketchy */ - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; } static int vmd_read_header(AVFormatContext *s) { VmdDemuxContext *vmd = s->priv_data; AVIOContext *pb = s->pb; - AVStream *st = NULL, *vst; + AVStream *st = NULL, *vst = NULL; unsigned int toc_offset; unsigned char *raw_frame_table; int raw_frame_table_size; int64_t current_offset; - int i, j; + int i, j, width, height; unsigned int total_frames; int64_t current_audio_pts = 0; unsigned char chunk[BYTES_PER_FRAME_RECORD]; @@ -101,28 +103,33 @@ static int vmd_read_header(AVFormatContext *s) if (avio_read(pb, vmd->vmd_header, VMD_HEADER_SIZE) != VMD_HEADER_SIZE) return AVERROR(EIO); - if(vmd->vmd_header[24] == 'i' && vmd->vmd_header[25] == 'v' && vmd->vmd_header[26] == '3') - vmd->is_indeo3 = 1; - else - vmd->is_indeo3 = 0; - /* start up the decoders */ - vst = avformat_new_stream(s, NULL); - if (!vst) - return AVERROR(ENOMEM); - avpriv_set_pts_info(vst, 33, 1, 10); - vmd->video_stream_index = vst->index; - vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = vmd->is_indeo3 ? AV_CODEC_ID_INDEO3 : AV_CODEC_ID_VMDVIDEO; - vst->codec->codec_tag = 0; /* no fourcc */ - vst->codec->width = AV_RL16(&vmd->vmd_header[12]); - vst->codec->height = AV_RL16(&vmd->vmd_header[14]); - if(vmd->is_indeo3 && vst->codec->width > 320){ - vst->codec->width >>= 1; - vst->codec->height >>= 1; + width = AV_RL16(&vmd->vmd_header[12]); + height = AV_RL16(&vmd->vmd_header[14]); + if (width && height) { + if(vmd->vmd_header[24] == 'i' && vmd->vmd_header[25] == 'v' && vmd->vmd_header[26] == '3') { + vmd->is_indeo3 = 1; + } else { + vmd->is_indeo3 = 0; + } + /* start up the decoders */ + vst = avformat_new_stream(s, NULL); + if (!vst) + return AVERROR(ENOMEM); + avpriv_set_pts_info(vst, 33, 1, 10); + vmd->video_stream_index = vst->index; + vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codec->codec_id = vmd->is_indeo3 ? AV_CODEC_ID_INDEO3 : AV_CODEC_ID_VMDVIDEO; + vst->codec->codec_tag = 0; /* no fourcc */ + vst->codec->width = width; + vst->codec->height = height; + if(vmd->is_indeo3 && vst->codec->width > 320){ + vst->codec->width >>= 1; + vst->codec->height >>= 1; + } + vst->codec->extradata_size = VMD_HEADER_SIZE; + vst->codec->extradata = av_mallocz(VMD_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(vst->codec->extradata, vmd->vmd_header, VMD_HEADER_SIZE); } - vst->codec->extradata_size = VMD_HEADER_SIZE; - vst->codec->extradata = av_mallocz(VMD_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); - memcpy(vst->codec->extradata, vmd->vmd_header, VMD_HEADER_SIZE); /* if sample rate is 0, assume no audio */ vmd->sample_rate = AV_RL16(&vmd->vmd_header[804]); @@ -156,7 +163,8 @@ static int vmd_read_header(AVFormatContext *s) num = st->codec->block_align; den = st->codec->sample_rate * st->codec->channels; av_reduce(&num, &den, num, den, (1UL<<31)-1); - avpriv_set_pts_info(vst, 33, num, den); + if (vst) + avpriv_set_pts_info(vst, 33, num, den); avpriv_set_pts_info(st, 33, num, den); } diff --git a/chromium/third_party/ffmpeg/libavformat/smacker.c b/chromium/third_party/ffmpeg/libavformat/smacker.c index 84481e22a68..b4c1bf43358 100644 --- a/chromium/third_party/ffmpeg/libavformat/smacker.c +++ b/chromium/third_party/ffmpeg/libavformat/smacker.c @@ -210,7 +210,8 @@ static int smacker_read_header(AVFormatContext *s) /* load trees to extradata, they will be unpacked by decoder */ - st->codec->extradata = av_malloc(smk->treesize + 16 + FF_INPUT_BUFFER_PADDING_SIZE); + st->codec->extradata = av_mallocz(smk->treesize + 16 + + FF_INPUT_BUFFER_PADDING_SIZE); st->codec->extradata_size = smk->treesize + 16; if(!st->codec->extradata){ av_log(s, AV_LOG_ERROR, "Cannot allocate %i bytes of extradata\n", smk->treesize + 16); @@ -276,7 +277,7 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) } else if(t & 0x40){ /* copy with offset */ off = avio_r8(s->pb); j = (t & 0x3F) + 1; - if (off + j - 1 > 0xff) { + if (off + j > 0x100) { av_log(s, AV_LOG_ERROR, "Invalid palette update, offset=%d length=%d extends beyond palette size\n", off, j); @@ -305,12 +306,14 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) /* if audio chunks are present, put them to stack and retrieve later */ for(i = 0; i < 7; i++) { if(flags & 1) { - unsigned int size; + uint32_t size; uint8_t *tmpbuf; size = avio_rl32(s->pb) - 4; - if(size + 4L > frame_size) + if (!size || size + 4L > frame_size) { + av_log(s, AV_LOG_ERROR, "Invalid audio part size\n"); return AVERROR_INVALIDDATA; + } frame_size -= size; frame_size -= 4; smk->curstream++; @@ -338,6 +341,7 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt) if(ret != frame_size) return AVERROR(EIO); pkt->stream_index = smk->videoindex; + pkt->pts = smk->cur_frame; pkt->size = ret + 769; smk->cur_frame++; smk->nextpos = avio_tell(s->pb); diff --git a/chromium/third_party/ffmpeg/libavformat/smoothstreamingenc.c b/chromium/third_party/ffmpeg/libavformat/smoothstreamingenc.c index 096bf79c302..7163c90c4da 100644 --- a/chromium/third_party/ffmpeg/libavformat/smoothstreamingenc.c +++ b/chromium/third_party/ffmpeg/libavformat/smoothstreamingenc.c @@ -428,7 +428,7 @@ static int parse_fragment(AVFormatContext *s, const char *filename, int64_t *sta if (len < 8 || len >= *moof_size) goto fail; if (tag == MKTAG('u','u','i','d')) { - const uint8_t tfxd[] = { + static const uint8_t tfxd[] = { 0x6d, 0x1d, 0x9b, 0x05, 0x42, 0xd5, 0x44, 0xe6, 0x80, 0xe2, 0x14, 0x1d, 0xaf, 0xf7, 0x57, 0xb2 }; diff --git a/chromium/third_party/ffmpeg/libavformat/spdifdec.c b/chromium/third_party/ffmpeg/libavformat/spdifdec.c index 726a85cbe58..69843503b00 100644 --- a/chromium/third_party/ffmpeg/libavformat/spdifdec.c +++ b/chromium/third_party/ffmpeg/libavformat/spdifdec.c @@ -154,10 +154,10 @@ int ff_spdif_probe(const uint8_t *p_buf, int buf_size, enum AVCodecID *codec) if (sync_codes >= 6) /* good amount of sync codes but with unexpected offsets */ - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; /* some sync codes were found */ - return AVPROBE_SCORE_MAX / 8; + return AVPROBE_SCORE_EXTENSION / 4; } static int spdif_read_header(AVFormatContext *s) diff --git a/chromium/third_party/ffmpeg/libavformat/spdifenc.c b/chromium/third_party/ffmpeg/libavformat/spdifenc.c index 857c20de221..210d63f39cd 100644 --- a/chromium/third_party/ffmpeg/libavformat/spdifenc.c +++ b/chromium/third_party/ffmpeg/libavformat/spdifenc.c @@ -92,7 +92,7 @@ static const AVOption options[] = { { NULL }, }; -static const AVClass class = { +static const AVClass spdif_class = { .class_name = "spdif", .item_name = av_default_item_name, .option = options, @@ -395,15 +395,15 @@ static int spdif_header_truehd(AVFormatContext *s, AVPacket *pkt) { IEC61937Context *ctx = s->priv_data; int mat_code_length = 0; - const char mat_end_code[16] = { 0xC3, 0xC2, 0xC0, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x11 }; + static const char mat_end_code[16] = { 0xC3, 0xC2, 0xC0, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x97, 0x11 }; if (!ctx->hd_buf_count) { - const char mat_start_code[20] = { 0x07, 0x9E, 0x00, 0x03, 0x84, 0x01, 0x01, 0x01, 0x80, 0x00, 0x56, 0xA5, 0x3B, 0xF4, 0x81, 0x83, 0x49, 0x80, 0x77, 0xE0 }; + static const char mat_start_code[20] = { 0x07, 0x9E, 0x00, 0x03, 0x84, 0x01, 0x01, 0x01, 0x80, 0x00, 0x56, 0xA5, 0x3B, 0xF4, 0x81, 0x83, 0x49, 0x80, 0x77, 0xE0 }; mat_code_length = sizeof(mat_start_code) + BURST_HEADER_SIZE; memcpy(ctx->hd_buf, mat_start_code, sizeof(mat_start_code)); } else if (ctx->hd_buf_count == 12) { - const char mat_middle_code[12] = { 0xC3, 0xC1, 0x42, 0x49, 0x3B, 0xFA, 0x82, 0x83, 0x49, 0x80, 0x77, 0xE0 }; + static const char mat_middle_code[12] = { 0xC3, 0xC1, 0x42, 0x49, 0x3B, 0xFA, 0x82, 0x83, 0x49, 0x80, 0x77, 0xE0 }; mat_code_length = sizeof(mat_middle_code) + MAT_MIDDLE_CODE_OFFSET; memcpy(&ctx->hd_buf[12 * TRUEHD_FRAME_OFFSET - BURST_HEADER_SIZE + MAT_MIDDLE_CODE_OFFSET], mat_middle_code, sizeof(mat_middle_code)); @@ -552,5 +552,5 @@ AVOutputFormat ff_spdif_muxer = { .write_packet = spdif_write_packet, .write_trailer = spdif_write_trailer, .flags = AVFMT_NOTIMESTAMPS, - .priv_class = &class, + .priv_class = &spdif_class, }; diff --git a/chromium/third_party/ffmpeg/libavformat/srtdec.c b/chromium/third_party/ffmpeg/libavformat/srtdec.c index 76e06e41654..dbf1866202d 100644 --- a/chromium/third_party/ffmpeg/libavformat/srtdec.c +++ b/chromium/third_party/ffmpeg/libavformat/srtdec.c @@ -63,10 +63,12 @@ static int64_t get_pts(const char **buf, int *duration, int64_t start = (hh1*3600LL + mm1*60LL + ss1) * 1000LL + ms1; int64_t end = (hh2*3600LL + mm2*60LL + ss2) * 1000LL + ms2; *duration = end - start; - *buf += strcspn(*buf, "\n") + 1; + *buf += strcspn(*buf, "\n"); + *buf += !!**buf; return start; } - *buf += strcspn(*buf, "\n") + 1; + *buf += strcspn(*buf, "\n"); + *buf += !!**buf; } return AV_NOPTS_VALUE; } diff --git a/chromium/third_party/ffmpeg/libavformat/subviewer1dec.c b/chromium/third_party/ffmpeg/libavformat/subviewer1dec.c index 0dc1942a428..1b831b7b8ff 100644 --- a/chromium/third_party/ffmpeg/libavformat/subviewer1dec.c +++ b/chromium/third_party/ffmpeg/libavformat/subviewer1dec.c @@ -36,7 +36,7 @@ static int subviewer1_probe(AVProbeData *p) const unsigned char *ptr = p->buf; if (strstr(ptr, "******** START SCRIPT ********")) - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/subviewerdec.c b/chromium/third_party/ffmpeg/libavformat/subviewerdec.c index 7cacd973dbc..9e645d25c7c 100644 --- a/chromium/third_party/ffmpeg/libavformat/subviewerdec.c +++ b/chromium/third_party/ffmpeg/libavformat/subviewerdec.c @@ -44,7 +44,7 @@ static int subviewer_probe(AVProbeData *p) if (AV_RB24(ptr) == 0xEFBBBF) ptr += 3; /* skip UTF-8 BOM */ if (sscanf(ptr, "%*u:%*u:%*u.%*u,%*u:%*u:%*u.%*u%c", &c) == 1) - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; if (!strncmp(ptr, "[INFORMATION]", 13)) return AVPROBE_SCORE_MAX/3; return 0; diff --git a/chromium/third_party/ffmpeg/libavformat/swf.h b/chromium/third_party/ffmpeg/libavformat/swf.h index b9722c1c9a8..c1667b3c24c 100644 --- a/chromium/third_party/ffmpeg/libavformat/swf.h +++ b/chromium/third_party/ffmpeg/libavformat/swf.h @@ -120,9 +120,6 @@ enum { #define VIDEO_ID 0 #define SHAPE_ID 1 -#undef NDEBUG -#include <assert.h> - typedef struct SWFContext { int64_t duration_pos; int64_t tag_pos; diff --git a/chromium/third_party/ffmpeg/libavformat/swfenc.c b/chromium/third_party/ffmpeg/libavformat/swfenc.c index 70183625c37..8d9cf0c246c 100644 --- a/chromium/third_party/ffmpeg/libavformat/swfenc.c +++ b/chromium/third_party/ffmpeg/libavformat/swfenc.c @@ -234,7 +234,7 @@ static int swf_write_header(AVFormatContext *s) } if (!swf->audio_enc) - swf->samples_per_frame = (44100. * rate_base) / rate; + swf->samples_per_frame = (44100.0 * rate_base) / rate; else swf->samples_per_frame = (swf->audio_enc->sample_rate * rate_base) / rate; diff --git a/chromium/third_party/ffmpeg/libavformat/takdec.c b/chromium/third_party/ffmpeg/libavformat/takdec.c index 377c10c1abd..2ed8a1e3b71 100644 --- a/chromium/third_party/ffmpeg/libavformat/takdec.c +++ b/chromium/third_party/ffmpeg/libavformat/takdec.c @@ -19,8 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/crc.h" #include "libavcodec/tak.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #include "rawdec.h" #include "apetag.h" @@ -33,10 +35,16 @@ typedef struct TAKDemuxContext { static int tak_probe(AVProbeData *p) { if (!memcmp(p->buf, "tBaK", 4)) - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; return 0; } +static unsigned long tak_check_crc(unsigned long checksum, const uint8_t *buf, + unsigned int len) +{ + return av_crc(av_crc_get_table(AV_CRC_24_IEEE), checksum, buf, len); +} + static int tak_read_header(AVFormatContext *s) { TAKDemuxContext *tc = s->priv_data; @@ -71,16 +79,27 @@ static int tak_read_header(AVFormatContext *s) case TAK_METADATA_STREAMINFO: case TAK_METADATA_LAST_FRAME: case TAK_METADATA_ENCODER: - buffer = av_malloc(size + FF_INPUT_BUFFER_PADDING_SIZE); + if (size <= 3) + return AVERROR_INVALIDDATA; + + buffer = av_malloc(size - 3 + FF_INPUT_BUFFER_PADDING_SIZE); if (!buffer) return AVERROR(ENOMEM); - if (avio_read(pb, buffer, size) != size) { + ffio_init_checksum(pb, tak_check_crc, 0xCE04B7U); + if (avio_read(pb, buffer, size - 3) != size - 3) { av_freep(&buffer); return AVERROR(EIO); } + if (ffio_get_checksum(s->pb) != avio_rb24(pb)) { + av_log(s, AV_LOG_ERROR, "%d metadata block CRC error.\n", type); + if (s->error_recognition & AV_EF_EXPLODE) { + av_freep(&buffer); + return AVERROR_INVALIDDATA; + } + } - init_get_bits(&gb, buffer, size * 8); + init_get_bits8(&gb, buffer, size - 3); break; case TAK_METADATA_MD5: { uint8_t md5[16]; @@ -88,8 +107,14 @@ static int tak_read_header(AVFormatContext *s) if (size != 19) return AVERROR_INVALIDDATA; + ffio_init_checksum(pb, tak_check_crc, 0xCE04B7U); avio_read(pb, md5, 16); - avio_skip(pb, 3); + if (ffio_get_checksum(s->pb) != avio_rb24(pb)) { + av_log(s, AV_LOG_ERROR, "MD5 metadata block CRC error.\n"); + if (s->error_recognition & AV_EF_EXPLODE) + return AVERROR_INVALIDDATA; + } + av_log(s, AV_LOG_VERBOSE, "MD5="); for (i = 0; i < 16; i++) av_log(s, AV_LOG_VERBOSE, "%02x", md5[i]); @@ -127,7 +152,7 @@ static int tak_read_header(AVFormatContext *s) st->start_time = 0; avpriv_set_pts_info(st, 64, 1, st->codec->sample_rate); st->codec->extradata = buffer; - st->codec->extradata_size = size; + st->codec->extradata_size = size - 3; buffer = NULL; } else if (type == TAK_METADATA_LAST_FRAME) { if (size != 11) @@ -155,7 +180,7 @@ static int raw_read_packet(AVFormatContext *s, AVPacket *pkt) AVIOContext *pb = s->pb; int64_t size, left; - left = tc->data_end - avio_tell(s->pb); + left = tc->data_end - avio_tell(pb); size = FFMIN(left, 1024); if (size <= 0) return AVERROR_EOF; diff --git a/chromium/third_party/ffmpeg/libavformat/tcp.c b/chromium/third_party/ffmpeg/libavformat/tcp.c index 0d792e75b42..36af37a94a1 100644 --- a/chromium/third_party/ffmpeg/libavformat/tcp.c +++ b/chromium/third_party/ffmpeg/libavformat/tcp.c @@ -34,6 +34,7 @@ typedef struct TCPContext { const AVClass *class; int fd; int listen; + int open_timeout; int rw_timeout; int listen_timeout; } TCPContext; @@ -43,7 +44,7 @@ typedef struct TCPContext { #define E AV_OPT_FLAG_ENCODING_PARAM static const AVOption options[] = { {"listen", "listen on port instead of connecting", OFFSET(listen), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, D|E }, -{"timeout", "timeout of socket i/o operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, D|E }, +{"timeout", "timeout of socket i/o operations", OFFSET(rw_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E }, {"listen_timeout", "connection awaiting timeout", OFFSET(listen_timeout), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, D|E }, {NULL} }; @@ -64,10 +65,9 @@ static int tcp_open(URLContext *h, const char *uri, int flags) const char *p; char buf[256]; int ret; - socklen_t optlen; char hostname[1024],proto[1024],path[1024]; char portstr[10]; - h->rw_timeout = 5000000; + s->open_timeout = 5000000; av_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port, path, sizeof(path), uri); @@ -88,7 +88,10 @@ static int tcp_open(URLContext *h, const char *uri, int flags) s->listen_timeout = strtol(buf, NULL, 10); } } - h->rw_timeout = s->rw_timeout; + if (s->rw_timeout >= 0) { + s->open_timeout = + h->rw_timeout = s->rw_timeout; + } hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; snprintf(portstr, sizeof(portstr), "%d", port); @@ -108,89 +111,31 @@ static int tcp_open(URLContext *h, const char *uri, int flags) cur_ai = ai; restart: - ret = AVERROR(EIO); - fd = socket(cur_ai->ai_family, cur_ai->ai_socktype, cur_ai->ai_protocol); - if (fd < 0) + fd = ff_socket(cur_ai->ai_family, + cur_ai->ai_socktype, + cur_ai->ai_protocol); + if (fd < 0) { + ret = ff_neterrno(); goto fail; + } if (s->listen) { - int fd1; - int reuse = 1; - struct pollfd lp = { fd, POLLIN, 0 }; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); - ret = bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); - if (ret) { - ret = ff_neterrno(); - goto fail1; - } - ret = listen(fd, 1); - if (ret) { - ret = ff_neterrno(); - goto fail1; - } - ret = poll(&lp, 1, s->listen_timeout >= 0 ? s->listen_timeout : -1); - if (ret <= 0) { - ret = AVERROR(ETIMEDOUT); - goto fail1; - } - fd1 = accept(fd, NULL, NULL); - if (fd1 < 0) { - ret = ff_neterrno(); + if ((fd = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, + s->listen_timeout, h)) < 0) { + ret = fd; goto fail1; } - closesocket(fd); - fd = fd1; - ff_socket_nonblock(fd, 1); } else { - redo: - ff_socket_nonblock(fd, 1); - ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); - } - - if (ret < 0) { - struct pollfd p = {fd, POLLOUT, 0}; - int64_t wait_started; - ret = ff_neterrno(); - if (ret == AVERROR(EINTR)) { - if (ff_check_interrupt(&h->interrupt_callback)) { - ret = AVERROR_EXIT; - goto fail1; - } - goto redo; - } - if (ret != AVERROR(EINPROGRESS) && - ret != AVERROR(EAGAIN)) - goto fail; + if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, + s->open_timeout / 1000, h, cur_ai->ai_next)) < 0) { - /* wait until we are connected or until abort */ - wait_started = av_gettime(); - do { - if (ff_check_interrupt(&h->interrupt_callback)) { - ret = AVERROR_EXIT; + if (ret == AVERROR_EXIT) goto fail1; - } - ret = poll(&p, 1, 100); - if (ret > 0) - break; - } while (!h->rw_timeout || (av_gettime() - wait_started < h->rw_timeout)); - if (ret <= 0) { - ret = AVERROR(ETIMEDOUT); - goto fail; - } - /* test error */ - optlen = sizeof(ret); - if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) - ret = AVUNERROR(ff_neterrno()); - if (ret != 0) { - char errbuf[100]; - ret = AVERROR(ret); - av_strerror(ret, errbuf, sizeof(errbuf)); - av_log(h, AV_LOG_ERROR, - "TCP connection to %s:%d failed: %s\n", - hostname, port, errbuf); - goto fail; + else + goto fail; } } + h->is_streamed = 1; s->fd = fd; freeaddrinfo(ai); @@ -202,6 +147,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) cur_ai = cur_ai->ai_next; if (fd >= 0) closesocket(fd); + ret = 0; goto restart; } fail1: diff --git a/chromium/third_party/ffmpeg/libavformat/tedcaptionsdec.c b/chromium/third_party/ffmpeg/libavformat/tedcaptionsdec.c index 048ba96981d..68063fafbe0 100644 --- a/chromium/third_party/ffmpeg/libavformat/tedcaptionsdec.c +++ b/chromium/third_party/ffmpeg/libavformat/tedcaptionsdec.c @@ -153,7 +153,8 @@ static int parse_label(AVIOContext *pb, int *cur_byte, AVBPrint *bp) static int parse_boolean(AVIOContext *pb, int *cur_byte, int *result) { - const char *text[] = { "false", "true" }, *p; + static const char * const text[] = { "false", "true" }; + const char *p; int i; skip_spaces(pb, cur_byte); @@ -340,7 +341,7 @@ static av_cold int tedcaptions_read_probe(AVProbeData *p) count++; } return count == FF_ARRAY_ELEMS(tags) ? AVPROBE_SCORE_MAX : - count ? AVPROBE_SCORE_MAX / 2 : 0; + count ? AVPROBE_SCORE_EXTENSION : 0; } static int tedcaptions_read_seek(AVFormatContext *avf, int stream_index, diff --git a/chromium/third_party/ffmpeg/libavformat/tee.c b/chromium/third_party/ffmpeg/libavformat/tee.c index 10787cad294..71f245e4f11 100644 --- a/chromium/third_party/ffmpeg/libavformat/tee.c +++ b/chromium/third_party/ffmpeg/libavformat/tee.c @@ -1,5 +1,5 @@ /* - * Tee pesudo-muxer + * Tee pseudo-muxer * Copyright (c) 2012 Nicolas George * * This file is part of FFmpeg. @@ -27,16 +27,26 @@ #define MAX_SLAVES 16 +typedef struct { + AVFormatContext *avf; + AVBitStreamFilterContext **bsfs; ///< bitstream filters per stream + + /** map from input to output streams indexes, + * disabled output streams are set to -1 */ + int *stream_map; +} TeeSlave; + typedef struct TeeContext { const AVClass *class; unsigned nb_slaves; - AVFormatContext *slaves[MAX_SLAVES]; + TeeSlave slaves[MAX_SLAVES]; } TeeContext; static const char *const slave_delim = "|"; static const char *const slave_opt_open = "["; static const char *const slave_opt_close = "]"; static const char *const slave_opt_delim = ":]"; /* must have the close too */ +static const char *const slave_bsfs_spec_sep = "/"; static const AVClass tee_muxer_class = { .class_name = "Tee muxer", @@ -82,34 +92,103 @@ fail: return ret; } -static int open_slave(AVFormatContext *avf, char *slave, AVFormatContext **ravf) +/** + * Parse list of bitstream filters and add them to the list of filters + * pointed to by bsfs. + * + * The list must be specified in the form: + * BSFS ::= BSF[,BSFS] + */ +static int parse_bsfs(void *log_ctx, const char *bsfs_spec, + AVBitStreamFilterContext **bsfs) +{ + char *bsf_name, *buf, *saveptr; + int ret = 0; + + if (!(buf = av_strdup(bsfs_spec))) + return AVERROR(ENOMEM); + + while (bsf_name = av_strtok(buf, ",", &saveptr)) { + AVBitStreamFilterContext *bsf = av_bitstream_filter_init(bsf_name); + + if (!bsf) { + av_log(log_ctx, AV_LOG_ERROR, + "Cannot initialize bitstream filter with name '%s', " + "unknown filter or internal error happened\n", + bsf_name); + ret = AVERROR_UNKNOWN; + goto end; + } + + /* append bsf context to the list of bsf contexts */ + *bsfs = bsf; + bsfs = &bsf->next; + + buf = NULL; + } + +end: + av_free(buf); + return ret; +} + +static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave) { int i, ret; AVDictionary *options = NULL; AVDictionaryEntry *entry; char *filename; - char *format = NULL; + char *format = NULL, *select = NULL; AVFormatContext *avf2 = NULL; AVStream *st, *st2; + int stream_count; if ((ret = parse_slave_options(avf, slave, &options, &filename)) < 0) return ret; - if ((entry = av_dict_get(options, "f", NULL, 0))) { - format = entry->value; - entry->value = NULL; /* prevent it from being freed */ - av_dict_set(&options, "f", NULL, 0); - } + +#define STEAL_OPTION(option, field) do { \ + if ((entry = av_dict_get(options, option, NULL, 0))) { \ + field = entry->value; \ + entry->value = NULL; /* prevent it from being freed */ \ + av_dict_set(&options, option, NULL, 0); \ + } \ + } while (0) + + STEAL_OPTION("f", format); + STEAL_OPTION("select", select); ret = avformat_alloc_output_context2(&avf2, NULL, format, filename); if (ret < 0) - goto fail; - av_free(format); + goto end; + tee_slave->stream_map = av_calloc(avf->nb_streams, sizeof(*tee_slave->stream_map)); + if (!tee_slave->stream_map) { + ret = AVERROR(ENOMEM); + goto end; + } + + stream_count = 0; for (i = 0; i < avf->nb_streams; i++) { st = avf->streams[i]; + if (select) { + ret = avformat_match_stream_specifier(avf, avf->streams[i], select); + if (ret < 0) { + av_log(avf, AV_LOG_ERROR, + "Invalid stream specifier '%s' for output '%s'\n", + select, slave); + goto end; + } + + if (ret == 0) { /* no match */ + tee_slave->stream_map[i] = -1; + continue; + } + } + tee_slave->stream_map[i] = stream_count++; + if (!(st2 = avformat_new_stream(avf2, NULL))) { ret = AVERROR(ENOMEM); - goto fail; + goto end; } st2->id = st->id; st2->r_frame_rate = st->r_frame_rate; @@ -122,34 +201,84 @@ static int open_slave(AVFormatContext *avf, char *slave, AVFormatContext **ravf) st2->avg_frame_rate = st->avg_frame_rate; av_dict_copy(&st2->metadata, st->metadata, 0); if ((ret = avcodec_copy_context(st2->codec, st->codec)) < 0) - goto fail; + goto end; } if (!(avf2->oformat->flags & AVFMT_NOFILE)) { if ((ret = avio_open(&avf2->pb, filename, AVIO_FLAG_WRITE)) < 0) { av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n", slave, av_err2str(ret)); - goto fail; + goto end; } } if ((ret = avformat_write_header(avf2, &options)) < 0) { av_log(avf, AV_LOG_ERROR, "Slave '%s': error writing header: %s\n", slave, av_err2str(ret)); - goto fail; + goto end; } + + tee_slave->avf = avf2; + tee_slave->bsfs = av_calloc(avf2->nb_streams, sizeof(TeeSlave)); + if (!tee_slave->bsfs) { + ret = AVERROR(ENOMEM); + goto end; + } + + entry = NULL; + while (entry = av_dict_get(options, "bsfs", NULL, AV_DICT_IGNORE_SUFFIX)) { + const char *spec = entry->key + strlen("bsfs"); + if (*spec) { + if (strspn(spec, slave_bsfs_spec_sep) != 1) { + av_log(avf, AV_LOG_ERROR, + "Specifier separator in '%s' is '%c', but only characters '%s' " + "are allowed\n", entry->key, *spec, slave_bsfs_spec_sep); + return AVERROR(EINVAL); + } + spec++; /* consume separator */ + } + + for (i = 0; i < avf2->nb_streams; i++) { + ret = avformat_match_stream_specifier(avf2, avf2->streams[i], spec); + if (ret < 0) { + av_log(avf, AV_LOG_ERROR, + "Invalid stream specifier '%s' in bsfs option '%s' for slave " + "output '%s'\n", spec, entry->key, filename); + goto end; + } + + if (ret > 0) { + av_log(avf, AV_LOG_DEBUG, "spec:%s bsfs:%s matches stream %d of slave " + "output '%s'\n", spec, entry->value, i, filename); + if (tee_slave->bsfs[i]) { + av_log(avf, AV_LOG_WARNING, + "Duplicate bsfs specification associated to stream %d of slave " + "output '%s', filters will be ignored\n", i, filename); + continue; + } + ret = parse_bsfs(avf, entry->value, &tee_slave->bsfs[i]); + if (ret < 0) { + av_log(avf, AV_LOG_ERROR, + "Error parsing bitstream filter sequence '%s' associated to " + "stream %d of slave output '%s'\n", entry->value, i, filename); + goto end; + } + } + } + + av_dict_set(&options, entry->key, NULL, 0); + } + if (options) { entry = NULL; while ((entry = av_dict_get(options, "", entry, AV_DICT_IGNORE_SUFFIX))) av_log(avf2, AV_LOG_ERROR, "Unknown option '%s'\n", entry->key); ret = AVERROR_OPTION_NOT_FOUND; - goto fail; + goto end; } - *ravf = avf2; - return 0; - -fail: +end: + av_free(format); av_dict_free(&options); return ret; } @@ -158,14 +287,49 @@ static void close_slaves(AVFormatContext *avf) { TeeContext *tee = avf->priv_data; AVFormatContext *avf2; - unsigned i; + unsigned i, j; for (i = 0; i < tee->nb_slaves; i++) { - avf2 = tee->slaves[i]; + avf2 = tee->slaves[i].avf; + + for (j = 0; j < avf2->nb_streams; j++) { + AVBitStreamFilterContext *bsf_next, *bsf = tee->slaves[i].bsfs[j]; + while (bsf) { + bsf_next = bsf->next; + av_bitstream_filter_close(bsf); + bsf = bsf_next; + } + } + av_freep(&tee->slaves[i].stream_map); + avio_close(avf2->pb); avf2->pb = NULL; avformat_free_context(avf2); - tee->slaves[i] = NULL; + tee->slaves[i].avf = NULL; + } +} + +static void log_slave(TeeSlave *slave, void *log_ctx, int log_level) +{ + int i; + av_log(log_ctx, log_level, "filename:'%s' format:%s\n", + slave->avf->filename, slave->avf->oformat->name); + for (i = 0; i < slave->avf->nb_streams; i++) { + AVStream *st = slave->avf->streams[i]; + AVBitStreamFilterContext *bsf = slave->bsfs[i]; + + av_log(log_ctx, log_level, " stream:%d codec:%s type:%s", + i, avcodec_get_name(st->codec->codec_id), + av_get_media_type_string(st->codec->codec_type)); + if (bsf) { + av_log(log_ctx, log_level, " bsfs:"); + while (bsf) { + av_log(log_ctx, log_level, "%s%s", + bsf->filter->name, bsf->next ? "," : ""); + bsf = bsf->next; + } + } + av_log(log_ctx, log_level, "\n"); } } @@ -195,10 +359,20 @@ static int tee_write_header(AVFormatContext *avf) for (i = 0; i < nb_slaves; i++) { if ((ret = open_slave(avf, slaves[i], &tee->slaves[i])) < 0) goto fail; + log_slave(&tee->slaves[i], avf, AV_LOG_VERBOSE); av_freep(&slaves[i]); } tee->nb_slaves = nb_slaves; + + for (i = 0; i < avf->nb_streams; i++) { + int j, mapped = 0; + for (j = 0; j < tee->nb_slaves; j++) + mapped += tee->slaves[j].stream_map[i] >= 0; + if (!mapped) + av_log(avf, AV_LOG_WARNING, "Input stream #%d is not mapped " + "to any slave.\n", i); + } return 0; fail: @@ -208,6 +382,46 @@ fail: return ret; } +static int filter_packet(void *log_ctx, AVPacket *pkt, + AVFormatContext *fmt_ctx, AVBitStreamFilterContext *bsf_ctx) +{ + AVCodecContext *enc_ctx = fmt_ctx->streams[pkt->stream_index]->codec; + int ret; + + while (bsf_ctx) { + AVPacket new_pkt = *pkt; + ret = av_bitstream_filter_filter(bsf_ctx, enc_ctx, NULL, + &new_pkt.data, &new_pkt.size, + pkt->data, pkt->size, + pkt->flags & AV_PKT_FLAG_KEY); + if (ret == 0 && new_pkt.data != pkt->data && new_pkt.destruct) { + if ((ret = av_copy_packet(&new_pkt, pkt)) < 0) + break; + ret = 1; + } + + if (ret > 0) { + av_free_packet(pkt); + new_pkt.buf = av_buffer_create(new_pkt.data, new_pkt.size, + av_buffer_default_free, NULL, 0); + if (!new_pkt.buf) + break; + } + *pkt = new_pkt; + + bsf_ctx = bsf_ctx->next; + } + + if (ret < 0) { + av_log(log_ctx, AV_LOG_ERROR, + "Failed to filter bitstream with filter %s for stream %d in file '%s' with codec %s\n", + bsf_ctx->filter->name, pkt->stream_index, fmt_ctx->filename, + avcodec_get_name(enc_ctx->codec_id)); + } + + return ret; +} + static int tee_write_trailer(AVFormatContext *avf) { TeeContext *tee = avf->priv_data; @@ -216,7 +430,7 @@ static int tee_write_trailer(AVFormatContext *avf) unsigned i; for (i = 0; i < tee->nb_slaves; i++) { - avf2 = tee->slaves[i]; + avf2 = tee->slaves[i].avf; if ((ret = av_write_trailer(avf2)) < 0) if (!ret_all) ret_all = ret; @@ -238,27 +452,30 @@ static int tee_write_packet(AVFormatContext *avf, AVPacket *pkt) AVPacket pkt2; int ret_all = 0, ret; unsigned i, s; + int s2; AVRational tb, tb2; for (i = 0; i < tee->nb_slaves; i++) { - avf2 = tee->slaves[i]; + avf2 = tee->slaves[i].avf; s = pkt->stream_index; - if (s >= avf2->nb_streams) { - if (!ret_all) - ret_all = AVERROR(EINVAL); + s2 = tee->slaves[i].stream_map[s]; + if (s2 < 0) continue; - } + if ((ret = av_copy_packet(&pkt2, pkt)) < 0 || (ret = av_dup_packet(&pkt2))< 0) if (!ret_all) { ret = ret_all; continue; } - tb = avf ->streams[s]->time_base; - tb2 = avf2->streams[s]->time_base; + tb = avf ->streams[s ]->time_base; + tb2 = avf2->streams[s2]->time_base; pkt2.pts = av_rescale_q(pkt->pts, tb, tb2); pkt2.dts = av_rescale_q(pkt->dts, tb, tb2); pkt2.duration = av_rescale_q(pkt->duration, tb, tb2); + pkt2.stream_index = s2; + + filter_packet(avf2, &pkt2, avf2, tee->slaves[i].bsfs[s2]); if ((ret = av_interleaved_write_frame(avf2, &pkt2)) < 0) if (!ret_all) ret_all = ret; diff --git a/chromium/third_party/ffmpeg/libavformat/tta.c b/chromium/third_party/ffmpeg/libavformat/tta.c index 445389ed954..bbb6a2292c5 100644 --- a/chromium/third_party/ffmpeg/libavformat/tta.c +++ b/chromium/third_party/ffmpeg/libavformat/tta.c @@ -20,9 +20,12 @@ */ #include "libavcodec/get_bits.h" +#include "apetag.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #include "id3v1.h" +#include "libavutil/crc.h" #include "libavutil/dict.h" typedef struct { @@ -31,12 +34,20 @@ typedef struct { int last_frame_size; } TTAContext; -static int tta_probe(AVProbeData *p) +static unsigned long tta_check_crc(unsigned long checksum, const uint8_t *buf, + unsigned int len) { - const uint8_t *d = p->buf; + return av_crc(av_crc_get_table(AV_CRC_32_IEEE_LE), checksum, buf, len); +} - if (d[0] == 'T' && d[1] == 'T' && d[2] == 'A' && d[3] == '1') - return 80; +static int tta_probe(AVProbeData *p) +{ + if (AV_RL32(&p->buf[0]) == MKTAG('T', 'T', 'A', '1') && + (AV_RL16(&p->buf[4]) == 1 || AV_RL16(&p->buf[4]) == 2) && + AV_RL16(&p->buf[6]) > 0 && + AV_RL16(&p->buf[8]) > 0 && + AV_RL32(&p->buf[10]) > 0) + return AVPROBE_SCORE_EXTENSION + 30; return 0; } @@ -46,14 +57,14 @@ static int tta_read_header(AVFormatContext *s) AVStream *st; int i, channels, bps, samplerate; uint64_t framepos, start_offset; - uint32_t datalen; + uint32_t nb_samples, crc; - if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) - ff_id3v1_read(s); + ff_id3v1_read(s); start_offset = avio_tell(s->pb); + ffio_init_checksum(s->pb, tta_check_crc, UINT32_MAX); if (avio_rl32(s->pb) != AV_RL32("TTA1")) - return -1; // not tta file + return AVERROR_INVALIDDATA; avio_skip(s->pb, 2); // FIXME: flags channels = avio_rl16(s->pb); @@ -61,27 +72,31 @@ static int tta_read_header(AVFormatContext *s) samplerate = avio_rl32(s->pb); if(samplerate <= 0 || samplerate > 1000000){ av_log(s, AV_LOG_ERROR, "nonsense samplerate\n"); - return -1; + return AVERROR_INVALIDDATA; } - datalen = avio_rl32(s->pb); - if (!datalen) { - av_log(s, AV_LOG_ERROR, "invalid datalen\n"); + nb_samples = avio_rl32(s->pb); + if (!nb_samples) { + av_log(s, AV_LOG_ERROR, "invalid number of samples\n"); return AVERROR_INVALIDDATA; } - avio_skip(s->pb, 4); // header crc + crc = ffio_get_checksum(s->pb) ^ UINT32_MAX; + if (crc != avio_rl32(s->pb)) { + av_log(s, AV_LOG_ERROR, "Header CRC error\n"); + return AVERROR_INVALIDDATA; + } c->frame_size = samplerate * 256 / 245; - c->last_frame_size = datalen % c->frame_size; + c->last_frame_size = nb_samples % c->frame_size; if (!c->last_frame_size) c->last_frame_size = c->frame_size; - c->totalframes = datalen / c->frame_size + (c->last_frame_size < c->frame_size); + c->totalframes = nb_samples / c->frame_size + (c->last_frame_size < c->frame_size); c->currentframe = 0; if(c->totalframes >= UINT_MAX/sizeof(uint32_t) || c->totalframes <= 0){ av_log(s, AV_LOG_ERROR, "totalframes %d invalid\n", c->totalframes); - return -1; + return AVERROR_INVALIDDATA; } st = avformat_new_stream(s, NULL); @@ -90,17 +105,32 @@ static int tta_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, samplerate); st->start_time = 0; - st->duration = datalen; + st->duration = nb_samples; framepos = avio_tell(s->pb) + 4*c->totalframes + 4; + st->codec->extradata_size = avio_tell(s->pb) - start_offset; + st->codec->extradata = av_mallocz(st->codec->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE); + if (!st->codec->extradata) { + st->codec->extradata_size = 0; + return AVERROR(ENOMEM); + } + + avio_seek(s->pb, start_offset, SEEK_SET); + avio_read(s->pb, st->codec->extradata, st->codec->extradata_size); + + ffio_init_checksum(s->pb, tta_check_crc, UINT32_MAX); for (i = 0; i < c->totalframes; i++) { uint32_t size = avio_rl32(s->pb); av_add_index_entry(st, framepos, i * c->frame_size, size, 0, AVINDEX_KEYFRAME); framepos += size; } - avio_skip(s->pb, 4); // seektable crc + crc = ffio_get_checksum(s->pb) ^ UINT32_MAX; + if (crc != avio_rl32(s->pb)) { + av_log(s, AV_LOG_ERROR, "Seek table CRC error\n"); + return AVERROR_INVALIDDATA; + } st->codec->codec_type = AVMEDIA_TYPE_AUDIO; st->codec->codec_id = AV_CODEC_ID_TTA; @@ -108,19 +138,11 @@ static int tta_read_header(AVFormatContext *s) st->codec->sample_rate = samplerate; st->codec->bits_per_coded_sample = bps; - st->codec->extradata_size = avio_tell(s->pb) - start_offset; - if(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE <= (unsigned)st->codec->extradata_size){ - //this check is redundant as avio_read should fail - av_log(s, AV_LOG_ERROR, "extradata_size too large\n"); - return -1; + if (s->pb->seekable) { + int64_t pos = avio_tell(s->pb); + ff_ape_parse_tag(s); + avio_seek(s->pb, pos, SEEK_SET); } - st->codec->extradata = av_mallocz(st->codec->extradata_size+FF_INPUT_BUFFER_PADDING_SIZE); - if (!st->codec->extradata) { - st->codec->extradata_size = 0; - return AVERROR(ENOMEM); - } - avio_seek(s->pb, start_offset, SEEK_SET); - avio_read(s->pb, st->codec->extradata, st->codec->extradata_size); return 0; } diff --git a/chromium/third_party/ffmpeg/libavformat/udp.c b/chromium/third_party/ffmpeg/libavformat/udp.c index e8a01dbd286..3c0d6bf0123 100644 --- a/chromium/third_party/ffmpeg/libavformat/udp.c +++ b/chromium/third_party/ffmpeg/libavformat/udp.c @@ -237,7 +237,7 @@ static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr, int level = addr->sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; struct addrinfo *sourceaddr = udp_resolve_host(sources[i], 0, SOCK_DGRAM, AF_UNSPEC, - AI_NUMERICHOST); + 0); if (!sourceaddr) return AVERROR(ENOENT); @@ -267,7 +267,7 @@ static int udp_set_multicast_sources(int sockfd, struct sockaddr *addr, struct ip_mreq_source mreqs; struct addrinfo *sourceaddr = udp_resolve_host(sources[i], 0, SOCK_DGRAM, AF_UNSPEC, - AI_NUMERICHOST); + 0); if (!sourceaddr) return AVERROR(ENOENT); if (sourceaddr->ai_addr->sa_family != AF_INET) { @@ -326,7 +326,7 @@ static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, if (res0 == 0) goto fail; for (res = res0; res; res=res->ai_next) { - udp_fd = socket(res->ai_family, SOCK_DGRAM, 0); + udp_fd = ff_socket(res->ai_family, SOCK_DGRAM, 0); if (udp_fd != -1) break; log_net_error(NULL, AV_LOG_ERROR, "socket"); } @@ -494,6 +494,27 @@ end: } #endif +static int parse_source_list(char *buf, char **sources, int *num_sources, + int max_sources) +{ + char *source_start; + + source_start = buf; + while (1) { + char *next = strchr(source_start, ','); + if (next) + *next = '\0'; + sources[*num_sources] = av_strdup(source_start); + if (!sources[*num_sources]) + return AVERROR(ENOMEM); + source_start = next + 1; + (*num_sources)++; + if (*num_sources >= max_sources || !next) + break; + } + return 0; +} + /* put it in UDP context */ /* return non zero if error */ static int udp_open(URLContext *h, const char *uri, int flags) @@ -507,8 +528,8 @@ static int udp_open(URLContext *h, const char *uri, int flags) struct sockaddr_storage my_addr; socklen_t len; int reuse_specified = 0; - int i, include = 0, num_sources = 0; - char *sources[32]; + int i, num_include_sources = 0, num_exclude_sources = 0; + char *include_sources[32], *exclude_sources[32]; h->is_streamed = 1; @@ -562,31 +583,26 @@ static int udp_open(URLContext *h, const char *uri, int flags) if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { av_strlcpy(localaddr, buf, sizeof(localaddr)); } - if (av_find_info_tag(buf, sizeof(buf), "sources", p)) - include = 1; - if (include || av_find_info_tag(buf, sizeof(buf), "block", p)) { - char *source_start; - - source_start = buf; - while (1) { - char *next = strchr(source_start, ','); - if (next) - *next = '\0'; - sources[num_sources] = av_strdup(source_start); - if (!sources[num_sources]) - goto fail; - source_start = next + 1; - num_sources++; - if (num_sources >= FF_ARRAY_ELEMS(sources) || !next) - break; - } + if (av_find_info_tag(buf, sizeof(buf), "sources", p)) { + if (parse_source_list(buf, include_sources, &num_include_sources, + FF_ARRAY_ELEMS(include_sources))) + goto fail; + } + if (av_find_info_tag(buf, sizeof(buf), "block", p)) { + if (parse_source_list(buf, exclude_sources, &num_exclude_sources, + FF_ARRAY_ELEMS(exclude_sources))) + goto fail; } if (!is_output && av_find_info_tag(buf, sizeof(buf), "timeout", p)) s->timeout = strtol(buf, NULL, 10); } /* handling needed to support options picking from both AVOption and URL */ s->circular_buffer_size *= 188; - h->max_packet_size = s->packet_size; + if (flags & AVIO_FLAG_WRITE) { + h->max_packet_size = s->packet_size; + } else { + h->max_packet_size = UDP_MAX_PKT_SIZE; + } h->rw_timeout = s->timeout; /* fill the dest addr */ @@ -644,20 +660,20 @@ static int udp_open(URLContext *h, const char *uri, int flags) } if (h->flags & AVIO_FLAG_READ) { /* input */ - if (num_sources == 0 || !include) { + if (num_include_sources && num_exclude_sources) { + av_log(h, AV_LOG_ERROR, "Simultaneously including and excluding multicast sources is not supported\n"); + goto fail; + } + if (num_include_sources) { + if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, include_sources, num_include_sources, 1) < 0) + goto fail; + } else { if (udp_join_multicast_group(udp_fd, (struct sockaddr *)&s->dest_addr) < 0) goto fail; - - if (num_sources) { - if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, sources, num_sources, 0) < 0) - goto fail; - } - } else if (include && num_sources) { - if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, sources, num_sources, 1) < 0) + } + if (num_exclude_sources) { + if (udp_set_multicast_sources(udp_fd, (struct sockaddr *)&s->dest_addr, s->dest_addr_len, exclude_sources, num_exclude_sources, 0) < 0) goto fail; - } else { - av_log(NULL, AV_LOG_ERROR, "invalid udp settings: inclusive multicast but no sources given\n"); - goto fail; } } } @@ -686,8 +702,10 @@ static int udp_open(URLContext *h, const char *uri, int flags) } } - for (i = 0; i < num_sources; i++) - av_freep(&sources[i]); + for (i = 0; i < num_include_sources; i++) + av_freep(&include_sources[i]); + for (i = 0; i < num_exclude_sources; i++) + av_freep(&exclude_sources[i]); s->udp_fd = udp_fd; @@ -727,8 +745,10 @@ static int udp_open(URLContext *h, const char *uri, int flags) if (udp_fd >= 0) closesocket(udp_fd); av_fifo_free(s->fifo); - for (i = 0; i < num_sources; i++) - av_freep(&sources[i]); + for (i = 0; i < num_include_sources; i++) + av_freep(&include_sources[i]); + for (i = 0; i < num_exclude_sources; i++) + av_freep(&exclude_sources[i]); return AVERROR(EIO); } diff --git a/chromium/third_party/ffmpeg/libavformat/unix.c b/chromium/third_party/ffmpeg/libavformat/unix.c new file mode 100644 index 00000000000..0e61318fbd8 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/unix.c @@ -0,0 +1,155 @@ +/* + * Unix socket protocol + * Copyright (c) 2013 Luca Barbato + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * + * Unix socket url_protocol + * + */ + +#include "libavutil/avstring.h" +#include "libavutil/opt.h" +#include "os_support.h" +#include "network.h" +#include <sys/un.h> +#include "url.h" + +typedef struct UnixContext { + const AVClass *class; + struct sockaddr_un addr; + int timeout; + int listen; + int type; + int fd; +} UnixContext; + +#define OFFSET(x) offsetof(UnixContext, x) +#define ED AV_OPT_FLAG_DECODING_PARAM|AV_OPT_FLAG_ENCODING_PARAM +static const AVOption unix_options[] = { + { "listen", "Open socket for listening", OFFSET(listen), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ED }, + { "timeout", "Timeout in ms", OFFSET(timeout), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, ED }, + { "type", "Socket type", OFFSET(type), AV_OPT_TYPE_INT, { .i64 = SOCK_STREAM }, INT_MIN, INT_MAX, ED, "type" }, + { "stream", "Stream (reliable stream-oriented)", 0, AV_OPT_TYPE_CONST, { .i64 = SOCK_STREAM }, INT_MIN, INT_MAX, ED, "type" }, + { "datagram", "Datagram (unreliable packet-oriented)", 0, AV_OPT_TYPE_CONST, { .i64 = SOCK_DGRAM }, INT_MIN, INT_MAX, ED, "type" }, + { "seqpacket", "Seqpacket (reliable packet-oriented", 0, AV_OPT_TYPE_CONST, { .i64 = SOCK_SEQPACKET }, INT_MIN, INT_MAX, ED, "type" }, + { NULL } +}; + +static const AVClass unix_class = { + .class_name = "unix", + .item_name = av_default_item_name, + .option = unix_options, + .version = LIBAVUTIL_VERSION_INT, +}; + +static int unix_open(URLContext *h, const char *filename, int flags) +{ + UnixContext *s = h->priv_data; + int fd, ret; + + av_strstart(filename, "unix:", &filename); + s->addr.sun_family = AF_UNIX; + av_strlcpy(s->addr.sun_path, filename, sizeof(s->addr.sun_path)); + + if ((fd = ff_socket(AF_UNIX, s->type, 0)) < 0) + return ff_neterrno(); + + if (s->listen) { + fd = ff_listen_bind(fd, (struct sockaddr *)&s->addr, + sizeof(s->addr), s->timeout, h); + if (fd < 0) { + ret = fd; + goto fail; + } + } else { + ret = ff_listen_connect(fd, (struct sockaddr *)&s->addr, + sizeof(s->addr), s->timeout, h, 0); + if (ret < 0) + goto fail; + } + + s->fd = fd; + + return 0; + +fail: + if (s->listen && AVUNERROR(ret) != EADDRINUSE) + unlink(s->addr.sun_path); + if (fd >= 0) + closesocket(fd); + return ret; +} + +static int unix_read(URLContext *h, uint8_t *buf, int size) +{ + UnixContext *s = h->priv_data; + int ret; + + if (!(h->flags & AVIO_FLAG_NONBLOCK)) { + ret = ff_network_wait_fd(s->fd, 0); + if (ret < 0) + return ret; + } + ret = recv(s->fd, buf, size, 0); + return ret < 0 ? ff_neterrno() : ret; +} + +static int unix_write(URLContext *h, const uint8_t *buf, int size) +{ + UnixContext *s = h->priv_data; + int ret; + + if (!(h->flags & AVIO_FLAG_NONBLOCK)) { + ret = ff_network_wait_fd(s->fd, 1); + if (ret < 0) + return ret; + } + ret = send(s->fd, buf, size, 0); + return ret < 0 ? ff_neterrno() : ret; +} + +static int unix_close(URLContext *h) +{ + UnixContext *s = h->priv_data; + if (s->listen) + unlink(s->addr.sun_path); + closesocket(s->fd); + return 0; +} + +static int unix_get_file_handle(URLContext *h) +{ + UnixContext *s = h->priv_data; + return s->fd; +} + +URLProtocol ff_unix_protocol = { + .name = "unix", + .url_open = unix_open, + .url_read = unix_read, + .url_write = unix_write, + .url_close = unix_close, + .url_get_file_handle = unix_get_file_handle, + .priv_data_size = sizeof(UnixContext), + .priv_data_class = &unix_class, + .flags = URL_PROTOCOL_FLAG_NETWORK, +}; diff --git a/chromium/third_party/ffmpeg/libavformat/url-test.c b/chromium/third_party/ffmpeg/libavformat/url-test.c index ee5f06e9ee1..a1da82e4936 100644 --- a/chromium/third_party/ffmpeg/libavformat/url-test.c +++ b/chromium/third_party/ffmpeg/libavformat/url-test.c @@ -18,7 +18,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "internal.h" +#include "url.h" static void test(const char *base, const char *rel) { diff --git a/chromium/third_party/ffmpeg/libavformat/url.c b/chromium/third_party/ffmpeg/libavformat/url.c new file mode 100644 index 00000000000..47e15843cf4 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/url.c @@ -0,0 +1,147 @@ +/* + * URL utility functions + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "avformat.h" +#include "config.h" +#include "url.h" +#if CONFIG_NETWORK +#include "network.h" +#endif +#include "libavutil/avstring.h" + +/** + * @file + * URL utility functions. + */ + +int ff_url_join(char *str, int size, const char *proto, + const char *authorization, const char *hostname, + int port, const char *fmt, ...) +{ +#if CONFIG_NETWORK + struct addrinfo hints = { 0 }, *ai; +#endif + + str[0] = '\0'; + if (proto) + av_strlcatf(str, size, "%s://", proto); + if (authorization && authorization[0]) + av_strlcatf(str, size, "%s@", authorization); +#if CONFIG_NETWORK && defined(AF_INET6) + /* Determine if hostname is a numerical IPv6 address, + * properly escape it within [] in that case. */ + hints.ai_flags = AI_NUMERICHOST; + if (!getaddrinfo(hostname, NULL, &hints, &ai)) { + if (ai->ai_family == AF_INET6) { + av_strlcat(str, "[", size); + av_strlcat(str, hostname, size); + av_strlcat(str, "]", size); + } else { + av_strlcat(str, hostname, size); + } + freeaddrinfo(ai); + } else +#endif + /* Not an IPv6 address, just output the plain string. */ + av_strlcat(str, hostname, size); + + if (port >= 0) + av_strlcatf(str, size, ":%d", port); + if (fmt) { + va_list vl; + int len = strlen(str); + + va_start(vl, fmt); + vsnprintf(str + len, size > len ? size - len : 0, fmt, vl); + va_end(vl); + } + return strlen(str); +} + +void ff_make_absolute_url(char *buf, int size, const char *base, + const char *rel) +{ + char *sep, *path_query; + /* Absolute path, relative to the current server */ + if (base && strstr(base, "://") && rel[0] == '/') { + if (base != buf) + av_strlcpy(buf, base, size); + sep = strstr(buf, "://"); + if (sep) { + /* Take scheme from base url */ + if (rel[1] == '/') { + sep[1] = '\0'; + } else { + /* Take scheme and host from base url */ + sep += 3; + sep = strchr(sep, '/'); + if (sep) + *sep = '\0'; + } + } + av_strlcat(buf, rel, size); + return; + } + /* If rel actually is an absolute url, just copy it */ + if (!base || strstr(rel, "://") || rel[0] == '/') { + av_strlcpy(buf, rel, size); + return; + } + if (base != buf) + av_strlcpy(buf, base, size); + + /* Strip off any query string from base */ + path_query = strchr(buf, '?'); + if (path_query != NULL) + *path_query = '\0'; + + /* Is relative path just a new query part? */ + if (rel[0] == '?') { + av_strlcat(buf, rel, size); + return; + } + + /* Remove the file name from the base url */ + sep = strrchr(buf, '/'); + if (sep) + sep[1] = '\0'; + else + buf[0] = '\0'; + while (av_strstart(rel, "../", NULL) && sep) { + /* Remove the path delimiter at the end */ + sep[0] = '\0'; + sep = strrchr(buf, '/'); + /* If the next directory name to pop off is "..", break here */ + if (!strcmp(sep ? &sep[1] : buf, "..")) { + /* Readd the slash we just removed */ + av_strlcat(buf, "/", size); + break; + } + /* Cut off the directory name */ + if (sep) + sep[1] = '\0'; + else + buf[0] = '\0'; + rel += 3; + } + av_strlcat(buf, rel, size); +} diff --git a/chromium/third_party/ffmpeg/libavformat/url.h b/chromium/third_party/ffmpeg/libavformat/url.h index 5f75dc91e17..06dfda111da 100644 --- a/chromium/third_party/ffmpeg/libavformat/url.h +++ b/chromium/third_party/ffmpeg/libavformat/url.h @@ -248,4 +248,41 @@ URLProtocol *ffurl_protocol_next(URLProtocol *prev); int ff_udp_set_remote_url(URLContext *h, const char *uri); int ff_udp_get_local_port(URLContext *h); +/** + * Assemble a URL string from components. This is the reverse operation + * of av_url_split. + * + * Note, this requires networking to be initialized, so the caller must + * ensure ff_network_init has been called. + * + * @see av_url_split + * + * @param str the buffer to fill with the url + * @param size the size of the str buffer + * @param proto the protocol identifier, if null, the separator + * after the identifier is left out, too + * @param authorization an optional authorization string, may be null. + * An empty string is treated the same as a null string. + * @param hostname the host name string + * @param port the port number, left out from the string if negative + * @param fmt a generic format string for everything to add after the + * host/port, may be null + * @return the number of characters written to the destination buffer + */ +int ff_url_join(char *str, int size, const char *proto, + const char *authorization, const char *hostname, + int port, const char *fmt, ...) av_printf_format(7, 8); + +/** + * Convert a relative url into an absolute url, given a base url. + * + * @param buf the buffer where output absolute url is written + * @param size the size of buf + * @param base the base url, may be equal to buf. + * @param rel the new url, which is interpreted relative to base + */ +void ff_make_absolute_url(char *buf, int size, const char *base, + const char *rel); + + #endif /* AVFORMAT_URL_H */ diff --git a/chromium/third_party/ffmpeg/libavformat/utils.c b/chromium/third_party/ffmpeg/libavformat/utils.c index 04b61f78cae..dca4304963d 100644 --- a/chromium/third_party/ffmpeg/libavformat/utils.c +++ b/chromium/third_party/ffmpeg/libavformat/utils.c @@ -19,8 +19,6 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -/* #define DEBUG */ - #include "avformat.h" #include "avio_internal.h" #include "internal.h" @@ -30,6 +28,7 @@ #include "libavutil/avassert.h" #include "libavutil/opt.h" #include "libavutil/dict.h" +#include "libavutil/internal.h" #include "libavutil/pixdesc.h" #include "metadata.h" #include "id3v2.h" @@ -99,162 +98,8 @@ static int64_t wrap_timestamp(AVStream *st, int64_t timestamp) return timestamp; } -#define MAKE_ACCESSORS(str, name, type, field) \ - type av_##name##_get_##field(const str *s) { return s->field; } \ - void av_##name##_set_##field(str *s, type v) { s->field = v; } - MAKE_ACCESSORS(AVStream, stream, AVRational, r_frame_rate) -/** head of registered input format linked list */ -static AVInputFormat *first_iformat = NULL; -/** head of registered output format linked list */ -static AVOutputFormat *first_oformat = NULL; - -AVInputFormat *av_iformat_next(AVInputFormat *f) -{ - if(f) return f->next; - else return first_iformat; -} - -AVOutputFormat *av_oformat_next(AVOutputFormat *f) -{ - if(f) return f->next; - else return first_oformat; -} - -void av_register_input_format(AVInputFormat *format) -{ - AVInputFormat **p; - p = &first_iformat; - while (*p != NULL) p = &(*p)->next; - *p = format; - format->next = NULL; -} - -void av_register_output_format(AVOutputFormat *format) -{ - AVOutputFormat **p; - p = &first_oformat; - while (*p != NULL) p = &(*p)->next; - *p = format; - format->next = NULL; -} - -int av_match_ext(const char *filename, const char *extensions) -{ - const char *ext, *p; - char ext1[32], *q; - - if(!filename) - return 0; - - ext = strrchr(filename, '.'); - if (ext) { - ext++; - p = extensions; - for(;;) { - q = ext1; - while (*p != '\0' && *p != ',' && q-ext1<sizeof(ext1)-1) - *q++ = *p++; - *q = '\0'; - if (!av_strcasecmp(ext1, ext)) - return 1; - if (*p == '\0') - break; - p++; - } - } - return 0; -} - -static int match_format(const char *name, const char *names) -{ - const char *p; - int len, namelen; - - if (!name || !names) - return 0; - - namelen = strlen(name); - while ((p = strchr(names, ','))) { - len = FFMAX(p - names, namelen); - if (!av_strncasecmp(name, names, len)) - return 1; - names = p+1; - } - return !av_strcasecmp(name, names); -} - -AVOutputFormat *av_guess_format(const char *short_name, const char *filename, - const char *mime_type) -{ - AVOutputFormat *fmt = NULL, *fmt_found; - int score_max, score; - - /* specific test for image sequences */ -#if CONFIG_IMAGE2_MUXER - if (!short_name && filename && - av_filename_number_test(filename) && - ff_guess_image2_codec(filename) != AV_CODEC_ID_NONE) { - return av_guess_format("image2", NULL, NULL); - } -#endif - /* Find the proper file type. */ - fmt_found = NULL; - score_max = 0; - while ((fmt = av_oformat_next(fmt))) { - score = 0; - if (fmt->name && short_name && match_format(short_name, fmt->name)) - score += 100; - if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type)) - score += 10; - if (filename && fmt->extensions && - av_match_ext(filename, fmt->extensions)) { - score += 5; - } - if (score > score_max) { - score_max = score; - fmt_found = fmt; - } - } - return fmt_found; -} - -enum AVCodecID av_guess_codec(AVOutputFormat *fmt, const char *short_name, - const char *filename, const char *mime_type, enum AVMediaType type){ - if (!strcmp(fmt->name, "segment") || !strcmp(fmt->name, "ssegment")) { - fmt = av_guess_format(NULL, filename, NULL); - } - - if(type == AVMEDIA_TYPE_VIDEO){ - enum AVCodecID codec_id= AV_CODEC_ID_NONE; - -#if CONFIG_IMAGE2_MUXER - if(!strcmp(fmt->name, "image2") || !strcmp(fmt->name, "image2pipe")){ - codec_id= ff_guess_image2_codec(filename); - } -#endif - if(codec_id == AV_CODEC_ID_NONE) - codec_id= fmt->video_codec; - return codec_id; - }else if(type == AVMEDIA_TYPE_AUDIO) - return fmt->audio_codec; - else if (type == AVMEDIA_TYPE_SUBTITLE) - return fmt->subtitle_codec; - else - return AV_CODEC_ID_NONE; -} - -AVInputFormat *av_find_input_format(const char *short_name) -{ - AVInputFormat *fmt = NULL; - while ((fmt = av_iformat_next(fmt))) { - if (match_format(short_name, fmt->name)) - return fmt; - } - return NULL; -} - /* an arbitrarily chosen "sane" max packet size -- 50M */ #define SANE_CHUNK_SIZE (50000000) @@ -376,10 +221,10 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score if (fmt1->read_probe) { score = fmt1->read_probe(&lpd); if(fmt1->extensions && av_match_ext(lpd.filename, fmt1->extensions)) - score = FFMAX(score, nodat ? AVPROBE_SCORE_MAX/4-1 : 1); + score = FFMAX(score, nodat ? AVPROBE_SCORE_EXTENSION / 2 - 1 : 1); } else if (fmt1->extensions) { if (av_match_ext(lpd.filename, fmt1->extensions)) { - score = 50; + score = AVPROBE_SCORE_EXTENSION; } } if (score > score_max) { @@ -389,7 +234,7 @@ AVInputFormat *av_probe_input_format3(AVProbeData *pd, int is_opened, int *score fmt = NULL; } if(nodat) - score_max = FFMIN(AVPROBE_SCORE_MAX/4-1, score_max); + score_max = FFMIN(AVPROBE_SCORE_EXTENSION / 2 - 1, score_max); *score_ret= score_max; return fmt; @@ -671,7 +516,8 @@ int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputForma goto fail; if (id3v2_extra_meta) { - if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac")) { + if (!strcmp(s->iformat->name, "mp3") || !strcmp(s->iformat->name, "aac") || + !strcmp(s->iformat->name, "tta")) { if((ret = ff_id3v2_parse_apic(s, &id3v2_extra_meta)) < 0) goto fail; } else @@ -876,7 +722,7 @@ int ff_get_audio_frame_size(AVCodecContext *enc, int size, int mux) if ((frame_size = av_get_audio_frame_duration(enc, size)) > 0) return frame_size; - /* fallback to using frame_size if muxing */ + /* Fall back on using frame_size if muxing. */ if (enc->frame_size > 1) return enc->frame_size; @@ -956,7 +802,7 @@ static int is_intra_only(AVCodecContext *enc){ static int has_decode_delay_been_guessed(AVStream *st) { if(st->codec->codec_id != AV_CODEC_ID_H264) return 1; - if(!st->info) // if we have left find_stream_info then nb_decoded_frames wont increase anymore for stream copy + if(!st->info) // if we have left find_stream_info then nb_decoded_frames won't increase anymore for stream copy return 1; #if CONFIG_H264_DECODER if(st->codec->has_b_frames && @@ -1168,7 +1014,9 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, pc && pc->pict_type != AV_PICTURE_TYPE_B) presentation_delayed = 1; - if(pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && st->pts_wrap_bits<63 && pkt->dts - (1LL<<(st->pts_wrap_bits-1)) > pkt->pts){ + if (pkt->pts != AV_NOPTS_VALUE && pkt->dts != AV_NOPTS_VALUE && + st->pts_wrap_bits < 63 && + pkt->dts - (1LL << (st->pts_wrap_bits - 1)) > pkt->pts) { if(is_relative(st->cur_dts) || pkt->dts - (1LL<<(st->pts_wrap_bits-1)) > st->cur_dts) { pkt->dts -= 1LL<<st->pts_wrap_bits; } else @@ -1344,6 +1192,13 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) if (!out_pkt.size) continue; + if (pkt->side_data) { + out_pkt.side_data = pkt->side_data; + out_pkt.side_data_elems = pkt->side_data_elems; + pkt->side_data = NULL; + pkt->side_data_elems = 0; + } + /* set the duration */ out_pkt.duration = 0; if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -1383,8 +1238,10 @@ static int parse_packet(AVFormatContext *s, AVPacket *pkt, int stream_index) out_pkt.buf = pkt->buf; pkt->buf = NULL; #if FF_API_DESTRUCT_PACKET +FF_DISABLE_DEPRECATION_WARNINGS out_pkt.destruct = pkt->destruct; pkt->destruct = NULL; +FF_ENABLE_DEPRECATION_WARNINGS #endif } if ((ret = av_dup_packet(&out_pkt)) < 0) @@ -1889,14 +1746,50 @@ int ff_seek_frame_binary(AVFormatContext *s, int stream_index, int64_t target_ts return 0; } +int ff_find_last_ts(AVFormatContext *s, int stream_index, int64_t *ts, int64_t *pos, + int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )) +{ + int64_t step= 1024; + int64_t limit, ts_max; + int64_t filesize = avio_size(s->pb); + int64_t pos_max = filesize - 1; + do{ + limit = pos_max; + pos_max = FFMAX(0, (pos_max) - step); + ts_max = ff_read_timestamp(s, stream_index, &pos_max, limit, read_timestamp); + step += step; + }while(ts_max == AV_NOPTS_VALUE && 2*limit > step); + if (ts_max == AV_NOPTS_VALUE) + return -1; + + for(;;){ + int64_t tmp_pos = pos_max + 1; + int64_t tmp_ts = ff_read_timestamp(s, stream_index, &tmp_pos, INT64_MAX, read_timestamp); + if(tmp_ts == AV_NOPTS_VALUE) + break; + ts_max = tmp_ts; + pos_max = tmp_pos; + if(tmp_pos >= filesize) + break; + } + + if (ts) + *ts = ts_max; + if (pos) + *pos = pos_max; + + return 0; +} + int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, int64_t pos_min, int64_t pos_max, int64_t pos_limit, int64_t ts_min, int64_t ts_max, int flags, int64_t *ts_ret, int64_t (*read_timestamp)(struct AVFormatContext *, int , int64_t *, int64_t )) { int64_t pos, ts; - int64_t start_pos, filesize; + int64_t start_pos; int no_change; + int ret; av_dlog(s, "gen_seek: %d %s\n", stream_index, av_ts2str(target_ts)); @@ -1913,27 +1806,8 @@ int64_t ff_gen_search(AVFormatContext *s, int stream_index, int64_t target_ts, } if(ts_max == AV_NOPTS_VALUE){ - int step= 1024; - filesize = avio_size(s->pb); - pos_max = filesize - 1; - do{ - pos_max = FFMAX(0, pos_max - step); - ts_max = ff_read_timestamp(s, stream_index, &pos_max, pos_max + step, read_timestamp); - step += step; - }while(ts_max == AV_NOPTS_VALUE && pos_max > 0); - if (ts_max == AV_NOPTS_VALUE) - return -1; - - for(;;){ - int64_t tmp_pos= pos_max + 1; - int64_t tmp_ts= ff_read_timestamp(s, stream_index, &tmp_pos, INT64_MAX, read_timestamp); - if(tmp_ts == AV_NOPTS_VALUE) - break; - ts_max= tmp_ts; - pos_max= tmp_pos; - if(tmp_pos >= filesize) - break; - } + if ((ret = ff_find_last_ts(s, stream_index, &ts_max, &pos_max, read_timestamp)) < 0) + return ret; pos_limit= pos_max; } @@ -2138,7 +2012,19 @@ static int seek_frame_internal(AVFormatContext *s, int stream_index, int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int flags) { - int ret = seek_frame_internal(s, stream_index, timestamp, flags); + int ret; + + if (s->iformat->read_seek2 && !s->iformat->read_seek) { + int64_t min_ts = INT64_MIN, max_ts = INT64_MAX; + if ((flags & AVSEEK_FLAG_BACKWARD)) + max_ts = timestamp; + else + min_ts = timestamp; + return avformat_seek_file(s, stream_index, min_ts, timestamp, max_ts, + flags & ~AVSEEK_FLAG_BACKWARD); + } + + ret = seek_frame_internal(s, stream_index, timestamp, flags); if (ret >= 0) ret = avformat_queue_attached_pictures(s); @@ -2155,6 +2041,7 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int if(s->seek2any>0) flags |= AVSEEK_FLAG_ANY; + flags &= ~AVSEEK_FLAG_BACKWARD; if (s->iformat->read_seek2) { int ret; @@ -2182,8 +2069,8 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int //try to seek via read_timestamp() } - //Fallback to old API if new is not implemented but old is - //Note the old has somewhat different semantics + // Fall back on old API if new is not implemented but old is. + // Note the old API has somewhat different semantics. if (s->iformat->read_seek || 1) { int dir = (ts - (uint64_t)min_ts > (uint64_t)max_ts - ts ? AVSEEK_FLAG_BACKWARD : 0); int ret = av_seek_frame(s, stream_index, ts, flags | dir); @@ -2750,7 +2637,7 @@ int av_find_stream_info(AVFormatContext *ic) int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) { - int i, count, ret, j; + int i, count, ret = 0, j; int64_t read_size; AVStream *st; AVPacket pkt1, *pkt; @@ -2892,11 +2779,15 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) break; } - if (ic->flags & AVFMT_FLAG_NOBUFFER) { - pkt = &pkt1; - } else { + if (ic->flags & AVFMT_FLAG_NOBUFFER) + free_packet_buffer(&ic->packet_buffer, &ic->packet_buffer_end); + { pkt = add_to_pktbuf(&ic->packet_buffer, &pkt1, &ic->packet_buffer_end); + if (!pkt) { + ret = AVERROR(ENOMEM); + goto find_stream_info_err; + } if ((ret = av_dup_packet(pkt)) < 0) goto find_stream_info_err; } @@ -2943,8 +2834,14 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (st->avg_frame_rate.num > 0) t = FFMAX(t, av_rescale_q(st->codec_info_nb_frames, av_inv_q(st->avg_frame_rate), AV_TIME_BASE_Q)); + if ( t==0 + && st->codec_info_nb_frames>30 + && st->info->fps_first_dts != AV_NOPTS_VALUE + && st->info->fps_last_dts != AV_NOPTS_VALUE) + t = FFMAX(t, av_rescale_q(st->info->fps_last_dts - st->info->fps_first_dts, st->time_base, AV_TIME_BASE_Q)); + if (t >= ic->max_analyze_duration) { - av_log(ic, AV_LOG_WARNING, "max_analyze_duration %d reached at %"PRId64" microseconds\n", ic->max_analyze_duration, t); + av_log(ic, AV_LOG_VERBOSE, "max_analyze_duration %d reached at %"PRId64" microseconds\n", ic->max_analyze_duration, t); break; } if (pkt->duration) { @@ -2963,6 +2860,8 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if (!st->info->duration_error) st->info->duration_error = av_mallocz(sizeof(st->info->duration_error[0])*2); + if (!st->info->duration_error) + return AVERROR(ENOMEM); // if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO) // av_log(NULL, AV_LOG_ERROR, "%f\n", dts); @@ -3017,9 +2916,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) int err = 0; av_init_packet(&empty_pkt); - ret = -1; /* we could not have all the codec parameters before EOF */ for(i=0;i<ic->nb_streams;i++) { - const char *errmsg; st = ic->streams[i]; @@ -3036,17 +2933,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) "decoding for stream %d failed\n", st->index); } } - - if (!has_codec_parameters(st, &errmsg)) { - char buf[256]; - avcodec_string(buf, sizeof(buf), st->codec, 0); - av_log(ic, AV_LOG_WARNING, - "Could not find codec parameters for stream %d (%s): %s\n" - "Consider increasing the value for the 'analyzeduration' and 'probesize' options\n", - i, buf, errmsg); - } else { - ret = 0; - } } } @@ -3069,6 +2955,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) int best_fps = 0; double best_error = 0.01; + if (st->info->codec_info_duration >= INT64_MAX / st->time_base.num / 2|| + st->info->codec_info_duration_fields >= INT64_MAX / st->time_base.den) + continue; av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, st->info->codec_info_duration_fields*(int64_t)st->time_base.den, st->info->codec_info_duration*2*(int64_t)st->time_base.num, 60000); @@ -3156,12 +3045,29 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) if(ic->probesize) estimate_timings(ic, old_offset); + if (ret >= 0 && ic->nb_streams) + ret = -1; /* we could not have all the codec parameters before EOF */ + for(i=0;i<ic->nb_streams;i++) { + const char *errmsg; + st = ic->streams[i]; + if (!has_codec_parameters(st, &errmsg)) { + char buf[256]; + avcodec_string(buf, sizeof(buf), st->codec, 0); + av_log(ic, AV_LOG_WARNING, + "Could not find codec parameters for stream %d (%s): %s\n" + "Consider increasing the value for the 'analyzeduration' and 'probesize' options\n", + i, buf, errmsg); + } else { + ret = 0; + } + } + compute_chapters_end(ic); find_stream_info_err: for (i=0; i < ic->nb_streams; i++) { st = ic->streams[i]; - if (ic->streams[i]->codec) + if (ic->streams[i]->codec && ic->streams[i]->codec->codec_type != AVMEDIA_TYPE_AUDIO) ic->streams[i]->codec->thread_count = 0; if (st->info) av_freep(&st->info->duration_error); @@ -3803,27 +3709,11 @@ static void pkt_dump_internal(void *avcl, FILE *f, int level, AVPacket *pkt, int av_hex_dump(f, pkt->data, pkt->size); } -#if FF_API_PKT_DUMP -void av_pkt_dump(FILE *f, AVPacket *pkt, int dump_payload) -{ - AVRational tb = { 1, AV_TIME_BASE }; - pkt_dump_internal(NULL, f, 0, pkt, dump_payload, tb); -} -#endif - void av_pkt_dump2(FILE *f, AVPacket *pkt, int dump_payload, AVStream *st) { pkt_dump_internal(NULL, f, 0, pkt, dump_payload, st->time_base); } -#if FF_API_PKT_DUMP -void av_pkt_dump_log(void *avcl, int level, AVPacket *pkt, int dump_payload) -{ - AVRational tb = { 1, AV_TIME_BASE }; - pkt_dump_internal(avcl, NULL, level, pkt, dump_payload, tb); -} -#endif - void av_pkt_dump_log2(void *avcl, int level, AVPacket *pkt, int dump_payload, AVStream *st) { @@ -3971,72 +3861,6 @@ void avpriv_set_pts_info(AVStream *s, int pts_wrap_bits, s->pts_wrap_bits = pts_wrap_bits; } -int ff_url_join(char *str, int size, const char *proto, - const char *authorization, const char *hostname, - int port, const char *fmt, ...) -{ -#if CONFIG_NETWORK - struct addrinfo hints = { 0 }, *ai; -#endif - - str[0] = '\0'; - if (proto) - av_strlcatf(str, size, "%s://", proto); - if (authorization && authorization[0]) - av_strlcatf(str, size, "%s@", authorization); -#if CONFIG_NETWORK && defined(AF_INET6) - /* Determine if hostname is a numerical IPv6 address, - * properly escape it within [] in that case. */ - hints.ai_flags = AI_NUMERICHOST; - if (!getaddrinfo(hostname, NULL, &hints, &ai)) { - if (ai->ai_family == AF_INET6) { - av_strlcat(str, "[", size); - av_strlcat(str, hostname, size); - av_strlcat(str, "]", size); - } else { - av_strlcat(str, hostname, size); - } - freeaddrinfo(ai); - } else -#endif - /* Not an IPv6 address, just output the plain string. */ - av_strlcat(str, hostname, size); - - if (port >= 0) - av_strlcatf(str, size, ":%d", port); - if (fmt) { - va_list vl; - int len = strlen(str); - - va_start(vl, fmt); - vsnprintf(str + len, size > len ? size - len : 0, fmt, vl); - va_end(vl); - } - return strlen(str); -} - -int ff_write_chained(AVFormatContext *dst, int dst_stream, AVPacket *pkt, - AVFormatContext *src) -{ - AVPacket local_pkt; - - local_pkt = *pkt; - local_pkt.stream_index = dst_stream; - if (pkt->pts != AV_NOPTS_VALUE) - local_pkt.pts = av_rescale_q(pkt->pts, - src->streams[pkt->stream_index]->time_base, - dst->streams[dst_stream]->time_base); - if (pkt->dts != AV_NOPTS_VALUE) - local_pkt.dts = av_rescale_q(pkt->dts, - src->streams[pkt->stream_index]->time_base, - dst->streams[dst_stream]->time_base); - if (pkt->duration) - local_pkt.duration = av_rescale_q(pkt->duration, - src->streams[pkt->stream_index]->time_base, - dst->streams[dst_stream]->time_base); - return av_write_frame(dst, &local_pkt); -} - void ff_parse_key_value(const char *str, ff_parse_key_val_cb callback_get_buf, void *context) { @@ -4101,75 +3925,6 @@ int ff_find_stream_index(AVFormatContext *s, int id) return -1; } -void ff_make_absolute_url(char *buf, int size, const char *base, - const char *rel) -{ - char *sep, *path_query; - /* Absolute path, relative to the current server */ - if (base && strstr(base, "://") && rel[0] == '/') { - if (base != buf) - av_strlcpy(buf, base, size); - sep = strstr(buf, "://"); - if (sep) { - /* Take scheme from base url */ - if (rel[1] == '/') { - sep[1] = '\0'; - } else { - /* Take scheme and host from base url */ - sep += 3; - sep = strchr(sep, '/'); - if (sep) - *sep = '\0'; - } - } - av_strlcat(buf, rel, size); - return; - } - /* If rel actually is an absolute url, just copy it */ - if (!base || strstr(rel, "://") || rel[0] == '/') { - av_strlcpy(buf, rel, size); - return; - } - if (base != buf) - av_strlcpy(buf, base, size); - - /* Strip off any query string from base */ - path_query = strchr(buf, '?'); - if (path_query != NULL) - *path_query = '\0'; - - /* Is relative path just a new query part? */ - if (rel[0] == '?') { - av_strlcat(buf, rel, size); - return; - } - - /* Remove the file name from the base url */ - sep = strrchr(buf, '/'); - if (sep) - sep[1] = '\0'; - else - buf[0] = '\0'; - while (av_strstart(rel, "../", NULL) && sep) { - /* Remove the path delimiter at the end */ - sep[0] = '\0'; - sep = strrchr(buf, '/'); - /* If the next directory name to pop off is "..", break here */ - if (!strcmp(sep ? &sep[1] : buf, "..")) { - /* Readd the slash we just removed */ - av_strlcat(buf, "/", size); - break; - } - /* Cut off the directory name */ - if (sep) - sep[1] = '\0'; - else - buf[0] = '\0'; - rel += 3; - } - av_strlcat(buf, rel, size); -} - int64_t ff_iso8601_to_unix_time(const char *datestr) { struct tm time1 = {0}, time2 = {0}; @@ -4259,15 +4014,6 @@ int ff_add_param_change(AVPacket *pkt, int32_t channels, return 0; } -const struct AVCodecTag *avformat_get_riff_video_tags(void) -{ - return ff_codec_bmp_tags; -} -const struct AVCodecTag *avformat_get_riff_audio_tags(void) -{ - return ff_codec_wav_tags; -} - AVRational av_guess_sample_aspect_ratio(AVFormatContext *format, AVStream *stream, AVFrame *frame) { AVRational undef = {0, 1}; @@ -4462,57 +4208,3 @@ void ff_generate_avci_extradata(AVStream *st) memcpy(st->codec->extradata, data, size); st->codec->extradata_size = size; } - -static int match_host_pattern(const char *pattern, const char *hostname) -{ - int len_p, len_h; - if (!strcmp(pattern, "*")) - return 1; - // Skip a possible *. at the start of the pattern - if (pattern[0] == '*') - pattern++; - if (pattern[0] == '.') - pattern++; - len_p = strlen(pattern); - len_h = strlen(hostname); - if (len_p > len_h) - return 0; - // Simply check if the end of hostname is equal to 'pattern' - if (!strcmp(pattern, &hostname[len_h - len_p])) { - if (len_h == len_p) - return 1; // Exact match - if (hostname[len_h - len_p - 1] == '.') - return 1; // The matched substring is a domain and not just a substring of a domain - } - return 0; -} - -int ff_http_match_no_proxy(const char *no_proxy, const char *hostname) -{ - char *buf, *start; - int ret = 0; - if (!no_proxy) - return 0; - if (!hostname) - return 0; - buf = av_strdup(no_proxy); - if (!buf) - return 0; - start = buf; - while (start) { - char *sep, *next = NULL; - start += strspn(start, " ,"); - sep = start + strcspn(start, " ,"); - if (*sep) { - next = sep + 1; - *sep = '\0'; - } - if (match_host_pattern(start, hostname)) { - ret = 1; - break; - } - start = next; - } - av_free(buf); - return ret; -} diff --git a/chromium/third_party/ffmpeg/libavformat/vc1test.c b/chromium/third_party/ffmpeg/libavformat/vc1test.c index e411a257f13..7c6bcde089e 100644 --- a/chromium/third_party/ffmpeg/libavformat/vc1test.c +++ b/chromium/third_party/ffmpeg/libavformat/vc1test.c @@ -39,7 +39,7 @@ static int vc1t_probe(AVProbeData *p) if (p->buf[3] != 0xC5 || AV_RL32(&p->buf[4]) != 4 || AV_RL32(&p->buf[20]) != 0xC) return 0; - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; } static int vc1t_read_header(AVFormatContext *s) diff --git a/chromium/third_party/ffmpeg/libavformat/version.h b/chromium/third_party/ffmpeg/libavformat/version.h index 8fd08cf032d..1dfde221a20 100644 --- a/chromium/third_party/ffmpeg/libavformat/version.h +++ b/chromium/third_party/ffmpeg/libavformat/version.h @@ -30,8 +30,8 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 55 -#define LIBAVFORMAT_VERSION_MINOR 3 -#define LIBAVFORMAT_VERSION_MICRO 100 +#define LIBAVFORMAT_VERSION_MINOR 14 +#define LIBAVFORMAT_VERSION_MICRO 102 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ LIBAVFORMAT_VERSION_MINOR, \ @@ -49,12 +49,6 @@ * the public API and may change, break or disappear at any time. */ -#ifndef FF_API_OLD_AVIO -#define FF_API_OLD_AVIO (LIBAVFORMAT_VERSION_MAJOR < 55) -#endif -#ifndef FF_API_PKT_DUMP -#define FF_API_PKT_DUMP (LIBAVFORMAT_VERSION_MAJOR < 54) -#endif #ifndef FF_API_ALLOC_OUTPUT_CONTEXT #define FF_API_ALLOC_OUTPUT_CONTEXT (LIBAVFORMAT_VERSION_MAJOR < 56) #endif diff --git a/chromium/third_party/ffmpeg/libavformat/vorbiscomment.c b/chromium/third_party/ffmpeg/libavformat/vorbiscomment.c index 9b38e6a7910..f17a0c1d13e 100644 --- a/chromium/third_party/ffmpeg/libavformat/vorbiscomment.c +++ b/chromium/third_party/ffmpeg/libavformat/vorbiscomment.c @@ -34,6 +34,7 @@ const AVMetadataConv ff_vorbiscomment_metadata_conv[] = { { "ALBUMARTIST", "album_artist"}, { "TRACKNUMBER", "track" }, { "DISCNUMBER", "disc" }, + { "DESCRIPTION", "comment" }, { 0 } }; diff --git a/chromium/third_party/ffmpeg/libavformat/vqf.c b/chromium/third_party/ffmpeg/libavformat/vqf.c index f1e6aafd989..1ce53595d60 100644 --- a/chromium/third_party/ffmpeg/libavformat/vqf.c +++ b/chromium/third_party/ffmpeg/libavformat/vqf.c @@ -43,7 +43,7 @@ static int vqf_probe(AVProbeData *probe_packet) if (!memcmp(probe_packet->buf + 4, "00052200", 8)) return AVPROBE_SCORE_MAX; - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; } static void add_metadata(AVFormatContext *s, uint32_t tag, @@ -132,6 +132,11 @@ static int vqf_read_header(AVFormatContext *s) rate_flag = AV_RB32(comm_chunk + 8); avio_skip(s->pb, len-12); + if (st->codec->channels <= 0) { + av_log(s, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR_INVALIDDATA; + } + st->codec->bit_rate = read_bitrate*1000; break; case MKTAG('D','S','I','Z'): // size of compressed data diff --git a/chromium/third_party/ffmpeg/libavformat/w64.c b/chromium/third_party/ffmpeg/libavformat/w64.c index 7bf5502f7cd..ef2d90a600c 100644 --- a/chromium/third_party/ffmpeg/libavformat/w64.c +++ b/chromium/third_party/ffmpeg/libavformat/w64.c @@ -20,20 +20,31 @@ #include "w64.h" -const uint8_t ff_w64_guid_riff[16] = { 'r', 'i', 'f', 'f', - 0x2E, 0x91, 0xCF, 0x11, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 }; +const uint8_t ff_w64_guid_riff[16] = { + 'r', 'i', 'f', 'f', + 0x2E, 0x91, 0xCF, 0x11, 0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00 +}; -const uint8_t ff_w64_guid_wave[16] = { 'w', 'a', 'v', 'e', - 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; +const uint8_t ff_w64_guid_wave[16] = { + 'w', 'a', 'v', 'e', + 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A +}; -const uint8_t ff_w64_guid_fmt [16] = { 'f', 'm', 't', ' ', - 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; +const uint8_t ff_w64_guid_fmt [16] = { + 'f', 'm', 't', ' ', + 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A +}; const uint8_t ff_w64_guid_fact[16] = { 'f', 'a', 'c', 't', - 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; + 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A +}; -const uint8_t ff_w64_guid_data[16] = { 'd', 'a', 't', 'a', - 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; +const uint8_t ff_w64_guid_data[16] = { + 'd', 'a', 't', 'a', + 0xF3, 0xAC, 0xD3, 0x11, 0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A +}; -const uint8_t ff_w64_guid_summarylist[16] = { 0xBC, 0x94, 0x5F, 0x92, - 0x5A, 0x52, 0xD2, 0x11, 0x86, 0xDC, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A }; +const uint8_t ff_w64_guid_summarylist[16] = { + 0xBC, 0x94, 0x5F, 0x92, + 0x5A, 0x52, 0xD2, 0x11, 0x86, 0xDC, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A +}; diff --git a/chromium/third_party/ffmpeg/libavformat/wavdec.c b/chromium/third_party/ffmpeg/libavformat/wavdec.c index 14c52f810a7..d5b3b9ef2f3 100644 --- a/chromium/third_party/ffmpeg/libavformat/wavdec.c +++ b/chromium/third_party/ffmpeg/libavformat/wavdec.c @@ -25,17 +25,18 @@ #include "libavutil/avassert.h" #include "libavutil/dict.h" +#include "libavutil/intreadwrite.h" #include "libavutil/log.h" #include "libavutil/mathematics.h" #include "libavutil/opt.h" #include "avformat.h" -#include "internal.h" +#include "avio.h" #include "avio_internal.h" +#include "internal.h" +#include "metadata.h" #include "pcm.h" #include "riff.h" #include "w64.h" -#include "avio.h" -#include "metadata.h" #include "spdif.h" typedef struct WAVDemuxContext { @@ -51,9 +52,11 @@ typedef struct WAVDemuxContext { int audio_eof; int ignore_length; int spdif; + int smv_cur_pt; + int smv_given_first; + int unaligned; // e.g. if an odd number of bytes ID3 tag was prepended } WAVDemuxContext; - #if CONFIG_WAV_DEMUXER static int64_t next_tag(AVIOContext *pb, uint32_t *tag) @@ -62,19 +65,27 @@ static int64_t next_tag(AVIOContext *pb, uint32_t *tag) return avio_rl32(pb); } +/* RIFF chunks are always at even offsets relative to where they start. */ +static int64_t wav_seek_tag(WAVDemuxContext * wav, AVIOContext *s, int64_t offset, int whence) +{ + offset += offset < INT64_MAX && offset + wav->unaligned & 1; + + return avio_seek(s, offset, whence); +} + /* return the size of the found tag */ -static int64_t find_tag(AVIOContext *pb, uint32_t tag1) +static int64_t find_tag(WAVDemuxContext * wav, AVIOContext *pb, uint32_t tag1) { unsigned int tag; int64_t size; for (;;) { if (url_feof(pb)) - return -1; + return AVERROR_EOF; size = next_tag(pb, &tag); if (tag == tag1) break; - avio_skip(pb, size + (size & 1)); + wav_seek_tag(wav, pb, size, SEEK_CUR); } return size; } @@ -86,11 +97,9 @@ static int wav_probe(AVProbeData *p) return 0; if (!memcmp(p->buf + 8, "WAVE", 4)) { if (!memcmp(p->buf, "RIFF", 4)) - /* - Since ACT demuxer has standard WAV header at top of it's own, - returning score is decreased to avoid probe conflict - between ACT and WAV. - */ + /* Since the ACT demuxer has a standard WAV header at the top of + * its own, the returned score is decreased to avoid a probe + * conflict between ACT and WAV. */ return AVPROBE_SCORE_MAX - 1; else if (!memcmp(p->buf, "RF64", 4) && !memcmp(p->buf + 12, "ds64", 4)) @@ -102,7 +111,7 @@ static int wav_probe(AVProbeData *p) static void handle_stream_probing(AVStream *st) { if (st->codec->codec_id == AV_CODEC_ID_PCM_S16LE) { - st->request_probe = AVPROBE_SCORE_MAX/2; + st->request_probe = AVPROBE_SCORE_EXTENSION; st->probe_packets = FFMIN(st->probe_packets, 4); } } @@ -173,16 +182,22 @@ static int wav_parse_bext_tag(AVFormatContext *s, int64_t size) if (umid_mask) { /* the string formatting below is per SMPTE 330M-2004 Annex C */ - if (umid_parts[4] == 0 && umid_parts[5] == 0 && umid_parts[6] == 0 && umid_parts[7] == 0) { + if (umid_parts[4] == 0 && umid_parts[5] == 0 && + umid_parts[6] == 0 && umid_parts[7] == 0) { /* basic UMID */ - snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, - umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3]); + snprintf(temp, sizeof(temp), + "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, + umid_parts[0], umid_parts[1], + umid_parts[2], umid_parts[3]); } else { /* extended UMID */ - snprintf(temp, sizeof(temp), "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64 - "%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, - umid_parts[0], umid_parts[1], umid_parts[2], umid_parts[3], - umid_parts[4], umid_parts[5], umid_parts[6], umid_parts[7]); + snprintf(temp, sizeof(temp), + "0x%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64 + "%016"PRIX64"%016"PRIX64"%016"PRIX64"%016"PRIX64, + umid_parts[0], umid_parts[1], + umid_parts[2], umid_parts[3], + umid_parts[4], umid_parts[5], + umid_parts[6], umid_parts[7]); } if ((ret = av_dict_set(&s->metadata, "umid", temp, 0)) < 0) @@ -197,7 +212,7 @@ static int wav_parse_bext_tag(AVFormatContext *s, int64_t size) /* CodingHistory present */ size -= 602; - if (!(coding_history = av_malloc(size+1))) + if (!(coding_history = av_malloc(size + 1))) return AVERROR(ENOMEM); if ((ret = avio_read(s->pb, coding_history, size)) < 0) @@ -213,26 +228,28 @@ static int wav_parse_bext_tag(AVFormatContext *s, int64_t size) } static const AVMetadataConv wav_metadata_conv[] = { - {"description", "comment" }, - {"originator", "encoded_by" }, - {"origination_date", "date" }, - {"origination_time", "creation_time"}, - {0}, + { "description", "comment" }, + { "originator", "encoded_by" }, + { "origination_date", "date" }, + { "origination_time", "creation_time" }, + { 0 }, }; /* wav input */ static int wav_read_header(AVFormatContext *s) { int64_t size, av_uninit(data_size); - int64_t sample_count=0; + int64_t sample_count = 0; int rf64; uint32_t tag; - AVIOContext *pb = s->pb; - AVStream *st = NULL; + AVIOContext *pb = s->pb; + AVStream *st = NULL; WAVDemuxContext *wav = s->priv_data; int ret, got_fmt = 0; int64_t next_tag_ofs, data_ofs = -1; + wav->unaligned = avio_tell(s->pb) & 1; + wav->smv_data_ofs = -1; /* check RIFF header */ @@ -240,21 +257,23 @@ static int wav_read_header(AVFormatContext *s) rf64 = tag == MKTAG('R', 'F', '6', '4'); if (!rf64 && tag != MKTAG('R', 'I', 'F', 'F')) - return -1; + return AVERROR_INVALIDDATA; avio_rl32(pb); /* file size */ tag = avio_rl32(pb); if (tag != MKTAG('W', 'A', 'V', 'E')) - return -1; + return AVERROR_INVALIDDATA; if (rf64) { if (avio_rl32(pb) != MKTAG('d', 's', '6', '4')) - return -1; + return AVERROR_INVALIDDATA; size = avio_rl32(pb); if (size < 24) - return -1; + return AVERROR_INVALIDDATA; avio_rl64(pb); /* RIFF size */ - data_size = avio_rl64(pb); + + data_size = avio_rl64(pb); sample_count = avio_rl64(pb); + if (data_size < 0 || sample_count < 0) { av_log(s, AV_LOG_ERROR, "negative data_size and/or sample_count in " "ds64: data_size = %"PRId64", sample_count = %"PRId64"\n", @@ -267,7 +286,7 @@ static int wav_read_header(AVFormatContext *s) for (;;) { AVStream *vst; - size = next_tag(pb, &tag); + size = next_tag(pb, &tag); next_tag_ofs = avio_tell(pb) + size; if (url_feof(pb)) @@ -285,14 +304,15 @@ static int wav_read_header(AVFormatContext *s) break; case MKTAG('d', 'a', 't', 'a'): if (!got_fmt) { - av_log(s, AV_LOG_ERROR, "found no 'fmt ' tag before the 'data' tag\n"); + av_log(s, AV_LOG_ERROR, + "found no 'fmt ' tag before the 'data' tag\n"); return AVERROR_INVALIDDATA; } if (rf64) { next_tag_ofs = wav->data_end = avio_tell(pb) + data_size; } else { - data_size = size; + data_size = size; next_tag_ofs = wav->data_end = size ? next_tag_ofs : INT64_MAX; } @@ -304,11 +324,11 @@ static int wav_read_header(AVFormatContext *s) if (!pb->seekable || (!rf64 && !size)) goto break_loop; break; - case MKTAG('f','a','c','t'): + case MKTAG('f', 'a', 'c', 't'): if (!sample_count) sample_count = avio_rl32(pb); break; - case MKTAG('b','e','x','t'): + case MKTAG('b', 'e', 'x', 't'): if ((ret = wav_parse_bext_tag(s, size)) < 0) return ret; break; @@ -323,15 +343,23 @@ static int wav_read_header(AVFormatContext *s) goto break_loop; } av_log(s, AV_LOG_DEBUG, "Found SMV data\n"); + wav->smv_given_first = 0; vst = avformat_new_stream(s, NULL); if (!vst) return AVERROR(ENOMEM); avio_r8(pb); vst->id = 1; vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; - vst->codec->codec_id = AV_CODEC_ID_MJPEG; + vst->codec->codec_id = AV_CODEC_ID_SMVJPEG; vst->codec->width = avio_rl24(pb); vst->codec->height = avio_rl24(pb); + vst->codec->extradata_size = 4; + vst->codec->extradata = av_malloc(vst->codec->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + if (!vst->codec->extradata) { + av_log(s, AV_LOG_ERROR, "Could not allocate extradata.\n"); + return AVERROR(ENOMEM); + } size = avio_rl24(pb); wav->smv_data_ofs = avio_tell(pb) + (size - 5) * 3; avio_rl24(pb); @@ -341,6 +369,8 @@ static int wav_read_header(AVFormatContext *s) avio_rl24(pb); avio_rl24(pb); wav->smv_frames_per_jpeg = avio_rl24(pb); + AV_WL32(vst->codec->extradata, wav->smv_frames_per_jpeg); + wav->smv_cur_pt = 0; goto break_loop; case MKTAG('L', 'I', 'S', 'T'): if (size < 4) { @@ -354,15 +384,13 @@ static int wav_read_header(AVFormatContext *s) break; } - /* skip padding byte */ - next_tag_ofs += (next_tag_ofs < INT64_MAX && next_tag_ofs & 1); - /* seek to next tag unless we know that we'll run into EOF */ if ((avio_size(pb) > 0 && next_tag_ofs >= avio_size(pb)) || - avio_seek(pb, next_tag_ofs, SEEK_SET) < 0) { + wav_seek_tag(wav, pb, next_tag_ofs, SEEK_SET) < 0) { break; } } + break_loop: if (data_ofs < 0) { av_log(s, AV_LOG_ERROR, "no 'data' tag found\n"); @@ -371,8 +399,11 @@ break_loop: avio_seek(pb, data_ofs, SEEK_SET); - if (!sample_count && st->codec->channels && av_get_bits_per_sample(st->codec->codec_id) && wav->data_end <= avio_size(pb)) - sample_count = (data_size<<3) / (st->codec->channels * (uint64_t)av_get_bits_per_sample(st->codec->codec_id)); + if (!sample_count && st->codec->channels && + av_get_bits_per_sample(st->codec->codec_id) && wav->data_end <= avio_size(pb)) + sample_count = (data_size << 3) / + (st->codec->channels * + (uint64_t)av_get_bits_per_sample(st->codec->codec_id)); if (sample_count) st->duration = sample_count; @@ -382,7 +413,8 @@ break_loop: return 0; } -/** Find chunk with w64 GUID by skipping over other chunks +/** + * Find chunk with w64 GUID by skipping over other chunks. * @return the size of the found chunk */ static int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16]) @@ -394,18 +426,17 @@ static int64_t find_guid(AVIOContext *pb, const uint8_t guid1[16]) avio_read(pb, guid, 16); size = avio_rl64(pb); if (size <= 24) - return -1; + return AVERROR_INVALIDDATA; if (!memcmp(guid, guid1, 16)) return size; avio_skip(pb, FFALIGN(size, INT64_C(8)) - 24); } - return -1; + return AVERROR_EOF; } #define MAX_SIZE 4096 -static int wav_read_packet(AVFormatContext *s, - AVPacket *pkt) +static int wav_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, size; int64_t left; @@ -417,7 +448,7 @@ static int wav_read_packet(AVFormatContext *s, enum AVCodecID codec; ret = ff_spdif_probe(s->pb->buffer, s->pb->buf_end - s->pb->buffer, &codec); - if (ret > AVPROBE_SCORE_MAX / 2) { + if (ret > AVPROBE_SCORE_EXTENSION) { s->streams[0]->codec->codec_id = codec; wav->spdif = 1; } else { @@ -432,10 +463,13 @@ static int wav_read_packet(AVFormatContext *s, smv_retry: audio_dts = s->streams[0]->cur_dts; video_dts = s->streams[1]->cur_dts; + if (audio_dts != AV_NOPTS_VALUE && video_dts != AV_NOPTS_VALUE) { - audio_dts = av_rescale_q(audio_dts, s->streams[0]->time_base, AV_TIME_BASE_Q); - video_dts = av_rescale_q(video_dts, s->streams[1]->time_base, AV_TIME_BASE_Q); - wav->smv_last_stream = video_dts >= audio_dts; + /*We always return a video frame first to get the pixel format first*/ + wav->smv_last_stream = wav->smv_given_first ? + av_compare_ts(video_dts, s->streams[1]->time_base, + audio_dts, s->streams[0]->time_base) > 0 : 0; + wav->smv_given_first = 1; } wav->smv_last_stream = !wav->smv_last_stream; wav->smv_last_stream |= wav->audio_eof; @@ -453,8 +487,13 @@ smv_retry: if (ret < 0) goto smv_out; pkt->pos -= 3; - pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg; - wav->smv_block++; + pkt->pts = wav->smv_block * wav->smv_frames_per_jpeg + wav->smv_cur_pt; + wav->smv_cur_pt++; + if (wav->smv_frames_per_jpeg > 0) + wav->smv_cur_pt %= wav->smv_frames_per_jpeg; + if (!wav->smv_cur_pt) + wav->smv_block++; + pkt->stream_index = 1; smv_out: avio_seek(s->pb, old_pos, SEEK_SET); @@ -470,19 +509,19 @@ smv_out: left = wav->data_end - avio_tell(s->pb); if (wav->ignore_length) - left= INT_MAX; - if (left <= 0){ + left = INT_MAX; + if (left <= 0) { if (CONFIG_W64_DEMUXER && wav->w64) left = find_guid(s->pb, ff_w64_guid_data) - 24; else - left = find_tag(s->pb, MKTAG('d', 'a', 't', 'a')); + left = find_tag(wav, s->pb, MKTAG('d', 'a', 't', 'a')); if (left < 0) { wav->audio_eof = 1; if (wav->smv_data_ofs > 0 && !wav->smv_eof) goto smv_retry; return AVERROR_EOF; } - wav->data_end= avio_tell(s->pb) + left; + wav->data_end = avio_tell(s->pb) + left; } size = MAX_SIZE; @@ -513,7 +552,10 @@ static int wav_read_seek(AVFormatContext *s, smv_timestamp = av_rescale_q(timestamp, s->streams[0]->time_base, s->streams[1]->time_base); else timestamp = av_rescale_q(smv_timestamp, s->streams[1]->time_base, s->streams[0]->time_base); - wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg; + if (wav->smv_frames_per_jpeg > 0) { + wav->smv_block = smv_timestamp / wav->smv_frames_per_jpeg; + wav->smv_cur_pt = smv_timestamp % wav->smv_frames_per_jpeg; + } } st = s->streams[0]; @@ -552,12 +594,11 @@ AVInputFormat ff_wav_demuxer = { .read_packet = wav_read_packet, .read_seek = wav_read_seek, .flags = AVFMT_GENERIC_INDEX, - .codec_tag = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 }, + .codec_tag = (const AVCodecTag * const []) { ff_codec_wav_tags, 0 }, .priv_class = &wav_demuxer_class, }; #endif /* CONFIG_WAV_DEMUXER */ - #if CONFIG_W64_DEMUXER static int w64_probe(AVProbeData *p) { @@ -573,23 +614,24 @@ static int w64_probe(AVProbeData *p) static int w64_read_header(AVFormatContext *s) { int64_t size, data_ofs = 0; - AVIOContext *pb = s->pb; - WAVDemuxContext *wav = s->priv_data; + AVIOContext *pb = s->pb; + WAVDemuxContext *wav = s->priv_data; AVStream *st; uint8_t guid[16]; int ret; avio_read(pb, guid, 16); if (memcmp(guid, ff_w64_guid_riff, 16)) - return -1; + return AVERROR_INVALIDDATA; - if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) /* riff + wave + fmt + sizes */ - return -1; + /* riff + wave + fmt + sizes */ + if (avio_rl64(pb) < 16 + 8 + 16 + 8 + 16 + 8) + return AVERROR_INVALIDDATA; avio_read(pb, guid, 16); if (memcmp(guid, ff_w64_guid_wave, 16)) { av_log(s, AV_LOG_ERROR, "could not find wave guid\n"); - return -1; + return AVERROR_INVALIDDATA; } wav->w64 = 1; @@ -685,6 +727,6 @@ AVInputFormat ff_w64_demuxer = { .read_packet = wav_read_packet, .read_seek = wav_read_seek, .flags = AVFMT_GENERIC_INDEX, - .codec_tag = (const AVCodecTag* const []){ ff_codec_wav_tags, 0 }, + .codec_tag = (const AVCodecTag * const []) { ff_codec_wav_tags, 0 }, }; #endif /* CONFIG_W64_DEMUXER */ diff --git a/chromium/third_party/ffmpeg/libavformat/webvttdec.c b/chromium/third_party/ffmpeg/libavformat/webvttdec.c index 694a020b198..065448532d3 100644 --- a/chromium/third_party/ffmpeg/libavformat/webvttdec.c +++ b/chromium/third_party/ffmpeg/libavformat/webvttdec.c @@ -29,9 +29,12 @@ #include "subtitles.h" #include "libavutil/bprint.h" #include "libavutil/intreadwrite.h" +#include "libavutil/opt.h" typedef struct { + const AVClass *class; FFDemuxSubtitlesQueue q; + int kind; } WebVTTContext; static int webvtt_probe(AVProbeData *p) @@ -66,6 +69,7 @@ static int webvtt_read_header(AVFormatContext *s) avpriv_set_pts_info(st, 64, 1, 1000); st->codec->codec_type = AVMEDIA_TYPE_SUBTITLE; st->codec->codec_id = AV_CODEC_ID_WEBVTT; + st->disposition |= webvtt->kind; av_bprint_init(&header, 0, AV_BPRINT_SIZE_UNLIMITED); av_bprint_init(&cue, 0, AV_BPRINT_SIZE_UNLIMITED); @@ -74,8 +78,8 @@ static int webvtt_read_header(AVFormatContext *s) int i; int64_t pos; AVPacket *sub; - const char *p, *identifier; - //const char *settings = NULL; + const char *p, *identifier, *settings; + int identifier_len, settings_len; int64_t ts_start, ts_end; ff_subtitles_read_chunk(s->pb, &cue); @@ -92,15 +96,23 @@ static int webvtt_read_header(AVFormatContext *s) continue; /* optional cue identifier (can be a number like in SRT or some kind of - * chaptering id), silently skip it */ - for (i = 0; p[i] && p[i] != '\n'; i++) { + * chaptering id) */ + for (i = 0; p[i] && p[i] != '\n' && p[i] != '\r'; i++) { if (!strncmp(p + i, "-->", 3)) { identifier = NULL; break; } } - if (identifier) - p += strcspn(p, "\n"); + if (!identifier) + identifier_len = 0; + else { + identifier_len = strcspn(p, "\r\n"); + p += identifier_len; + if (*p == '\r') + p++; + if (*p == '\n') + p++; + } /* cue timestamps */ if ((ts_start = read_ts(p)) == AV_NOPTS_VALUE) @@ -112,14 +124,15 @@ static int webvtt_read_header(AVFormatContext *s) if ((ts_end = read_ts(p)) == AV_NOPTS_VALUE) break; - /* optional cue settings, TODO: store in side_data */ + /* optional cue settings */ p += strcspn(p, "\n\t "); while (*p == '\t' || *p == ' ') p++; - if (*p != '\n') { - //settings = p; - p += strcspn(p, "\n"); - } + settings = p; + settings_len = strcspn(p, "\r\n"); + p += settings_len; + if (*p == '\r') + p++; if (*p == '\n') p++; @@ -132,6 +145,20 @@ static int webvtt_read_header(AVFormatContext *s) sub->pos = pos; sub->pts = ts_start; sub->duration = ts_end - ts_start; + +#define SET_SIDE_DATA(name, type) do { \ + if (name##_len) { \ + uint8_t *buf = av_packet_new_side_data(sub, type, name##_len); \ + if (!buf) { \ + res = AVERROR(ENOMEM); \ + goto end; \ + } \ + memcpy(buf, name, name##_len); \ + } \ +} while (0) + + SET_SIDE_DATA(identifier, AV_PKT_DATA_WEBVTT_IDENTIFIER); + SET_SIDE_DATA(settings, AV_PKT_DATA_WEBVTT_SETTINGS); } ff_subtitles_queue_finalize(&webvtt->q); @@ -163,6 +190,25 @@ static int webvtt_read_close(AVFormatContext *s) return 0; } +#define OFFSET(x) offsetof(WebVTTContext, x) +#define KIND_FLAGS AV_OPT_FLAG_SUBTITLE_PARAM + +static const AVOption options[] = { + { "kind", "Set kind of WebVTT track", OFFSET(kind), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, KIND_FLAGS, "webvtt_kind" }, + { "subtitles", "WebVTT subtitles kind", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, 0, "webvtt_kind" }, + { "captions", "WebVTT captions kind", 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_CAPTIONS }, INT_MIN, INT_MAX, 0, "webvtt_kind" }, + { "descriptions", "WebVTT descriptions kind", 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_DESCRIPTIONS }, INT_MIN, INT_MAX, 0, "webvtt_kind" }, + { "metadata", "WebVTT metadata kind", 0, AV_OPT_TYPE_CONST, { .i64 = AV_DISPOSITION_METADATA }, INT_MIN, INT_MAX, 0, "webvtt_kind" }, + { NULL } +}; + +static const AVClass webvtt_demuxer_class = { + .class_name = "WebVTT demuxer", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + AVInputFormat ff_webvtt_demuxer = { .name = "webvtt", .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), @@ -173,4 +219,5 @@ AVInputFormat ff_webvtt_demuxer = { .read_seek2 = webvtt_read_seek, .read_close = webvtt_read_close, .extensions = "vtt", + .priv_class = &webvtt_demuxer_class, }; diff --git a/chromium/third_party/ffmpeg/libavformat/webvttenc.c b/chromium/third_party/ffmpeg/libavformat/webvttenc.c new file mode 100644 index 00000000000..bd19a834546 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/webvttenc.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013 Matthew Heaney + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * WebVTT subtitle muxer + * @see http://dev.w3.org/html5/webvtt/ + */ + +#include "avformat.h" +#include "internal.h" + +static void webvtt_write_time(AVIOContext *pb, int64_t millisec) +{ + int64_t sec, min, hour; + sec = millisec / 1000; + millisec -= 1000 * sec; + min = sec / 60; + sec -= 60 * min; + hour = min / 60; + min -= 60 * hour; + + if (hour > 0) + avio_printf(pb, "%"PRId64":", hour); + + avio_printf(pb, "%02"PRId64":%02"PRId64".%03"PRId64"", min, sec, millisec); +} + +static int webvtt_write_header(AVFormatContext *ctx) +{ + AVStream *s = ctx->streams[0]; + AVIOContext *pb = ctx->pb; + + avpriv_set_pts_info(s, 64, 1, 1000); + + avio_printf(pb, "WEBVTT\n"); + avio_flush(pb); + + return 0; +} + +static int webvtt_write_packet(AVFormatContext *ctx, AVPacket *pkt) +{ + AVIOContext *pb = ctx->pb; + int id_size, settings_size; + uint8_t *id, *settings; + + avio_printf(pb, "\n"); + + id = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_IDENTIFIER, + &id_size); + + if (id && id_size > 0) + avio_printf(pb, "%.*s\n", id_size, id); + + webvtt_write_time(pb, pkt->pts); + avio_printf(pb, " --> "); + webvtt_write_time(pb, pkt->pts + pkt->duration); + + settings = av_packet_get_side_data(pkt, AV_PKT_DATA_WEBVTT_SETTINGS, + &settings_size); + + if (settings && settings_size > 0) + avio_printf(pb, " %.*s", settings_size, settings); + + avio_printf(pb, "\n"); + + avio_write(pb, pkt->data, pkt->size); + avio_printf(pb, "\n"); + + return 0; +} + +AVOutputFormat ff_webvtt_muxer = { + .name = "webvtt", + .long_name = NULL_IF_CONFIG_SMALL("WebVTT subtitle"), + .extensions = "vtt", + .mime_type = "text/vtt", + .subtitle_codec = AV_CODEC_ID_WEBVTT, + .write_header = webvtt_write_header, + .write_packet = webvtt_write_packet, +}; diff --git a/chromium/third_party/ffmpeg/libavformat/westwood_aud.c b/chromium/third_party/ffmpeg/libavformat/westwood_aud.c index d66611758be..f2bd3a130e1 100644 --- a/chromium/third_party/ffmpeg/libavformat/westwood_aud.c +++ b/chromium/third_party/ffmpeg/libavformat/westwood_aud.c @@ -77,7 +77,7 @@ static int wsaud_probe(AVProbeData *p) return 0; /* return 1/2 certainty since this file check is a little sketchy */ - return AVPROBE_SCORE_MAX / 2; + return AVPROBE_SCORE_EXTENSION; } static int wsaud_read_header(AVFormatContext *s) diff --git a/chromium/third_party/ffmpeg/libavformat/westwood_vqa.c b/chromium/third_party/ffmpeg/libavformat/westwood_vqa.c index c996dad8a25..d8791da1319 100644 --- a/chromium/third_party/ffmpeg/libavformat/westwood_vqa.c +++ b/chromium/third_party/ffmpeg/libavformat/westwood_vqa.c @@ -101,12 +101,13 @@ static int wsvqa_read_header(AVFormatContext *s) avio_seek(pb, 20, SEEK_SET); /* the VQA header needs to go to the decoder */ - st->codec->extradata_size = VQA_HEADER_SIZE; st->codec->extradata = av_mallocz(VQA_HEADER_SIZE + FF_INPUT_BUFFER_PADDING_SIZE); + if (!st->codec->extradata) + return AVERROR(ENOMEM); + st->codec->extradata_size = VQA_HEADER_SIZE; header = (unsigned char *)st->codec->extradata; if (avio_read(pb, st->codec->extradata, VQA_HEADER_SIZE) != VQA_HEADER_SIZE) { - av_free(st->codec->extradata); return AVERROR(EIO); } st->codec->width = AV_RL16(&header[6]); diff --git a/chromium/third_party/ffmpeg/libavformat/wtv.h b/chromium/third_party/ffmpeg/libavformat/wtv.h index efe90d68466..51ac626115b 100644 --- a/chromium/third_party/ffmpeg/libavformat/wtv.h +++ b/chromium/third_party/ffmpeg/libavformat/wtv.h @@ -25,7 +25,7 @@ #include "riff.h" #include "asf.h" -#define WTV_SECTOR_BITS 12 +#define WTV_SECTOR_BITS INT64_C(12) #define WTV_SECTOR_SIZE (1 << WTV_SECTOR_BITS) #define WTV_BIGSECTOR_BITS 18 #define WTV_PAD8(x) (((x) + 7) & ~7) diff --git a/chromium/third_party/ffmpeg/libavformat/wtvdec.c b/chromium/third_party/ffmpeg/libavformat/wtvdec.c index e423370a9b8..551242d8a1f 100644 --- a/chromium/third_party/ffmpeg/libavformat/wtvdec.c +++ b/chromium/third_party/ffmpeg/libavformat/wtvdec.c @@ -47,11 +47,11 @@ */ typedef struct { - AVIOContext *pb_filesystem; /** file system (AVFormatContext->pb) */ + AVIOContext *pb_filesystem; /**< file system (AVFormatContext->pb) */ - int sector_bits; /** sector shift bits; used to convert sector number into pb_filesystem offset */ - uint32_t *sectors; /** file allocation table */ - int nb_sectors; /** number of sectors */ + int sector_bits; /**< sector shift bits; used to convert sector number into pb_filesystem offset */ + uint32_t *sectors; /**< file allocation table */ + int nb_sectors; /**< number of sectors */ int error; int64_t position; @@ -88,7 +88,7 @@ static int wtvfile_read_packet(void *opaque, uint8_t *buf, int buf_size) int i = wf->position >> wf->sector_bits; if (i >= wf->nb_sectors || (wf->sectors[i] != wf->sectors[i - 1] + (1 << (wf->sector_bits - WTV_SECTOR_BITS)) && - avio_seek(pb, (int64_t)wf->sectors[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)) { + avio_seek(pb, wf->sectors[i] << WTV_SECTOR_BITS, SEEK_SET) < 0)) { wf->error = 1; break; } @@ -113,7 +113,7 @@ static int64_t wtvfile_seek(void *opaque, int64_t offset, int whence) offset = wf->length; wf->error = offset < 0 || offset >= wf->length || - avio_seek(pb, ((int64_t)wf->sectors[offset >> wf->sector_bits] << WTV_SECTOR_BITS) + avio_seek(pb, (wf->sectors[offset >> wf->sector_bits] << WTV_SECTOR_BITS) + (offset & ((1 << wf->sector_bits) - 1)), SEEK_SET) < 0; wf->position = offset; return offset; @@ -183,7 +183,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int } wf->nb_sectors = 0; for (i = 0; i < nb_sectors1; i++) { - if (avio_seek(s->pb, (int64_t)sectors1[i] << WTV_SECTOR_BITS, SEEK_SET) < 0) + if (avio_seek(s->pb, sectors1[i] << WTV_SECTOR_BITS, SEEK_SET) < 0) break; wf->nb_sectors += read_ints(s->pb, wf->sectors + i * WTV_SECTOR_SIZE / 4, WTV_SECTOR_SIZE / 4); } @@ -213,7 +213,7 @@ static AVIOContext * wtvfile_open_sector(int first_sector, uint64_t length, int /* seek to initial sector */ wf->position = 0; - if (avio_seek(s->pb, (int64_t)wf->sectors[0] << WTV_SECTOR_BITS, SEEK_SET) < 0) { + if (avio_seek(s->pb, wf->sectors[0] << WTV_SECTOR_BITS, SEEK_SET) < 0) { av_free(wf->sectors); av_free(wf); return NULL; @@ -306,10 +306,10 @@ typedef struct { } WtvStream; typedef struct { - AVIOContext *pb; /** timeline file */ + AVIOContext *pb; /**< timeline file */ int64_t epoch; - int64_t pts; /** pts for next data chunk */ - int64_t last_valid_pts; /** latest valid pts, used for interative seeking */ + int64_t pts; /**< pts for next data chunk */ + int64_t last_valid_pts; /**< latest valid pts, used for interative seeking */ /* maintain private seek index, as the AVIndexEntry->pos is relative to the start of the 'timeline' file, not the file system (AVFormatContext->pb) */ @@ -436,6 +436,7 @@ static void get_attachment(AVFormatContext *s, AVIOContext *pb, int length) av_dict_set(&st->metadata, "title", description, 0); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->codec->codec_id = AV_CODEC_ID_MJPEG; + st->id = -1; ret = av_get_packet(pb, &st->attached_pic, filesize); if (ret < 0) goto done; diff --git a/chromium/third_party/ffmpeg/libavformat/wtvenc.c b/chromium/third_party/ffmpeg/libavformat/wtvenc.c index 410a2dc355e..04e6cc22f8d 100644 --- a/chromium/third_party/ffmpeg/libavformat/wtvenc.c +++ b/chromium/third_party/ffmpeg/libavformat/wtvenc.c @@ -28,6 +28,7 @@ #include "libavutil/intreadwrite.h" #include "libavutil/avassert.h" #include "avformat.h" +#include "avio_internal.h" #include "internal.h" #include "wtv.h" #include "asf.h" @@ -87,10 +88,10 @@ typedef struct { typedef struct { int64_t timeline_start_pos; WtvFile file[WTV_FILES]; - int64_t serial; /** chunk serial number */ - int64_t last_chunk_pos; /** last chunk position */ - int64_t last_timestamp_pos; /** last timestamp chunk position */ - int64_t first_index_pos; /** first index_chunk position */ + int64_t serial; /**< chunk serial number */ + int64_t last_chunk_pos; /**< last chunk position */ + int64_t last_timestamp_pos; /**< last timestamp chunk position */ + int64_t first_index_pos; /**< first index_chunk position */ WtvChunkEntry index[MAX_NB_INDEX]; int nb_index; @@ -127,12 +128,7 @@ typedef struct { WTVHeaderWriteFunc *write_header; } WTVRootEntryTable; -static int write_pad(AVIOContext *pb, int size) -{ - for (; size > 0; size--) - avio_w8(pb, 0); - return 0; -} +#define write_pad(pb, size) ffio_fill(pb, 0, size) static const ff_asf_guid *get_codec_guid(enum AVCodecID id, const AVCodecGuid *av_guid) { diff --git a/chromium/third_party/ffmpeg/libavformat/wv.c b/chromium/third_party/ffmpeg/libavformat/wv.c index 97a6c1f2e8d..0f4f80761ac 100644 --- a/chromium/third_party/ffmpeg/libavformat/wv.c +++ b/chromium/third_party/ffmpeg/libavformat/wv.c @@ -1,6 +1,5 @@ /* - * WavPack demuxer - * Copyright (c) 2006,2011 Konstantin Shishkov + * WavPack shared functions * * This file is part of FFmpeg. * @@ -19,379 +18,35 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/channel_layout.h" -#include "libavutil/intreadwrite.h" -#include "libavutil/dict.h" -#include "avformat.h" -#include "internal.h" -#include "apetag.h" -#include "id3v1.h" - -// specs say that maximum block size is 1Mb -#define WV_BLOCK_LIMIT 1047576 - -#define WV_EXTRA_SIZE 12 - -#define WV_START_BLOCK 0x0800 -#define WV_END_BLOCK 0x1000 -#define WV_SINGLE_BLOCK (WV_START_BLOCK | WV_END_BLOCK) - -enum WV_FLAGS { - WV_MONO = 0x0004, - WV_HYBRID = 0x0008, - WV_JOINT = 0x0010, - WV_CROSSD = 0x0020, - WV_HSHAPE = 0x0040, - WV_FLOAT = 0x0080, - WV_INT32 = 0x0100, - WV_HBR = 0x0200, - WV_HBAL = 0x0400, - WV_MCINIT = 0x0800, - WV_MCEND = 0x1000, -}; +#include <stdint.h> +#include <string.h> -static const int wv_rates[16] = { - 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, - 32000, 44100, 48000, 64000, 88200, 96000, 192000, -1 -}; - -typedef struct { - uint32_t blksize, flags; - int rate, chan, bpp; - uint32_t chmask; - uint32_t samples, soff; - int multichannel; - int block_parsed; - uint8_t extra[WV_EXTRA_SIZE]; - int64_t pos; - - int64_t apetag_start; -} WVContext; +#include "libavutil/common.h" +#include "libavutil/intreadwrite.h" -static int wv_probe(AVProbeData *p) -{ - /* check file header */ - if (p->buf_size <= 32) - return 0; - if (p->buf[0] == 'w' && p->buf[1] == 'v' && - p->buf[2] == 'p' && p->buf[3] == 'k') - return AVPROBE_SCORE_MAX; - else - return 0; -} +#include "wv.h" -static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb, - int append) +int ff_wv_parse_header(WvHeader *wv, const uint8_t *data) { - WVContext *wc = ctx->priv_data; - uint32_t tag, ver; - int size; - int rate, bpp, chan; - uint32_t chmask; - - wc->pos = avio_tell(pb); - - /* don't return bogus packets with the ape tag data */ - if (wc->apetag_start && wc->pos >= wc->apetag_start) - return AVERROR_EOF; + memset(wv, 0, sizeof(*wv)); - if (!append) { - tag = avio_rl32(pb); - if (tag != MKTAG('w', 'v', 'p', 'k')) - return AVERROR_INVALIDDATA; - size = avio_rl32(pb); - if (size < 24 || size > WV_BLOCK_LIMIT) { - av_log(ctx, AV_LOG_ERROR, "Incorrect block size %i\n", size); - return AVERROR_INVALIDDATA; - } - wc->blksize = size; - ver = avio_rl16(pb); - if (ver < 0x402 || ver > 0x410) { - av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", ver); - return AVERROR_PATCHWELCOME; - } - avio_r8(pb); // track no - avio_r8(pb); // track sub index - wc->samples = avio_rl32(pb); // total samples in file - wc->soff = avio_rl32(pb); // offset in samples of current block - avio_read(pb, wc->extra, WV_EXTRA_SIZE); - } else { - size = wc->blksize; - } - wc->flags = AV_RL32(wc->extra + 4); - /* Blocks with zero samples don't contain actual audio information - * and should be ignored */ - if (!AV_RN32(wc->extra)) - return 0; - // parse flags - bpp = ((wc->flags & 3) + 1) << 3; - chan = 1 + !(wc->flags & WV_MONO); - chmask = wc->flags & WV_MONO ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; - rate = wv_rates[(wc->flags >> 23) & 0xF]; - wc->multichannel = !!((wc->flags & WV_SINGLE_BLOCK) != WV_SINGLE_BLOCK); - if (wc->multichannel) { - chan = wc->chan; - chmask = wc->chmask; - } - if ((rate == -1 || !chan) && !wc->block_parsed) { - int64_t block_end = avio_tell(pb) + wc->blksize - 24; - if (!pb->seekable) { - av_log(ctx, AV_LOG_ERROR, - "Cannot determine additional parameters\n"); - return AVERROR_INVALIDDATA; - } - while (avio_tell(pb) < block_end) { - int id, size; - id = avio_r8(pb); - size = (id & 0x80) ? avio_rl24(pb) : avio_r8(pb); - size <<= 1; - if (id & 0x40) - size--; - switch (id & 0x3F) { - case 0xD: - if (size <= 1) { - av_log(ctx, AV_LOG_ERROR, - "Insufficient channel information\n"); - return AVERROR_INVALIDDATA; - } - chan = avio_r8(pb); - switch (size - 2) { - case 0: - chmask = avio_r8(pb); - break; - case 1: - chmask = avio_rl16(pb); - break; - case 2: - chmask = avio_rl24(pb); - break; - case 3: - chmask = avio_rl32(pb); - break; - case 5: - avio_skip(pb, 1); - chan |= (avio_r8(pb) & 0xF) << 8; - chmask = avio_rl24(pb); - break; - default: - av_log(ctx, AV_LOG_ERROR, - "Invalid channel info size %d\n", size); - return AVERROR_INVALIDDATA; - } - break; - case 0x27: - rate = avio_rl24(pb); - break; - default: - avio_skip(pb, size); - } - if (id & 0x40) - avio_skip(pb, 1); - } - if (rate == -1) { - av_log(ctx, AV_LOG_ERROR, - "Cannot determine custom sampling rate\n"); - return AVERROR_INVALIDDATA; - } - avio_seek(pb, block_end - wc->blksize + 24, SEEK_SET); - } - if (!wc->bpp) - wc->bpp = bpp; - if (!wc->chan) - wc->chan = chan; - if (!wc->chmask) - wc->chmask = chmask; - if (!wc->rate) - wc->rate = rate; - - if (wc->flags && bpp != wc->bpp) { - av_log(ctx, AV_LOG_ERROR, - "Bits per sample differ, this block: %i, header block: %i\n", - bpp, wc->bpp); - return AVERROR_INVALIDDATA; - } - if (wc->flags && !wc->multichannel && chan != wc->chan) { - av_log(ctx, AV_LOG_ERROR, - "Channels differ, this block: %i, header block: %i\n", - chan, wc->chan); + if (AV_RL32(data) != MKTAG('w', 'v', 'p', 'k')) return AVERROR_INVALIDDATA; - } - if (wc->flags && rate != -1 && rate != wc->rate) { - av_log(ctx, AV_LOG_ERROR, - "Sampling rate differ, this block: %i, header block: %i\n", - rate, wc->rate); - return AVERROR_INVALIDDATA; - } - wc->blksize = size - 24; - return 0; -} -static int wv_read_header(AVFormatContext *s) -{ - AVIOContext *pb = s->pb; - WVContext *wc = s->priv_data; - AVStream *st; - int ret; - - wc->block_parsed = 0; - for (;;) { - if ((ret = wv_read_block_header(s, pb, 0)) < 0) - return ret; - if (!AV_RN32(wc->extra)) - avio_skip(pb, wc->blksize - 24); - else - break; - } - - /* now we are ready: build format streams */ - st = avformat_new_stream(s, NULL); - if (!st) - return AVERROR(ENOMEM); - st->codec->codec_type = AVMEDIA_TYPE_AUDIO; - st->codec->codec_id = AV_CODEC_ID_WAVPACK; - st->codec->channels = wc->chan; - st->codec->channel_layout = wc->chmask; - st->codec->sample_rate = wc->rate; - st->codec->bits_per_coded_sample = wc->bpp; - avpriv_set_pts_info(st, 64, 1, wc->rate); - st->start_time = 0; - if (wc->samples != 0xFFFFFFFFu) - st->duration = wc->samples; - - if (s->pb->seekable) { - int64_t cur = avio_tell(s->pb); - wc->apetag_start = ff_ape_parse_tag(s); - if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) - ff_id3v1_read(s); - avio_seek(s->pb, cur, SEEK_SET); - } - - return 0; -} - -static int wv_read_packet(AVFormatContext *s, AVPacket *pkt) -{ - WVContext *wc = s->priv_data; - int ret; - int size, ver, off; - int64_t pos; - uint32_t block_samples; - - if (url_feof(s->pb)) - return AVERROR_EOF; - if (wc->block_parsed) { - if ((ret = wv_read_block_header(s, s->pb, 0)) < 0) - return ret; - } - - pos = wc->pos; - off = wc->multichannel ? 4 : 0; - if (av_new_packet(pkt, wc->blksize + WV_EXTRA_SIZE + off) < 0) - return AVERROR(ENOMEM); - if (wc->multichannel) - AV_WL32(pkt->data, wc->blksize + WV_EXTRA_SIZE + 12); - memcpy(pkt->data + off, wc->extra, WV_EXTRA_SIZE); - ret = avio_read(s->pb, pkt->data + WV_EXTRA_SIZE + off, wc->blksize); - if (ret != wc->blksize) { - av_free_packet(pkt); - return AVERROR(EIO); - } - while (!(wc->flags & WV_END_BLOCK)) { - if (avio_rl32(s->pb) != MKTAG('w', 'v', 'p', 'k')) { - av_free_packet(pkt); - return AVERROR_INVALIDDATA; - } - if ((ret = av_append_packet(s->pb, pkt, 4)) < 0) { - av_free_packet(pkt); - return ret; - } - size = AV_RL32(pkt->data + pkt->size - 4); - if (size < 24 || size > WV_BLOCK_LIMIT) { - av_free_packet(pkt); - av_log(s, AV_LOG_ERROR, "Incorrect block size %d\n", size); - return AVERROR_INVALIDDATA; - } - wc->blksize = size; - ver = avio_rl16(s->pb); - if (ver < 0x402 || ver > 0x410) { - av_free_packet(pkt); - av_log(s, AV_LOG_ERROR, "Unsupported version %03X\n", ver); - return AVERROR_PATCHWELCOME; - } - avio_r8(s->pb); // track no - avio_r8(s->pb); // track sub index - wc->samples = avio_rl32(s->pb); // total samples in file - wc->soff = avio_rl32(s->pb); // offset in samples of current block - if ((ret = av_append_packet(s->pb, pkt, WV_EXTRA_SIZE)) < 0) { - av_free_packet(pkt); - return ret; - } - memcpy(wc->extra, pkt->data + pkt->size - WV_EXTRA_SIZE, WV_EXTRA_SIZE); - - if ((ret = wv_read_block_header(s, s->pb, 1)) < 0) { - av_free_packet(pkt); - return ret; - } - ret = av_append_packet(s->pb, pkt, wc->blksize); - if (ret < 0) { - av_free_packet(pkt); - return ret; - } - } - pkt->stream_index = 0; - wc->block_parsed = 1; - pkt->pts = wc->soff; - block_samples = AV_RL32(wc->extra); - if (block_samples > INT32_MAX) - av_log(s, AV_LOG_WARNING, - "Too many samples in block: %"PRIu32"\n", block_samples); - else - pkt->duration = block_samples; - - av_add_index_entry(s->streams[0], pos, pkt->pts, 0, 0, AVINDEX_KEYFRAME); - return 0; -} + wv->blocksize = AV_RL32(data + 4); + if (wv->blocksize < 24 || wv->blocksize > WV_BLOCK_LIMIT) + return AVERROR_INVALIDDATA; + wv->blocksize -= 24; -static int wv_read_seek(AVFormatContext *s, int stream_index, - int64_t timestamp, int flags) -{ - AVStream *st = s->streams[stream_index]; - WVContext *wc = s->priv_data; - AVPacket pkt1, *pkt = &pkt1; - int ret; - int index = av_index_search_timestamp(st, timestamp, flags); - int64_t pos, pts; + wv->version = AV_RL16(data + 8); + wv->total_samples = AV_RL32(data + 12); + wv->block_idx = AV_RL32(data + 16); + wv->samples = AV_RL32(data + 20); + wv->flags = AV_RL32(data + 24); + wv->crc = AV_RL32(data + 28); - /* if found, seek there */ - if (index >= 0 && - timestamp <= st->index_entries[st->nb_index_entries - 1].timestamp) { - wc->block_parsed = 1; - avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET); - return 0; - } - /* if timestamp is out of bounds, return error */ - if (timestamp < 0 || timestamp >= s->duration) - return AVERROR(EINVAL); + wv->initial = !!(wv->flags & WV_FLAG_INITIAL_BLOCK); + wv->final = !!(wv->flags & WV_FLAG_FINAL_BLOCK); - pos = avio_tell(s->pb); - do { - ret = av_read_frame(s, pkt); - if (ret < 0) { - avio_seek(s->pb, pos, SEEK_SET); - return ret; - } - pts = pkt->pts; - av_free_packet(pkt); - } while(pts < timestamp); return 0; } - -AVInputFormat ff_wv_demuxer = { - .name = "wv", - .long_name = NULL_IF_CONFIG_SMALL("WavPack"), - .priv_data_size = sizeof(WVContext), - .read_probe = wv_probe, - .read_header = wv_read_header, - .read_packet = wv_read_packet, - .read_seek = wv_read_seek, -}; diff --git a/chromium/third_party/ffmpeg/libavformat/wv.h b/chromium/third_party/ffmpeg/libavformat/wv.h new file mode 100644 index 00000000000..07d2e1bc0a8 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/wv.h @@ -0,0 +1,56 @@ +/* + * WavPack shared functions + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef AVFORMAT_WV_H +#define AVFORMAT_WV_H + +#include <stdint.h> + +#define WV_HEADER_SIZE 32 + +#define WV_FLAG_INITIAL_BLOCK (1 << 11) +#define WV_FLAG_FINAL_BLOCK (1 << 12) + +// specs say that maximum block size is 1Mb +#define WV_BLOCK_LIMIT 1048576 + +typedef struct WvHeader { + uint32_t blocksize; //< size of the block data (excluding the header) + uint16_t version; //< bitstream version + uint32_t total_samples; //< total number of samples in the stream + uint32_t block_idx; //< index of the first sample in this block + uint32_t samples; //< number of samples in this block + uint32_t flags; + uint32_t crc; + + int initial, final; +} WvHeader; + +/** + * Parse a WavPack block header. + * + * @param wv this struct will be filled with parse header information + * @param data header data, must be WV_HEADER_SIZE bytes long + * + * @return 0 on success, a negative AVERROR code on failure + */ +int ff_wv_parse_header(WvHeader *wv, const uint8_t *data); + +#endif /* AVFORMAT_WV_H */ diff --git a/chromium/third_party/ffmpeg/libavformat/wvdec.c b/chromium/third_party/ffmpeg/libavformat/wvdec.c new file mode 100644 index 00000000000..4eaec402f71 --- /dev/null +++ b/chromium/third_party/ffmpeg/libavformat/wvdec.c @@ -0,0 +1,354 @@ +/* + * WavPack demuxer + * Copyright (c) 2006,2011 Konstantin Shishkov + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/channel_layout.h" +#include "libavutil/intreadwrite.h" +#include "libavutil/dict.h" +#include "avformat.h" +#include "internal.h" +#include "apetag.h" +#include "id3v1.h" +#include "wv.h" + +enum WV_FLAGS { + WV_MONO = 0x0004, + WV_HYBRID = 0x0008, + WV_JOINT = 0x0010, + WV_CROSSD = 0x0020, + WV_HSHAPE = 0x0040, + WV_FLOAT = 0x0080, + WV_INT32 = 0x0100, + WV_HBR = 0x0200, + WV_HBAL = 0x0400, + WV_MCINIT = 0x0800, + WV_MCEND = 0x1000, +}; + +static const int wv_rates[16] = { + 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, + 32000, 44100, 48000, 64000, 88200, 96000, 192000, -1 +}; + +typedef struct { + uint8_t block_header[WV_HEADER_SIZE]; + WvHeader header; + int rate, chan, bpp; + uint32_t chmask; + int multichannel; + int block_parsed; + int64_t pos; + + int64_t apetag_start; +} WVContext; + +static int wv_probe(AVProbeData *p) +{ + /* check file header */ + if (p->buf_size <= 32) + return 0; + if (AV_RL32(&p->buf[0]) == MKTAG('w', 'v', 'p', 'k') && + AV_RL32(&p->buf[4]) >= 24 && + AV_RL32(&p->buf[4]) <= WV_BLOCK_LIMIT && + AV_RL16(&p->buf[8]) >= 0x402 && + AV_RL16(&p->buf[8]) <= 0x410) + return AVPROBE_SCORE_MAX; + else + return 0; +} + +static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb) +{ + WVContext *wc = ctx->priv_data; + int ret; + int rate, bpp, chan; + uint32_t chmask, flags; + + wc->pos = avio_tell(pb); + + /* don't return bogus packets with the ape tag data */ + if (wc->apetag_start && wc->pos >= wc->apetag_start) + return AVERROR_EOF; + + ret = avio_read(pb, wc->block_header, WV_HEADER_SIZE); + if (ret != WV_HEADER_SIZE) + return (ret < 0) ? ret : AVERROR_EOF; + + ret = ff_wv_parse_header(&wc->header, wc->block_header); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid block header.\n"); + return ret; + } + + if (wc->header.version < 0x402 || wc->header.version > 0x410) { + av_log(ctx, AV_LOG_ERROR, "Unsupported version %03X\n", wc->header.version); + return AVERROR_PATCHWELCOME; + } + + /* Blocks with zero samples don't contain actual audio information + * and should be ignored */ + if (!wc->header.samples) + return 0; + // parse flags + flags = wc->header.flags; + bpp = ((flags & 3) + 1) << 3; + chan = 1 + !(flags & WV_MONO); + chmask = flags & WV_MONO ? AV_CH_LAYOUT_MONO : AV_CH_LAYOUT_STEREO; + rate = wv_rates[(flags >> 23) & 0xF]; + wc->multichannel = !(wc->header.initial && wc->header.final); + if (wc->multichannel) { + chan = wc->chan; + chmask = wc->chmask; + } + if ((rate == -1 || !chan) && !wc->block_parsed) { + int64_t block_end = avio_tell(pb) + wc->header.blocksize; + if (!pb->seekable) { + av_log(ctx, AV_LOG_ERROR, + "Cannot determine additional parameters\n"); + return AVERROR_INVALIDDATA; + } + while (avio_tell(pb) < block_end) { + int id, size; + id = avio_r8(pb); + size = (id & 0x80) ? avio_rl24(pb) : avio_r8(pb); + size <<= 1; + if (id & 0x40) + size--; + switch (id & 0x3F) { + case 0xD: + if (size <= 1) { + av_log(ctx, AV_LOG_ERROR, + "Insufficient channel information\n"); + return AVERROR_INVALIDDATA; + } + chan = avio_r8(pb); + switch (size - 2) { + case 0: + chmask = avio_r8(pb); + break; + case 1: + chmask = avio_rl16(pb); + break; + case 2: + chmask = avio_rl24(pb); + break; + case 3: + chmask = avio_rl32(pb); + break; + case 5: + avio_skip(pb, 1); + chan |= (avio_r8(pb) & 0xF) << 8; + chmask = avio_rl24(pb); + break; + default: + av_log(ctx, AV_LOG_ERROR, + "Invalid channel info size %d\n", size); + return AVERROR_INVALIDDATA; + } + break; + case 0x27: + rate = avio_rl24(pb); + break; + default: + avio_skip(pb, size); + } + if (id & 0x40) + avio_skip(pb, 1); + } + if (rate == -1) { + av_log(ctx, AV_LOG_ERROR, + "Cannot determine custom sampling rate\n"); + return AVERROR_INVALIDDATA; + } + avio_seek(pb, block_end - wc->header.blocksize, SEEK_SET); + } + if (!wc->bpp) + wc->bpp = bpp; + if (!wc->chan) + wc->chan = chan; + if (!wc->chmask) + wc->chmask = chmask; + if (!wc->rate) + wc->rate = rate; + + if (flags && bpp != wc->bpp) { + av_log(ctx, AV_LOG_ERROR, + "Bits per sample differ, this block: %i, header block: %i\n", + bpp, wc->bpp); + return AVERROR_INVALIDDATA; + } + if (flags && !wc->multichannel && chan != wc->chan) { + av_log(ctx, AV_LOG_ERROR, + "Channels differ, this block: %i, header block: %i\n", + chan, wc->chan); + return AVERROR_INVALIDDATA; + } + if (flags && rate != -1 && rate != wc->rate) { + av_log(ctx, AV_LOG_ERROR, + "Sampling rate differ, this block: %i, header block: %i\n", + rate, wc->rate); + return AVERROR_INVALIDDATA; + } + return 0; +} + +static int wv_read_header(AVFormatContext *s) +{ + AVIOContext *pb = s->pb; + WVContext *wc = s->priv_data; + AVStream *st; + int ret; + + wc->block_parsed = 0; + for (;;) { + if ((ret = wv_read_block_header(s, pb)) < 0) + return ret; + if (!wc->header.samples) + avio_skip(pb, wc->header.blocksize); + else + break; + } + + /* now we are ready: build format streams */ + st = avformat_new_stream(s, NULL); + if (!st) + return AVERROR(ENOMEM); + st->codec->codec_type = AVMEDIA_TYPE_AUDIO; + st->codec->codec_id = AV_CODEC_ID_WAVPACK; + st->codec->channels = wc->chan; + st->codec->channel_layout = wc->chmask; + st->codec->sample_rate = wc->rate; + st->codec->bits_per_coded_sample = wc->bpp; + avpriv_set_pts_info(st, 64, 1, wc->rate); + st->start_time = 0; + if (wc->header.total_samples != 0xFFFFFFFFu) + st->duration = wc->header.total_samples; + + if (s->pb->seekable) { + int64_t cur = avio_tell(s->pb); + wc->apetag_start = ff_ape_parse_tag(s); + if (!av_dict_get(s->metadata, "", NULL, AV_DICT_IGNORE_SUFFIX)) + ff_id3v1_read(s); + avio_seek(s->pb, cur, SEEK_SET); + } + + return 0; +} + +static int wv_read_packet(AVFormatContext *s, AVPacket *pkt) +{ + WVContext *wc = s->priv_data; + int ret; + int off; + int64_t pos; + uint32_t block_samples; + + if (url_feof(s->pb)) + return AVERROR_EOF; + if (wc->block_parsed) { + if ((ret = wv_read_block_header(s, s->pb)) < 0) + return ret; + } + + pos = wc->pos; + if (av_new_packet(pkt, wc->header.blocksize + WV_HEADER_SIZE) < 0) + return AVERROR(ENOMEM); + memcpy(pkt->data, wc->block_header, WV_HEADER_SIZE); + ret = avio_read(s->pb, pkt->data + WV_HEADER_SIZE, wc->header.blocksize); + if (ret != wc->header.blocksize) { + av_free_packet(pkt); + return AVERROR(EIO); + } + while (!(wc->header.flags & WV_FLAG_FINAL_BLOCK)) { + if ((ret = wv_read_block_header(s, s->pb)) < 0) { + av_free_packet(pkt); + return ret; + } + + off = pkt->size; + if ((ret = av_grow_packet(pkt, WV_HEADER_SIZE + wc->header.blocksize)) < 0) { + av_free_packet(pkt); + return ret; + } + memcpy(pkt->data + off, wc->block_header, WV_HEADER_SIZE); + + ret = avio_read(s->pb, pkt->data + off + WV_HEADER_SIZE, wc->header.blocksize); + if (ret != wc->header.blocksize) { + av_free_packet(pkt); + return (ret < 0) ? ret : AVERROR_EOF; + } + } + pkt->stream_index = 0; + wc->block_parsed = 1; + pkt->pts = wc->header.block_idx; + block_samples = wc->header.samples; + if (block_samples > INT32_MAX) + av_log(s, AV_LOG_WARNING, + "Too many samples in block: %"PRIu32"\n", block_samples); + else + pkt->duration = block_samples; + + av_add_index_entry(s->streams[0], pos, pkt->pts, 0, 0, AVINDEX_KEYFRAME); + return 0; +} + +static int wv_read_seek(AVFormatContext *s, int stream_index, + int64_t timestamp, int flags) +{ + AVStream *st = s->streams[stream_index]; + WVContext *wc = s->priv_data; + AVPacket pkt1, *pkt = &pkt1; + int ret; + int index = av_index_search_timestamp(st, timestamp, flags); + int64_t pos, pts; + + /* if found, seek there */ + if (index >= 0 && + timestamp <= st->index_entries[st->nb_index_entries - 1].timestamp) { + wc->block_parsed = 1; + avio_seek(s->pb, st->index_entries[index].pos, SEEK_SET); + return 0; + } + /* if timestamp is out of bounds, return error */ + if (timestamp < 0 || timestamp >= s->duration) + return AVERROR(EINVAL); + + pos = avio_tell(s->pb); + do { + ret = av_read_frame(s, pkt); + if (ret < 0) { + avio_seek(s->pb, pos, SEEK_SET); + return ret; + } + pts = pkt->pts; + av_free_packet(pkt); + } while(pts < timestamp); + return 0; +} + +AVInputFormat ff_wv_demuxer = { + .name = "wv", + .long_name = NULL_IF_CONFIG_SMALL("WavPack"), + .priv_data_size = sizeof(WVContext), + .read_probe = wv_probe, + .read_header = wv_read_header, + .read_packet = wv_read_packet, + .read_seek = wv_read_seek, +}; diff --git a/chromium/third_party/ffmpeg/libavformat/wvenc.c b/chromium/third_party/ffmpeg/libavformat/wvenc.c index c33d4309acf..b0d74caaec9 100644 --- a/chromium/third_party/ffmpeg/libavformat/wvenc.c +++ b/chromium/third_party/ffmpeg/libavformat/wvenc.c @@ -1,5 +1,6 @@ /* * WavPack muxer + * Copyright (c) 2013 Konstantin Shishkov <kostya.shishkov@gmail.com> * Copyright (c) 2012 Paul B Mahol * * This file is part of FFmpeg. @@ -19,125 +20,72 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "libavutil/intreadwrite.h" -#include "avformat.h" -#include "internal.h" -#include "avio_internal.h" -#include "apetag.h" +#include "libavutil/attributes.h" -#define WV_EXTRA_SIZE 12 -#define WV_END_BLOCK 0x1000 +#include "apetag.h" +#include "avformat.h" +#include "wv.h" -typedef struct{ - uint32_t duration; -} WVMuxContext; +typedef struct WvMuxContext { + int64_t samples; +} WvMuxContext; -static int write_header(AVFormatContext *s) +static av_cold int wv_write_header(AVFormatContext *ctx) { - AVCodecContext *codec = s->streams[0]->codec; - - if (s->nb_streams > 1) { - av_log(s, AV_LOG_ERROR, "only one stream is supported\n"); - return AVERROR(EINVAL); - } - if (codec->codec_id != AV_CODEC_ID_WAVPACK) { - av_log(s, AV_LOG_ERROR, "unsupported codec\n"); + if (ctx->nb_streams > 1 || + ctx->streams[0]->codec->codec_id != AV_CODEC_ID_WAVPACK) { + av_log(ctx, AV_LOG_ERROR, "This muxer only supports a single WavPack stream.\n"); return AVERROR(EINVAL); } - if (codec->extradata_size > 0) { - avpriv_report_missing_feature(s, "remuxing from matroska container"); - return AVERROR_PATCHWELCOME; - } - avpriv_set_pts_info(s->streams[0], 64, 1, codec->sample_rate); return 0; } -static int write_packet(AVFormatContext *s, AVPacket *pkt) +static int wv_write_packet(AVFormatContext *ctx, AVPacket *pkt) { - WVMuxContext *wc = s->priv_data; - AVCodecContext *codec = s->streams[0]->codec; - AVIOContext *pb = s->pb; - uint64_t size; - uint32_t flags; - uint32_t left = pkt->size; - uint8_t *ptr = pkt->data; - int off = codec->channels > 2 ? 4 : 0; + WvMuxContext *s = ctx->priv_data; + WvHeader header; + int ret; - /* FIXME: Simplify decoder/demuxer so bellow code can support midstream - * change of stream parameters */ - wc->duration += pkt->duration; - ffio_wfourcc(pb, "wvpk"); - if (off) { - size = AV_RL32(pkt->data); - if (size <= 12) - return AVERROR_INVALIDDATA; - size -= 12; - } else { - size = pkt->size; + if (pkt->size < WV_HEADER_SIZE || + (ret = ff_wv_parse_header(&header, pkt->data)) < 0) { + av_log(ctx, AV_LOG_ERROR, "Invalid WavPack packet.\n"); + return AVERROR(EINVAL); } + s->samples += header.samples; - if (size + off > left) - return AVERROR_INVALIDDATA; - - avio_wl32(pb, size + 12); - avio_wl16(pb, 0x410); - avio_w8(pb, 0); - avio_w8(pb, 0); - avio_wl32(pb, -1); - avio_wl32(pb, pkt->pts); - ptr += off; left -= off; - flags = AV_RL32(ptr + 4); - avio_write(pb, ptr, size); - ptr += size; left -= size; - - while (!(flags & WV_END_BLOCK) && - (left >= 4 + WV_EXTRA_SIZE)) { - ffio_wfourcc(pb, "wvpk"); - size = AV_RL32(ptr); - ptr += 4; left -= 4; - if (size < 24 || size - 24 > left) - return AVERROR_INVALIDDATA; - avio_wl32(pb, size); - avio_wl16(pb, 0x410); - avio_w8(pb, 0); - avio_w8(pb, 0); - avio_wl32(pb, -1); - avio_wl32(pb, pkt->pts); - flags = AV_RL32(ptr + 4); - avio_write(pb, ptr, WV_EXTRA_SIZE); - ptr += WV_EXTRA_SIZE; left -= WV_EXTRA_SIZE; - avio_write(pb, ptr, size - 24); - ptr += size - 24; left -= size - 24; - } + avio_write(ctx->pb, pkt->data, pkt->size); return 0; } -static int write_trailer(AVFormatContext *s) +static av_cold int wv_write_trailer(AVFormatContext *ctx) { - WVMuxContext *wc = s->priv_data; - AVIOContext *pb = s->pb; - - ff_ape_write(s); - - if (pb->seekable) { - avio_seek(pb, 12, SEEK_SET); - avio_wl32(pb, wc->duration); - avio_flush(pb); + WvMuxContext *s = ctx->priv_data; + + /* update total number of samples in the first block */ + if (ctx->pb->seekable && s->samples && + s->samples < UINT32_MAX) { + int64_t pos = avio_tell(ctx->pb); + avio_seek(ctx->pb, 12, SEEK_SET); + avio_wl32(ctx->pb, s->samples); + avio_seek(ctx->pb, pos, SEEK_SET); } + ff_ape_write_tag(ctx); return 0; } AVOutputFormat ff_wv_muxer = { .name = "wv", - .long_name = NULL_IF_CONFIG_SMALL("WavPack"), - .priv_data_size = sizeof(WVMuxContext), + .long_name = NULL_IF_CONFIG_SMALL("raw WavPack"), + .mime_type = "audio/x-wavpack", .extensions = "wv", + .priv_data_size = sizeof(WvMuxContext), .audio_codec = AV_CODEC_ID_WAVPACK, .video_codec = AV_CODEC_ID_NONE, - .write_header = write_header, - .write_packet = write_packet, - .write_trailer = write_trailer, + .write_header = wv_write_header, + .write_packet = wv_write_packet, + .write_trailer = wv_write_trailer, + .flags = AVFMT_NOTIMESTAMPS, }; diff --git a/chromium/third_party/ffmpeg/libavformat/xa.c b/chromium/third_party/ffmpeg/libavformat/xa.c index e3d36e61b5f..43661dea43c 100644 --- a/chromium/third_party/ffmpeg/libavformat/xa.c +++ b/chromium/third_party/ffmpeg/libavformat/xa.c @@ -59,7 +59,7 @@ static int xa_probe(AVProbeData *p) if (!channels || channels > 8 || !srate || srate > 192000 || bits_per_sample < 4 || bits_per_sample > 32) return 0; - return AVPROBE_SCORE_MAX/2; + return AVPROBE_SCORE_EXTENSION; } static int xa_read_header(AVFormatContext *s) @@ -84,6 +84,9 @@ static int xa_read_header(AVFormatContext *s) avio_skip(pb, 2); /* Skip block align */ avio_skip(pb, 2); /* Skip bits-per-sample */ + if (!st->codec->channels || !st->codec->sample_rate) + return AVERROR_INVALIDDATA; + st->codec->bit_rate = av_clip(15LL * st->codec->channels * 8 * st->codec->sample_rate / 28, 0, INT_MAX); diff --git a/chromium/third_party/ffmpeg/libavformat/yuv4mpeg.c b/chromium/third_party/ffmpeg/libavformat/yuv4mpeg.c index bf48230bb3f..a6d83469ef2 100644 --- a/chromium/third_party/ffmpeg/libavformat/yuv4mpeg.c +++ b/chromium/third_party/ffmpeg/libavformat/yuv4mpeg.c @@ -217,8 +217,8 @@ static int yuv4_write_packet(AVFormatContext *s, AVPacket *pkt) // Adjust for smaller Cb and Cr planes av_pix_fmt_get_chroma_sub_sample(st->codec->pix_fmt, &h_chroma_shift, &v_chroma_shift); - width >>= h_chroma_shift; - height >>= v_chroma_shift; + width = FF_CEIL_RSHIFT(width, h_chroma_shift); + height = FF_CEIL_RSHIFT(height, v_chroma_shift); ptr1 = picture->data[1]; ptr2 = picture->data[2]; |