From 331971116d7d36743601bd2dc5384c5211d3bb48 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Wed, 17 Aug 2011 10:36:33 +0200 Subject: [PATCH 01/23] rv10/20: tell decoder to use edge emulation This removes out-of-edge motion compensation artifacts (easily spotted green blocks in avplay, gray blocks in transcoding), for example here: http://samples.libav.org/samples/real/tv_watching_t1.rm Signed-off-by: Diego Biurrun --- libavcodec/rv10.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/rv10.c b/libavcodec/rv10.c index 3939984031..d789eff787 100644 --- a/libavcodec/rv10.c +++ b/libavcodec/rv10.c @@ -431,6 +431,7 @@ static av_cold int rv10_decode_init(AVCodecContext *avctx) s->avctx= avctx; s->out_format = FMT_H263; s->codec_id= avctx->codec_id; + avctx->flags |= CODEC_FLAG_EMU_EDGE; s->orig_width = s->width = avctx->coded_width; s->orig_height= s->height = avctx->coded_height; From 7c1f6df4b5f80ead35b66e5373af6c8046bace56 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Thu, 11 Aug 2011 14:44:05 +0200 Subject: [PATCH 02/23] rmdec: correct DTS calculation in RealMedia container. First, container stores only DTS and not PTS as it was believed. Second, multiple frames in a packet store timestamp instead of position after the frame length. Signed-off-by: Anton Khirnov --- libavformat/rmdec.c | 11 +++++++---- tests/ref/fate/rv30 | 24 ++++++++++++------------ 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index 54267485b7..5ee75b53b9 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -568,7 +568,8 @@ skip: static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, RMDemuxContext *rm, RMStream *vst, - AVPacket *pkt, int len, int *pseq) + AVPacket *pkt, int len, int *pseq, + int64_t *timestamp) { int hdr, seq, pic_num, len2, pos; int type; @@ -588,8 +589,10 @@ static int rm_assemble_video_frame(AVFormatContext *s, AVIOContext *pb, return -1; rm->remaining_len = len; if(type&1){ // frame, not slice - if(type == 3) // frame as a part of packet + if(type == 3){ // frame as a part of packet len= len2; + *timestamp = pos; + } if(rm->remaining_len < len) return -1; rm->remaining_len -= len; @@ -697,7 +700,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, 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)) + if(rm_assemble_video_frame(s, pb, rm, ast, pkt, len, seq, ×tamp)) return -1; //got partial frame } else if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { if ((st->codec->codec_id == CODEC_ID_RA_288) || @@ -772,7 +775,7 @@ ff_rm_parse_packet (AVFormatContext *s, AVIOContext *pb, } #endif - pkt->pts= timestamp; + pkt->pts = timestamp; if (flags & 2) pkt->flags |= AV_PKT_FLAG_KEY; diff --git a/tests/ref/fate/rv30 b/tests/ref/fate/rv30 index 6c99871eb6..867151bd66 100644 --- a/tests/ref/fate/rv30 +++ b/tests/ref/fate/rv30 @@ -1,16 +1,16 @@ 0, 0, 126720, 0xcefaec47 0, 7500, 126720, 0xa416ece5 0, 15000, 126720, 0xa416ece5 -0, 22500, 126720, 0xa416ece5 -0, 30000, 126720, 0xcc10f4b7 +0, 22500, 126720, 0x259af497 +0, 30000, 126720, 0x5e6ff4d7 0, 37500, 126720, 0xeb6fb8d7 -0, 45000, 126720, 0xda71b917 -0, 52500, 126720, 0xbb1abbb7 -0, 60000, 126720, 0x273fbc37 -0, 67500, 126720, 0x16eebbd7 -0, 75000, 126720, 0x105eb927 -0, 82500, 126720, 0x7fa3ae27 -0, 90000, 126720, 0xd115a757 +0, 45000, 126720, 0xbb1abbb7 +0, 52500, 126720, 0x273fbc37 +0, 60000, 126720, 0x7fa3ae27 +0, 67500, 126720, 0x722e99f7 +0, 75000, 126720, 0x29d6a887 +0, 82500, 126720, 0xd115a757 +0, 90000, 126720, 0x6ddaef32 0, 97500, 126720, 0x04e7897c 0, 105000, 126720, 0x68cfda2b 0, 112500, 126720, 0xe572dfc9 @@ -25,11 +25,11 @@ 0, 180000, 126720, 0x72f2a47d 0, 187500, 126720, 0x4f639ebe 0, 195000, 126720, 0x534a10cc -0, 202500, 126720, 0xfdca11d3 +0, 202500, 126720, 0x5fd753d8 0, 210000, 126720, 0x0c735615 0, 217500, 126720, 0x0eaf0c1b -0, 225000, 126720, 0xce5e6794 -0, 232500, 126720, 0x14cf7974 +0, 225000, 126720, 0x14cf7974 +0, 232500, 126720, 0x1c2a513d 0, 240000, 126720, 0xbc513f2a 0, 247500, 126720, 0xbc303fae 0, 255000, 126720, 0xd9f67585 From 48ce8b8da714558c8738610d5512b6c3c95c901a Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Mon, 15 Aug 2011 12:03:40 +0200 Subject: [PATCH 03/23] Use parsers for RealVideo 3/4 to determine correct PTS Signed-off-by: Anton Khirnov --- libavcodec/Makefile | 2 + libavcodec/allcodecs.c | 2 + libavcodec/rv34_parser.c | 97 ++++++++++++++++++ libavformat/rmdec.c | 1 + tests/ref/fate/real-rv40 | 205 +++++++++++++++++++-------------------- tests/ref/fate/rv30 | 63 ++++++------ 6 files changed, 235 insertions(+), 135 deletions(-) create mode 100644 libavcodec/rv34_parser.c diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 36e07a9fc1..2264e86b7d 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -616,6 +616,8 @@ OBJS-$(CONFIG_MPEGVIDEO_PARSER) += mpegvideo_parser.o \ mpeg12.o mpeg12data.o \ mpegvideo.o error_resilience.o OBJS-$(CONFIG_PNM_PARSER) += pnm_parser.o pnm.o +OBJS-$(CONFIG_RV30_PARSER) += rv34_parser.o +OBJS-$(CONFIG_RV40_PARSER) += rv34_parser.o OBJS-$(CONFIG_VC1_PARSER) += vc1_parser.o vc1.o vc1data.o \ msmpeg4.o msmpeg4data.o mpeg4video.o \ h263.o mpegvideo.o error_resilience.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index dcef0d6d94..7ba945c3d4 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -396,6 +396,8 @@ void avcodec_register_all(void) REGISTER_PARSER (MPEGAUDIO, mpegaudio); REGISTER_PARSER (MPEGVIDEO, mpegvideo); REGISTER_PARSER (PNM, pnm); + REGISTER_PARSER (RV30, rv30); + REGISTER_PARSER (RV40, rv40); REGISTER_PARSER (VC1, vc1); REGISTER_PARSER (VP3, vp3); REGISTER_PARSER (VP8, vp8); diff --git a/libavcodec/rv34_parser.c b/libavcodec/rv34_parser.c new file mode 100644 index 0000000000..c2563a5fdc --- /dev/null +++ b/libavcodec/rv34_parser.c @@ -0,0 +1,97 @@ +/* + * RV30/40 parser + * Copyright (c) 2011 Konstantin Shishkov + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav 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 Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * RV30/40 parser + */ + +#include "parser.h" +#include "libavutil/intreadwrite.h" + +typedef struct { + ParseContext pc; + int64_t key_dts; + int key_pts; +} RV34ParseContext; + +static const int rv_to_av_frame_type[4] = { + AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, +}; + +static int rv34_parse(AVCodecParserContext *s, + AVCodecContext *avctx, + const uint8_t **poutbuf, int *poutbuf_size, + const uint8_t *buf, int buf_size) +{ + RV34ParseContext *pc = s->priv_data; + int off; + int type, pts, hdr; + + if (buf_size < 13 + *buf * 8) { + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; + } + + off = AV_RL32(buf + 5); + hdr = AV_RB32(buf + 9 + *buf * 8); + if (avctx->codec_id == CODEC_ID_RV30) { + type = (hdr >> 27) & 3; + pts = (hdr >> 7) & 0x1FFF; + } else { + type = (hdr >> 29) & 3; + pts = (hdr >> 6) & 0x1FFF; + } + + if (type != 3 && s->pts != AV_NOPTS_VALUE) { + pc->key_dts = s->pts; + pc->key_pts = pts; + } else { + if (type != 3) + s->pts = pc->key_dts + ((pts - pc->key_pts) & 0x1FFF); + else + s->pts = pc->key_dts - ((pc->key_pts - pts) & 0x1FFF); + } + s->pict_type = rv_to_av_frame_type[type]; + + *poutbuf = buf; + *poutbuf_size = buf_size; + return buf_size; +} + +#ifdef CONFIG_RV30_PARSER +AVCodecParser ff_rv30_parser = { + { CODEC_ID_RV30 }, + sizeof(RV34ParseContext), + NULL, + rv34_parse, +}; +#endif + +#ifdef CONFIG_RV40_PARSER +AVCodecParser ff_rv40_parser = { + { CODEC_ID_RV40 }, + sizeof(RV34ParseContext), + NULL, + rv34_parse, +}; +#endif diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index 5ee75b53b9..cf5c46a095 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -298,6 +298,7 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb, st->codec->time_base.num= 1; fps= avio_rb16(pb); st->codec->codec_type = AVMEDIA_TYPE_VIDEO; + st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; avio_rb32(pb); avio_skip(pb, 2); avio_rb16(pb); diff --git a/tests/ref/fate/real-rv40 b/tests/ref/fate/real-rv40 index 990a530436..22cc731c89 100644 --- a/tests/ref/fate/real-rv40 +++ b/tests/ref/fate/real-rv40 @@ -16,106 +16,105 @@ 0, 112500, 276480, 0x5f7a0d4f 0, 120000, 276480, 0x5f7a0d4f 0, 127500, 276480, 0x5f7a0d4f -0, 135000, 276480, 0x75641594 -0, 142500, 276480, 0x32ee3526 -0, 150000, 276480, 0x5ce39368 -0, 157500, 276480, 0x4ec1e418 -0, 165000, 276480, 0x85cbc3b5 -0, 172500, 276480, 0x377c7b46 -0, 180000, 276480, 0x756a4a2e -0, 187500, 276480, 0xcb379547 -0, 195000, 276480, 0x99c085be -0, 202500, 276480, 0xe479ffed -0, 210000, 276480, 0x1e4fae19 -0, 217500, 276480, 0x776412ef -0, 225000, 276480, 0x58ce0f38 -0, 232500, 276480, 0x5ab69b27 -0, 240000, 276480, 0xc3db9706 -0, 247500, 276480, 0xc9c57884 -0, 255000, 276480, 0x000b5269 -0, 262500, 276480, 0x27ff7a5d -0, 270000, 276480, 0x70647530 -0, 277500, 276480, 0x97612c4b -0, 285000, 276480, 0xdf4e04d7 -0, 292500, 276480, 0xbd98f57c -0, 300000, 276480, 0x5163b29b -0, 307500, 276480, 0x99170e64 -0, 315000, 276480, 0x8a4e991f -0, 322500, 276480, 0x6a45425f -0, 330000, 276480, 0x7bf6b1ef -0, 337500, 276480, 0x6de1e34b -0, 345000, 276480, 0xdcaaa99a -0, 352500, 276480, 0xd1e98808 -0, 360000, 276480, 0x6e2d524e -0, 367500, 276480, 0x22c50a3d -0, 375000, 276480, 0x62b76407 -0, 382500, 276480, 0x51e9b3eb -0, 390000, 276480, 0x441f7afd -0, 397500, 276480, 0xfb01efc6 -0, 405000, 276480, 0x294bb441 -0, 412500, 276480, 0xe04ac45e -0, 420000, 276480, 0x58f275ea -0, 427500, 276480, 0xf0b3b71b -0, 435000, 276480, 0x674e34e4 -0, 442500, 276480, 0x41dda2d9 -0, 450000, 276480, 0xf46ba7fb -0, 457500, 276480, 0x28b54815 -0, 465000, 276480, 0xaf2b5d89 -0, 472500, 276480, 0x8facba58 -0, 480000, 276480, 0x28a63236 -0, 487500, 276480, 0x1ad43fd7 -0, 495000, 276480, 0x71507bd2 -0, 502500, 276480, 0x35626022 -0, 510000, 276480, 0x7c1139b3 -0, 517500, 276480, 0x7fd73a99 -0, 525000, 276480, 0xb52e1aa2 -0, 532500, 276480, 0xd6f82cae -0, 540000, 276480, 0xf88f75d4 -0, 547500, 276480, 0x04a8e3ee -0, 555000, 276480, 0xa29f5b01 -0, 562500, 276480, 0x754ceaf5 -0, 570000, 276480, 0x5a38b4af -0, 577500, 276480, 0xfcebc261 -0, 585000, 276480, 0x3d3ca985 -0, 592500, 276480, 0x94a03c75 -0, 600000, 276480, 0x2f98911c -0, 607500, 276480, 0x923b9937 -0, 615000, 276480, 0xefab7ffd -0, 622500, 276480, 0x6b9fbc80 -0, 630000, 276480, 0xe4bdbd1e -0, 637500, 276480, 0x225a56c0 -0, 645000, 276480, 0xf58b1b7c -0, 652500, 276480, 0xbaffcdcc -0, 660000, 276480, 0xeb6eb88f -0, 667500, 276480, 0xdb753d35 -0, 675000, 276480, 0xea80a82e -0, 682500, 276480, 0x2aae902a -0, 690000, 276480, 0x9b9ee961 -0, 697500, 276480, 0xaa12b6fd -0, 705000, 276480, 0x50c31e73 -0, 712500, 276480, 0xdd9fb89f -0, 720000, 276480, 0xaf82399a -0, 727500, 276480, 0x7ce5f23c -0, 735000, 276480, 0x5aaa7519 -0, 742500, 276480, 0xe45a5599 -0, 750000, 276480, 0x704411fb -0, 757500, 276480, 0x9d7430a1 -0, 765000, 276480, 0x2c230702 -0, 772500, 276480, 0x4a4f76cd -0, 780000, 276480, 0x27f54854 -0, 787500, 276480, 0x694d76e3 -0, 795000, 276480, 0x525463e2 -0, 802500, 276480, 0x819898f9 -0, 810000, 276480, 0xeeed00fc -0, 817500, 276480, 0xb6f99ee3 -0, 825000, 276480, 0xefc83107 -0, 832500, 276480, 0xbb22e024 -0, 840000, 276480, 0x300f922a -0, 847500, 276480, 0x826fc3bd -0, 855000, 276480, 0x679a53f8 -0, 862500, 276480, 0x976c9e93 -0, 870000, 276480, 0xb194656e -0, 877500, 276480, 0xf002c5ca -0, 885000, 276480, 0xb243dda5 -0, 892500, 276480, 0x1700efbb -0, 900000, 276480, 0x8f316c66 +0, 135000, 276480, 0x32ee3526 +0, 142500, 276480, 0x7ca9658e +0, 150000, 276480, 0x4ec1e418 +0, 157500, 276480, 0xa9f1506f +0, 165000, 276480, 0x377c7b46 +0, 172500, 276480, 0xe1de7f0a +0, 180000, 276480, 0xcb379547 +0, 187500, 276480, 0x8e12331c +0, 195000, 276480, 0xe479ffed +0, 202500, 276480, 0xac7672dd +0, 210000, 276480, 0x776412ef +0, 217500, 276480, 0x1cd1ab29 +0, 225000, 276480, 0x5ab69b27 +0, 232500, 276480, 0x9eca3f11 +0, 240000, 276480, 0xc9c57884 +0, 247500, 276480, 0xdc07f3c9 +0, 255000, 276480, 0x27ff7a5d +0, 262500, 276480, 0x18d4b27d +0, 270000, 276480, 0x97612c4b +0, 277500, 276480, 0x4ec4d57f +0, 285000, 276480, 0xbd98f57c +0, 292500, 276480, 0xa5d670ec +0, 300000, 276480, 0x99170e64 +0, 307500, 276480, 0x7a4f2561 +0, 315000, 276480, 0x6a45425f +0, 322500, 276480, 0xd75482c6 +0, 330000, 276480, 0x6de1e34b +0, 337500, 276480, 0xf964e18e +0, 345000, 276480, 0xd1e98808 +0, 352500, 276480, 0x0cf65540 +0, 360000, 276480, 0x22c50a3d +0, 367500, 276480, 0xf4b1c461 +0, 375000, 276480, 0x51e9b3eb +0, 382500, 276480, 0x6dd14ca6 +0, 390000, 276480, 0xfb01efc6 +0, 397500, 276480, 0x5ac8e06f +0, 405000, 276480, 0xe04ac45e +0, 412500, 276480, 0xf688a3ed +0, 420000, 276480, 0xf0b3b71b +0, 427500, 276480, 0x01840548 +0, 435000, 276480, 0x41dda2d9 +0, 442500, 276480, 0x9b209f41 +0, 450000, 276480, 0x28b54815 +0, 457500, 276480, 0x34484aff +0, 465000, 276480, 0x8facba58 +0, 472500, 276480, 0x02162c7c +0, 480000, 276480, 0x1ad43fd7 +0, 487500, 276480, 0x2b8a89c5 +0, 495000, 276480, 0x35626022 +0, 502500, 276480, 0xce5af1ec +0, 510000, 276480, 0x7fd73a99 +0, 517500, 276480, 0xcb60725a +0, 525000, 276480, 0xd6f82cae +0, 532500, 276480, 0xfa88a483 +0, 540000, 276480, 0x04a8e3ee +0, 547500, 276480, 0x0b41f0d7 +0, 555000, 276480, 0x754ceaf5 +0, 562500, 276480, 0xde084059 +0, 570000, 276480, 0xfcebc261 +0, 577500, 276480, 0x046394ae +0, 585000, 276480, 0x94a03c75 +0, 592500, 276480, 0x6a841f41 +0, 600000, 276480, 0x923b9937 +0, 607500, 276480, 0xee82d657 +0, 615000, 276480, 0x6b9fbc80 +0, 622500, 276480, 0x6d4b49d7 +0, 630000, 276480, 0x225a56c0 +0, 637500, 276480, 0xff4e1a8c +0, 645000, 276480, 0xbaffcdcc +0, 652500, 276480, 0x3d861ae6 +0, 660000, 276480, 0xdb753d35 +0, 667500, 276480, 0xb24c8016 +0, 675000, 276480, 0x2aae902a +0, 682500, 276480, 0x5c6e97a9 +0, 690000, 276480, 0xaa12b6fd +0, 697500, 276480, 0xbf09053c +0, 705000, 276480, 0xdd9fb89f +0, 712500, 276480, 0x0b752d28 +0, 720000, 276480, 0x7ce5f23c +0, 727500, 276480, 0x55dadd30 +0, 735000, 276480, 0xe45a5599 +0, 742500, 276480, 0x2f447fd3 +0, 750000, 276480, 0x9d7430a1 +0, 757500, 276480, 0x51cb657c +0, 765000, 276480, 0x4a4f76cd +0, 772500, 276480, 0x87160f99 +0, 780000, 276480, 0x694d76e3 +0, 787500, 276480, 0x50742e1b +0, 795000, 276480, 0x819898f9 +0, 802500, 276480, 0x35c46927 +0, 810000, 276480, 0xb6f99ee3 +0, 817500, 276480, 0xde97d9fd +0, 825000, 276480, 0xbb22e024 +0, 832500, 276480, 0xbe1fbb19 +0, 840000, 276480, 0x826fc3bd +0, 847500, 276480, 0x5497097b +0, 855000, 276480, 0x976c9e93 +0, 862500, 276480, 0xdc2d7c6c +0, 870000, 276480, 0xf002c5ca +0, 877500, 276480, 0xf62d8581 +0, 885000, 276480, 0x1700efbb +0, 892500, 276480, 0x8f316c66 diff --git a/tests/ref/fate/rv30 b/tests/ref/fate/rv30 index 867151bd66..8777367c8e 100644 --- a/tests/ref/fate/rv30 +++ b/tests/ref/fate/rv30 @@ -2,45 +2,44 @@ 0, 7500, 126720, 0xa416ece5 0, 15000, 126720, 0xa416ece5 0, 22500, 126720, 0x259af497 -0, 30000, 126720, 0x5e6ff4d7 -0, 37500, 126720, 0xeb6fb8d7 +0, 30000, 126720, 0x763ab817 +0, 37500, 126720, 0xda71b917 0, 45000, 126720, 0xbb1abbb7 -0, 52500, 126720, 0x273fbc37 -0, 60000, 126720, 0x7fa3ae27 -0, 67500, 126720, 0x722e99f7 -0, 75000, 126720, 0x29d6a887 +0, 52500, 126720, 0x16eebbd7 +0, 60000, 126720, 0x722e99f7 +0, 67500, 126720, 0x07beba77 +0, 75000, 126720, 0x9ca7aac7 0, 82500, 126720, 0xd115a757 -0, 90000, 126720, 0x6ddaef32 -0, 97500, 126720, 0x04e7897c +0, 90000, 126720, 0xac6c071b +0, 97500, 126720, 0x5eee050f 0, 105000, 126720, 0x68cfda2b -0, 112500, 126720, 0xe572dfc9 -0, 120000, 126720, 0xbc3cc34f -0, 127500, 126720, 0xcf8cb0e2 -0, 135000, 126720, 0x75ae61b6 +0, 112500, 126720, 0x582fb176 +0, 120000, 126720, 0xcf8cb0e2 +0, 127500, 126720, 0xc6e10f9f +0, 135000, 126720, 0x85597543 0, 142500, 126720, 0x554fe3e4 -0, 150000, 126720, 0x72ecea95 -0, 157500, 126720, 0x5d00b5fe +0, 150000, 126720, 0x9bf6a605 +0, 157500, 126720, 0x93f7b040 0, 165000, 126720, 0xe39bba0d -0, 172500, 126720, 0x9c21bad8 -0, 180000, 126720, 0x72f2a47d -0, 187500, 126720, 0x4f639ebe -0, 195000, 126720, 0x534a10cc +0, 172500, 126720, 0xa567f25b +0, 180000, 126720, 0x4f639ebe +0, 187500, 126720, 0x6cf87d39 +0, 195000, 126720, 0xfdca11d3 0, 202500, 126720, 0x5fd753d8 -0, 210000, 126720, 0x0c735615 -0, 217500, 126720, 0x0eaf0c1b +0, 210000, 126720, 0xeaf3dd0b +0, 217500, 126720, 0xce5e6794 0, 225000, 126720, 0x14cf7974 -0, 232500, 126720, 0x1c2a513d -0, 240000, 126720, 0xbc513f2a -0, 247500, 126720, 0xbc303fae -0, 255000, 126720, 0xd9f67585 +0, 232500, 126720, 0xa3f515ab +0, 240000, 126720, 0xbc303fae +0, 247500, 126720, 0x0a22cc69 +0, 255000, 126720, 0xf92b2a25 0, 262500, 126720, 0x3378251f -0, 270000, 126720, 0xb3ed5911 -0, 277500, 126720, 0xc15a3577 +0, 270000, 126720, 0x8da30275 +0, 277500, 126720, 0xf2942f53 0, 285000, 126720, 0x0a24f256 -0, 292500, 126720, 0xfab9c45d -0, 300000, 126720, 0x45464610 -0, 307500, 126720, 0xfe2e057d -0, 315000, 126720, 0x23efdc35 +0, 292500, 126720, 0x10e939ce +0, 300000, 126720, 0xfe2e057d +0, 307500, 126720, 0x5284da7b +0, 315000, 126720, 0xc9e92bf1 0, 322500, 126720, 0x4d888b2e -0, 330000, 126720, 0xdd0d74df -0, 337500, 126720, 0x08382b8e +0, 330000, 126720, 0x08382b8e From a43b1e74e2abaac6e63eb001474855bd44335988 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Tue, 16 Aug 2011 09:10:57 +0200 Subject: [PATCH 04/23] rmdec: parse FPS in RealMedia properly Signed-off-by: Anton Khirnov --- libavformat/rmdec.c | 16 +- tests/ref/fate/real-rv40 | 355 ++++++++++++++++++++++++++------------- tests/ref/fate/rv30 | 152 ++++++++++++----- 3 files changed, 352 insertions(+), 171 deletions(-) diff --git a/libavformat/rmdec.c b/libavformat/rmdec.c index cf5c46a095..7cf5720fe0 100644 --- a/libavformat/rmdec.c +++ b/libavformat/rmdec.c @@ -293,21 +293,21 @@ ff_rm_read_mdpr_codecdata (AVFormatContext *s, AVIOContext *pb, // av_log(s, AV_LOG_DEBUG, "%X %X\n", st->codec->codec_tag, MKTAG('R', 'V', '2', '0')); if (st->codec->codec_id == CODEC_ID_NONE) goto fail1; - st->codec->width = avio_rb16(pb); + st->codec->width = avio_rb16(pb); st->codec->height = avio_rb16(pb); - st->codec->time_base.num= 1; - fps= avio_rb16(pb); + avio_skip(pb, 2); // looks like bits per sample + avio_skip(pb, 4); // always zero? st->codec->codec_type = AVMEDIA_TYPE_VIDEO; st->need_parsing = AVSTREAM_PARSE_TIMESTAMPS; - avio_rb32(pb); - avio_skip(pb, 2); - avio_rb16(pb); + fps = avio_rb32(pb); if ((ret = rm_read_extradata(pb, st->codec, codec_data_size - (avio_tell(pb) - codec_pos))) < 0) return ret; -// av_log(s, AV_LOG_DEBUG, "fps= %d fps2= %d\n", fps, fps2); - st->codec->time_base.den = fps * st->codec->time_base.num; + av_reduce(&st->codec->time_base.num, &st->codec->time_base.den, + 0x10000, fps, (1 << 30) - 1); + st->avg_frame_rate.num = st->codec->time_base.den; + st->avg_frame_rate.den = st->codec->time_base.num; } skip: diff --git a/tests/ref/fate/real-rv40 b/tests/ref/fate/real-rv40 index 22cc731c89..127cba2b4f 100644 --- a/tests/ref/fate/real-rv40 +++ b/tests/ref/fate/real-rv40 @@ -1,120 +1,237 @@ 0, 0, 276480, 0x5f7a0d4f -0, 7500, 276480, 0x5f7a0d4f -0, 15000, 276480, 0x5f7a0d4f -0, 22500, 276480, 0x5f7a0d4f -0, 30000, 276480, 0x5f7a0d4f -0, 37500, 276480, 0x5f7a0d4f -0, 45000, 276480, 0x5f7a0d4f -0, 52500, 276480, 0x5f7a0d4f -0, 60000, 276480, 0x5f7a0d4f -0, 67500, 276480, 0x5f7a0d4f -0, 75000, 276480, 0x5f7a0d4f -0, 82500, 276480, 0x5f7a0d4f -0, 90000, 276480, 0x5f7a0d4f -0, 97500, 276480, 0x5f7a0d4f -0, 105000, 276480, 0x5f7a0d4f -0, 112500, 276480, 0x5f7a0d4f -0, 120000, 276480, 0x5f7a0d4f -0, 127500, 276480, 0x5f7a0d4f -0, 135000, 276480, 0x32ee3526 -0, 142500, 276480, 0x7ca9658e -0, 150000, 276480, 0x4ec1e418 -0, 157500, 276480, 0xa9f1506f -0, 165000, 276480, 0x377c7b46 -0, 172500, 276480, 0xe1de7f0a -0, 180000, 276480, 0xcb379547 -0, 187500, 276480, 0x8e12331c -0, 195000, 276480, 0xe479ffed -0, 202500, 276480, 0xac7672dd -0, 210000, 276480, 0x776412ef -0, 217500, 276480, 0x1cd1ab29 -0, 225000, 276480, 0x5ab69b27 -0, 232500, 276480, 0x9eca3f11 -0, 240000, 276480, 0xc9c57884 -0, 247500, 276480, 0xdc07f3c9 -0, 255000, 276480, 0x27ff7a5d -0, 262500, 276480, 0x18d4b27d -0, 270000, 276480, 0x97612c4b -0, 277500, 276480, 0x4ec4d57f -0, 285000, 276480, 0xbd98f57c -0, 292500, 276480, 0xa5d670ec -0, 300000, 276480, 0x99170e64 -0, 307500, 276480, 0x7a4f2561 -0, 315000, 276480, 0x6a45425f -0, 322500, 276480, 0xd75482c6 -0, 330000, 276480, 0x6de1e34b -0, 337500, 276480, 0xf964e18e -0, 345000, 276480, 0xd1e98808 -0, 352500, 276480, 0x0cf65540 -0, 360000, 276480, 0x22c50a3d -0, 367500, 276480, 0xf4b1c461 -0, 375000, 276480, 0x51e9b3eb -0, 382500, 276480, 0x6dd14ca6 -0, 390000, 276480, 0xfb01efc6 -0, 397500, 276480, 0x5ac8e06f -0, 405000, 276480, 0xe04ac45e -0, 412500, 276480, 0xf688a3ed -0, 420000, 276480, 0xf0b3b71b -0, 427500, 276480, 0x01840548 -0, 435000, 276480, 0x41dda2d9 -0, 442500, 276480, 0x9b209f41 -0, 450000, 276480, 0x28b54815 -0, 457500, 276480, 0x34484aff -0, 465000, 276480, 0x8facba58 -0, 472500, 276480, 0x02162c7c -0, 480000, 276480, 0x1ad43fd7 -0, 487500, 276480, 0x2b8a89c5 -0, 495000, 276480, 0x35626022 -0, 502500, 276480, 0xce5af1ec -0, 510000, 276480, 0x7fd73a99 -0, 517500, 276480, 0xcb60725a -0, 525000, 276480, 0xd6f82cae -0, 532500, 276480, 0xfa88a483 -0, 540000, 276480, 0x04a8e3ee -0, 547500, 276480, 0x0b41f0d7 -0, 555000, 276480, 0x754ceaf5 -0, 562500, 276480, 0xde084059 -0, 570000, 276480, 0xfcebc261 -0, 577500, 276480, 0x046394ae -0, 585000, 276480, 0x94a03c75 -0, 592500, 276480, 0x6a841f41 -0, 600000, 276480, 0x923b9937 -0, 607500, 276480, 0xee82d657 -0, 615000, 276480, 0x6b9fbc80 -0, 622500, 276480, 0x6d4b49d7 -0, 630000, 276480, 0x225a56c0 -0, 637500, 276480, 0xff4e1a8c -0, 645000, 276480, 0xbaffcdcc -0, 652500, 276480, 0x3d861ae6 -0, 660000, 276480, 0xdb753d35 -0, 667500, 276480, 0xb24c8016 -0, 675000, 276480, 0x2aae902a -0, 682500, 276480, 0x5c6e97a9 -0, 690000, 276480, 0xaa12b6fd -0, 697500, 276480, 0xbf09053c -0, 705000, 276480, 0xdd9fb89f -0, 712500, 276480, 0x0b752d28 -0, 720000, 276480, 0x7ce5f23c -0, 727500, 276480, 0x55dadd30 -0, 735000, 276480, 0xe45a5599 -0, 742500, 276480, 0x2f447fd3 -0, 750000, 276480, 0x9d7430a1 -0, 757500, 276480, 0x51cb657c -0, 765000, 276480, 0x4a4f76cd -0, 772500, 276480, 0x87160f99 -0, 780000, 276480, 0x694d76e3 -0, 787500, 276480, 0x50742e1b -0, 795000, 276480, 0x819898f9 -0, 802500, 276480, 0x35c46927 -0, 810000, 276480, 0xb6f99ee3 -0, 817500, 276480, 0xde97d9fd -0, 825000, 276480, 0xbb22e024 -0, 832500, 276480, 0xbe1fbb19 -0, 840000, 276480, 0x826fc3bd -0, 847500, 276480, 0x5497097b -0, 855000, 276480, 0x976c9e93 -0, 862500, 276480, 0xdc2d7c6c -0, 870000, 276480, 0xf002c5ca -0, 877500, 276480, 0xf62d8581 -0, 885000, 276480, 0x1700efbb -0, 892500, 276480, 0x8f316c66 +0, 3754, 276480, 0x5f7a0d4f +0, 7507, 276480, 0x5f7a0d4f +0, 11261, 276480, 0x5f7a0d4f +0, 15015, 276480, 0x5f7a0d4f +0, 18769, 276480, 0x5f7a0d4f +0, 22522, 276480, 0x5f7a0d4f +0, 26276, 276480, 0x5f7a0d4f +0, 30030, 276480, 0x5f7a0d4f +0, 33784, 276480, 0x5f7a0d4f +0, 37537, 276480, 0x5f7a0d4f +0, 41291, 276480, 0x5f7a0d4f +0, 45045, 276480, 0x5f7a0d4f +0, 48799, 276480, 0x5f7a0d4f +0, 52552, 276480, 0x5f7a0d4f +0, 56306, 276480, 0x5f7a0d4f +0, 60060, 276480, 0x5f7a0d4f +0, 63814, 276480, 0x5f7a0d4f +0, 67567, 276480, 0x5f7a0d4f +0, 71321, 276480, 0x5f7a0d4f +0, 75075, 276480, 0x5f7a0d4f +0, 78829, 276480, 0x5f7a0d4f +0, 82582, 276480, 0x5f7a0d4f +0, 86336, 276480, 0x5f7a0d4f +0, 90090, 276480, 0x5f7a0d4f +0, 93844, 276480, 0x5f7a0d4f +0, 97597, 276480, 0x5f7a0d4f +0, 101351, 276480, 0x5f7a0d4f +0, 105105, 276480, 0x5f7a0d4f +0, 108859, 276480, 0x5f7a0d4f +0, 112612, 276480, 0x5f7a0d4f +0, 116366, 276480, 0x5f7a0d4f +0, 120120, 276480, 0x5f7a0d4f +0, 123874, 276480, 0x75641594 +0, 127627, 276480, 0x32ee3526 +0, 131381, 276480, 0xcb53479a +0, 135135, 276480, 0x7ca9658e +0, 138889, 276480, 0x5ce39368 +0, 142642, 276480, 0x4ec1e418 +0, 146396, 276480, 0xb3790499 +0, 150150, 276480, 0xa9f1506f +0, 153904, 276480, 0x85cbc3b5 +0, 157657, 276480, 0x377c7b46 +0, 161411, 276480, 0x1a61d8db +0, 165165, 276480, 0xe1de7f0a +0, 168919, 276480, 0x756a4a2e +0, 172672, 276480, 0xcb379547 +0, 176426, 276480, 0xbae14484 +0, 180180, 276480, 0x8e12331c +0, 183934, 276480, 0x99c085be +0, 187687, 276480, 0xe479ffed +0, 191441, 276480, 0x99c82949 +0, 195195, 276480, 0xac7672dd +0, 198949, 276480, 0x1e4fae19 +0, 202702, 276480, 0x776412ef +0, 206456, 276480, 0x7d9b579f +0, 210210, 276480, 0x1cd1ab29 +0, 213964, 276480, 0x58ce0f38 +0, 217717, 276480, 0x5ab69b27 +0, 221471, 276480, 0x0afad610 +0, 225225, 276480, 0x9eca3f11 +0, 228979, 276480, 0xc3db9706 +0, 232732, 276480, 0xc9c57884 +0, 236486, 276480, 0xd9fbb2cf +0, 240240, 276480, 0xdc07f3c9 +0, 243994, 276480, 0x000b5269 +0, 247747, 276480, 0x27ff7a5d +0, 251501, 276480, 0xd92e2017 +0, 255255, 276480, 0x18d4b27d +0, 259009, 276480, 0x70647530 +0, 262762, 276480, 0x97612c4b +0, 266516, 276480, 0xc9d4ac78 +0, 270270, 276480, 0x4ec4d57f +0, 274024, 276480, 0xdf4e04d7 +0, 277777, 276480, 0xbd98f57c +0, 281531, 276480, 0x7247ea3e +0, 285285, 276480, 0xa5d670ec +0, 289039, 276480, 0x5163b29b +0, 292792, 276480, 0x99170e64 +0, 296546, 276480, 0x37f4c0b0 +0, 300300, 276480, 0x7a4f2561 +0, 304053, 276480, 0x8a4e991f +0, 307807, 276480, 0x6a45425f +0, 311561, 276480, 0x1f0e2bb6 +0, 315315, 276480, 0xd75482c6 +0, 319068, 276480, 0x7bf6b1ef +0, 322822, 276480, 0x6de1e34b +0, 326576, 276480, 0x4526c89b +0, 330330, 276480, 0xf964e18e +0, 334083, 276480, 0xdcaaa99a +0, 337837, 276480, 0xd1e98808 +0, 341591, 276480, 0x556b2365 +0, 345345, 276480, 0x0cf65540 +0, 349098, 276480, 0x6e2d524e +0, 352852, 276480, 0x22c50a3d +0, 356606, 276480, 0x293f19af +0, 360360, 276480, 0xf4b1c461 +0, 364113, 276480, 0x62b76407 +0, 367867, 276480, 0x51e9b3eb +0, 371621, 276480, 0x7b910bc7 +0, 375375, 276480, 0x6dd14ca6 +0, 379128, 276480, 0x441f7afd +0, 382882, 276480, 0xfb01efc6 +0, 386636, 276480, 0x4f73ccea +0, 390390, 276480, 0x5ac8e06f +0, 394143, 276480, 0x294bb441 +0, 397897, 276480, 0xe04ac45e +0, 401651, 276480, 0xa7a38d41 +0, 405405, 276480, 0xf688a3ed +0, 409158, 276480, 0x58f275ea +0, 412912, 276480, 0xf0b3b71b +0, 416666, 276480, 0x3ce773bf +0, 420420, 276480, 0x01840548 +0, 424173, 276480, 0x674e34e4 +0, 427927, 276480, 0x41dda2d9 +0, 431681, 276480, 0xc5b60838 +0, 435435, 276480, 0x9b209f41 +0, 439188, 276480, 0xf46ba7fb +0, 442942, 276480, 0x28b54815 +0, 446696, 276480, 0xb605a933 +0, 450450, 276480, 0x34484aff +0, 454203, 276480, 0xaf2b5d89 +0, 457957, 276480, 0x8facba58 +0, 461711, 276480, 0xbbe3e99f +0, 465465, 276480, 0x02162c7c +0, 469218, 276480, 0x28a63236 +0, 472972, 276480, 0x1ad43fd7 +0, 476726, 276480, 0xe37883e5 +0, 480480, 276480, 0x2b8a89c5 +0, 484233, 276480, 0x71507bd2 +0, 487987, 276480, 0x35626022 +0, 491741, 276480, 0x461fc3e7 +0, 495495, 276480, 0xce5af1ec +0, 499248, 276480, 0x7c1139b3 +0, 503002, 276480, 0x7fd73a99 +0, 506756, 276480, 0x4ae4c3a6 +0, 510510, 276480, 0xcb60725a +0, 514263, 276480, 0xb52e1aa2 +0, 518017, 276480, 0xd6f82cae +0, 521771, 276480, 0x6310e665 +0, 525525, 276480, 0xfa88a483 +0, 529278, 276480, 0xf88f75d4 +0, 533032, 276480, 0x04a8e3ee +0, 536786, 276480, 0x54766a12 +0, 540540, 276480, 0x0b41f0d7 +0, 544293, 276480, 0xa29f5b01 +0, 548047, 276480, 0x754ceaf5 +0, 551801, 276480, 0x150c0423 +0, 555555, 276480, 0xde084059 +0, 559308, 276480, 0x5a38b4af +0, 563062, 276480, 0xfcebc261 +0, 566816, 276480, 0x0eb9770d +0, 570570, 276480, 0x046394ae +0, 574323, 276480, 0x3d3ca985 +0, 578077, 276480, 0x94a03c75 +0, 581831, 276480, 0x800eea2d +0, 585585, 276480, 0x6a841f41 +0, 589338, 276480, 0x2f98911c +0, 593092, 276480, 0x923b9937 +0, 596846, 276480, 0xe82f8e0f +0, 600600, 276480, 0xee82d657 +0, 604353, 276480, 0xefab7ffd +0, 608107, 276480, 0x6b9fbc80 +0, 611861, 276480, 0x4a1ada47 +0, 615614, 276480, 0x6d4b49d7 +0, 619368, 276480, 0xe4bdbd1e +0, 623122, 276480, 0x225a56c0 +0, 626876, 276480, 0xd4adadad +0, 630629, 276480, 0xff4e1a8c +0, 634383, 276480, 0xf58b1b7c +0, 638137, 276480, 0xbaffcdcc +0, 641891, 276480, 0x374f88f0 +0, 645644, 276480, 0x3d861ae6 +0, 649398, 276480, 0xeb6eb88f +0, 653152, 276480, 0xdb753d35 +0, 656906, 276480, 0x9aa543af +0, 660659, 276480, 0xb24c8016 +0, 664413, 276480, 0xea80a82e +0, 668167, 276480, 0x2aae902a +0, 671921, 276480, 0x5bba3cfb +0, 675674, 276480, 0x5c6e97a9 +0, 679428, 276480, 0x9b9ee961 +0, 683182, 276480, 0xaa12b6fd +0, 686936, 276480, 0xe9d2439f +0, 690689, 276480, 0xbf09053c +0, 694443, 276480, 0x50c31e73 +0, 698197, 276480, 0xdd9fb89f +0, 701951, 276480, 0x3e4e5aec +0, 705704, 276480, 0x0b752d28 +0, 709458, 276480, 0xaf82399a +0, 713212, 276480, 0x7ce5f23c +0, 716966, 276480, 0xad135d0f +0, 720719, 276480, 0x55dadd30 +0, 724473, 276480, 0x5aaa7519 +0, 728227, 276480, 0xe45a5599 +0, 731981, 276480, 0xc8e89913 +0, 735734, 276480, 0x2f447fd3 +0, 739488, 276480, 0x704411fb +0, 743242, 276480, 0x9d7430a1 +0, 746996, 276480, 0x24dd5fd3 +0, 750749, 276480, 0x51cb657c +0, 754503, 276480, 0x2c230702 +0, 758257, 276480, 0x4a4f76cd +0, 762011, 276480, 0xdcd71e88 +0, 765764, 276480, 0x87160f99 +0, 769518, 276480, 0x27f54854 +0, 773272, 276480, 0x694d76e3 +0, 777026, 276480, 0xcbe93c19 +0, 780779, 276480, 0x50742e1b +0, 784533, 276480, 0x525463e2 +0, 788287, 276480, 0x819898f9 +0, 792041, 276480, 0x08fac755 +0, 795794, 276480, 0x35c46927 +0, 799548, 276480, 0xeeed00fc +0, 803302, 276480, 0xb6f99ee3 +0, 807056, 276480, 0xd87f4c73 +0, 810809, 276480, 0xde97d9fd +0, 814563, 276480, 0xefc83107 +0, 818317, 276480, 0xbb22e024 +0, 822071, 276480, 0x53a7cfcb +0, 825824, 276480, 0xbe1fbb19 +0, 829578, 276480, 0x300f922a +0, 833332, 276480, 0x826fc3bd +0, 837086, 276480, 0x679aa57a +0, 840839, 276480, 0x5497097b +0, 844593, 276480, 0x679a53f8 +0, 848347, 276480, 0x976c9e93 +0, 852101, 276480, 0xe80f87f2 +0, 855854, 276480, 0xdc2d7c6c +0, 859608, 276480, 0xb194656e +0, 863362, 276480, 0xf002c5ca +0, 867116, 276480, 0x43fc1c64 +0, 870869, 276480, 0xf62d8581 +0, 874623, 276480, 0xb243dda5 +0, 878377, 276480, 0x1700efbb +0, 882131, 276480, 0x9ebe6ba2 +0, 885884, 276480, 0x8f316c66 diff --git a/tests/ref/fate/rv30 b/tests/ref/fate/rv30 index 8777367c8e..a3c5dcfbbf 100644 --- a/tests/ref/fate/rv30 +++ b/tests/ref/fate/rv30 @@ -1,45 +1,109 @@ 0, 0, 126720, 0xcefaec47 -0, 7500, 126720, 0xa416ece5 -0, 15000, 126720, 0xa416ece5 -0, 22500, 126720, 0x259af497 -0, 30000, 126720, 0x763ab817 -0, 37500, 126720, 0xda71b917 -0, 45000, 126720, 0xbb1abbb7 -0, 52500, 126720, 0x16eebbd7 -0, 60000, 126720, 0x722e99f7 -0, 67500, 126720, 0x07beba77 -0, 75000, 126720, 0x9ca7aac7 -0, 82500, 126720, 0xd115a757 -0, 90000, 126720, 0xac6c071b -0, 97500, 126720, 0x5eee050f -0, 105000, 126720, 0x68cfda2b -0, 112500, 126720, 0x582fb176 -0, 120000, 126720, 0xcf8cb0e2 -0, 127500, 126720, 0xc6e10f9f -0, 135000, 126720, 0x85597543 -0, 142500, 126720, 0x554fe3e4 -0, 150000, 126720, 0x9bf6a605 -0, 157500, 126720, 0x93f7b040 -0, 165000, 126720, 0xe39bba0d -0, 172500, 126720, 0xa567f25b -0, 180000, 126720, 0x4f639ebe -0, 187500, 126720, 0x6cf87d39 -0, 195000, 126720, 0xfdca11d3 -0, 202500, 126720, 0x5fd753d8 -0, 210000, 126720, 0xeaf3dd0b -0, 217500, 126720, 0xce5e6794 -0, 225000, 126720, 0x14cf7974 -0, 232500, 126720, 0xa3f515ab -0, 240000, 126720, 0xbc303fae -0, 247500, 126720, 0x0a22cc69 -0, 255000, 126720, 0xf92b2a25 -0, 262500, 126720, 0x3378251f -0, 270000, 126720, 0x8da30275 -0, 277500, 126720, 0xf2942f53 -0, 285000, 126720, 0x0a24f256 -0, 292500, 126720, 0x10e939ce -0, 300000, 126720, 0xfe2e057d -0, 307500, 126720, 0x5284da7b -0, 315000, 126720, 0xc9e92bf1 -0, 322500, 126720, 0x4d888b2e -0, 330000, 126720, 0x08382b8e +0, 3003, 126720, 0xa416ece5 +0, 6006, 126720, 0xa416ece5 +0, 9009, 126720, 0xa416ece5 +0, 12012, 126720, 0x60d6ed27 +0, 15015, 126720, 0x259af497 +0, 18018, 126720, 0x5e6ff4d7 +0, 21021, 126720, 0xcc10f4b7 +0, 24024, 126720, 0x763ab817 +0, 27027, 126720, 0xeb6fb8d7 +0, 30030, 126720, 0xda71b917 +0, 33033, 126720, 0x0967b8f7 +0, 36036, 126720, 0x4b62b947 +0, 39039, 126720, 0xbb1abbb7 +0, 42042, 126720, 0x273fbc37 +0, 45045, 126720, 0x16eebbd7 +0, 48048, 126720, 0x105eb927 +0, 51051, 126720, 0x7fa3ae27 +0, 54054, 126720, 0x722e99f7 +0, 57057, 126720, 0x5ac9a827 +0, 60060, 126720, 0x07beba77 +0, 63063, 126720, 0x29d6a887 +0, 66066, 126720, 0xa5caab87 +0, 69069, 126720, 0x9ca7aac7 +0, 72072, 126720, 0xb7debcd7 +0, 75075, 126720, 0xd115a757 +0, 78078, 126720, 0x6ddaef32 +0, 81081, 126720, 0xde1bb900 +0, 84084, 126720, 0xac6c071b +0, 87087, 126720, 0x04e7897c +0, 90090, 126720, 0x5eee050f +0, 93093, 126720, 0xe675be59 +0, 96096, 126720, 0xdc3e0837 +0, 99099, 126720, 0x68cfda2b +0, 102102, 126720, 0xe572dfc9 +0, 105105, 126720, 0x582fb176 +0, 108108, 126720, 0xa9477df0 +0, 111111, 126720, 0xbc3cc34f +0, 114114, 126720, 0xcf8cb0e2 +0, 117117, 126720, 0xcff1db35 +0, 120120, 126720, 0xc6e10f9f +0, 123123, 126720, 0x75ae61b6 +0, 126126, 126720, 0x12af3119 +0, 129129, 126720, 0x85597543 +0, 132132, 126720, 0x68c27aca +0, 135135, 126720, 0x554fe3e4 +0, 138138, 126720, 0x72ecea95 +0, 141141, 126720, 0xf4d003d1 +0, 144144, 126720, 0x9bf6a605 +0, 147147, 126720, 0x5d00b5fe +0, 150150, 126720, 0x93f7b040 +0, 153153, 126720, 0x0d6ad154 +0, 156156, 126720, 0x4be8b4ea +0, 159159, 126720, 0xe39bba0d +0, 162162, 126720, 0x9c21bad8 +0, 165165, 126720, 0xa567f25b +0, 168168, 126720, 0x7a82663a +0, 171171, 126720, 0x72f2a47d +0, 174174, 126720, 0x4f639ebe +0, 177177, 126720, 0xab0fce83 +0, 180180, 126720, 0x6cf87d39 +0, 183183, 126720, 0x534a10cc +0, 186186, 126720, 0x6bbcf44c +0, 189189, 126720, 0xfdca11d3 +0, 192192, 126720, 0x7e58f5a6 +0, 195195, 126720, 0x5fd753d8 +0, 198198, 126720, 0x0c735615 +0, 201201, 126720, 0x2a034ebf +0, 204204, 126720, 0xeaf3dd0b +0, 207207, 126720, 0x0eaf0c1b +0, 210210, 126720, 0xce5e6794 +0, 213213, 126720, 0xf27c31c3 +0, 216216, 126720, 0xb64af168 +0, 219219, 126720, 0x14cf7974 +0, 222222, 126720, 0x1c2a513d +0, 225225, 126720, 0xa3f515ab +0, 228228, 126720, 0xcfd62765 +0, 231231, 126720, 0xbc513f2a +0, 234234, 126720, 0xbc303fae +0, 237237, 126720, 0x2f8f69b9 +0, 240240, 126720, 0x0a22cc69 +0, 243243, 126720, 0xd9f67585 +0, 246246, 126720, 0x20403001 +0, 249249, 126720, 0xf92b2a25 +0, 252252, 126720, 0x3c170aad +0, 255255, 126720, 0x3378251f +0, 258258, 126720, 0xb3ed5911 +0, 261261, 126720, 0x35d24ef8 +0, 264264, 126720, 0x8da30275 +0, 267267, 126720, 0xc15a3577 +0, 270270, 126720, 0xf2942f53 +0, 273273, 126720, 0x44d8304a +0, 276276, 126720, 0xd688a932 +0, 279279, 126720, 0x0a24f256 +0, 282282, 126720, 0xfab9c45d +0, 285285, 126720, 0x10e939ce +0, 288288, 126720, 0x97fcaa3a +0, 291291, 126720, 0x45464610 +0, 294294, 126720, 0xfe2e057d +0, 297297, 126720, 0x0b6718ae +0, 300300, 126720, 0x5284da7b +0, 303303, 126720, 0x23efdc35 +0, 306306, 126720, 0xc387b2b3 +0, 309309, 126720, 0xc9e92bf1 +0, 312312, 126720, 0xfbf20a01 +0, 315315, 126720, 0x4d888b2e +0, 318318, 126720, 0xdd0d74df +0, 321321, 126720, 0x49d07aa4 +0, 324324, 126720, 0x08382b8e From c6c6c1aaa64f1ab6823b712c914c81dacc1898aa Mon Sep 17 00:00:00 2001 From: Sven Hesse Date: Tue, 16 Aug 2011 21:26:45 +0200 Subject: [PATCH 05/23] add XMV demuxer Signed-off-by: Diego Biurrun --- Changelog | 1 + doc/general.texi | 2 + libavformat/Makefile | 1 + libavformat/allformats.c | 1 + libavformat/version.h | 2 +- libavformat/xmv.c | 576 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 582 insertions(+), 1 deletion(-) create mode 100644 libavformat/xmv.c diff --git a/Changelog b/Changelog index c43412cf64..293376a2d7 100644 --- a/Changelog +++ b/Changelog @@ -39,6 +39,7 @@ easier to use. The changes are: * Presets in avconv are disabled, because only libx264 used them and presets for libx264 can now be specified using a private option '-preset '. +- XMV demuxer version 0.7: diff --git a/doc/general.texi b/doc/general.texi index be5b570419..430e93aecf 100644 --- a/doc/general.texi +++ b/doc/general.texi @@ -259,6 +259,8 @@ library: @tab Multimedia format used in Westwood Studios games. @item Westwood Studios VQA @tab @tab X @tab Multimedia format used in Westwood Studios games. +@item XMV @tab @tab X + @tab Microsoft video container used in Xbox games. @item xWMA @tab @tab X @tab Microsoft audio container used by XAudio 2. @item YUV4MPEG pipe @tab X @tab X diff --git a/libavformat/Makefile b/libavformat/Makefile index 917b38a0d8..3f84019eb8 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -298,6 +298,7 @@ OBJS-$(CONFIG_WTV_DEMUXER) += wtv.o asfdec.o asf.o asfcrypt.o \ avlanguage.o mpegts.o isom.o riff.o OBJS-$(CONFIG_WV_DEMUXER) += wv.o apetag.o OBJS-$(CONFIG_XA_DEMUXER) += xa.o +OBJS-$(CONFIG_XMV_DEMUXER) += xmv.o OBJS-$(CONFIG_XWMA_DEMUXER) += xwma.o riff.o OBJS-$(CONFIG_YOP_DEMUXER) += yop.o OBJS-$(CONFIG_YUV4MPEGPIPE_MUXER) += yuv4mpeg.o diff --git a/libavformat/allformats.c b/libavformat/allformats.c index f1c3d3b768..17c07a28e0 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -225,6 +225,7 @@ void av_register_all(void) REGISTER_DEMUXER (WTV, wtv); REGISTER_DEMUXER (WV, wv); REGISTER_DEMUXER (XA, xa); + REGISTER_DEMUXER (XMV, xmv); REGISTER_DEMUXER (XWMA, xwma); REGISTER_DEMUXER (YOP, yop); REGISTER_MUXDEMUX (YUV4MPEGPIPE, yuv4mpegpipe); diff --git a/libavformat/version.h b/libavformat/version.h index 4473717fd7..36f14390e5 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -24,7 +24,7 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 53 -#define LIBAVFORMAT_VERSION_MINOR 4 +#define LIBAVFORMAT_VERSION_MINOR 5 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ diff --git a/libavformat/xmv.c b/libavformat/xmv.c new file mode 100644 index 0000000000..a6081aff7b --- /dev/null +++ b/libavformat/xmv.c @@ -0,0 +1,576 @@ +/* + * Microsoft XMV demuxer + * Copyright (c) 2011 Sven Hesse + * Copyright (c) 2011 Matthew Hoops + * + * This file is part of Libav. + * + * Libav 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. + * + * Libav 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 Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Microsoft XMV demuxer + */ + +#include + +#include "libavutil/intreadwrite.h" + +#include "avformat.h" +#include "riff.h" + +#define XMV_MIN_HEADER_SIZE 36 + +#define XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT 1 +#define XMV_AUDIO_ADPCM51_FRONTCENTERLOW 2 +#define XMV_AUDIO_ADPCM51_REARLEFTRIGHT 4 + +#define XMV_AUDIO_ADPCM51 (XMV_AUDIO_ADPCM51_FRONTLEFTRIGHT | \ + XMV_AUDIO_ADPCM51_FRONTCENTERLOW | \ + XMV_AUDIO_ADPCM51_REARLEFTRIGHT) + +typedef struct XMVAudioTrack { + uint16_t compression; + uint16_t channels; + uint32_t sample_rate; + uint16_t bits_per_sample; + uint32_t bit_rate; + uint16_t flags; + uint16_t block_align; + uint16_t block_samples; + + enum CodecID codec_id; +} XMVAudioTrack; + +typedef struct XMVVideoPacket { + /* The decoder stream index for this video packet. */ + int stream_index; + + uint32_t data_size; + uint32_t data_offset; + + uint32_t current_frame; + uint32_t frame_count; + + /* Does the video packet contain extra data? */ + int has_extradata; + + /* Extra data */ + uint8_t extradata[4]; + + int64_t last_pts; + int64_t pts; +} XMVVideoPacket; + +typedef struct XMVAudioPacket { + /* The decoder stream index for this audio packet. */ + int stream_index; + + /* The audio track this packet encodes. */ + XMVAudioTrack *track; + + uint32_t data_size; + uint32_t data_offset; + + uint32_t frame_size; + + uint32_t block_count; +} XMVAudioPacket; + +typedef struct XMVDemuxContext { + uint16_t audio_track_count; + + XMVAudioTrack *audio_tracks; + + uint32_t this_packet_size; + uint32_t next_packet_size; + + uint32_t this_packet_offset; + uint32_t next_packet_offset; + + uint16_t current_stream; + uint16_t stream_count; + + XMVVideoPacket video; + XMVAudioPacket *audio; +} XMVDemuxContext; + +static int xmv_probe(AVProbeData *p) +{ + uint32_t file_version; + + if (p->buf_size < XMV_MIN_HEADER_SIZE) + return 0; + + file_version = AV_RL32(p->buf + 16); + if ((file_version == 0) || (file_version > 4)) + return 0; + + if (!memcmp(p->buf + 12, "xobX", 4)) + return AVPROBE_SCORE_MAX; + + return 0; +} + +static int xmv_read_header(AVFormatContext *s, + AVFormatParameters *ap) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + AVStream *vst = NULL; + + uint32_t file_version; + uint32_t this_packet_size; + uint16_t audio_track; + + avio_skip(pb, 4); /* Next packet size */ + + this_packet_size = avio_rl32(pb); + + avio_skip(pb, 4); /* Max packet size */ + avio_skip(pb, 4); /* "xobX" */ + + file_version = avio_rl32(pb); + if ((file_version != 4) && (file_version != 2)) + av_log_ask_for_sample(s, "Found uncommon version %d\n", file_version); + + + /* Video track */ + + vst = av_new_stream(s, 0); + if (!vst) + return AVERROR(ENOMEM); + + av_set_pts_info(vst, 32, 1, 1000); + + vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; + vst->codec->codec_id = CODEC_ID_WMV2; + vst->codec->codec_tag = MKBETAG('W', 'M', 'V', '2'); + vst->codec->width = avio_rl32(pb); + vst->codec->height = avio_rl32(pb); + + vst->duration = avio_rl32(pb); + + xmv->video.stream_index = vst->index; + + /* Audio tracks */ + + xmv->audio_track_count = avio_rl16(pb); + + avio_skip(pb, 2); /* Unknown (padding?) */ + + xmv->audio_tracks = av_malloc(xmv->audio_track_count * sizeof(XMVAudioTrack)); + if (!xmv->audio_tracks) + return AVERROR(ENOMEM); + + xmv->audio = av_malloc(xmv->audio_track_count * sizeof(XMVAudioPacket)); + if (!xmv->audio) + return AVERROR(ENOMEM); + + for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) { + XMVAudioTrack *track = &xmv->audio_tracks[audio_track]; + XMVAudioPacket *packet = &xmv->audio [audio_track]; + AVStream *ast = NULL; + + track->compression = avio_rl16(pb); + track->channels = avio_rl16(pb); + track->sample_rate = avio_rl32(pb); + track->bits_per_sample = avio_rl16(pb); + track->flags = avio_rl16(pb); + + track->bit_rate = track->bits_per_sample * + track->sample_rate * + track->channels; + track->block_align = 36 * track->channels; + track->block_samples = 64; + track->codec_id = ff_wav_codec_get_id(track->compression, + track->bits_per_sample); + + packet->track = track; + packet->stream_index = -1; + + packet->frame_size = 0; + packet->block_count = 0; + + /* TODO: ADPCM'd 5.1 sound is encoded in three separate streams. + * Those need to be interleaved to a proper 5.1 stream. */ + if (track->flags & XMV_AUDIO_ADPCM51) + av_log(s, AV_LOG_WARNING, "Unsupported 5.1 ADPCM audio stream " + "(0x%04X)\n", track->flags); + + ast = av_new_stream(s, audio_track); + if (!ast) + return AVERROR(ENOMEM); + + ast->codec->codec_type = AVMEDIA_TYPE_AUDIO; + ast->codec->codec_id = track->codec_id; + ast->codec->codec_tag = track->compression; + ast->codec->channels = track->channels; + ast->codec->sample_rate = track->sample_rate; + ast->codec->bits_per_coded_sample = track->bits_per_sample; + ast->codec->bit_rate = track->bit_rate; + ast->codec->block_align = 36 * track->channels; + + av_set_pts_info(ast, 32, track->block_samples, track->sample_rate); + + packet->stream_index = ast->index; + + ast->duration = vst->duration; + } + + + /** Initialize the packet context */ + + xmv->next_packet_offset = avio_tell(pb); + + xmv->next_packet_size = this_packet_size - xmv->next_packet_offset; + xmv->this_packet_size = 0; + + xmv->video.current_frame = 0; + xmv->video.frame_count = 0; + xmv->video.pts = 0; + xmv->video.last_pts = 0; + + xmv->current_stream = 0; + xmv->stream_count = xmv->audio_track_count + 1; + + return 0; +} + +static void xmv_read_extradata(uint8_t *extradata, AVIOContext *pb) +{ + /* Read the XMV extradata */ + + uint32_t data = avio_rl32(pb); + + int mspel_bit = !!(data & 0x01); + int loop_filter = !!(data & 0x02); + int abt_flag = !!(data & 0x04); + int j_type_bit = !!(data & 0x08); + int top_left_mv_flag = !!(data & 0x10); + int per_mb_rl_bit = !!(data & 0x20); + int slice_count = (data >> 6) & 7; + + /* Write it back as standard WMV2 extradata */ + + data = 0; + + data |= mspel_bit << 15; + data |= loop_filter << 14; + data |= abt_flag << 13; + data |= j_type_bit << 12; + data |= top_left_mv_flag << 11; + data |= per_mb_rl_bit << 10; + data |= slice_count << 7; + + AV_WB32(extradata, data); +} + +static int xmv_process_packet_header(AVFormatContext *s) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + + uint8_t data[8]; + uint16_t audio_track; + uint32_t data_offset; + + /* Next packet size */ + xmv->next_packet_size = avio_rl32(pb); + + /* Packet video header */ + + if (avio_read(pb, data, 8) != 8) + return AVERROR(EIO); + + xmv->video.data_size = AV_RL32(data) & 0x007FFFFF; + + xmv->video.current_frame = 0; + xmv->video.frame_count = (AV_RL32(data) >> 23) & 0xFF; + + xmv->video.has_extradata = (data[3] & 0x80) != 0; + + /* Adding the audio data sizes and the video data size keeps you 4 bytes + * short for every audio track. But as playing around with XMV files with + * ADPCM audio showed, taking the extra 4 bytes from the audio data gives + * you either completely distorted audio or click (when skipping the + * remaining 68 bytes of the ADPCM block). Substracting 4 bytes for every + * audio track from the video data works at least for the audio. Probably + * some alignment thing? + * The video data has (always?) lots of padding, so it should work out... + */ + xmv->video.data_size -= xmv->audio_track_count * 4; + + xmv->current_stream = 0; + if (!xmv->video.frame_count) { + xmv->video.frame_count = 1; + xmv->current_stream = 1; + } + + /* Packet audio header */ + + for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) { + XMVAudioPacket *packet = &xmv->audio[audio_track]; + + if (avio_read(pb, data, 4) != 4) + return AVERROR(EIO); + + packet->data_size = AV_RL32(data) & 0x007FFFFF; + if ((packet->data_size == 0) && (audio_track != 0)) + /* This happens when I create an XMV with several identical audio + * streams. From the size calculations, duplicating the previous + * stream's size works out, but the track data itself is silent. + * Maybe this should also redirect the offset to the previous track? + */ + packet->data_size = xmv->audio[audio_track - 1].data_size; + + /** Carve up the audio data in frame_count slices */ + packet->frame_size = packet->data_size / xmv->video.frame_count; + packet->frame_size -= packet->frame_size % packet->track->block_align; + } + + /* Packet data offsets */ + + data_offset = avio_tell(pb); + + xmv->video.data_offset = data_offset; + data_offset += xmv->video.data_size; + + for (audio_track = 0; audio_track < xmv->audio_track_count; audio_track++) { + xmv->audio[audio_track].data_offset = data_offset; + data_offset += xmv->audio[audio_track].data_size; + } + + /* Video frames header */ + + /* Read new video extra data */ + if (xmv->video.data_size > 0) { + if (xmv->video.has_extradata) { + xmv_read_extradata(xmv->video.extradata, pb); + + xmv->video.data_size -= 4; + xmv->video.data_offset += 4; + + if (xmv->video.stream_index >= 0) { + AVStream *vst = s->streams[xmv->video.stream_index]; + + assert(xmv->video.stream_index < s->nb_streams); + + if (vst->codec->extradata_size < 4) { + av_free(vst->codec->extradata); + + vst->codec->extradata = + av_malloc(4 + FF_INPUT_BUFFER_PADDING_SIZE); + vst->codec->extradata_size = 4; + } + + memcpy(vst->codec->extradata, xmv->video.extradata, 4); + } + } + } + + return 0; +} + +static int xmv_fetch_new_packet(AVFormatContext *s) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + int result; + + /* Seek to it */ + xmv->this_packet_offset = xmv->next_packet_offset; + if (avio_seek(pb, xmv->this_packet_offset, SEEK_SET) != xmv->this_packet_offset) + return AVERROR(EIO); + + /* Update the size */ + xmv->this_packet_size = xmv->next_packet_size; + if (xmv->this_packet_size < (12 + xmv->audio_track_count * 4)) + return AVERROR(EIO); + + /* Process the header */ + result = xmv_process_packet_header(s); + if (result) + return result; + + /* Update the offset */ + xmv->next_packet_offset = xmv->this_packet_offset + xmv->this_packet_size; + + return 0; +} + +static int xmv_fetch_audio_packet(AVFormatContext *s, + AVPacket *pkt, uint32_t stream) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + XMVAudioPacket *audio = &xmv->audio[stream]; + + uint32_t data_size; + uint32_t block_count; + int result; + + /* Seek to it */ + if (avio_seek(pb, audio->data_offset, SEEK_SET) != audio->data_offset) + return AVERROR(EIO); + + if ((xmv->video.current_frame + 1) < xmv->video.frame_count) + /* Not the last frame, get at most frame_size bytes. */ + data_size = FFMIN(audio->frame_size, audio->data_size); + else + /* Last frame, get the rest. */ + data_size = audio->data_size; + + /* Read the packet */ + result = av_get_packet(pb, pkt, data_size); + if (result <= 0) + return result; + + pkt->stream_index = audio->stream_index; + + /* Calculate the PTS */ + + block_count = data_size / audio->track->block_align; + + pkt->duration = block_count; + pkt->pts = audio->block_count; + pkt->dts = AV_NOPTS_VALUE; + + audio->block_count += block_count; + + /* Advance offset */ + audio->data_size -= data_size; + audio->data_offset += data_size; + + return 0; +} + +static int xmv_fetch_video_packet(AVFormatContext *s, + AVPacket *pkt) +{ + XMVDemuxContext *xmv = s->priv_data; + AVIOContext *pb = s->pb; + XMVVideoPacket *video = &xmv->video; + + int result; + uint32_t frame_header; + uint32_t frame_size, frame_timestamp; + uint32_t i; + + /* Seek to it */ + if (avio_seek(pb, video->data_offset, SEEK_SET) != video->data_offset) + return AVERROR(EIO); + + /* Read the frame header */ + frame_header = avio_rl32(pb); + + frame_size = (frame_header & 0x1FFFF) * 4 + 4; + frame_timestamp = (frame_header >> 17); + + if ((frame_size + 4) > video->data_size) + return AVERROR(EIO); + + /* Create the packet */ + result = av_new_packet(pkt, frame_size); + if (result) + return result; + + /* Contrary to normal WMV2 video, the bit stream in XMV's + * WMV2 is little-endian. + * TODO: This manual swap is of course suboptimal. + */ + for (i = 0; i < frame_size; i += 4) + AV_WB32(pkt->data + i, avio_rl32(pb)); + + pkt->stream_index = video->stream_index; + + /* Calculate the PTS */ + + video->last_pts = frame_timestamp + video->pts; + + pkt->duration = 0; + pkt->pts = video->last_pts; + pkt->dts = AV_NOPTS_VALUE; + + video->pts += frame_timestamp; + + /* Keyframe? */ + pkt->flags = (pkt->data[0] & 0x80) ? 0 : AV_PKT_FLAG_KEY; + + /* Advance offset */ + video->data_size -= frame_size + 4; + video->data_offset += frame_size + 4; + + return 0; +} + +static int xmv_read_packet(AVFormatContext *s, + AVPacket *pkt) +{ + XMVDemuxContext *xmv = s->priv_data; + int result; + + if (xmv->video.current_frame == xmv->video.frame_count) { + /* No frames left in this packet, so we fetch a new one */ + + result = xmv_fetch_new_packet(s); + if (result) + return result; + } + + if (xmv->current_stream == 0) { + /* Fetch a video frame */ + + result = xmv_fetch_video_packet(s, pkt); + if (result) + return result; + + } else { + /* Fetch an audio frame */ + + result = xmv_fetch_audio_packet(s, pkt, xmv->current_stream - 1); + if (result) + return result; + } + + /* Increase our counters */ + if (++xmv->current_stream >= xmv->stream_count) { + xmv->current_stream = 0; + xmv->video.current_frame += 1; + } + + return 0; +} + +static int xmv_read_close(AVFormatContext *s) +{ + XMVDemuxContext *xmv = s->priv_data; + + av_free(xmv->audio); + av_free(xmv->audio_tracks); + + return 0; +} + +AVInputFormat ff_xmv_demuxer = { + .name = "xmv", + .long_name = NULL_IF_CONFIG_SMALL("Microsoft XMV"), + .priv_data_size = sizeof(XMVDemuxContext), + .read_probe = xmv_probe, + .read_header = xmv_read_header, + .read_packet = xmv_read_packet, + .read_close = xmv_read_close, +}; From 91e209d720abf9f2851dc606859ab83c405591b1 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Wed, 17 Aug 2011 15:07:49 +0200 Subject: [PATCH 06/23] RV3/4 parser: remove unused variable 'off' Signed-off-by: Diego Biurrun --- libavcodec/rv34_parser.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/rv34_parser.c b/libavcodec/rv34_parser.c index c2563a5fdc..ce8604345e 100644 --- a/libavcodec/rv34_parser.c +++ b/libavcodec/rv34_parser.c @@ -43,7 +43,6 @@ static int rv34_parse(AVCodecParserContext *s, const uint8_t *buf, int buf_size) { RV34ParseContext *pc = s->priv_data; - int off; int type, pts, hdr; if (buf_size < 13 + *buf * 8) { @@ -52,7 +51,6 @@ static int rv34_parse(AVCodecParserContext *s, return buf_size; } - off = AV_RL32(buf + 5); hdr = AV_RB32(buf + 9 + *buf * 8); if (avctx->codec_id == CODEC_ID_RV30) { type = (hdr >> 27) & 3; From f056fc2c6ce73267c7fcb15f1aad2c2109813fee Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Wed, 17 Aug 2011 15:35:42 +0200 Subject: [PATCH 07/23] ffmpeg: remove unsed variable nopts --- ffmpeg.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ffmpeg.c b/ffmpeg.c index 1443dd3dc8..c4ac3f9f62 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -695,7 +695,6 @@ static int read_avserver_streams(AVFormatContext *s, const char *filename) { int i, err; AVFormatContext *ic = NULL; - int nopts = 0; err = avformat_open_input(&ic, filename, NULL, NULL); if (err < 0) @@ -726,9 +725,6 @@ static int read_avserver_streams(AVFormatContext *s, const char *filename) } else choose_pixel_fmt(st, codec); } - - if(st->codec->flags & CODEC_FLAG_BITEXACT) - nopts = 1; } av_close_input_file(ic); From 9be3c1245f6a4331baf1beb28d368cbdaa1b47f5 Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Tue, 16 Aug 2011 14:41:16 -0700 Subject: [PATCH 08/23] avconv: Don't unnecessarily convert ipts to a double. --- avconv.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/avconv.c b/avconv.c index 66772aab9c..50fa1a70db 100644 --- a/avconv.c +++ b/avconv.c @@ -2213,25 +2213,26 @@ static int transcode(AVFormatContext **output_files, for(; received_sigterm == 0;) { int file_index, ist_index; AVPacket pkt; - double ipts_min; + int64_t ipts_min; double opts_min; redo: - ipts_min= 1e100; + ipts_min = INT64_MAX; opts_min= 1e100; /* select the stream that we must read now by looking at the smallest output pts */ file_index = -1; for(i=0;ifile_index]; ist = &input_streams[ost->source_index]; if(ist->is_past_recording_time || no_packet[ist->file_index]) continue; opts = ost->st->pts.val * av_q2d(ost->st->time_base); - ipts = (double)ist->pts; + ipts = ist->pts; if (!input_files[ist->file_index].eof_reached){ if(ipts < ipts_min) { ipts_min = ipts; From 87ef060c3b0425d520ae42cd3dd61dd6574a5c26 Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Tue, 16 Aug 2011 18:43:27 -0700 Subject: [PATCH 09/23] avconv: Factorize video resampling. --- avconv.c | 120 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 65 insertions(+), 55 deletions(-) diff --git a/avconv.c b/avconv.c index 50fa1a70db..6fa3e9426f 100644 --- a/avconv.c +++ b/avconv.c @@ -1030,14 +1030,76 @@ static void do_subtitle_out(AVFormatContext *s, static int bit_buffer_size= 1024*256; static uint8_t *bit_buffer= NULL; +static void do_video_resample(OutputStream *ost, + InputStream *ist, + AVFrame *in_picture, + AVFrame **out_picture) +{ + int resample_changed = 0; + AVCodecContext *dec = ist->st->codec; + *out_picture = in_picture; + + resample_changed = ost->resample_width != dec->width || + ost->resample_height != dec->height || + ost->resample_pix_fmt != dec->pix_fmt; + + if (resample_changed) { + av_log(NULL, AV_LOG_INFO, + "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", + ist->file_index, ist->st->index, + ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt), + dec->width , dec->height , av_get_pix_fmt_name(dec->pix_fmt)); + if(!ost->video_resample) + ost->video_resample = 1; + } + +#if !CONFIG_AVFILTER + if (ost->video_resample) { + *out_picture = &ost->pict_tmp; + if (resample_changed) { + /* initialize a new scaler context */ + sws_freeContext(ost->img_resample_ctx); + ost->img_resample_ctx = sws_getContext( + ist->st->codec->width, + ist->st->codec->height, + ist->st->codec->pix_fmt, + ost->st->codec->width, + ost->st->codec->height, + ost->st->codec->pix_fmt, + ost->sws_flags, NULL, NULL, NULL); + if (ost->img_resample_ctx == NULL) { + fprintf(stderr, "Cannot get resampling context\n"); + exit_program(1); + } + } + sws_scale(ost->img_resample_ctx, in_picture->data, in_picture->linesize, + 0, ost->resample_height, (*out_picture)->data, (*out_picture)->linesize); + } +#else + if (resample_changed) { + avfilter_graph_free(&ost->graph); + if (configure_video_filters(ist, ost)) { + fprintf(stderr, "Error reinitialising filters!\n"); + exit_program(1); + } + } +#endif + if (resample_changed) { + ost->resample_width = dec->width; + ost->resample_height = dec->height; + ost->resample_pix_fmt = dec->pix_fmt; + } +} + + static void do_video_out(AVFormatContext *s, OutputStream *ost, InputStream *ist, AVFrame *in_picture, int *frame_size, float quality) { - int nb_frames, i, ret, resample_changed; - AVFrame *final_picture, *formatted_picture; + int nb_frames, i, ret; + AVFrame *final_picture; AVCodecContext *enc, *dec; double sync_ipts; @@ -1080,59 +1142,7 @@ static void do_video_out(AVFormatContext *s, if (nb_frames <= 0) return; - formatted_picture = in_picture; - final_picture = formatted_picture; - - resample_changed = ost->resample_width != dec->width || - ost->resample_height != dec->height || - ost->resample_pix_fmt != dec->pix_fmt; - - if (resample_changed) { - av_log(NULL, AV_LOG_INFO, - "Input stream #%d.%d frame changed from size:%dx%d fmt:%s to size:%dx%d fmt:%s\n", - ist->file_index, ist->st->index, - ost->resample_width, ost->resample_height, av_get_pix_fmt_name(ost->resample_pix_fmt), - dec->width , dec->height , av_get_pix_fmt_name(dec->pix_fmt)); - if(!ost->video_resample) - ost->video_resample = 1; - } - -#if !CONFIG_AVFILTER - if (ost->video_resample) { - final_picture = &ost->pict_tmp; - if (resample_changed) { - /* initialize a new scaler context */ - sws_freeContext(ost->img_resample_ctx); - ost->img_resample_ctx = sws_getContext( - ist->st->codec->width, - ist->st->codec->height, - ist->st->codec->pix_fmt, - ost->st->codec->width, - ost->st->codec->height, - ost->st->codec->pix_fmt, - ost->sws_flags, NULL, NULL, NULL); - if (ost->img_resample_ctx == NULL) { - fprintf(stderr, "Cannot get resampling context\n"); - exit_program(1); - } - } - sws_scale(ost->img_resample_ctx, formatted_picture->data, formatted_picture->linesize, - 0, ost->resample_height, final_picture->data, final_picture->linesize); - } -#else - if (resample_changed) { - avfilter_graph_free(&ost->graph); - if (configure_video_filters(ist, ost)) { - fprintf(stderr, "Error reinitialising filters!\n"); - exit_program(1); - } - } -#endif - if (resample_changed) { - ost->resample_width = dec->width; - ost->resample_height = dec->height; - ost->resample_pix_fmt = dec->pix_fmt; - } + do_video_resample(ost, ist, in_picture, &final_picture); /* duplicates frame if needed */ for(i=0;i Date: Tue, 16 Aug 2011 19:06:46 -0700 Subject: [PATCH 10/23] avconv: Factorize combining auto vsync with format. --- avconv.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/avconv.c b/avconv.c index 6fa3e9426f..9017d489d8 100644 --- a/avconv.c +++ b/avconv.c @@ -1098,7 +1098,7 @@ static void do_video_out(AVFormatContext *s, AVFrame *in_picture, int *frame_size, float quality) { - int nb_frames, i, ret; + int nb_frames, i, ret, format_video_sync; AVFrame *final_picture; AVCodecContext *enc, *dec; double sync_ipts; @@ -1113,12 +1113,16 @@ static void do_video_out(AVFormatContext *s, *frame_size = 0; - if(video_sync_method){ + format_video_sync = video_sync_method; + if (format_video_sync < 0) + format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? 2 : 1; + + if (format_video_sync) { double vdelta = sync_ipts - ost->sync_opts; //FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c if (vdelta < -1.1) nb_frames = 0; - else if (video_sync_method == 2 || (video_sync_method<0 && (s->oformat->flags & AVFMT_VARIABLE_FPS))){ + else if (format_video_sync == 2) { if(vdelta<=-0.6){ nb_frames=0; }else if(vdelta>0.6) From 88867844c640c01c6cf0f379fc51409d5bf2c056 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 5 Jul 2011 19:38:50 +0200 Subject: [PATCH 11/23] avconv: factor out adding input streams. --- avconv.c | 137 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 74 insertions(+), 63 deletions(-) diff --git a/avconv.c b/avconv.c index 9017d489d8..fbdd899602 100644 --- a/avconv.c +++ b/avconv.c @@ -2861,11 +2861,83 @@ static AVCodec *choose_codec(AVFormatContext *s, AVStream *st, enum AVMediaType return NULL; } +/** + * Add all the streams from the given input file to the global + * list of input streams. + */ +static void add_input_streams(AVFormatContext *ic) +{ + int i, rfps, rfps_base; + + for (i = 0; i < ic->nb_streams; i++) { + AVStream *st = ic->streams[i]; + AVCodecContext *dec = st->codec; + InputStream *ist; + + dec->thread_count = thread_count; + + input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1); + ist = &input_streams[nb_input_streams - 1]; + ist->st = st; + ist->file_index = nb_input_files; + ist->discard = 1; + ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st); + + if (i < nb_ts_scale) + ist->ts_scale = ts_scale[i]; + + ist->dec = choose_codec(ic, st, dec->codec_type, codec_names); + + switch (dec->codec_type) { + case AVMEDIA_TYPE_AUDIO: + if(audio_disable) + st->discard= AVDISCARD_ALL; + break; + case AVMEDIA_TYPE_VIDEO: + rfps = ic->streams[i]->r_frame_rate.num; + rfps_base = ic->streams[i]->r_frame_rate.den; + if (dec->lowres) { + dec->flags |= CODEC_FLAG_EMU_EDGE; + dec->height >>= dec->lowres; + dec->width >>= dec->lowres; + } + if(me_threshold) + dec->debug |= FF_DEBUG_MV; + + if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) { + + if (verbose >= 0) + fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n", + i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num, + + (float)rfps / rfps_base, rfps, rfps_base); + } + + if(video_disable) + st->discard= AVDISCARD_ALL; + else if(video_discard) + st->discard= video_discard; + break; + case AVMEDIA_TYPE_DATA: + break; + case AVMEDIA_TYPE_SUBTITLE: + if(subtitle_disable) + st->discard = AVDISCARD_ALL; + break; + case AVMEDIA_TYPE_ATTACHMENT: + case AVMEDIA_TYPE_UNKNOWN: + break; + default: + abort(); + } + } +} + static int opt_input_file(const char *opt, const char *filename) { AVFormatContext *ic; AVInputFormat *file_iformat = NULL; - int err, i, ret, rfps, rfps_base; + int err, i, ret; int64_t timestamp; uint8_t buf[128]; AVDictionary **opts; @@ -2978,68 +3050,7 @@ static int opt_input_file(const char *opt, const char *filename) } /* update the current parameters so that they match the one of the input stream */ - for(i=0;inb_streams;i++) { - AVStream *st = ic->streams[i]; - AVCodecContext *dec = st->codec; - InputStream *ist; - - dec->thread_count = thread_count; - - input_streams = grow_array(input_streams, sizeof(*input_streams), &nb_input_streams, nb_input_streams + 1); - ist = &input_streams[nb_input_streams - 1]; - ist->st = st; - ist->file_index = nb_input_files; - ist->discard = 1; - ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st); - - if (i < nb_ts_scale) - ist->ts_scale = ts_scale[i]; - - ist->dec = choose_codec(ic, st, dec->codec_type, codec_names); - - switch (dec->codec_type) { - case AVMEDIA_TYPE_AUDIO: - if(audio_disable) - st->discard= AVDISCARD_ALL; - break; - case AVMEDIA_TYPE_VIDEO: - rfps = ic->streams[i]->r_frame_rate.num; - rfps_base = ic->streams[i]->r_frame_rate.den; - if (dec->lowres) { - dec->flags |= CODEC_FLAG_EMU_EDGE; - dec->height >>= dec->lowres; - dec->width >>= dec->lowres; - } - if(me_threshold) - dec->debug |= FF_DEBUG_MV; - - if (dec->time_base.den != rfps*dec->ticks_per_frame || dec->time_base.num != rfps_base) { - - if (verbose >= 0) - fprintf(stderr,"\nSeems stream %d codec frame rate differs from container frame rate: %2.2f (%d/%d) -> %2.2f (%d/%d)\n", - i, (float)dec->time_base.den / dec->time_base.num, dec->time_base.den, dec->time_base.num, - - (float)rfps / rfps_base, rfps, rfps_base); - } - - if(video_disable) - st->discard= AVDISCARD_ALL; - else if(video_discard) - st->discard= video_discard; - break; - case AVMEDIA_TYPE_DATA: - break; - case AVMEDIA_TYPE_SUBTITLE: - if(subtitle_disable) - st->discard = AVDISCARD_ALL; - break; - case AVMEDIA_TYPE_ATTACHMENT: - case AVMEDIA_TYPE_UNKNOWN: - break; - default: - abort(); - } - } + add_input_streams(ic); /* dump the file content */ if (verbose >= 0) From 09af7fb3091d890074f8499547178d0b9323d7d8 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 Aug 2011 09:12:04 +0200 Subject: [PATCH 12/23] avconv: make itsscale syntax consistent with other options. Move the stream specifier to the option name. --- avconv.c | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/avconv.c b/avconv.c index fbdd899602..f3536d2673 100644 --- a/avconv.c +++ b/avconv.c @@ -100,8 +100,7 @@ static const OptionDef options[]; #define MAX_FILES 100 static const char *last_asked_format = NULL; -static double *ts_scale; -static int nb_ts_scale; +static AVDictionary *ts_scale; static AVFormatContext *output_files[MAX_FILES]; static AVDictionary *output_opts[MAX_FILES]; @@ -2777,18 +2776,7 @@ static int opt_map_metadata(const char *opt, const char *arg) static int opt_input_ts_scale(const char *opt, const char *arg) { - unsigned int stream; - double scale; - char *p; - - stream = strtol(arg, &p, 0); - if (*p) - p++; - scale= strtod(p, &p); - - ts_scale = grow_array(ts_scale, sizeof(*ts_scale), &nb_ts_scale, stream + 1); - ts_scale[stream] = scale; - return 0; + return av_dict_set(&ts_scale, opt, arg, 0); } static int opt_recording_time(const char *opt, const char *arg) @@ -2867,12 +2855,14 @@ static AVCodec *choose_codec(AVFormatContext *s, AVStream *st, enum AVMediaType */ static void add_input_streams(AVFormatContext *ic) { - int i, rfps, rfps_base; + int i, rfps, rfps_base, ret; for (i = 0; i < ic->nb_streams; i++) { AVStream *st = ic->streams[i]; AVCodecContext *dec = st->codec; + AVDictionaryEntry *e = NULL; InputStream *ist; + char *scale = NULL; dec->thread_count = thread_count; @@ -2883,8 +2873,16 @@ static void add_input_streams(AVFormatContext *ic) ist->discard = 1; ist->opts = filter_codec_opts(codec_opts, ist->st->codec->codec_id, ic, st); - if (i < nb_ts_scale) - ist->ts_scale = ts_scale[i]; + while (e = av_dict_get(ts_scale, "", e, AV_DICT_IGNORE_SUFFIX)) { + char *p = strchr(e->key, ':'); + + if ((ret = check_stream_specifier(ic, st, p ? p + 1 : "")) > 0) + scale = e->value; + else if (ret < 0) + exit_program(1); + } + if (scale) + ist->ts_scale = strtod(scale, NULL); ist->dec = choose_codec(ic, st, dec->codec_type, codec_names); @@ -3068,8 +3066,7 @@ static int opt_input_file(const char *opt, const char *filename) audio_sample_rate = 0; audio_channels = 0; audio_sample_fmt = AV_SAMPLE_FMT_NONE; - av_freep(&ts_scale); - nb_ts_scale = 0; + av_dict_free(&ts_scale); for (i = 0; i < orig_nb_streams; i++) av_dict_free(&opts[i]); @@ -4061,7 +4058,7 @@ static const OptionDef options[] = { { "fs", HAS_ARG | OPT_INT64, {(void*)&limit_filesize}, "set the limit file size in bytes", "limit_size" }, // { "ss", HAS_ARG, {(void*)opt_start_time}, "set the start time offset", "time_off" }, { "itsoffset", HAS_ARG, {(void*)opt_input_ts_offset}, "set the input ts offset", "time_off" }, - { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "stream:scale" }, + { "itsscale", HAS_ARG, {(void*)opt_input_ts_scale}, "set the input ts scale", "scale" }, { "metadata", HAS_ARG, {(void*)opt_metadata}, "add metadata", "string=string" }, { "dframes", OPT_INT | HAS_ARG, {(void*)&max_frames[AVMEDIA_TYPE_DATA]}, "set the number of data frames to record", "number" }, { "benchmark", OPT_BOOL | OPT_EXPERT, {(void*)&do_benchmark}, From af70aa4526b24f4715ff3eec65a8260b159e71de Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 Aug 2011 09:56:08 +0200 Subject: [PATCH 13/23] avconv: add a wrapper for output AVFormatContexts and merge output_opts into it --- avconv.c | 73 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/avconv.c b/avconv.c index f3536d2673..6b9c1b9eb0 100644 --- a/avconv.c +++ b/avconv.c @@ -102,10 +102,6 @@ static const OptionDef options[]; static const char *last_asked_format = NULL; static AVDictionary *ts_scale; -static AVFormatContext *output_files[MAX_FILES]; -static AVDictionary *output_opts[MAX_FILES]; -static int nb_output_files = 0; - static StreamMap *stream_maps = NULL; static int nb_stream_maps; @@ -310,11 +306,19 @@ typedef struct InputFile { int64_t ts_offset; } InputFile; +typedef struct OutputFile { + AVFormatContext *ctx; + AVDictionary *opts; +} OutputFile; + static InputStream *input_streams = NULL; static int nb_input_streams = 0; static InputFile *input_files = NULL; static int nb_input_files = 0; +static OutputFile *output_files = NULL; +static int nb_output_files = 0; + #if CONFIG_AVFILTER static int configure_video_filters(InputStream *ist, OutputStream *ost) @@ -437,12 +441,12 @@ static int exit_program(int ret) /* close files */ for(i=0;ioformat->flags & AVFMT_NOFILE) && s->pb) avio_close(s->pb); avformat_free_context(s); av_free(output_streams_for_file[i]); - av_dict_free(&output_opts[i]); + av_dict_free(&output_files[i].opts); } for(i=0;ipb); if(total_size<0) // FIXME improve avio_size() so it works with non seekable output too @@ -1607,7 +1612,7 @@ static int output_packet(InputStream *ist, int ist_index, if (ost->picref) ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); #endif - os = output_files[ost->file_index]; + os = output_files[ost->file_index].ctx; /* set the input output pts pairs */ //ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE; @@ -1721,7 +1726,7 @@ static int output_packet(InputStream *ist, int ist_index, ost = ost_table[i]; if (ost->source_index == ist_index) { AVCodecContext *enc= ost->st->codec; - os = output_files[ost->file_index]; + os = output_files[ost->file_index].ctx; if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO && enc->frame_size <=1) continue; @@ -1802,19 +1807,27 @@ static int output_packet(InputStream *ist, int ist_index, return 0; } -static void print_sdp(AVFormatContext **avc, int n) +static void print_sdp(OutputFile *output_files, int n) { char sdp[2048]; + int i; + AVFormatContext **avc = av_malloc(sizeof(*avc)*n); + + if (!avc) + exit_program(1); + for (i = 0; i < n; i++) + avc[i] = output_files[i].ctx; av_sdp_create(avc, n, sdp, sizeof(sdp)); printf("SDP:\n%s\n", sdp); fflush(stdout); + av_freep(&avc); } /* * The following code is the main loop of the file converter */ -static int transcode(AVFormatContext **output_files, +static int transcode(OutputFile *output_files, int nb_output_files, InputFile *input_files, int nb_input_files) @@ -1836,9 +1849,9 @@ static int transcode(AVFormatContext **output_files, /* output stream init */ nb_ostreams = 0; for(i=0;inb_streams && !(os->oformat->flags & AVFMT_NOSTREAMS)) { - av_dump_format(output_files[i], i, output_files[i]->filename, 1); + av_dump_format(os, i, os->filename, 1); fprintf(stderr, "Output file #%d does not contain any stream\n", i); ret = AVERROR(EINVAL); goto fail; @@ -1851,7 +1864,7 @@ static int transcode(AVFormatContext **output_files, goto fail; n = 0; for(k=0;knb_streams; i++, n++) ost_table[n] = output_streams_for_file[k][i]; } @@ -1859,7 +1872,7 @@ static int transcode(AVFormatContext **output_files, /* for each output stream, we compute the right encoding parameters */ for(i=0;ifile_index]; + os = output_files[ost->file_index].ctx; ist = &input_streams[ost->source_index]; codec = ost->st->codec; @@ -2168,15 +2181,15 @@ static int transcode(AVFormatContext **output_files, } /* open files and write file headers */ - for(i=0;ioformat->name, "rtp")) { + assert_avoptions(output_files[i].opts); + if (strcmp(os->oformat->name, "rtp")) { want_sdp = 0; } } @@ -2185,7 +2198,7 @@ static int transcode(AVFormatContext **output_files, /* dump the file output parameters - cannot be done before in case of stream copy */ for(i=0;ifilename, 1); + av_dump_format(output_files[i].ctx, i, output_files[i].ctx->filename, 1); } /* dump the stream mapping */ @@ -2240,7 +2253,7 @@ static int transcode(AVFormatContext **output_files, int64_t ipts; double opts; ost = ost_table[i]; - os = output_files[ost->file_index]; + os = output_files[ost->file_index].ctx; ist = &input_streams[ost->source_index]; if(ist->is_past_recording_time || no_packet[ist->file_index]) continue; @@ -2273,7 +2286,7 @@ static int transcode(AVFormatContext **output_files, } /* finish if limit size exhausted */ - if (limit_filesize != 0 && limit_filesize <= avio_tell(output_files[0]->pb)) + if (limit_filesize != 0 && limit_filesize <= avio_tell(output_files[0].ctx->pb)) break; /* read a frame from it and output it in the fifo */ @@ -2374,7 +2387,7 @@ static int transcode(AVFormatContext **output_files, /* write the trailer if needed and close file */ for(i=0;inb_chapters; i++) { @@ -3571,8 +3584,12 @@ static void opt_output_file(const char *filename) av_dict_copy(&oc->metadata, metadata, 0); av_dict_free(&metadata); - av_dict_copy(&output_opts[nb_output_files], format_opts, 0); - output_files[nb_output_files++] = oc; + + if (nb_output_files == MAX_FILES) + exit_program(1); /* a temporary hack until all the other MAX_FILES-sized arrays are removed */ + output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1); + output_files[nb_output_files - 1].ctx = oc; + av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0); /* check filename in case of an image number is expected */ if (oc->oformat->flags & AVFMT_NEEDNUMBER) { From 4288e0316ad22a067e6694aa432bf6464c601c9e Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 Aug 2011 10:21:37 +0200 Subject: [PATCH 14/23] avconv: get rid of the output_streams_for_file vs. ost_table schizophrenia Instead store output streams in the same way as input streams. --- avconv.c | 97 ++++++++++++++++++++++---------------------------------- 1 file changed, 38 insertions(+), 59 deletions(-) diff --git a/avconv.c b/avconv.c index 6b9c1b9eb0..182535dc27 100644 --- a/avconv.c +++ b/avconv.c @@ -276,9 +276,6 @@ typedef struct OutputStream { AVDictionary *opts; } OutputStream; -static OutputStream **output_streams_for_file[MAX_FILES] = { NULL }; -static int nb_output_streams_for_file[MAX_FILES] = { 0 }; - typedef struct InputStream { int file_index; AVStream *st; @@ -309,6 +306,7 @@ typedef struct InputFile { typedef struct OutputFile { AVFormatContext *ctx; AVDictionary *opts; + int ost_index; /* index of the first stream in output_streams */ } OutputFile; static InputStream *input_streams = NULL; @@ -316,6 +314,8 @@ static int nb_input_streams = 0; static InputFile *input_files = NULL; static int nb_input_files = 0; +static OutputStream *output_streams = NULL; +static int nb_output_streams = 0; static OutputFile *output_files = NULL; static int nb_output_files = 0; @@ -445,7 +445,6 @@ static int exit_program(int ret) if (!(s->oformat->flags & AVFMT_NOFILE) && s->pb) avio_close(s->pb); avformat_free_context(s); - av_free(output_streams_for_file[i]); av_dict_free(&output_files[i].opts); } for(i=0;ist->codec; if (!ost->st->stream_copy && enc->coded_frame) q = enc->coded_frame->quality/(float)FF_QP2LAMBDA; @@ -1407,7 +1407,7 @@ static void generate_silence(uint8_t* buf, enum AVSampleFormat sample_fmt, size_ /* pkt = NULL means EOF (needed to flush decoder buffers) */ static int output_packet(InputStream *ist, int ist_index, - OutputStream **ost_table, int nb_ostreams, + OutputStream *ost_table, int nb_ostreams, const AVPacket *pkt) { AVFormatContext *os; @@ -1557,7 +1557,7 @@ static int output_packet(InputStream *ist, int ist_index, #if CONFIG_AVFILTER if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { for (i = 0; i < nb_ostreams; i++) { - ost = ost_table[i]; + ost = &ost_table[i]; if (ost->input_video_filter && ost->source_index == ist_index) { AVRational sar; if (ist->st->sample_aspect_ratio.num) @@ -1600,7 +1600,7 @@ static int output_packet(InputStream *ist, int ist_index, for(i=0;isource_index == ist_index) { #if CONFIG_AVFILTER frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || @@ -1723,7 +1723,7 @@ static int output_packet(InputStream *ist, int ist_index, /* EOF handling */ for(i=0;isource_index == ist_index) { AVCodecContext *enc= ost->st->codec; os = output_files[ost->file_index].ctx; @@ -1832,10 +1832,10 @@ static int transcode(OutputFile *output_files, InputFile *input_files, int nb_input_files) { - int ret = 0, i, j, k, n, nb_ostreams = 0; + int ret = 0, i, j; AVFormatContext *is, *os; AVCodecContext *codec, *icodec; - OutputStream *ost, **ost_table = NULL; + OutputStream *ost; InputStream *ist; char error[1024]; int want_sdp = 1; @@ -1847,7 +1847,6 @@ static int transcode(OutputFile *output_files, input_streams[i].start = av_gettime(); /* output stream init */ - nb_ostreams = 0; for(i=0;inb_streams && !(os->oformat->flags & AVFMT_NOSTREAMS)) { @@ -1856,22 +1855,11 @@ static int transcode(OutputFile *output_files, ret = AVERROR(EINVAL); goto fail; } - nb_ostreams += os->nb_streams; - } - - ost_table = av_mallocz(sizeof(OutputStream *) * nb_ostreams); - if (!ost_table) - goto fail; - n = 0; - for(k=0;knb_streams; i++, n++) - ost_table[n] = output_streams_for_file[k][i]; } /* for each output stream, we compute the right encoding parameters */ - for(i=0;ifile_index].ctx; ist = &input_streams[ost->source_index]; @@ -2099,8 +2087,8 @@ static int transcode(OutputFile *output_files, } /* open each encoder */ - for(i=0;iencoding_needed) { AVCodec *codec = ost->enc; AVCodecContext *dec = input_streams[ost->source_index].st->codec; @@ -2150,8 +2138,8 @@ static int transcode(OutputFile *output_files, /* update requested sample format for the decoder based on the corresponding encoder sample format */ - for (j = 0; j < nb_ostreams; j++) { - ost = ost_table[j]; + for (j = 0; j < nb_output_streams; j++) { + ost = &output_streams[j]; if (ost->source_index == i) { update_sample_fmt(ist->st->codec, codec, ost->st->codec); break; @@ -2204,8 +2192,8 @@ static int transcode(OutputFile *output_files, /* dump the stream mapping */ if (verbose >= 0) { fprintf(stderr, "Stream mapping:\n"); - for(i=0;i #%d.%d", input_streams[ost->source_index].file_index, input_streams[ost->source_index].st->index, @@ -2249,10 +2237,10 @@ static int transcode(OutputFile *output_files, /* select the stream that we must read now by looking at the smallest output pts */ file_index = -1; - for(i=0;ifile_index].ctx; ist = &input_streams[ost->source_index]; if(ist->is_past_recording_time || no_packet[ist->file_index]) @@ -2357,7 +2345,7 @@ static int transcode(OutputFile *output_files, } //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size); - if (output_packet(ist, ist_index, ost_table, nb_ostreams, &pkt) < 0) { + if (output_packet(ist, ist_index, output_streams, nb_output_streams, &pkt) < 0) { if (verbose >= 0) fprintf(stderr, "Error while decoding stream #%d.%d\n", @@ -2372,14 +2360,14 @@ static int transcode(OutputFile *output_files, av_free_packet(&pkt); /* dump report by using the output first video and audio streams */ - print_report(output_files, ost_table, nb_ostreams, 0); + print_report(output_files, output_streams, nb_output_streams, 0); } /* at the end of stream, we must flush the decoder buffers */ for (i = 0; i < nb_input_streams; i++) { ist = &input_streams[i]; if (ist->decoding_needed) { - output_packet(ist, i, ost_table, nb_ostreams, NULL); + output_packet(ist, i, output_streams, nb_output_streams, NULL); } } @@ -2392,11 +2380,11 @@ static int transcode(OutputFile *output_files, } /* dump report by using the first video and audio streams */ - print_report(output_files, ost_table, nb_ostreams, 1); + print_report(output_files, output_streams, nb_output_streams, 1); /* close each encoder */ - for(i=0;iencoding_needed) { av_freep(&ost->st->codec->stats_in); avcodec_close(ost->st->codec); @@ -2420,9 +2408,9 @@ static int transcode(OutputFile *output_files, fail: av_freep(&bit_buffer); - if (ost_table) { - for(i=0;ist->stream_copy) av_freep(&ost->st->codec->extradata); @@ -2442,10 +2430,8 @@ static int transcode(OutputFile *output_files, if (ost->reformat_ctx) av_audio_convert_free(ost->reformat_ctx); av_dict_free(&ost->opts); - av_free(ost); } } - av_free(ost_table); } return ret; } @@ -3124,17 +3110,9 @@ static OutputStream *new_output_stream(AVFormatContext *oc, enum AVMediaType typ exit_program(1); } - output_streams_for_file[nb_output_files] = - grow_array(output_streams_for_file[nb_output_files], - sizeof(*output_streams_for_file[nb_output_files]), - &nb_output_streams_for_file[nb_output_files], - oc->nb_streams); - ost = output_streams_for_file[nb_output_files][idx] = - av_mallocz(sizeof(OutputStream)); - if (!ost) { - fprintf(stderr, "Could not alloc output stream\n"); - exit_program(1); - } + output_streams = grow_array(output_streams, sizeof(*output_streams), &nb_output_streams, + nb_output_streams + 1); + ost = &output_streams[nb_output_streams - 1]; ost->file_index = nb_output_files; ost->index = idx; ost->st = st; @@ -3589,6 +3567,7 @@ static void opt_output_file(const char *filename) exit_program(1); /* a temporary hack until all the other MAX_FILES-sized arrays are removed */ output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1); output_files[nb_output_files - 1].ctx = oc; + output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams; av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0); /* check filename in case of an image number is expected */ @@ -3702,9 +3681,9 @@ static void opt_output_file(const char *filename) av_dict_copy(&oc->metadata, input_files[0].ctx->metadata, AV_DICT_DONT_OVERWRITE); if (metadata_streams_autocopy) - for (i = 0; i < oc->nb_streams; i++) { - InputStream *ist = &input_streams[output_streams_for_file[nb_output_files-1][i]->source_index]; - av_dict_copy(&oc->streams[i]->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); + for (i = output_files[nb_output_files - 1].ost_index; i < nb_output_streams; i++) { + InputStream *ist = &input_streams[output_streams[i].source_index]; + av_dict_copy(&output_streams[i].st->metadata, ist->st->metadata, AV_DICT_DONT_OVERWRITE); } frame_rate = (AVRational){0, 0}; From b0c9e8e0249d9aec66e38e172649c643bb30a267 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 Aug 2011 10:27:17 +0200 Subject: [PATCH 15/23] avconv: get rid of the arbitrary MAX_FILES limit. --- avconv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/avconv.c b/avconv.c index 182535dc27..80924c108d 100644 --- a/avconv.c +++ b/avconv.c @@ -97,8 +97,6 @@ typedef struct MetadataMap { static const OptionDef options[]; -#define MAX_FILES 100 - static const char *last_asked_format = NULL; static AVDictionary *ts_scale; @@ -1839,9 +1837,12 @@ static int transcode(OutputFile *output_files, InputStream *ist; char error[1024]; int want_sdp = 1; - uint8_t no_packet[MAX_FILES]={0}; + uint8_t *no_packet; int no_packet_count=0; + if (!(no_packet = av_mallocz(nb_input_files))) + exit_program(1); + if (rate_emu) for (i = 0; i < nb_input_streams; i++) input_streams[i].start = av_gettime(); @@ -2266,7 +2267,7 @@ static int transcode(OutputFile *output_files, if (file_index < 0) { if(no_packet_count){ no_packet_count=0; - memset(no_packet, 0, sizeof(no_packet)); + memset(no_packet, 0, nb_input_files); usleep(10000); continue; } @@ -2294,7 +2295,7 @@ static int transcode(OutputFile *output_files, } no_packet_count=0; - memset(no_packet, 0, sizeof(no_packet)); + memset(no_packet, 0, nb_input_files); if (do_pkt_dump) { av_pkt_dump_log2(NULL, AV_LOG_DEBUG, &pkt, do_hex_dump, @@ -2407,6 +2408,7 @@ static int transcode(OutputFile *output_files, fail: av_freep(&bit_buffer); + av_freep(&no_packet); if (output_streams) { for (i = 0; i < nb_output_streams; i++) { @@ -3563,8 +3565,6 @@ static void opt_output_file(const char *filename) av_dict_free(&metadata); - if (nb_output_files == MAX_FILES) - exit_program(1); /* a temporary hack until all the other MAX_FILES-sized arrays are removed */ output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1); output_files[nb_output_files - 1].ctx = oc; output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams; From f1176d41af9cd15164b8691e723d412c30da3777 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 Aug 2011 11:33:30 +0200 Subject: [PATCH 16/23] avconv: fix broken indentation. --- avconv.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/avconv.c b/avconv.c index 80924c108d..18af625ce5 100644 --- a/avconv.c +++ b/avconv.c @@ -1599,7 +1599,9 @@ static int output_packet(InputStream *ist, int ist_index, int frame_size; ost = &ost_table[i]; - if (ost->source_index == ist_index) { + if (ost->source_index != ist_index) + continue; + #if CONFIG_AVFILTER frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]); @@ -1706,7 +1708,6 @@ static int output_packet(InputStream *ist, int ist_index, avfilter_unref_buffer(ost->picref); } #endif - } } av_free(buffer_to_free); From 2886aee73f12f11e201f4c229d80eef549a43e1f Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 Aug 2011 14:09:22 +0200 Subject: [PATCH 17/23] avconv: merge two loops in output_packet(). --- avconv.c | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/avconv.c b/avconv.c index 18af625ce5..fe01dc6c08 100644 --- a/avconv.c +++ b/avconv.c @@ -1552,25 +1552,6 @@ static int output_packet(InputStream *ist, int ist_index, avpkt.size = 0; } -#if CONFIG_AVFILTER - if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - for (i = 0; i < nb_ostreams; i++) { - ost = &ost_table[i]; - if (ost->input_video_filter && ost->source_index == ist_index) { - AVRational sar; - if (ist->st->sample_aspect_ratio.num) - sar = ist->st->sample_aspect_ratio; - else - sar = ist->st->codec->sample_aspect_ratio; - // add it to be filtered - av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, - ist->pts, - sar); - } - } - } -#endif - // preprocess audio (volume) if (ist->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { if (audio_volume != 256) { @@ -1603,6 +1584,15 @@ static int output_packet(InputStream *ist, int ist_index, continue; #if CONFIG_AVFILTER + if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + ost->input_video_filter) { + AVRational sar; + if (ist->st->sample_aspect_ratio.num) + sar = ist->st->sample_aspect_ratio; + else + sar = ist->st->codec->sample_aspect_ratio; + av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, ist->pts, sar); + } frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]); while (frame_available) { From ef44a607107e6781947d4fdcdde7b3e148c281d7 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 Aug 2011 11:42:44 +0200 Subject: [PATCH 18/23] avconv: rescue poor abused recording_time global. Keep a per-OutputFile instance of it, thus making -t work with multiple output files. --- avconv.c | 22 ++- tests/ref/fate/feeble-dxa | 1 - tests/ref/fate/lmlm4-demux | 332 ------------------------------------- tests/ref/fate/real-rv40 | 3 + 4 files changed, 16 insertions(+), 342 deletions(-) diff --git a/avconv.c b/avconv.c index fe01dc6c08..65aa853412 100644 --- a/avconv.c +++ b/avconv.c @@ -272,6 +272,7 @@ typedef struct OutputStream { int sws_flags; AVDictionary *opts; + int is_past_recording_time; } OutputStream; typedef struct InputStream { @@ -289,7 +290,6 @@ typedef struct InputStream { double ts_scale; int is_start; /* is 1 at the start and after a discontinuity */ int showed_multi_packet_warning; - int is_past_recording_time; AVDictionary *opts; } InputStream; @@ -305,6 +305,7 @@ typedef struct OutputFile { AVFormatContext *ctx; AVDictionary *opts; int ost_index; /* index of the first stream in output_streams */ + int64_t recording_time; /* desired length of the resulting file in microseconds */ } OutputFile; static InputStream *input_streams = NULL; @@ -1577,12 +1578,20 @@ static int output_packet(InputStream *ist, int ist_index, encode packets and output them */ if (start_time == 0 || ist->pts >= start_time) for(i=0;isource_index != ist_index) continue; + if (of->recording_time != INT64_MAX && + av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + start_time, + (AVRational){1, 1000000}) >= 0) { + ost->is_past_recording_time = 1; + continue; + } + #if CONFIG_AVFILTER if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->input_video_filter) { @@ -2235,7 +2244,7 @@ static int transcode(OutputFile *output_files, ost = &output_streams[i]; os = output_files[ost->file_index].ctx; ist = &input_streams[ost->source_index]; - if(ist->is_past_recording_time || no_packet[ist->file_index]) + if(ost->is_past_recording_time || no_packet[ist->file_index]) continue; opts = ost->st->pts.val * av_q2d(ost->st->time_base); ipts = ist->pts; @@ -2329,13 +2338,6 @@ static int transcode(OutputFile *output_files, } } - /* finish if recording time exhausted */ - if (recording_time != INT64_MAX && - av_compare_ts(pkt.pts, ist->st->time_base, recording_time + start_time, (AVRational){1, 1000000}) >= 0) { - ist->is_past_recording_time = 1; - goto discard_packet; - } - //fprintf(stderr,"read #%d.%d size=%d\n", ist->file_index, ist->st->index, pkt.size); if (output_packet(ist, ist_index, output_streams, nb_output_streams, &pkt) < 0) { @@ -3559,6 +3561,7 @@ static void opt_output_file(const char *filename) output_files = grow_array(output_files, sizeof(*output_files), &nb_output_files, nb_output_files + 1); output_files[nb_output_files - 1].ctx = oc; output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams; + output_files[nb_output_files - 1].recording_time = recording_time; av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0); /* check filename in case of an image number is expected */ @@ -3684,6 +3687,7 @@ static void opt_output_file(const char *filename) audio_channels = 0; audio_sample_fmt = AV_SAMPLE_FMT_NONE; chapters_input_file = INT_MAX; + recording_time = INT64_MAX; av_freep(&meta_data_maps); nb_meta_data_maps = 0; diff --git a/tests/ref/fate/feeble-dxa b/tests/ref/fate/feeble-dxa index 9013f99118..caea4c2e2a 100644 --- a/tests/ref/fate/feeble-dxa +++ b/tests/ref/fate/feeble-dxa @@ -62,4 +62,3 @@ 0, 171000, 921600, 0x5639e670 1, 171429, 1000, 0xa491f3ef 1, 175510, 1000, 0x2c036e18 -1, 179592, 1000, 0x52d65e2a diff --git a/tests/ref/fate/lmlm4-demux b/tests/ref/fate/lmlm4-demux index f322300eee..f3214234d7 100644 --- a/tests/ref/fate/lmlm4-demux +++ b/tests/ref/fate/lmlm4-demux @@ -213,335 +213,3 @@ 1, 265680, 768, 0xfd6c7597 0, 267267, 1327, 0x7d15307c 1, 267840, 768, 0x8d766d40 -0, 270270, 1225, 0x1b5d0f5f -0, 273273, 1173, 0x840efed5 -0, 276276, 1215, 0xa8e0035e -0, 279279, 1295, 0x142918ca -0, 282282, 1144, 0xf50cef50 -0, 285285, 1527, 0x7d13bd9d -0, 288288, 5609, 0x1ae1921d -0, 291291, 1303, 0xabdc264f -0, 294294, 1419, 0x878169bf -0, 297297, 972, 0x00c4a257 -0, 300300, 1277, 0x87d520cf -0, 303303, 1014, 0x5946b4ee -0, 306306, 1177, 0x124e0e23 -0, 309309, 1402, 0x8e6363cc -0, 312312, 1171, 0x9bdaeda2 -0, 315315, 1389, 0x2db53b22 -0, 318318, 1056, 0xd1c3de3e -0, 321321, 1320, 0x1ea142c7 -0, 324324, 1250, 0x33612229 -0, 327327, 1477, 0xb9648b48 -0, 330330, 1522, 0x5352c318 -0, 333333, 1391, 0x5e9157e0 -0, 336336, 5545, 0x569e64c1 -0, 339339, 1354, 0xdb39469e -0, 342342, 1302, 0x79912b5d -0, 345345, 1065, 0x4befcdd2 -0, 348348, 1408, 0x7d2f65a2 -0, 351351, 1727, 0x9cac0398 -0, 354354, 1590, 0xa321b563 -0, 357357, 1039, 0xfa35cabf -0, 360360, 1184, 0xb332fde7 -0, 363363, 669, 0xb10e3783 -0, 366366, 784, 0x57275e09 -0, 369369, 1051, 0xe072cd33 -0, 372372, 1119, 0x635ee9ee -0, 375375, 1147, 0x3916f981 -0, 378378, 1086, 0x306ef895 -0, 381381, 827, 0x213f7aef -0, 384384, 5525, 0x19157827 -0, 387387, 1044, 0xb661abc5 -0, 390390, 1143, 0x032e1109 -0, 393393, 1460, 0x5a2f9503 -0, 396396, 1178, 0xd038141f -0, 399399, 1004, 0x410ec3b2 -0, 402402, 1089, 0xc89af8c9 -0, 405405, 1367, 0x52085e0a -0, 408408, 1115, 0x8bb2ee7f -0, 411411, 1325, 0xc2e05647 -0, 414414, 1295, 0x213951c9 -0, 417417, 1054, 0xbb8bdaae -0, 420420, 1210, 0x431122bd -0, 423423, 1400, 0x47526fcc -0, 426426, 1188, 0x19770b07 -0, 429429, 1301, 0x437161c8 -0, 432432, 5281, 0xc0c92b55 -0, 435435, 840, 0x67da7b2f -0, 438438, 1094, 0x3fd6d944 -0, 441441, 832, 0x0eda74bc -0, 444444, 1096, 0x3300da7b -0, 447447, 1018, 0xa208c971 -0, 450450, 1389, 0x1167724c -0, 453453, 1411, 0xe3be666b -0, 456456, 1294, 0xa8f35cc6 -0, 459459, 1232, 0xfd0d20fd -0, 462462, 1252, 0xadd83a26 -0, 465465, 844, 0xcbaf6a55 -0, 468468, 979, 0x78d9b241 -0, 471471, 1057, 0x6743e16c -0, 474474, 776, 0xfedd6615 -0, 477477, 1158, 0xa39fee34 -0, 480480, 5288, 0x5f26ee02 -0, 483483, 1029, 0xa681bee8 -0, 486486, 1106, 0xa68dea33 -0, 489489, 844, 0x42fd83ec -0, 492492, 779, 0xb5006759 -0, 495495, 951, 0xec13af4f -0, 498498, 1011, 0x90e5c86e -0, 501501, 892, 0x4db48ca4 -0, 504504, 804, 0x59bf73a7 -0, 507507, 1001, 0x10c2b3ff -0, 510510, 879, 0x65c57eaf -0, 513513, 1320, 0x80815836 -0, 516516, 1448, 0xaf457b3b -0, 519519, 1168, 0x65b9f96a -0, 522522, 1002, 0x053fafb9 -0, 525525, 1101, 0x2d30c3d5 -0, 528528, 5314, 0x87cee383 -0, 531531, 1305, 0xb19035db -0, 534534, 1240, 0xdc6a0a65 -0, 537537, 1067, 0x9c88ba67 -0, 540540, 823, 0x2f736a43 -0, 543543, 1183, 0x2ef9f3c9 -0, 546546, 899, 0x3fcc8d11 -0, 549549, 886, 0xccec8d49 -0, 552552, 1190, 0x2d020fa1 -0, 555555, 1017, 0x0776b627 -0, 558558, 1202, 0xbdd808d5 -0, 561561, 998, 0x64c7c246 -0, 564564, 1200, 0x9d6e2289 -0, 567567, 895, 0xa8a68d80 -0, 570570, 748, 0xe61a49fb -0, 573573, 929, 0x30168b50 -0, 576576, 5276, 0xceb2edf2 -0, 579579, 1127, 0xab43ddc3 -0, 582582, 1028, 0xaacfbff5 -0, 585585, 914, 0xb63c8fb0 -0, 588588, 1067, 0xbdacd1ed -0, 591591, 1109, 0x6792ddec -0, 594594, 1310, 0x71bc4da2 -0, 597597, 1098, 0xc464de9b -0, 600600, 1018, 0x6833b875 -0, 603603, 1210, 0x44faf34b -0, 606606, 1200, 0x9ee816f6 -0, 609609, 1461, 0xc76b7d2b -0, 612612, 829, 0x006677e6 -0, 615615, 1145, 0xc769fb13 -0, 618618, 1292, 0xb63225f5 -0, 621621, 1252, 0x0e2a2626 -0, 624624, 5257, 0x3877eca1 -0, 627627, 952, 0x7f708d25 -0, 630630, 1125, 0x140cd81b -0, 633633, 1095, 0x3025dade -0, 636636, 1388, 0xd7494d4e -0, 639639, 1124, 0x0c48ee92 -0, 642642, 1556, 0xa0749ee2 -0, 645645, 1461, 0xe5fd7d7f -0, 648648, 903, 0x07a58303 -0, 651651, 1049, 0x4b6cd03b -0, 654654, 1044, 0x5f47cb48 -0, 657657, 1253, 0xba281c6a -0, 660660, 1618, 0xed7cd040 -0, 663663, 981, 0x2926b6f4 -0, 666666, 1560, 0xa0e1ab73 -0, 669669, 1479, 0x41a77e88 -0, 672672, 5222, 0xc2dbd182 -0, 675675, 925, 0x967580dd -0, 678678, 1284, 0x5b7822e0 -0, 681681, 1512, 0xe84da1e0 -0, 684684, 1514, 0xc38bb09e -0, 687687, 1224, 0x8752228e -0, 690690, 1296, 0xcf053c03 -0, 693693, 1117, 0x9a81e659 -0, 696696, 1090, 0x003ed687 -0, 699699, 1196, 0x3a510937 -0, 702702, 1075, 0x05eec8d4 -0, 705705, 1048, 0x3b19cb96 -0, 708708, 944, 0xaad89770 -0, 711711, 960, 0x94649e4c -0, 714714, 1079, 0x530ddaba -0, 717717, 1150, 0x0339e696 -0, 720720, 5189, 0xb8dac0bf -0, 723723, 1129, 0x3b2cd64d -0, 726726, 962, 0xe9df9a07 -0, 729729, 1113, 0xc6ccddb2 -0, 732732, 1069, 0xf589d4a4 -0, 735735, 889, 0x5f7b8762 -0, 738738, 863, 0xe9c36be4 -0, 741741, 1021, 0xcfb5a737 -0, 744744, 1048, 0x203ac9ff -0, 747747, 1223, 0x3e30fe35 -0, 750750, 814, 0x59c076fc -0, 753753, 1157, 0x0dcf0bd0 -0, 756756, 1691, 0xdd030547 -0, 759759, 1700, 0x7641fb7e -0, 762762, 1791, 0x57ac147b -0, 765765, 2008, 0x3d4483ca -0, 768768, 4579, 0x874aa75b -0, 771771, 1647, 0xeddef621 -0, 774774, 1999, 0x61d4a23a -0, 777777, 1572, 0x1c3ae6e1 -0, 780780, 1803, 0xb31c3a11 -0, 783783, 1919, 0xccbf64e3 -0, 786786, 1720, 0xa4d010e5 -0, 789789, 1721, 0x87ee0c7b -0, 792792, 1626, 0x8211f3d0 -0, 795795, 1675, 0xef8a0b3d -0, 798798, 1609, 0x8731ce06 -0, 801801, 1691, 0xcf24038b -0, 804804, 1637, 0x21d8e1b2 -0, 807807, 1546, 0xc597a700 -0, 810810, 1518, 0xb944bc11 -0, 813813, 1403, 0x999e59a8 -0, 816816, 2467, 0xe69f2507 -0, 819819, 531, 0x3c7cea7e -0, 822822, 555, 0xdf20fb22 -0, 825825, 500, 0xebeee00d -0, 828828, 446, 0x664cc711 -0, 831831, 521, 0xf223df4b -0, 834834, 559, 0x4dc60028 -0, 837837, 593, 0xec440ba9 -0, 840840, 557, 0xef0100b1 -0, 843843, 602, 0x7b1cfd88 -0, 846846, 566, 0x77700a1d -0, 849849, 523, 0x3df7eb64 -0, 852852, 482, 0x5da1dba9 -0, 855855, 541, 0x9c8ff3d7 -0, 858858, 572, 0x3e1204b2 -0, 861861, 549, 0x0921fe3d -0, 864864, 2429, 0xba4fe5a8 -0, 867867, 495, 0xc35ade54 -0, 870870, 453, 0xcc66c9dc -0, 873873, 421, 0x3aa7ce8f -0, 876876, 448, 0x56c6d3d7 -0, 879879, 478, 0x4131d467 -0, 882882, 497, 0xac3ce3ca -0, 885885, 470, 0x41b9d9d3 -0, 888888, 454, 0x44c2d956 -0, 891891, 460, 0x6629db01 -0, 894894, 488, 0x6be2dd68 -0, 897897, 512, 0xda4cf116 -0, 900900, 550, 0x6e990da9 -0, 903903, 561, 0x81180e5e -0, 906906, 689, 0xe58a5a9a -0, 909909, 548, 0xfa1417a9 -0, 912912, 2832, 0x942495a5 -0, 915915, 610, 0x6b201ab9 -0, 918918, 1015, 0x5f36b3f9 -0, 921921, 870, 0x14e48f0c -0, 924924, 716, 0xf4034b52 -0, 927927, 763, 0xcbf4694e -0, 930930, 778, 0xb9396764 -0, 933933, 831, 0x31999005 -0, 936936, 877, 0xc95e977f -0, 939939, 836, 0xb56c7d61 -0, 942942, 853, 0x2d5980cf -0, 945945, 861, 0x25629295 -0, 948948, 897, 0x0ff78a5f -0, 951951, 1016, 0x4dd8cdfd -0, 954954, 1117, 0x763f06c4 -0, 957957, 984, 0xcf7bc906 -0, 960960, 2750, 0xd428962d -0, 963963, 995, 0x5cbdd6a4 -0, 966966, 894, 0xc42b9e25 -0, 969969, 1028, 0xdf8ad906 -0, 972972, 1059, 0x4c49f0cc -0, 975975, 1122, 0x8880eed8 -0, 978978, 1007, 0xa9b4c243 -0, 981981, 1055, 0x6051dcd6 -0, 984984, 1293, 0xc3b32fa5 -0, 987987, 1101, 0xf986f9af -0, 990990, 1272, 0x13883127 -0, 993993, 1037, 0xb97cebff -0, 996996, 980, 0x0931d807 -0, 999999, 928, 0xbc3eb30b -0, 1003002, 1068, 0x62d9e8de -0, 1006005, 852, 0x9278a49a -0, 1009008, 2841, 0x3091d12d -0, 1012011, 931, 0x60f6c26e -0, 1015014, 949, 0x31b9c856 -0, 1018017, 835, 0xfe018775 -0, 1021020, 779, 0x85356cd7 -0, 1024023, 748, 0x862756bf -0, 1027026, 768, 0x0b7d645c -0, 1030029, 786, 0x7c196f5b -0, 1033032, 716, 0x4e8252cc -0, 1036035, 671, 0x0b2d3023 -0, 1039038, 708, 0x3b2b4f25 -0, 1042041, 786, 0x523d670e -0, 1045044, 680, 0x329142ec -0, 1048047, 703, 0x841b456c -0, 1051050, 660, 0x5cf332f1 -0, 1054053, 681, 0xcd7b3915 -0, 1057056, 2445, 0x27660ecb -0, 1060059, 667, 0xf3d53d2a -0, 1063062, 652, 0xe2b037b0 -0, 1066065, 695, 0x200248fc -0, 1069068, 659, 0x7f6434c5 -0, 1072071, 682, 0x8d243afb -0, 1075074, 701, 0x16e6476f -0, 1078077, 636, 0x319a3236 -0, 1081080, 679, 0x81fa41f9 -0, 1084083, 740, 0xb32850af -0, 1087086, 694, 0xe3f832c2 -0, 1090089, 681, 0x8174353f -0, 1093092, 757, 0xebbe5a1f -0, 1096095, 683, 0x9b46383c -0, 1099098, 816, 0xd41e6bdf -0, 1102101, 1058, 0x6170d2e6 -0, 1105104, 2489, 0x58fb28e1 -0, 1108107, 804, 0xb3037da8 -0, 1111110, 1053, 0x81ffc0a8 -0, 1114113, 868, 0xf73583cb -0, 1117116, 875, 0xfa5d85bd -0, 1120119, 723, 0x0714418d -0, 1123122, 670, 0xd04333a1 -0, 1126125, 854, 0x370e730d -0, 1129128, 794, 0x3d8a5e3c -0, 1132131, 836, 0xebe26aa7 -0, 1135134, 871, 0x1da58c5e -0, 1138137, 827, 0xda1e6ccb -0, 1141140, 805, 0x10ad6a44 -0, 1144143, 831, 0x826f6fc9 -0, 1147146, 832, 0xb2517364 -0, 1150149, 887, 0x11bf8a3f -0, 1153152, 2718, 0x26a8a174 -0, 1156155, 805, 0x4d0179f9 -0, 1159158, 699, 0x176c4f45 -0, 1162161, 758, 0xc1fc5b16 -0, 1165164, 707, 0x161b4891 -0, 1168167, 733, 0x99b554c0 -0, 1171170, 671, 0xccee2f89 -0, 1174173, 762, 0xd6416c9d -0, 1177176, 721, 0x2ad94f0c -0, 1180179, 727, 0x6280572e -0, 1183182, 856, 0x0a7b797e -0, 1186185, 843, 0xc64288aa -0, 1189188, 877, 0x6d1c945d -0, 1192191, 780, 0x4ba464e8 -0, 1195194, 808, 0xb3087cca -0, 1198197, 870, 0x75809930 -0, 1201200, 2919, 0x5a80f685 -0, 1204203, 1027, 0xc98add3d -0, 1207206, 1003, 0x0d88bd54 -0, 1210209, 1189, 0xb2f91ec7 -0, 1213212, 1320, 0x5acc4db3 -0, 1216215, 1381, 0xbd585feb -0, 1219218, 1378, 0xe1a656f0 -0, 1222221, 1398, 0x88b57a5e -0, 1225224, 1449, 0x1c737698 -0, 1228227, 1420, 0x6f0f80cd -0, 1231230, 1032, 0x2d16d643 -0, 1234233, 1275, 0x38844729 -0, 1237236, 1112, 0x300207ea -0, 1240239, 1105, 0xa2b700be -0, 1243242, 1283, 0x08d04bef -0, 1246245, 1056, 0xf795d994 -0, 1249248, 3202, 0xebf07050 -0, 1252251, 1034, 0x1099dbe5 -0, 1255254, 922, 0x88be9edc -0, 1258257, 1050, 0xd3d7eb96 -0, 1261260, 979, 0x8de6b302 -0, 1264263, 1053, 0x5de2eca8 diff --git a/tests/ref/fate/real-rv40 b/tests/ref/fate/real-rv40 index 127cba2b4f..c63c525d08 100644 --- a/tests/ref/fate/real-rv40 +++ b/tests/ref/fate/real-rv40 @@ -235,3 +235,6 @@ 0, 878377, 276480, 0x1700efbb 0, 882131, 276480, 0x9ebe6ba2 0, 885884, 276480, 0x8f316c66 +0, 889638, 276480, 0x6348ecf5 +0, 893392, 276480, 0x34b5b78a +0, 897146, 276480, 0xcbf66922 From ea065176b2ce0dcac7630cc833326ef9eb4e6a8c Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 Aug 2011 11:42:44 +0200 Subject: [PATCH 19/23] avconv: rescue poor abused start_time global. Keep a per-OutputFile instance of it, thus making -ss work with multiple output files. --- avconv.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/avconv.c b/avconv.c index 65aa853412..2d53bed84f 100644 --- a/avconv.c +++ b/avconv.c @@ -306,6 +306,7 @@ typedef struct OutputFile { AVDictionary *opts; int ost_index; /* index of the first stream in output_streams */ int64_t recording_time; /* desired length of the resulting file in microseconds */ + int64_t start_time; /* start time in microseconds */ } OutputFile; static InputStream *input_streams = NULL; @@ -644,7 +645,8 @@ static double get_sync_ipts(const OutputStream *ost) { const InputStream *ist = ost->sync_ist; - return (double)(ist->pts - start_time)/AV_TIME_BASE; + OutputFile *of = &output_files[ost->file_index]; + return (double)(ist->pts - of->start_time)/AV_TIME_BASE; } static void write_frame(AVFormatContext *s, AVPacket *pkt, AVCodecContext *avctx, AVBitStreamFilterContext *bsfc){ @@ -1576,8 +1578,7 @@ static int output_packet(InputStream *ist, int ist_index, } /* if output time reached then transcode raw format, encode packets and output them */ - if (start_time == 0 || ist->pts >= start_time) - for(i=0;isource_index != ist_index) continue; + if (of->start_time && ist->pts < of->start_time) + continue; + if (of->recording_time != INT64_MAX && - av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + start_time, + av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time, (AVRational){1, 1000000}) >= 0) { ost->is_past_recording_time = 1; continue; @@ -1642,7 +1646,7 @@ static int output_packet(InputStream *ist, int ist_index, } else { AVFrame avframe; //FIXME/XXX remove this AVPacket opkt; - int64_t ost_tb_start_time= av_rescale_q(start_time, AV_TIME_BASE_Q, ost->st->time_base); + int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); av_init_packet(&opkt); @@ -3562,6 +3566,7 @@ static void opt_output_file(const char *filename) output_files[nb_output_files - 1].ctx = oc; output_files[nb_output_files - 1].ost_index = nb_output_streams - oc->nb_streams; output_files[nb_output_files - 1].recording_time = recording_time; + output_files[nb_output_files - 1].start_time = start_time; av_dict_copy(&output_files[nb_output_files - 1].opts, format_opts, 0); /* check filename in case of an image number is expected */ @@ -3688,6 +3693,7 @@ static void opt_output_file(const char *filename) audio_sample_fmt = AV_SAMPLE_FMT_NONE; chapters_input_file = INT_MAX; recording_time = INT64_MAX; + start_time = 0; av_freep(&meta_data_maps); nb_meta_data_maps = 0; From 45f861283e307c17df303d37c41bc3b2026d5ad0 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 17 Aug 2011 12:08:41 +0200 Subject: [PATCH 20/23] avconv: reindent. --- avconv.c | 238 +++++++++++++++++++++++++++---------------------------- 1 file changed, 119 insertions(+), 119 deletions(-) diff --git a/avconv.c b/avconv.c index 2d53bed84f..b9410e110f 100644 --- a/avconv.c +++ b/avconv.c @@ -1579,137 +1579,137 @@ static int output_packet(InputStream *ist, int ist_index, /* if output time reached then transcode raw format, encode packets and output them */ for (i = 0; i < nb_ostreams; i++) { - OutputFile *of = &output_files[ost_table[i].file_index]; - int frame_size; + OutputFile *of = &output_files[ost_table[i].file_index]; + int frame_size; - ost = &ost_table[i]; - if (ost->source_index != ist_index) - continue; + ost = &ost_table[i]; + if (ost->source_index != ist_index) + continue; - if (of->start_time && ist->pts < of->start_time) - continue; + if (of->start_time && ist->pts < of->start_time) + continue; - if (of->recording_time != INT64_MAX && - av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time, - (AVRational){1, 1000000}) >= 0) { - ost->is_past_recording_time = 1; - continue; - } + if (of->recording_time != INT64_MAX && + av_compare_ts(ist->pts, AV_TIME_BASE_Q, of->recording_time + of->start_time, + (AVRational){1, 1000000}) >= 0) { + ost->is_past_recording_time = 1; + continue; + } #if CONFIG_AVFILTER - if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && - ost->input_video_filter) { - AVRational sar; - if (ist->st->sample_aspect_ratio.num) - sar = ist->st->sample_aspect_ratio; - else - sar = ist->st->codec->sample_aspect_ratio; - av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, ist->pts, sar); - } - frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || - !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]); - while (frame_available) { - AVRational ist_pts_tb; - if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) - get_filtered_video_frame(ost->output_video_filter, &picture, &ost->picref, &ist_pts_tb); - if (ost->picref) - ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); + if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && + ost->input_video_filter) { + AVRational sar; + if (ist->st->sample_aspect_ratio.num) + sar = ist->st->sample_aspect_ratio; + else + sar = ist->st->codec->sample_aspect_ratio; + av_vsrc_buffer_add_frame(ost->input_video_filter, &picture, ist->pts, sar); + } + frame_available = ist->st->codec->codec_type != AVMEDIA_TYPE_VIDEO || + !ost->output_video_filter || avfilter_poll_frame(ost->output_video_filter->inputs[0]); + while (frame_available) { + AVRational ist_pts_tb; + if (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO && ost->output_video_filter) + get_filtered_video_frame(ost->output_video_filter, &picture, &ost->picref, &ist_pts_tb); + if (ost->picref) + ist->pts = av_rescale_q(ost->picref->pts, ist_pts_tb, AV_TIME_BASE_Q); #endif - os = output_files[ost->file_index].ctx; + os = output_files[ost->file_index].ctx; - /* set the input output pts pairs */ - //ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE; + /* set the input output pts pairs */ + //ost->sync_ipts = (double)(ist->pts + input_files[ist->file_index].ts_offset - start_time)/ AV_TIME_BASE; - if (ost->encoding_needed) { - av_assert0(ist->decoding_needed); - switch(ost->st->codec->codec_type) { - case AVMEDIA_TYPE_AUDIO: - do_audio_out(os, ost, ist, decoded_data_buf, decoded_data_size); - break; - case AVMEDIA_TYPE_VIDEO: + if (ost->encoding_needed) { + av_assert0(ist->decoding_needed); + switch(ost->st->codec->codec_type) { + case AVMEDIA_TYPE_AUDIO: + do_audio_out(os, ost, ist, decoded_data_buf, decoded_data_size); + break; + case AVMEDIA_TYPE_VIDEO: #if CONFIG_AVFILTER - if (ost->picref->video && !ost->frame_aspect_ratio) - ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect; + if (ost->picref->video && !ost->frame_aspect_ratio) + ost->st->codec->sample_aspect_ratio = ost->picref->video->pixel_aspect; #endif - do_video_out(os, ost, ist, &picture, &frame_size, - same_quant ? quality : ost->st->codec->global_quality); - if (vstats_filename && frame_size) - do_video_stats(os, ost, frame_size); - break; - case AVMEDIA_TYPE_SUBTITLE: - do_subtitle_out(os, ost, ist, &subtitle, - pkt->pts); - break; - default: - abort(); - } - } else { - AVFrame avframe; //FIXME/XXX remove this - AVPacket opkt; - int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); - - av_init_packet(&opkt); - - if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes) -#if !CONFIG_AVFILTER - continue; -#else - goto cont; -#endif - - /* no reencoding needed : output the packet directly */ - /* force the input stream PTS */ - - avcodec_get_frame_defaults(&avframe); - ost->st->codec->coded_frame= &avframe; - avframe.key_frame = pkt->flags & AV_PKT_FLAG_KEY; - - if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) - audio_size += data_size; - else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - video_size += data_size; - ost->sync_opts++; - } - - opkt.stream_index= ost->index; - if(pkt->pts != AV_NOPTS_VALUE) - opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time; - else - opkt.pts= AV_NOPTS_VALUE; - - if (pkt->dts == AV_NOPTS_VALUE) - opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base); - else - opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); - opkt.dts -= ost_tb_start_time; - - opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); - opkt.flags= pkt->flags; - - //FIXME remove the following 2 lines they shall be replaced by the bitstream filters - if( ost->st->codec->codec_id != CODEC_ID_H264 - && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO - && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO - ) { - if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY)) - opkt.destruct= av_destruct_packet; - } else { - opkt.data = data_buf; - opkt.size = data_size; - } - - write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters); - ost->st->codec->frame_number++; - ost->frame_number++; - av_free_packet(&opkt); + do_video_out(os, ost, ist, &picture, &frame_size, + same_quant ? quality : ost->st->codec->global_quality); + if (vstats_filename && frame_size) + do_video_stats(os, ost, frame_size); + break; + case AVMEDIA_TYPE_SUBTITLE: + do_subtitle_out(os, ost, ist, &subtitle, + pkt->pts); + break; + default: + abort(); } -#if CONFIG_AVFILTER - cont: - frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && - ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]); - if (ost->picref) - avfilter_unref_buffer(ost->picref); + } else { + AVFrame avframe; //FIXME/XXX remove this + AVPacket opkt; + int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); + + av_init_packet(&opkt); + + if ((!ost->frame_number && !(pkt->flags & AV_PKT_FLAG_KEY)) && !copy_initial_nonkeyframes) +#if !CONFIG_AVFILTER + continue; +#else + goto cont; +#endif + + /* no reencoding needed : output the packet directly */ + /* force the input stream PTS */ + + avcodec_get_frame_defaults(&avframe); + ost->st->codec->coded_frame= &avframe; + avframe.key_frame = pkt->flags & AV_PKT_FLAG_KEY; + + if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) + audio_size += data_size; + else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { + video_size += data_size; + ost->sync_opts++; + } + + opkt.stream_index= ost->index; + if(pkt->pts != AV_NOPTS_VALUE) + opkt.pts= av_rescale_q(pkt->pts, ist->st->time_base, ost->st->time_base) - ost_tb_start_time; + else + opkt.pts= AV_NOPTS_VALUE; + + if (pkt->dts == AV_NOPTS_VALUE) + opkt.dts = av_rescale_q(ist->pts, AV_TIME_BASE_Q, ost->st->time_base); + else + opkt.dts = av_rescale_q(pkt->dts, ist->st->time_base, ost->st->time_base); + opkt.dts -= ost_tb_start_time; + + opkt.duration = av_rescale_q(pkt->duration, ist->st->time_base, ost->st->time_base); + opkt.flags= pkt->flags; + + //FIXME remove the following 2 lines they shall be replaced by the bitstream filters + if( ost->st->codec->codec_id != CODEC_ID_H264 + && ost->st->codec->codec_id != CODEC_ID_MPEG1VIDEO + && ost->st->codec->codec_id != CODEC_ID_MPEG2VIDEO + ) { + if(av_parser_change(ist->st->parser, ost->st->codec, &opkt.data, &opkt.size, data_buf, data_size, pkt->flags & AV_PKT_FLAG_KEY)) + opkt.destruct= av_destruct_packet; + } else { + opkt.data = data_buf; + opkt.size = data_size; + } + + write_frame(os, &opkt, ost->st->codec, ost->bitstream_filters); + ost->st->codec->frame_number++; + ost->frame_number++; + av_free_packet(&opkt); } +#if CONFIG_AVFILTER + cont: + frame_available = (ist->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) && + ost->output_video_filter && avfilter_poll_frame(ost->output_video_filter->inputs[0]); + if (ost->picref) + avfilter_unref_buffer(ost->picref); + } #endif } From 38e06c2969184b5b55ec41d0c053b2480ab52846 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Tue, 16 Aug 2011 21:23:53 -0700 Subject: [PATCH 21/23] Move clipd macros to x86util.asm. This allows sharing them between multiple .asm files. --- libavcodec/x86/dsputil_yasm.asm | 34 +-------------------------------- libavutil/x86/x86util.asm | 33 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/libavcodec/x86/dsputil_yasm.asm b/libavcodec/x86/dsputil_yasm.asm index 4e1ec24a7a..2a2108404a 100644 --- a/libavcodec/x86/dsputil_yasm.asm +++ b/libavcodec/x86/dsputil_yasm.asm @@ -20,6 +20,7 @@ ;****************************************************************************** %include "x86inc.asm" +%include "x86util.asm" SECTION_RODATA pb_f: times 16 db 15 @@ -1054,39 +1055,6 @@ emu_edge mmx ; int32_t max, unsigned int len) ;----------------------------------------------------------------------------- -%macro PMINSD_MMX 3 ; dst, src, tmp - mova %3, %2 - pcmpgtd %3, %1 - pxor %1, %2 - pand %1, %3 - pxor %1, %2 -%endmacro - -%macro PMAXSD_MMX 3 ; dst, src, tmp - mova %3, %1 - pcmpgtd %3, %2 - pand %1, %3 - pandn %3, %2 - por %1, %3 -%endmacro - -%macro CLIPD_MMX 3-4 ; src/dst, min, max, tmp - PMINSD_MMX %1, %3, %4 - PMAXSD_MMX %1, %2, %4 -%endmacro - -%macro CLIPD_SSE2 3-4 ; src/dst, min (float), max (float), unused - cvtdq2ps %1, %1 - minps %1, %3 - maxps %1, %2 - cvtps2dq %1, %1 -%endmacro - -%macro CLIPD_SSE41 3-4 ; src/dst, min, max, unused - pminsd %1, %3 - pmaxsd %1, %2 -%endmacro - %macro SPLATD_MMX 1 punpckldq %1, %1 %endmacro diff --git a/libavutil/x86/x86util.asm b/libavutil/x86/x86util.asm index 5f39107379..7e16c15db2 100644 --- a/libavutil/x86/x86util.asm +++ b/libavutil/x86/x86util.asm @@ -540,3 +540,36 @@ pmaxsw %1, %2 pminsw %1, %3 %endmacro + +%macro PMINSD_MMX 3 ; dst, src, tmp + mova %3, %2 + pcmpgtd %3, %1 + pxor %1, %2 + pand %1, %3 + pxor %1, %2 +%endmacro + +%macro PMAXSD_MMX 3 ; dst, src, tmp + mova %3, %1 + pcmpgtd %3, %2 + pand %1, %3 + pandn %3, %2 + por %1, %3 +%endmacro + +%macro CLIPD_MMX 3-4 ; src/dst, min, max, tmp + PMINSD_MMX %1, %3, %4 + PMAXSD_MMX %1, %2, %4 +%endmacro + +%macro CLIPD_SSE2 3-4 ; src/dst, min (float), max (float), unused + cvtdq2ps %1, %1 + minps %1, %3 + maxps %1, %2 + cvtps2dq %1, %1 +%endmacro + +%macro CLIPD_SSE41 3-4 ; src/dst, min, max, unused + pminsd %1, %3 + pmaxsd %1, %2 +%endmacro From 3f04ab4fcddaaf166da2d623927a6b8547ab87a6 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 3 Aug 2011 11:25:01 -0700 Subject: [PATCH 22/23] swscale: split hScale() function pointer into h[cy]Scale(). This allows using more specific implementations for chroma/luma, e.g. we can make assumptions on filterSize being constant, thus avoiding that test at runtime. --- libswscale/ppc/swscale_altivec.c | 2 +- libswscale/swscale.c | 12 ++++++------ libswscale/swscale_internal.h | 11 ++++++++--- libswscale/x86/swscale_template.c | 2 +- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c index 7fdca39acb..67db2de687 100644 --- a/libswscale/ppc/swscale_altivec.c +++ b/libswscale/ppc/swscale_altivec.c @@ -400,7 +400,7 @@ void ff_sws_init_swScale_altivec(SwsContext *c) return; if (c->srcBpc == 8 && c->dstBpc <= 10) { - c->hScale = hScale_altivec_real; + c->hyScale = c->hcScale = hScale_altivec_real; } if (!is16BPS(dstFormat) && !is9_OR_10BPS(dstFormat) && dstFormat != PIX_FMT_NV12 && dstFormat != PIX_FMT_NV21 && diff --git a/libswscale/swscale.c b/libswscale/swscale.c index f5b0ab4986..733f57b049 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -2087,7 +2087,7 @@ static av_always_inline void hyscale(SwsContext *c, int16_t *dst, int dstWidth, } if (!c->hyscale_fast) { - c->hScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize); + c->hyScale(c, dst, dstWidth, src, hLumFilter, hLumFilterPos, hLumFilterSize); } else { // fast bilinear upscale / crap downscale c->hyscale_fast(c, dst, dstWidth, src, srcW, xInc); } @@ -2125,8 +2125,8 @@ static av_always_inline void hcscale(SwsContext *c, int16_t *dst1, int16_t *dst2 } if (!c->hcscale_fast) { - c->hScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize); - c->hScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize); + c->hcScale(c, dst1, dstWidth, src1, hChrFilter, hChrFilterPos, hChrFilterSize); + c->hcScale(c, dst2, dstWidth, src2, hChrFilter, hChrFilterPos, hChrFilterSize); } else { // fast bilinear upscale / crap downscale c->hcscale_fast(c, dst1, dst2, dstWidth, src1, src2, srcW, xInc); } @@ -2789,16 +2789,16 @@ static av_cold void sws_init_swScale_c(SwsContext *c) if (c->srcBpc == 8) { if (c->dstBpc <= 10) { - c->hScale = hScale8To15_c; + c->hyScale = c->hcScale = hScale8To15_c; if (c->flags & SWS_FAST_BILINEAR) { c->hyscale_fast = hyscale_fast_c; c->hcscale_fast = hcscale_fast_c; } } else { - c->hScale = hScale8To19_c; + c->hyScale = c->hcScale = hScale8To19_c; } } else { - c->hScale = c->dstBpc > 10 ? hScale16To19_c : hScale16To15_c; + c->hyScale = c->hcScale = c->dstBpc > 10 ? hScale16To19_c : hScale16To15_c; } if (c->srcRange != c->dstRange && !isAnyRGB(c->dstFormat)) { diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index d09477ec4c..a13b89d203 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -481,9 +481,14 @@ typedef struct SwsContext { * (and input coefficients thus padded with zeroes) * to simplify creating SIMD code. */ - void (*hScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, - const int16_t *filter, const int16_t *filterPos, - int filterSize); + /** @{ */ + void (*hyScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, + const int16_t *filter, const int16_t *filterPos, + int filterSize); + void (*hcScale)(struct SwsContext *c, int16_t *dst, int dstW, const uint8_t *src, + const int16_t *filter, const int16_t *filterPos, + int filterSize); + /** @} */ void (*lumConvertRange)(int16_t *dst, int width); ///< Color range conversion function for luma plane if needed. void (*chrConvertRange)(int16_t *dst1, int16_t *dst2, int width); ///< Color range conversion function for chroma planes if needed. diff --git a/libswscale/x86/swscale_template.c b/libswscale/x86/swscale_template.c index 0a5f5d5f30..705c62333c 100644 --- a/libswscale/x86/swscale_template.c +++ b/libswscale/x86/swscale_template.c @@ -2318,7 +2318,7 @@ static av_cold void RENAME(sws_init_swScale)(SwsContext *c) if (c->srcBpc == 8 && c->dstBpc <= 10) { #if !COMPILE_TEMPLATE_MMX2 - c->hScale = RENAME(hScale ); + c->hyScale = c->hcScale = RENAME(hScale ); #endif /* !COMPILE_TEMPLATE_MMX2 */ // Use the new MMX scaler if the MMX2 one can't be used (it is faster than the x86 ASM one). From b490f0c2bcec9d66d8878187f7e6661017e6d398 Mon Sep 17 00:00:00 2001 From: Dustin Brody Date: Wed, 17 Aug 2011 18:08:09 -0400 Subject: [PATCH 23/23] h264: hide reference frame errors unless requested Signed-off-by: Ronald S. Bultje --- libavcodec/h264_refs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c index b7e43e7dca..ce29caf2f0 100644 --- a/libavcodec/h264_refs.c +++ b/libavcodec/h264_refs.c @@ -655,7 +655,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ print_short_term(h); print_long_term(h); - return err; + return h->s.avctx->error_recognition >= FF_ER_EXPLODE ? err : 0; } int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb){