* qatar/master: (46 commits) mtv: Make sure audio_subsegments is not 0 v4l2: use V4L2_FMT_FLAG_EMULATED only if it is defined avconv: add symbolic names for -vsync parameters flvdec: Fix compiler warning for uninitialized variables rtsp: Fix compiler warning for uninitialized variable ulti: convert to new bytestream API. swscale: Use standard multiple inclusion guards in ppc/ header files. Place some START_TIMER invocations in separate blocks. v4l2: list available formats v4l2: set the proper codec_tag v4l2: refactor device_open v4l2: simplify away io_method v4l2: cosmetics v4l2: uniform and format options v4l2: do not force interlaced mode avio: exit early in fill_buffer without read_packet vc1dec: fix invalid memory access for small video dimensions rv34: fix invalid memory access for small video dimensions rv34: joint coefficient decoding and dequantization avplay: Don't call avio_set_interrupt_cb(NULL) ... Conflicts: Changelog avconv.c doc/APIchanges doc/indevs.texi libavcodec/adxenc.c libavcodec/dnxhdenc.c libavcodec/h264.c libavdevice/v4l2.c libavformat/flvdec.c libavformat/mtv.c libswscale/utils.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n0.10
| @@ -145,7 +145,7 @@ easier to use. The changes are: | |||||
| - pan audio filter | - pan audio filter | ||||
| - IFF Amiga Continuous Bitmap (ACBM) decoder | - IFF Amiga Continuous Bitmap (ACBM) decoder | ||||
| - ass filter | - ass filter | ||||
| - CRI ADX audio format demuxer | |||||
| - CRI ADX audio format muxer and demuxer | |||||
| - Playstation Portable PMP format demuxer | - Playstation Portable PMP format demuxer | ||||
| - Microsoft Windows ICO demuxer | - Microsoft Windows ICO demuxer | ||||
| - life source | - life source | ||||
| @@ -88,6 +88,11 @@ | |||||
| #include "libavutil/avassert.h" | #include "libavutil/avassert.h" | ||||
| #define VSYNC_AUTO -1 | |||||
| #define VSYNC_PASSTHROUGH 0 | |||||
| #define VSYNC_CFR 1 | |||||
| #define VSYNC_VFR 2 | |||||
| const char program_name[] = "avconv"; | const char program_name[] = "avconv"; | ||||
| const int program_birth_year = 2000; | const int program_birth_year = 2000; | ||||
| @@ -127,7 +132,7 @@ static int do_hex_dump = 0; | |||||
| static int do_pkt_dump = 0; | static int do_pkt_dump = 0; | ||||
| static int do_pass = 0; | static int do_pass = 0; | ||||
| static const char *pass_logfilename_prefix; | static const char *pass_logfilename_prefix; | ||||
| static int video_sync_method = -1; | |||||
| static int video_sync_method = VSYNC_AUTO; | |||||
| static int audio_sync_method = 0; | static int audio_sync_method = 0; | ||||
| static float audio_drift_threshold = 0.1; | static float audio_drift_threshold = 0.1; | ||||
| static int copy_ts = 0; | static int copy_ts = 0; | ||||
| @@ -1390,16 +1395,16 @@ static void do_video_out(AVFormatContext *s, | |||||
| *frame_size = 0; | *frame_size = 0; | ||||
| format_video_sync = video_sync_method; | format_video_sync = video_sync_method; | ||||
| if (format_video_sync < 0) | |||||
| format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? 0 : | |||||
| (s->oformat->flags & AVFMT_VARIABLE_FPS) ? 2 : 1; | |||||
| if (format_video_sync == VSYNC_AUTO) | |||||
| format_video_sync = (s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : | |||||
| (s->oformat->flags & AVFMT_VARIABLE_FPS) ? VSYNC_VFR : VSYNC_CFR; | |||||
| if (format_video_sync) { | |||||
| if (format_video_sync != VSYNC_PASSTHROUGH) { | |||||
| double vdelta = sync_ipts - ost->sync_opts; | double vdelta = sync_ipts - ost->sync_opts; | ||||
| // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c | // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c | ||||
| if (vdelta < -1.1) | if (vdelta < -1.1) | ||||
| nb_frames = 0; | nb_frames = 0; | ||||
| else if (format_video_sync == 2) { | |||||
| else if (format_video_sync == VSYNC_VFR) { | |||||
| if (vdelta <= -0.6) { | if (vdelta <= -0.6) { | ||||
| nb_frames = 0; | nb_frames = 0; | ||||
| } else if (vdelta > 0.6) | } else if (vdelta > 0.6) | ||||
| @@ -4426,6 +4431,17 @@ static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg | |||||
| return parse_option(o, "filter:v", arg, options); | return parse_option(o, "filter:v", arg, options); | ||||
| } | } | ||||
| static int opt_vsync(const char *opt, const char *arg) | |||||
| { | |||||
| if (!av_strcasecmp(arg, "cfr")) video_sync_method = VSYNC_CFR; | |||||
| else if (!av_strcasecmp(arg, "vfr")) video_sync_method = VSYNC_VFR; | |||||
| else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH; | |||||
| if (video_sync_method == VSYNC_AUTO) | |||||
| video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); | |||||
| return 0; | |||||
| } | |||||
| #define OFFSET(x) offsetof(OptionsContext, x) | #define OFFSET(x) offsetof(OptionsContext, x) | ||||
| static const OptionDef options[] = { | static const OptionDef options[] = { | ||||
| /* main options */ | /* main options */ | ||||
| @@ -4457,7 +4473,7 @@ static const OptionDef options[] = { | |||||
| "when dumping packets, also dump the payload" }, | "when dumping packets, also dump the payload" }, | ||||
| { "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(rate_emu)}, "read input at native frame rate", "" }, | { "re", OPT_BOOL | OPT_EXPERT | OPT_OFFSET, {.off = OFFSET(rate_emu)}, "read input at native frame rate", "" }, | ||||
| { "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" }, | { "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" }, | ||||
| { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" }, | |||||
| { "vsync", HAS_ARG | OPT_EXPERT, {(void*)opt_vsync}, "video sync method", "" }, | |||||
| { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" }, | { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" }, | ||||
| { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, | { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, | ||||
| { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" }, | { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" }, | ||||
| @@ -1226,6 +1226,7 @@ HAVE_LIST=" | |||||
| struct_sockaddr_in6 | struct_sockaddr_in6 | ||||
| struct_sockaddr_sa_len | struct_sockaddr_sa_len | ||||
| struct_sockaddr_storage | struct_sockaddr_storage | ||||
| struct_v4l2_frmivalenum_discrete | |||||
| symver | symver | ||||
| symver_asm_label | symver_asm_label | ||||
| symver_gnu_asm | symver_gnu_asm | ||||
| @@ -3174,6 +3175,8 @@ makeinfo --version > /dev/null 2>&1 && enable makeinfo || disable makeinfo | |||||
| check_header linux/fb.h | check_header linux/fb.h | ||||
| check_header linux/videodev.h | check_header linux/videodev.h | ||||
| check_header linux/videodev2.h | check_header linux/videodev2.h | ||||
| check_struct linux/videodev2.h "struct v4l2_frmivalenum" discrete | |||||
| check_header sys/videoio.h | check_header sys/videoio.h | ||||
| check_func_headers "windows.h vfw.h" capCreateCaptureWindow "$vfwcap_indev_extralibs" | check_func_headers "windows.h vfw.h" capCreateCaptureWindow "$vfwcap_indev_extralibs" | ||||
| @@ -174,6 +174,10 @@ API changes, most recent first: | |||||
| 2011-08-14 - 323b930 - lavu 51.12.0 | 2011-08-14 - 323b930 - lavu 51.12.0 | ||||
| Add av_fifo_peek2(), deprecate av_fifo_peek(). | Add av_fifo_peek2(), deprecate av_fifo_peek(). | ||||
| 2011-08-26 - lavu 51.9.0 | |||||
| - add41de..abc78a5 Do not include intfloat_readwrite.h, | |||||
| mathematics.h, rational.h, pixfmt.h, or log.h from avutil.h. | |||||
| 2011-08-16 - 48f9e45 - lavf 53.8.0 | 2011-08-16 - 48f9e45 - lavf 53.8.0 | ||||
| Add avformat_query_codec(). | Add avformat_query_codec(). | ||||
| @@ -749,15 +749,15 @@ Thread count. | |||||
| Video sync method. | Video sync method. | ||||
| @table @option | @table @option | ||||
| @item 0 | |||||
| @item passthrough | |||||
| Each frame is passed with its timestamp from the demuxer to the muxer. | Each frame is passed with its timestamp from the demuxer to the muxer. | ||||
| @item 1 | |||||
| @item cfr | |||||
| Frames will be duplicated and dropped to achieve exactly the requested | Frames will be duplicated and dropped to achieve exactly the requested | ||||
| constant framerate. | constant framerate. | ||||
| @item 2 | |||||
| @item vfr | |||||
| Frames are passed through with their timestamp or dropped so as to | Frames are passed through with their timestamp or dropped so as to | ||||
| prevent 2 frames from having the same timestamp. | prevent 2 frames from having the same timestamp. | ||||
| @item -1 | |||||
| @item auto | |||||
| Chooses between 1 and 2 depending on muxer capabilities. This is the | Chooses between 1 and 2 depending on muxer capabilities. This is the | ||||
| default method. | default method. | ||||
| @end table | @end table | ||||
| @@ -134,7 +134,7 @@ library: | |||||
| @item Brute Force & Ignorance @tab @tab X | @item Brute Force & Ignorance @tab @tab X | ||||
| @tab Used in the game Flash Traffic: City of Angels. | @tab Used in the game Flash Traffic: City of Angels. | ||||
| @item BWF @tab X @tab X | @item BWF @tab X @tab X | ||||
| @item CRI ADX @tab @tab X | |||||
| @item CRI ADX @tab X @tab X | |||||
| @tab Audio-only format used in console video games. | @tab Audio-only format used in console video games. | ||||
| @item Discworld II BMV @tab @tab X | @item Discworld II BMV @tab @tab X | ||||
| @item Interplay C93 @tab @tab X | @item Interplay C93 @tab @tab X | ||||
| @@ -515,9 +515,9 @@ kind @file{/dev/video@var{N}}, where @var{N} is a number associated to | |||||
| the device. | the device. | ||||
| Video4Linux and Video4Linux2 devices only support a limited set of | Video4Linux and Video4Linux2 devices only support a limited set of | ||||
| @var{width}x@var{height} sizes and frame rates. You can check which are | |||||
| @var{width}x@var{height} sizes and framerates. You can check which are | |||||
| supported for example with the command @command{dov4l} for Video4Linux | supported for example with the command @command{dov4l} for Video4Linux | ||||
| devices and the command @command{v4l-info} for Video4Linux2 devices. | |||||
| devices and using @command{-list_formats all} for Video4Linux2 devices. | |||||
| If the size for the device is set to 0x0, the input device will | If the size for the device is set to 0x0, the input device will | ||||
| try to auto-detect the size to use. | try to auto-detect the size to use. | ||||
| @@ -93,6 +93,11 @@ | |||||
| #include "libavutil/avassert.h" | #include "libavutil/avassert.h" | ||||
| #define VSYNC_AUTO -1 | |||||
| #define VSYNC_PASSTHROUGH 0 | |||||
| #define VSYNC_CFR 1 | |||||
| #define VSYNC_VFR 2 | |||||
| const char program_name[] = "ffmpeg"; | const char program_name[] = "ffmpeg"; | ||||
| const int program_birth_year = 2000; | const int program_birth_year = 2000; | ||||
| @@ -144,7 +149,7 @@ static int do_pkt_dump = 0; | |||||
| static int do_psnr = 0; | static int do_psnr = 0; | ||||
| static int do_pass = 0; | static int do_pass = 0; | ||||
| static const char *pass_logfilename_prefix; | static const char *pass_logfilename_prefix; | ||||
| static int video_sync_method = -1; | |||||
| static int video_sync_method = VSYNC_AUTO; | |||||
| static int audio_sync_method = 0; | static int audio_sync_method = 0; | ||||
| static float audio_drift_threshold = 0.1; | static float audio_drift_threshold = 0.1; | ||||
| static int copy_ts = 0; | static int copy_ts = 0; | ||||
| @@ -1433,15 +1438,15 @@ static void do_video_out(AVFormatContext *s, | |||||
| *frame_size = 0; | *frame_size = 0; | ||||
| format_video_sync = video_sync_method; | format_video_sync = video_sync_method; | ||||
| if (format_video_sync < 0) | |||||
| format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? 0 : 2) : 1; | |||||
| if (format_video_sync == VSYNC_AUTO) | |||||
| format_video_sync = (s->oformat->flags & AVFMT_VARIABLE_FPS) ? ((s->oformat->flags & AVFMT_NOTIMESTAMPS) ? VSYNC_PASSTHROUGH : VSYNC_VFR) : 1; | |||||
| if (format_video_sync) { | |||||
| if (format_video_sync != VSYNC_PASSTHROUGH) { | |||||
| double vdelta = sync_ipts - ost->sync_opts + duration; | double vdelta = sync_ipts - ost->sync_opts + duration; | ||||
| // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c | // FIXME set to 0.5 after we fix some dts/pts bugs like in avidec.c | ||||
| if (vdelta < -1.1) | if (vdelta < -1.1) | ||||
| nb_frames = 0; | nb_frames = 0; | ||||
| else if (format_video_sync == 2) { | |||||
| else if (format_video_sync == VSYNC_VFR) { | |||||
| if (vdelta <= -0.6) { | if (vdelta <= -0.6) { | ||||
| nb_frames = 0; | nb_frames = 0; | ||||
| } else if (vdelta > 0.6) | } else if (vdelta > 0.6) | ||||
| @@ -4873,6 +4878,17 @@ static int opt_video_filters(OptionsContext *o, const char *opt, const char *arg | |||||
| return parse_option(o, "filter:v", arg, options); | return parse_option(o, "filter:v", arg, options); | ||||
| } | } | ||||
| static int opt_vsync(const char *opt, const char *arg) | |||||
| { | |||||
| if (!av_strcasecmp(arg, "cfr")) video_sync_method = VSYNC_CFR; | |||||
| else if (!av_strcasecmp(arg, "vfr")) video_sync_method = VSYNC_VFR; | |||||
| else if (!av_strcasecmp(arg, "passthrough")) video_sync_method = VSYNC_PASSTHROUGH; | |||||
| if (video_sync_method == VSYNC_AUTO) | |||||
| video_sync_method = parse_number_or_die("vsync", arg, OPT_INT, VSYNC_AUTO, VSYNC_VFR); | |||||
| return 0; | |||||
| } | |||||
| #define OFFSET(x) offsetof(OptionsContext, x) | #define OFFSET(x) offsetof(OptionsContext, x) | ||||
| static const OptionDef options[] = { | static const OptionDef options[] = { | ||||
| /* main options */ | /* main options */ | ||||
| @@ -4908,7 +4924,7 @@ static const OptionDef options[] = { | |||||
| { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "deprecated, use -loop" }, | { "loop_input", OPT_BOOL | OPT_EXPERT, {(void*)&loop_input}, "deprecated, use -loop" }, | ||||
| { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "deprecated, use -loop", "" }, | { "loop_output", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&loop_output}, "deprecated, use -loop", "" }, | ||||
| { "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" }, | { "target", HAS_ARG | OPT_FUNC2, {(void*)opt_target}, "specify target file type (\"vcd\", \"svcd\", \"dvd\", \"dv\", \"dv50\", \"pal-vcd\", \"ntsc-svcd\", ...)", "type" }, | ||||
| { "vsync", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&video_sync_method}, "video sync method", "" }, | |||||
| { "vsync", HAS_ARG | OPT_EXPERT, {(void*)opt_vsync}, "video sync method", "" }, | |||||
| { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" }, | { "async", HAS_ARG | OPT_INT | OPT_EXPERT, {(void*)&audio_sync_method}, "audio sync method", "" }, | ||||
| { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, | { "adrift_threshold", HAS_ARG | OPT_FLOAT | OPT_EXPERT, {(void*)&audio_drift_threshold}, "audio drift threshold", "threshold" }, | ||||
| { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" }, | { "copyts", OPT_BOOL | OPT_EXPERT, {(void*)©_ts}, "copy timestamps" }, | ||||
| @@ -165,6 +165,13 @@ static int adx_decode_frame(AVCodecContext *avctx, void *data, | |||||
| return buf - avpkt->data; | return buf - avpkt->data; | ||||
| } | } | ||||
| static void adx_decode_flush(AVCodecContext *avctx) | |||||
| { | |||||
| ADXContext *c = avctx->priv_data; | |||||
| memset(c->prev, 0, sizeof(c->prev)); | |||||
| c->eof = 0; | |||||
| } | |||||
| AVCodec ff_adpcm_adx_decoder = { | AVCodec ff_adpcm_adx_decoder = { | ||||
| .name = "adpcm_adx", | .name = "adpcm_adx", | ||||
| .type = AVMEDIA_TYPE_AUDIO, | .type = AVMEDIA_TYPE_AUDIO, | ||||
| @@ -172,6 +179,7 @@ AVCodec ff_adpcm_adx_decoder = { | |||||
| .priv_data_size = sizeof(ADXContext), | .priv_data_size = sizeof(ADXContext), | ||||
| .init = adx_decode_init, | .init = adx_decode_init, | ||||
| .decode = adx_decode_frame, | .decode = adx_decode_frame, | ||||
| .flush = adx_decode_flush, | |||||
| .capabilities = CODEC_CAP_DR1, | .capabilities = CODEC_CAP_DR1, | ||||
| .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), | .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), | ||||
| }; | }; | ||||
| @@ -19,9 +19,9 @@ | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
| */ | */ | ||||
| #include "libavutil/intreadwrite.h" | |||||
| #include "avcodec.h" | #include "avcodec.h" | ||||
| #include "adx.h" | #include "adx.h" | ||||
| #include "bytestream.h" | |||||
| #include "put_bits.h" | #include "put_bits.h" | ||||
| /** | /** | ||||
| @@ -33,167 +33,135 @@ | |||||
| * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ | * adx2wav & wav2adx http://www.geocities.co.jp/Playtown/2004/ | ||||
| */ | */ | ||||
| /* 18 bytes <-> 32 samples */ | |||||
| static void adx_encode(ADXContext *c, unsigned char *adx, const short *wav, | |||||
| ADXChannelState *prev) | |||||
| static void adx_encode(ADXContext *c, uint8_t *adx, const int16_t *wav, | |||||
| ADXChannelState *prev, int channels) | |||||
| { | { | ||||
| PutBitContext pb; | PutBitContext pb; | ||||
| int scale; | int scale; | ||||
| int i; | |||||
| int s0,s1,s2,d; | |||||
| int max=0; | |||||
| int min=0; | |||||
| int data[32]; | |||||
| int i, j; | |||||
| int s0, s1, s2, d; | |||||
| int max = 0; | |||||
| int min = 0; | |||||
| int data[BLOCK_SAMPLES]; | |||||
| s1 = prev->s1; | s1 = prev->s1; | ||||
| s2 = prev->s2; | s2 = prev->s2; | ||||
| for(i=0;i<32;i++) { | |||||
| for (i = 0, j = 0; j < 32; i += channels, j++) { | |||||
| s0 = wav[i]; | s0 = wav[i]; | ||||
| d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS; | d = ((s0 << COEFF_BITS) - c->coeff[0] * s1 - c->coeff[1] * s2) >> COEFF_BITS; | ||||
| data[i]=d; | |||||
| if (max<d) max=d; | |||||
| if (min>d) min=d; | |||||
| data[j] = d; | |||||
| if (max < d) | |||||
| max = d; | |||||
| if (min > d) | |||||
| min = d; | |||||
| s2 = s1; | s2 = s1; | ||||
| s1 = s0; | s1 = s0; | ||||
| } | } | ||||
| prev->s1 = s1; | prev->s1 = s1; | ||||
| prev->s2 = s2; | prev->s2 = s2; | ||||
| /* -8..+7 */ | |||||
| if (max==0 && min==0) { | |||||
| memset(adx,0,18); | |||||
| if (max == 0 && min == 0) { | |||||
| memset(adx, 0, BLOCK_SIZE); | |||||
| return; | return; | ||||
| } | } | ||||
| if (max/7>-min/8) scale = max/7; | |||||
| else scale = -min/8; | |||||
| if (max / 7 > -min / 8) | |||||
| scale = max / 7; | |||||
| else | |||||
| scale = -min / 8; | |||||
| if (scale==0) scale=1; | |||||
| if (scale == 0) | |||||
| scale = 1; | |||||
| AV_WB16(adx, scale); | AV_WB16(adx, scale); | ||||
| init_put_bits(&pb, adx + 2, 16); | init_put_bits(&pb, adx + 2, 16); | ||||
| for (i = 0; i < 32; i++) | |||||
| put_sbits(&pb, 4, av_clip(data[i]/scale, -8, 7)); | |||||
| for (i = 0; i < BLOCK_SAMPLES; i++) | |||||
| put_sbits(&pb, 4, av_clip(data[i] / scale, -8, 7)); | |||||
| flush_put_bits(&pb); | flush_put_bits(&pb); | ||||
| } | } | ||||
| static int adx_encode_header(AVCodecContext *avctx,unsigned char *buf,size_t bufsize) | |||||
| #define HEADER_SIZE 36 | |||||
| static int adx_encode_header(AVCodecContext *avctx, uint8_t *buf, int bufsize) | |||||
| { | { | ||||
| #if 0 | |||||
| struct { | |||||
| uint32_t offset; /* 0x80000000 + sample start - 4 */ | |||||
| unsigned char unknown1[3]; /* 03 12 04 */ | |||||
| unsigned char channel; /* 1 or 2 */ | |||||
| uint32_t freq; | |||||
| uint32_t size; | |||||
| uint32_t unknown2; /* 01 f4 03 00 */ | |||||
| uint32_t unknown3; /* 00 00 00 00 */ | |||||
| uint32_t unknown4; /* 00 00 00 00 */ | |||||
| /* if loop | |||||
| unknown3 00 15 00 01 | |||||
| unknown4 00 00 00 01 | |||||
| long loop_start_sample; | |||||
| long loop_start_byte; | |||||
| long loop_end_sample; | |||||
| long loop_end_byte; | |||||
| long | |||||
| */ | |||||
| } adxhdr; /* big endian */ | |||||
| /* offset-6 "(c)CRI" */ | |||||
| #endif | |||||
| ADXContext *c = avctx->priv_data; | ADXContext *c = avctx->priv_data; | ||||
| AV_WB32(buf+0x00,0x80000000|0x20); | |||||
| AV_WB32(buf+0x04,0x03120400|avctx->channels); | |||||
| AV_WB32(buf+0x08,avctx->sample_rate); | |||||
| AV_WB32(buf+0x0c,0); /* FIXME: set after */ | |||||
| AV_WB16(buf + 0x10, c->cutoff); | |||||
| AV_WB32(buf + 0x12, 0x03000000); | |||||
| AV_WB32(buf + 0x16, 0x00000000); | |||||
| AV_WB32(buf + 0x1a, 0x00000000); | |||||
| memcpy (buf + 0x1e, "(c)CRI", 6); | |||||
| return 0x20+4; | |||||
| if (bufsize < HEADER_SIZE) | |||||
| return AVERROR(EINVAL); | |||||
| bytestream_put_be16(&buf, 0x8000); /* header signature */ | |||||
| bytestream_put_be16(&buf, HEADER_SIZE - 4); /* copyright offset */ | |||||
| bytestream_put_byte(&buf, 3); /* encoding */ | |||||
| bytestream_put_byte(&buf, BLOCK_SIZE); /* block size */ | |||||
| bytestream_put_byte(&buf, 4); /* sample size */ | |||||
| bytestream_put_byte(&buf, avctx->channels); /* channels */ | |||||
| bytestream_put_be32(&buf, avctx->sample_rate); /* sample rate */ | |||||
| bytestream_put_be32(&buf, 0); /* total sample count */ | |||||
| bytestream_put_be16(&buf, c->cutoff); /* cutoff frequency */ | |||||
| bytestream_put_byte(&buf, 3); /* version */ | |||||
| bytestream_put_byte(&buf, 0); /* flags */ | |||||
| bytestream_put_be32(&buf, 0); /* unknown */ | |||||
| bytestream_put_be32(&buf, 0); /* loop enabled */ | |||||
| bytestream_put_be16(&buf, 0); /* padding */ | |||||
| bytestream_put_buffer(&buf, "(c)CRI", 6); /* copyright signature */ | |||||
| return HEADER_SIZE; | |||||
| } | } | ||||
| static av_cold int adx_encode_init(AVCodecContext *avctx) | static av_cold int adx_encode_init(AVCodecContext *avctx) | ||||
| { | { | ||||
| ADXContext *c = avctx->priv_data; | ADXContext *c = avctx->priv_data; | ||||
| if (avctx->channels > 2) | |||||
| return -1; /* only stereo or mono =) */ | |||||
| avctx->frame_size = 32; | |||||
| avctx->coded_frame= avcodec_alloc_frame(); | |||||
| avctx->coded_frame->key_frame= 1; | |||||
| if (avctx->channels > 2) { | |||||
| av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); | |||||
| return AVERROR(EINVAL); | |||||
| } | |||||
| avctx->frame_size = BLOCK_SAMPLES; | |||||
| // avctx->bit_rate = avctx->sample_rate*avctx->channels*18*8/32; | |||||
| avctx->coded_frame = avcodec_alloc_frame(); | |||||
| /* the cutoff can be adjusted, but this seems to work pretty well */ | /* the cutoff can be adjusted, but this seems to work pretty well */ | ||||
| c->cutoff = 500; | c->cutoff = 500; | ||||
| ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff); | ff_adx_calculate_coeffs(c->cutoff, avctx->sample_rate, COEFF_BITS, c->coeff); | ||||
| av_log(avctx, AV_LOG_DEBUG, "adx encode init\n"); | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static av_cold int adx_encode_close(AVCodecContext *avctx) | static av_cold int adx_encode_close(AVCodecContext *avctx) | ||||
| { | { | ||||
| av_freep(&avctx->coded_frame); | av_freep(&avctx->coded_frame); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| static int adx_encode_frame(AVCodecContext *avctx, | |||||
| uint8_t *frame, int buf_size, void *data) | |||||
| static int adx_encode_frame(AVCodecContext *avctx, uint8_t *frame, | |||||
| int buf_size, void *data) | |||||
| { | { | ||||
| ADXContext *c = avctx->priv_data; | |||||
| const short *samples = data; | |||||
| unsigned char *dst = frame; | |||||
| int rest = avctx->frame_size; | |||||
| /* | |||||
| input data size = | |||||
| ffmpeg.c: do_audio_out() | |||||
| frame_bytes = enc->frame_size * 2 * enc->channels; | |||||
| */ | |||||
| ADXContext *c = avctx->priv_data; | |||||
| const int16_t *samples = data; | |||||
| uint8_t *dst = frame; | |||||
| int ch; | |||||
| // printf("sz=%d ",buf_size); fflush(stdout); | |||||
| if (!c->header_parsed) { | if (!c->header_parsed) { | ||||
| int hdrsize = adx_encode_header(avctx,dst,buf_size); | |||||
| dst+=hdrsize; | |||||
| int hdrsize; | |||||
| if ((hdrsize = adx_encode_header(avctx, dst, buf_size)) < 0) { | |||||
| av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); | |||||
| return AVERROR(EINVAL); | |||||
| } | |||||
| dst += hdrsize; | |||||
| buf_size -= hdrsize; | |||||
| c->header_parsed = 1; | c->header_parsed = 1; | ||||
| } | } | ||||
| if (buf_size < BLOCK_SIZE * avctx->channels) { | |||||
| av_log(avctx, AV_LOG_ERROR, "output buffer is too small\n"); | |||||
| return AVERROR(EINVAL); | |||||
| } | |||||
| if (avctx->channels==1) { | |||||
| while(rest>=32) { | |||||
| adx_encode(c, dst, samples, c->prev); | |||||
| dst+=18; | |||||
| samples+=32; | |||||
| rest-=32; | |||||
| } | |||||
| } else { | |||||
| while(rest>=32*2) { | |||||
| short tmpbuf[32*2]; | |||||
| int i; | |||||
| for(i=0;i<32;i++) { | |||||
| tmpbuf[i] = samples[i*2]; | |||||
| tmpbuf[i+32] = samples[i*2+1]; | |||||
| } | |||||
| adx_encode(c, dst, tmpbuf, c->prev); | |||||
| adx_encode(c, dst + 18, tmpbuf + 32, c->prev + 1); | |||||
| dst+=18*2; | |||||
| samples+=32*2; | |||||
| rest-=32*2; | |||||
| } | |||||
| for (ch = 0; ch < avctx->channels; ch++) { | |||||
| adx_encode(c, dst, samples + ch, &c->prev[ch], avctx->channels); | |||||
| dst += BLOCK_SIZE; | |||||
| } | } | ||||
| return dst-frame; | |||||
| return dst - frame; | |||||
| } | } | ||||
| AVCodec ff_adpcm_adx_encoder = { | AVCodec ff_adpcm_adx_encoder = { | ||||
| @@ -204,6 +172,7 @@ AVCodec ff_adpcm_adx_encoder = { | |||||
| .init = adx_encode_init, | .init = adx_encode_init, | ||||
| .encode = adx_encode_frame, | .encode = adx_encode_frame, | ||||
| .close = adx_encode_close, | .close = adx_encode_close, | ||||
| .sample_fmts = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_S16,AV_SAMPLE_FMT_NONE}, | |||||
| .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), | |||||
| .sample_fmts = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, | |||||
| AV_SAMPLE_FMT_NONE }, | |||||
| .long_name = NULL_IF_CONFIG_SMALL("SEGA CRI ADX ADPCM"), | |||||
| }; | }; | ||||
| @@ -25,12 +25,9 @@ | |||||
| void ff_rv34_inv_transform_neon(DCTELEM *block); | void ff_rv34_inv_transform_neon(DCTELEM *block); | ||||
| void ff_rv34_inv_transform_noround_neon(DCTELEM *block); | void ff_rv34_inv_transform_noround_neon(DCTELEM *block); | ||||
| void ff_rv34_dequant4x4_neon(DCTELEM *block, int Qdc, int Q); | |||||
| void ff_rv34dsp_init_neon(RV34DSPContext *c, DSPContext* dsp) | void ff_rv34dsp_init_neon(RV34DSPContext *c, DSPContext* dsp) | ||||
| { | { | ||||
| c->rv34_inv_transform_tab[0] = ff_rv34_inv_transform_neon; | c->rv34_inv_transform_tab[0] = ff_rv34_inv_transform_neon; | ||||
| c->rv34_inv_transform_tab[1] = ff_rv34_inv_transform_noround_neon; | c->rv34_inv_transform_tab[1] = ff_rv34_inv_transform_noround_neon; | ||||
| c->rv34_dequant4x4 = ff_rv34_dequant4x4_neon; | |||||
| } | } | ||||
| @@ -107,27 +107,3 @@ function ff_rv34_inv_transform_noround_neon, export=1 | |||||
| vst4.16 {d0[3], d1[3], d2[3], d3[3]}, [r2,:64], r1 | vst4.16 {d0[3], d1[3], d2[3], d3[3]}, [r2,:64], r1 | ||||
| bx lr | bx lr | ||||
| endfunc | endfunc | ||||
| function ff_rv34_dequant4x4_neon, export=1 | |||||
| mov r3, r0 | |||||
| mov r12, #16 | |||||
| vdup.16 q0, r2 | |||||
| vmov.16 d0[0], r1 | |||||
| vld1.16 {d2}, [r0,:64], r12 | |||||
| vld1.16 {d4}, [r0,:64], r12 | |||||
| vld1.16 {d6}, [r0,:64], r12 | |||||
| vld1.16 {d16}, [r0,:64], r12 | |||||
| vmull.s16 q1, d2, d0 | |||||
| vmull.s16 q2, d4, d1 | |||||
| vmull.s16 q3, d6, d1 | |||||
| vmull.s16 q8, d16, d1 | |||||
| vqrshrn.s32 d2, q1, #4 | |||||
| vqrshrn.s32 d4, q2, #4 | |||||
| vqrshrn.s32 d6, q3, #4 | |||||
| vqrshrn.s32 d16, q8, #4 | |||||
| vst1.16 {d2}, [r3,:64], r12 | |||||
| vst1.16 {d4}, [r3,:64], r12 | |||||
| vst1.16 {d6}, [r3,:64], r12 | |||||
| vst1.16 {d16}, [r3,:64], r12 | |||||
| bx lr | |||||
| endfunc | |||||
| @@ -39,11 +39,15 @@ static av_always_inline void bytestream_put_ ##name(uint8_t **b, const type valu | |||||
| write(*b, value);\ | write(*b, value);\ | ||||
| (*b) += bytes;\ | (*b) += bytes;\ | ||||
| }\ | }\ | ||||
| static av_always_inline type bytestream2_get_ ## name ## u(GetByteContext *g)\ | |||||
| {\ | |||||
| return bytestream_get_ ## name(&g->buffer);\ | |||||
| }\ | |||||
| static av_always_inline type bytestream2_get_ ## name(GetByteContext *g)\ | static av_always_inline type bytestream2_get_ ## name(GetByteContext *g)\ | ||||
| {\ | {\ | ||||
| if (g->buffer_end - g->buffer < bytes)\ | if (g->buffer_end - g->buffer < bytes)\ | ||||
| return 0;\ | return 0;\ | ||||
| return bytestream_get_ ## name(&g->buffer);\ | |||||
| return bytestream2_get_ ## name ## u(g);\ | |||||
| }\ | }\ | ||||
| static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g)\ | static av_always_inline type bytestream2_peek_ ## name(GetByteContext *g)\ | ||||
| {\ | {\ | ||||
| @@ -109,10 +109,6 @@ void ff_init_cabac_encoder(CABACContext *c, uint8_t *buf, int buf_size){ | |||||
| c->low= 0; | c->low= 0; | ||||
| c->range= 0x1FE; | c->range= 0x1FE; | ||||
| c->outstanding_count= 0; | c->outstanding_count= 0; | ||||
| #ifdef STRICT_LIMITS | |||||
| c->sym_count =0; | |||||
| #endif | |||||
| c->pb.bit_left++; //avoids firstBitFlag | c->pb.bit_left++; //avoids firstBitFlag | ||||
| } | } | ||||
| @@ -183,10 +179,6 @@ static void put_cabac(CABACContext *c, uint8_t * const state, int bit){ | |||||
| } | } | ||||
| renorm_cabac_encoder(c); | renorm_cabac_encoder(c); | ||||
| #ifdef STRICT_LIMITS | |||||
| c->symCount++; | |||||
| #endif | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -208,10 +200,6 @@ static void put_cabac_bypass(CABACContext *c, int bit){ | |||||
| put_cabac_bit(c, 1); | put_cabac_bit(c, 1); | ||||
| c->low -= 0x400; | c->low -= 0x400; | ||||
| } | } | ||||
| #ifdef STRICT_LIMITS | |||||
| c->symCount++; | |||||
| #endif | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -236,10 +224,6 @@ static int put_cabac_terminate(CABACContext *c, int bit){ | |||||
| flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong | flush_put_bits(&c->pb); //FIXME FIXME FIXME XXX wrong | ||||
| } | } | ||||
| #ifdef STRICT_LIMITS | |||||
| c->symCount++; | |||||
| #endif | |||||
| return (put_bits_count(&c->pb)+7)>>3; | return (put_bits_count(&c->pb)+7)>>3; | ||||
| } | } | ||||
| @@ -365,21 +349,6 @@ START_TIMER | |||||
| av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i); | av_log(NULL, AV_LOG_ERROR, "CABAC failure at %d\n", i); | ||||
| STOP_TIMER("get_cabac") | STOP_TIMER("get_cabac") | ||||
| } | } | ||||
| #if 0 | |||||
| for(i=0; i<SIZE; i++){ | |||||
| START_TIMER | |||||
| if( r[i] != get_cabac_u(&c, state, (i&1) ? 6 : 7, 3, i&1) ) | |||||
| av_log(NULL, AV_LOG_ERROR, "CABAC unary (truncated) binarization failure at %d\n", i); | |||||
| STOP_TIMER("get_cabac_u") | |||||
| } | |||||
| for(i=0; i<SIZE; i++){ | |||||
| START_TIMER | |||||
| if( r[i] != get_cabac_ueg(&c, state, 3, 0, 1, 2)) | |||||
| av_log(NULL, AV_LOG_ERROR, "CABAC unary (truncated) binarization failure at %d\n", i); | |||||
| STOP_TIMER("get_cabac_ueg") | |||||
| } | |||||
| #endif | |||||
| if(!get_cabac_terminate(&c)) | if(!get_cabac_terminate(&c)) | ||||
| av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n"); | av_log(NULL, AV_LOG_ERROR, "where's the Terminator?\n"); | ||||
| @@ -41,9 +41,6 @@ typedef struct CABACContext{ | |||||
| int low; | int low; | ||||
| int range; | int range; | ||||
| int outstanding_count; | int outstanding_count; | ||||
| #ifdef STRICT_LIMITS | |||||
| int symCount; | |||||
| #endif | |||||
| const uint8_t *bytestream_start; | const uint8_t *bytestream_start; | ||||
| const uint8_t *bytestream; | const uint8_t *bytestream; | ||||
| const uint8_t *bytestream_end; | const uint8_t *bytestream_end; | ||||
| @@ -216,62 +213,4 @@ static int av_unused get_cabac_terminate(CABACContext *c){ | |||||
| } | } | ||||
| } | } | ||||
| #if 0 | |||||
| /** | |||||
| * Get (truncated) unary binarization. | |||||
| */ | |||||
| static int get_cabac_u(CABACContext *c, uint8_t * state, int max, int max_index, int truncated){ | |||||
| int i; | |||||
| for(i=0; i<max; i++){ | |||||
| if(get_cabac(c, state)==0) | |||||
| return i; | |||||
| if(i< max_index) state++; | |||||
| } | |||||
| return truncated ? max : -1; | |||||
| } | |||||
| /** | |||||
| * get unary exp golomb k-th order binarization. | |||||
| */ | |||||
| static int get_cabac_ueg(CABACContext *c, uint8_t * state, int max, int is_signed, int k, int max_index){ | |||||
| int i, v; | |||||
| int m= 1<<k; | |||||
| if(get_cabac(c, state)==0) | |||||
| return 0; | |||||
| if(0 < max_index) state++; | |||||
| for(i=1; i<max; i++){ | |||||
| if(get_cabac(c, state)==0){ | |||||
| if(is_signed && get_cabac_bypass(c)){ | |||||
| return -i; | |||||
| }else | |||||
| return i; | |||||
| } | |||||
| if(i < max_index) state++; | |||||
| } | |||||
| while(get_cabac_bypass(c)){ | |||||
| i+= m; | |||||
| m+= m; | |||||
| } | |||||
| v=0; | |||||
| while(m>>=1){ | |||||
| v+= v + get_cabac_bypass(c); | |||||
| } | |||||
| i += v; | |||||
| if(is_signed && get_cabac_bypass(c)){ | |||||
| return -i; | |||||
| }else | |||||
| return i; | |||||
| } | |||||
| #endif /* 0 */ | |||||
| #endif /* AVCODEC_CABAC_H */ | #endif /* AVCODEC_CABAC_H */ | ||||
| @@ -578,9 +578,8 @@ static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg, int jobnr, int | |||||
| for (i = 0; i < 8; i++) { | for (i = 0; i < 8; i++) { | ||||
| DCTELEM *block = ctx->blocks[i]; | DCTELEM *block = ctx->blocks[i]; | ||||
| int last_index, overflow; | |||||
| int n = dnxhd_switch_matrix(ctx, i); | |||||
| last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow); | |||||
| int overflow, n = dnxhd_switch_matrix(ctx, i); | |||||
| int last_index = ctx->m.dct_quantize(&ctx->m, block, 4&(2*i), qscale, &overflow); | |||||
| //START_TIMER; | //START_TIMER; | ||||
| dnxhd_encode_block(ctx, block, last_index, n); | dnxhd_encode_block(ctx, block, last_index, n); | ||||
| //STOP_TIMER("encode_block"); | //STOP_TIMER("encode_block"); | ||||
| @@ -4051,7 +4051,7 @@ static int decode_frame(AVCodecContext *avctx, | |||||
| H264Context *h = avctx->priv_data; | H264Context *h = avctx->priv_data; | ||||
| MpegEncContext *s = &h->s; | MpegEncContext *s = &h->s; | ||||
| AVFrame *pict = data; | AVFrame *pict = data; | ||||
| int buf_index; | |||||
| int buf_index = 0; | |||||
| Picture *out; | Picture *out; | ||||
| int i, out_idx; | int i, out_idx; | ||||
| @@ -4081,7 +4081,7 @@ static int decode_frame(AVCodecContext *avctx, | |||||
| *pict= *(AVFrame*)out; | *pict= *(AVFrame*)out; | ||||
| } | } | ||||
| return buf_size; | |||||
| return buf_index; | |||||
| } | } | ||||
| if(h->is_avc && buf_size >= 9 && buf[0]==1 && buf[2]==0 && (buf[4]&0xFC)==0xFC && (buf[5]&0x1F) && buf[8]==0x67){ | if(h->is_avc && buf_size >= 9 && buf[0]==1 && buf[2]==0 && (buf[4]&0xFC)==0xFC && (buf[5]&0x1F) && buf[8]==0x67){ | ||||
| int cnt= buf[5]&0x1f; | int cnt= buf[5]&0x1f; | ||||
| @@ -4112,7 +4112,6 @@ not_extra: | |||||
| if (!s->current_picture_ptr && h->nal_unit_type == NAL_END_SEQUENCE) { | if (!s->current_picture_ptr && h->nal_unit_type == NAL_END_SEQUENCE) { | ||||
| av_assert0(buf_index <= buf_size); | av_assert0(buf_index <= buf_size); | ||||
| buf_size = buf_index; | |||||
| goto out; | goto out; | ||||
| } | } | ||||
| @@ -4193,9 +4192,7 @@ int main(void){ | |||||
| init_get_bits(&gb, temp, 8*SIZE); | init_get_bits(&gb, temp, 8*SIZE); | ||||
| for(i=0; i<COUNT; i++){ | for(i=0; i<COUNT; i++){ | ||||
| int j, s; | |||||
| s= show_bits(&gb, 24); | |||||
| int j, s = show_bits(&gb, 24); | |||||
| {START_TIMER | {START_TIMER | ||||
| j= get_ue_golomb(&gb); | j= get_ue_golomb(&gb); | ||||
| @@ -4218,9 +4215,7 @@ int main(void){ | |||||
| init_get_bits(&gb, temp, 8*SIZE); | init_get_bits(&gb, temp, 8*SIZE); | ||||
| for(i=0; i<COUNT; i++){ | for(i=0; i<COUNT; i++){ | ||||
| int j, s; | |||||
| s= show_bits(&gb, 24); | |||||
| int j, s = show_bits(&gb, 24); | |||||
| {START_TIMER | {START_TIMER | ||||
| j= get_se_golomb(&gb); | j= get_se_golomb(&gb); | ||||
| @@ -760,7 +760,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |||||
| switch_buffers(ctx); | switch_buffers(ctx); | ||||
| //START_TIMER; | |||||
| //{ START_TIMER; | |||||
| if (ctx->frame_type != FRAMETYPE_NULL) { | if (ctx->frame_type != FRAMETYPE_NULL) { | ||||
| for (p = 0; p < 3; p++) { | for (p = 0; p < 3; p++) { | ||||
| @@ -775,7 +775,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, | |||||
| } | } | ||||
| } | } | ||||
| //STOP_TIMER("decode_planes"); | |||||
| //STOP_TIMER("decode_planes"); } | |||||
| if (ctx->frame.data[0]) | if (ctx->frame.data[0]) | ||||
| avctx->release_buffer(avctx, &ctx->frame); | avctx->release_buffer(avctx, &ctx->frame); | ||||
| @@ -83,7 +83,8 @@ typedef struct { | |||||
| int abr; ///< flag to enable ABR | int abr; ///< flag to enable ABR | ||||
| int pkt_frame_count; ///< frame count for the current packet | int pkt_frame_count; ///< frame count for the current packet | ||||
| int lookahead; ///< encoder delay | int lookahead; ///< encoder delay | ||||
| int sample_count; ///< total sample count (used for pts) | |||||
| int64_t next_pts; ///< next pts, in sample_rate time base | |||||
| int pkt_sample_count; ///< sample count in the current packet | |||||
| } LibSpeexEncContext; | } LibSpeexEncContext; | ||||
| static av_cold void print_enc_params(AVCodecContext *avctx, | static av_cold void print_enc_params(AVCodecContext *avctx, | ||||
| @@ -201,7 +202,7 @@ static av_cold int encode_init(AVCodecContext *avctx) | |||||
| /* set encoding delay */ | /* set encoding delay */ | ||||
| speex_encoder_ctl(s->enc_state, SPEEX_GET_LOOKAHEAD, &s->lookahead); | speex_encoder_ctl(s->enc_state, SPEEX_GET_LOOKAHEAD, &s->lookahead); | ||||
| s->sample_count = -s->lookahead; | |||||
| s->next_pts = -s->lookahead; | |||||
| /* create header packet bytes from header struct */ | /* create header packet bytes from header struct */ | ||||
| /* note: libspeex allocates the memory for header_data, which is freed | /* note: libspeex allocates the memory for header_data, which is freed | ||||
| @@ -235,7 +236,6 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size, | |||||
| { | { | ||||
| LibSpeexEncContext *s = avctx->priv_data; | LibSpeexEncContext *s = avctx->priv_data; | ||||
| int16_t *samples = data; | int16_t *samples = data; | ||||
| int sample_count = s->sample_count; | |||||
| if (data) { | if (data) { | ||||
| /* encode Speex frame */ | /* encode Speex frame */ | ||||
| @@ -243,7 +243,7 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size, | |||||
| speex_encode_stereo_int(samples, s->header.frame_size, &s->bits); | speex_encode_stereo_int(samples, s->header.frame_size, &s->bits); | ||||
| speex_encode_int(s->enc_state, samples, &s->bits); | speex_encode_int(s->enc_state, samples, &s->bits); | ||||
| s->pkt_frame_count++; | s->pkt_frame_count++; | ||||
| s->sample_count += avctx->frame_size; | |||||
| s->pkt_sample_count += avctx->frame_size; | |||||
| } else { | } else { | ||||
| /* handle end-of-stream */ | /* handle end-of-stream */ | ||||
| if (!s->pkt_frame_count) | if (!s->pkt_frame_count) | ||||
| @@ -259,8 +259,10 @@ static int encode_frame(AVCodecContext *avctx, uint8_t *frame, int buf_size, | |||||
| if (s->pkt_frame_count == s->frames_per_packet) { | if (s->pkt_frame_count == s->frames_per_packet) { | ||||
| s->pkt_frame_count = 0; | s->pkt_frame_count = 0; | ||||
| avctx->coded_frame->pts = | avctx->coded_frame->pts = | ||||
| av_rescale_q(sample_count, (AVRational){ 1, avctx->sample_rate }, | |||||
| av_rescale_q(s->next_pts, (AVRational){ 1, avctx->sample_rate }, | |||||
| avctx->time_base); | avctx->time_base); | ||||
| s->next_pts += s->pkt_sample_count; | |||||
| s->pkt_sample_count = 0; | |||||
| if (buf_size > speex_bits_nbytes(&s->bits)) { | if (buf_size > speex_bits_nbytes(&s->bits)) { | ||||
| int ret = speex_bits_write(&s->bits, frame, buf_size); | int ret = speex_bits_write(&s->bits, frame, buf_size); | ||||
| speex_bits_reset(&s->bits); | speex_bits_reset(&s->bits); | ||||
| @@ -212,7 +212,7 @@ static int rv34_decode_cbp(GetBitContext *gb, RV34VLC *vlc, int table) | |||||
| /** | /** | ||||
| * Get one coefficient value from the bistream and store it. | * Get one coefficient value from the bistream and store it. | ||||
| */ | */ | ||||
| static inline void decode_coeff(DCTELEM *dst, int coef, int esc, GetBitContext *gb, VLC* vlc) | |||||
| static inline void decode_coeff(DCTELEM *dst, int coef, int esc, GetBitContext *gb, VLC* vlc, int q) | |||||
| { | { | ||||
| if(coef){ | if(coef){ | ||||
| if(coef == esc){ | if(coef == esc){ | ||||
| @@ -225,14 +225,14 @@ static inline void decode_coeff(DCTELEM *dst, int coef, int esc, GetBitContext * | |||||
| } | } | ||||
| if(get_bits1(gb)) | if(get_bits1(gb)) | ||||
| coef = -coef; | coef = -coef; | ||||
| *dst = coef; | |||||
| *dst = (coef*q + 8) >> 4; | |||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Decode 2x2 subblock of coefficients. | * Decode 2x2 subblock of coefficients. | ||||
| */ | */ | ||||
| static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc) | |||||
| static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc, int q) | |||||
| { | { | ||||
| int coeffs[4]; | int coeffs[4]; | ||||
| @@ -240,15 +240,35 @@ static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2, | |||||
| coeffs[1] = modulo_three_table[code][1]; | coeffs[1] = modulo_three_table[code][1]; | ||||
| coeffs[2] = modulo_three_table[code][2]; | coeffs[2] = modulo_three_table[code][2]; | ||||
| coeffs[3] = modulo_three_table[code][3]; | coeffs[3] = modulo_three_table[code][3]; | ||||
| decode_coeff(dst , coeffs[0], 3, gb, vlc); | |||||
| decode_coeff(dst , coeffs[0], 3, gb, vlc, q); | |||||
| if(is_block2){ | if(is_block2){ | ||||
| decode_coeff(dst+8, coeffs[1], 2, gb, vlc); | |||||
| decode_coeff(dst+1, coeffs[2], 2, gb, vlc); | |||||
| decode_coeff(dst+8, coeffs[1], 2, gb, vlc, q); | |||||
| decode_coeff(dst+1, coeffs[2], 2, gb, vlc, q); | |||||
| }else{ | }else{ | ||||
| decode_coeff(dst+1, coeffs[1], 2, gb, vlc); | |||||
| decode_coeff(dst+8, coeffs[2], 2, gb, vlc); | |||||
| decode_coeff(dst+1, coeffs[1], 2, gb, vlc, q); | |||||
| decode_coeff(dst+8, coeffs[2], 2, gb, vlc, q); | |||||
| } | } | ||||
| decode_coeff(dst+9, coeffs[3], 2, gb, vlc); | |||||
| decode_coeff(dst+9, coeffs[3], 2, gb, vlc, q); | |||||
| } | |||||
| static inline void decode_subblock3(DCTELEM *dst, int code, const int is_block2, GetBitContext *gb, VLC *vlc, | |||||
| int q_dc, int q_ac1, int q_ac2) | |||||
| { | |||||
| int coeffs[4]; | |||||
| coeffs[0] = modulo_three_table[code][0]; | |||||
| coeffs[1] = modulo_three_table[code][1]; | |||||
| coeffs[2] = modulo_three_table[code][2]; | |||||
| coeffs[3] = modulo_three_table[code][3]; | |||||
| decode_coeff(dst , coeffs[0], 3, gb, vlc, q_dc); | |||||
| if(is_block2){ | |||||
| decode_coeff(dst+8, coeffs[1], 2, gb, vlc, q_ac1); | |||||
| decode_coeff(dst+1, coeffs[2], 2, gb, vlc, q_ac1); | |||||
| }else{ | |||||
| decode_coeff(dst+1, coeffs[1], 2, gb, vlc, q_ac1); | |||||
| decode_coeff(dst+8, coeffs[2], 2, gb, vlc, q_ac1); | |||||
| } | |||||
| decode_coeff(dst+9, coeffs[3], 2, gb, vlc, q_ac2); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -262,7 +282,7 @@ static inline void decode_subblock(DCTELEM *dst, int code, const int is_block2, | |||||
| * o--o | * o--o | ||||
| */ | */ | ||||
| static inline void rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *rvlc, int fc, int sc) | |||||
| static inline void rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *rvlc, int fc, int sc, int q_dc, int q_ac1, int q_ac2) | |||||
| { | { | ||||
| int code, pattern; | int code, pattern; | ||||
| @@ -271,39 +291,23 @@ static inline void rv34_decode_block(DCTELEM *dst, GetBitContext *gb, RV34VLC *r | |||||
| pattern = code & 0x7; | pattern = code & 0x7; | ||||
| code >>= 3; | code >>= 3; | ||||
| decode_subblock(dst, code, 0, gb, &rvlc->coefficient); | |||||
| decode_subblock3(dst, code, 0, gb, &rvlc->coefficient, q_dc, q_ac1, q_ac2); | |||||
| if(pattern & 4){ | if(pattern & 4){ | ||||
| code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); | code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); | ||||
| decode_subblock(dst + 2, code, 0, gb, &rvlc->coefficient); | |||||
| decode_subblock(dst + 2, code, 0, gb, &rvlc->coefficient, q_ac2); | |||||
| } | } | ||||
| if(pattern & 2){ // Looks like coefficients 1 and 2 are swapped for this block | if(pattern & 2){ // Looks like coefficients 1 and 2 are swapped for this block | ||||
| code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); | code = get_vlc2(gb, rvlc->second_pattern[sc].table, 9, 2); | ||||
| decode_subblock(dst + 8*2, code, 1, gb, &rvlc->coefficient); | |||||
| decode_subblock(dst + 8*2, code, 1, gb, &rvlc->coefficient, q_ac2); | |||||
| } | } | ||||
| if(pattern & 1){ | if(pattern & 1){ | ||||
| code = get_vlc2(gb, rvlc->third_pattern[sc].table, 9, 2); | code = get_vlc2(gb, rvlc->third_pattern[sc].table, 9, 2); | ||||
| decode_subblock(dst + 8*2+2, code, 0, gb, &rvlc->coefficient); | |||||
| decode_subblock(dst + 8*2+2, code, 0, gb, &rvlc->coefficient, q_ac2); | |||||
| } | } | ||||
| } | } | ||||
| /** | |||||
| * Dequantize 4x4 block of DC values for 16x16 macroblock. | |||||
| * @todo optimize | |||||
| */ | |||||
| static inline void rv34_dequant4x4_16x16(DCTELEM *block, int Qdc, int Q) | |||||
| { | |||||
| int i; | |||||
| for(i = 0; i < 3; i++) | |||||
| block[rv34_dezigzag[i]] = (block[rv34_dezigzag[i]] * Qdc + 8) >> 4; | |||||
| for(; i < 16; i++) | |||||
| block[rv34_dezigzag[i]] = (block[rv34_dezigzag[i]] * Q + 8) >> 4; | |||||
| } | |||||
| /** @} */ //block functions | |||||
| /** | /** | ||||
| * @name RV30/40 bitstream parsing | * @name RV30/40 bitstream parsing | ||||
| * @{ | * @{ | ||||
| @@ -676,8 +680,9 @@ static inline void rv34_mc(RV34DecContext *r, const int block_type, | |||||
| srcY += src_y * s->linesize + src_x; | srcY += src_y * s->linesize + src_x; | ||||
| srcU += uvsrc_y * s->uvlinesize + uvsrc_x; | srcU += uvsrc_y * s->uvlinesize + uvsrc_x; | ||||
| srcV += uvsrc_y * s->uvlinesize + uvsrc_x; | srcV += uvsrc_y * s->uvlinesize + uvsrc_x; | ||||
| if( (unsigned)(src_x - !!lx*2) > s->h_edge_pos - !!lx*2 - (width <<3) - 4 | |||||
| || (unsigned)(src_y - !!ly*2) > s->v_edge_pos - !!ly*2 - (height<<3) - 4){ | |||||
| if(s->h_edge_pos - (width << 3) < 6 || s->v_edge_pos - (height << 3) < 6 || | |||||
| (unsigned)(src_x - !!lx*2) > s->h_edge_pos - !!lx*2 - (width <<3) - 4 || | |||||
| (unsigned)(src_y - !!ly*2) > s->v_edge_pos - !!ly*2 - (height<<3) - 4) { | |||||
| uint8_t *uvbuf = s->edge_emu_buffer + 22 * s->linesize; | uint8_t *uvbuf = s->edge_emu_buffer + 22 * s->linesize; | ||||
| srcY -= 2 + 2*s->linesize; | srcY -= 2 + 2*s->linesize; | ||||
| @@ -1097,6 +1102,7 @@ static int rv34_decode_macroblock(RV34DecContext *r, int8_t *intra_types) | |||||
| MpegEncContext *s = &r->s; | MpegEncContext *s = &r->s; | ||||
| GetBitContext *gb = &s->gb; | GetBitContext *gb = &s->gb; | ||||
| int cbp, cbp2; | int cbp, cbp2; | ||||
| int q_dc, q_ac; | |||||
| int i, blknum, blkoff; | int i, blknum, blkoff; | ||||
| LOCAL_ALIGNED_16(DCTELEM, block16, [64]); | LOCAL_ALIGNED_16(DCTELEM, block16, [64]); | ||||
| int luma_dc_quant; | int luma_dc_quant; | ||||
| @@ -1133,31 +1139,34 @@ static int rv34_decode_macroblock(RV34DecContext *r, int8_t *intra_types) | |||||
| luma_dc_quant = r->block_type == RV34_MB_P_MIX16x16 ? r->luma_dc_quant_p[s->qscale] : r->luma_dc_quant_i[s->qscale]; | luma_dc_quant = r->block_type == RV34_MB_P_MIX16x16 ? r->luma_dc_quant_p[s->qscale] : r->luma_dc_quant_i[s->qscale]; | ||||
| if(r->is16){ | if(r->is16){ | ||||
| q_dc = rv34_qscale_tab[luma_dc_quant]; | |||||
| q_ac = rv34_qscale_tab[s->qscale]; | |||||
| memset(block16, 0, 64 * sizeof(*block16)); | memset(block16, 0, 64 * sizeof(*block16)); | ||||
| rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0); | |||||
| rv34_dequant4x4_16x16(block16, rv34_qscale_tab[luma_dc_quant],rv34_qscale_tab[s->qscale]); | |||||
| rv34_decode_block(block16, gb, r->cur_vlcs, 3, 0, q_dc, q_dc, q_ac); | |||||
| r->rdsp.rv34_inv_transform_tab[1](block16); | r->rdsp.rv34_inv_transform_tab[1](block16); | ||||
| } | } | ||||
| q_ac = rv34_qscale_tab[s->qscale]; | |||||
| for(i = 0; i < 16; i++, cbp >>= 1){ | for(i = 0; i < 16; i++, cbp >>= 1){ | ||||
| if(!r->is16 && !(cbp & 1)) continue; | if(!r->is16 && !(cbp & 1)) continue; | ||||
| blknum = ((i & 2) >> 1) + ((i & 8) >> 2); | blknum = ((i & 2) >> 1) + ((i & 8) >> 2); | ||||
| blkoff = ((i & 1) << 2) + ((i & 4) << 3); | blkoff = ((i & 1) << 2) + ((i & 4) << 3); | ||||
| if(cbp & 1) | if(cbp & 1) | ||||
| rv34_decode_block(s->block[blknum] + blkoff, gb, r->cur_vlcs, r->luma_vlc, 0); | |||||
| r->rdsp.rv34_dequant4x4(s->block[blknum] + blkoff, rv34_qscale_tab[s->qscale],rv34_qscale_tab[s->qscale]); | |||||
| rv34_decode_block(s->block[blknum] + blkoff, gb, | |||||
| r->cur_vlcs, r->luma_vlc, 0, q_ac, q_ac, q_ac); | |||||
| if(r->is16) //FIXME: optimize | if(r->is16) //FIXME: optimize | ||||
| s->block[blknum][blkoff] = block16[(i & 3) | ((i & 0xC) << 1)]; | s->block[blknum][blkoff] = block16[(i & 3) | ((i & 0xC) << 1)]; | ||||
| r->rdsp.rv34_inv_transform_tab[0](s->block[blknum] + blkoff); | r->rdsp.rv34_inv_transform_tab[0](s->block[blknum] + blkoff); | ||||
| } | } | ||||
| if(r->block_type == RV34_MB_P_MIX16x16) | if(r->block_type == RV34_MB_P_MIX16x16) | ||||
| r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1); | r->cur_vlcs = choose_vlc_set(r->si.quant, r->si.vlc_set, 1); | ||||
| q_dc = rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]]; | |||||
| q_ac = rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]; | |||||
| for(; i < 24; i++, cbp >>= 1){ | for(; i < 24; i++, cbp >>= 1){ | ||||
| if(!(cbp & 1)) continue; | if(!(cbp & 1)) continue; | ||||
| blknum = ((i & 4) >> 2) + 4; | blknum = ((i & 4) >> 2) + 4; | ||||
| blkoff = ((i & 1) << 2) + ((i & 2) << 4); | blkoff = ((i & 1) << 2) + ((i & 2) << 4); | ||||
| rv34_decode_block(s->block[blknum] + blkoff, gb, r->cur_vlcs, r->chroma_vlc, 1); | |||||
| r->rdsp.rv34_dequant4x4(s->block[blknum] + blkoff, rv34_qscale_tab[rv34_chroma_quant[1][s->qscale]],rv34_qscale_tab[rv34_chroma_quant[0][s->qscale]]); | |||||
| rv34_decode_block(s->block[blknum] + blkoff, gb, r->cur_vlcs, r->chroma_vlc, 1, q_dc, q_ac, q_ac); | |||||
| r->rdsp.rv34_inv_transform_tab[0](s->block[blknum] + blkoff); | r->rdsp.rv34_inv_transform_tab[0](s->block[blknum] + blkoff); | ||||
| } | } | ||||
| if (IS_INTRA(s->current_picture_ptr->f.mb_type[mb_pos])) | if (IS_INTRA(s->current_picture_ptr->f.mb_type[mb_pos])) | ||||
| @@ -100,16 +100,6 @@ static const uint16_t rv34_qscale_tab[32] = { | |||||
| 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211 | 963, 1074, 1212, 1392, 1566, 1708, 1978, 2211 | ||||
| }; | }; | ||||
| /** | |||||
| * 4x4 dezigzag pattern | |||||
| */ | |||||
| static const uint8_t rv34_dezigzag[16] = { | |||||
| 0, 1, 8, 16, | |||||
| 9, 2, 3, 10, | |||||
| 17, 24, 25, 18, | |||||
| 11, 19, 26, 27 | |||||
| }; | |||||
| /** | /** | ||||
| * tables used to translate a quantizer value into a VLC set for decoding | * tables used to translate a quantizer value into a VLC set for decoding | ||||
| * The first table is used for intraframes. | * The first table is used for intraframes. | ||||
| @@ -100,26 +100,10 @@ static void rv34_inv_transform_noround_c(DCTELEM *block){ | |||||
| /** @} */ // transform | /** @} */ // transform | ||||
| /** | |||||
| * Dequantize ordinary 4x4 block. | |||||
| */ | |||||
| void ff_rv34_dequant4x4_neon(DCTELEM *block, int Qdc, int Q); | |||||
| static void rv34_dequant4x4_c(DCTELEM *block, int Qdc, int Q) | |||||
| { | |||||
| int i, j; | |||||
| block[0] = (block[0] * Qdc + 8) >> 4; | |||||
| for (i = 0; i < 4; i++) | |||||
| for (j = !i; j < 4; j++) | |||||
| block[j + i*8] = (block[j + i*8] * Q + 8) >> 4; | |||||
| } | |||||
| av_cold void ff_rv34dsp_init(RV34DSPContext *c, DSPContext* dsp) { | av_cold void ff_rv34dsp_init(RV34DSPContext *c, DSPContext* dsp) { | ||||
| c->rv34_inv_transform_tab[0] = rv34_inv_transform_c; | c->rv34_inv_transform_tab[0] = rv34_inv_transform_c; | ||||
| c->rv34_inv_transform_tab[1] = rv34_inv_transform_noround_c; | c->rv34_inv_transform_tab[1] = rv34_inv_transform_noround_c; | ||||
| c->rv34_dequant4x4 = rv34_dequant4x4_c; | |||||
| if (HAVE_NEON) | if (HAVE_NEON) | ||||
| ff_rv34dsp_init_neon(c, dsp); | ff_rv34dsp_init_neon(c, dsp); | ||||
| } | } | ||||
| @@ -56,7 +56,6 @@ typedef struct RV34DSPContext { | |||||
| h264_chroma_mc_func avg_chroma_pixels_tab[3]; | h264_chroma_mc_func avg_chroma_pixels_tab[3]; | ||||
| rv40_weight_func rv40_weight_pixels_tab[2]; | rv40_weight_func rv40_weight_pixels_tab[2]; | ||||
| rv34_inv_transform_func rv34_inv_transform_tab[2]; | rv34_inv_transform_func rv34_inv_transform_tab[2]; | ||||
| void (*rv34_dequant4x4)(DCTELEM *block, int Qdc, int Q); | |||||
| rv40_weak_loop_filter_func rv40_weak_loop_filter[2]; | rv40_weak_loop_filter_func rv40_weak_loop_filter[2]; | ||||
| rv40_strong_loop_filter_func rv40_strong_loop_filter[2]; | rv40_strong_loop_filter_func rv40_strong_loop_filter[2]; | ||||
| rv40_loop_filter_strength_func rv40_loop_filter_strength[2]; | rv40_loop_filter_strength_func rv40_loop_filter_strength[2]; | ||||
| @@ -38,16 +38,9 @@ typedef struct UltimotionDecodeContext { | |||||
| int width, height, blocks; | int width, height, blocks; | ||||
| AVFrame frame; | AVFrame frame; | ||||
| const uint8_t *ulti_codebook; | const uint8_t *ulti_codebook; | ||||
| GetByteContext gb; | |||||
| } UltimotionDecodeContext; | } UltimotionDecodeContext; | ||||
| #define CHECK_OVERREAD_SIZE(size) \ | |||||
| do { \ | |||||
| if (buf_end - buf < (size)) { \ | |||||
| av_log(avctx, AV_LOG_ERROR, "Insufficient data\n"); \ | |||||
| return AVERROR_INVALIDDATA; \ | |||||
| } \ | |||||
| } while(0) | |||||
| static av_cold int ulti_decode_init(AVCodecContext *avctx) | static av_cold int ulti_decode_init(AVCodecContext *avctx) | ||||
| { | { | ||||
| UltimotionDecodeContext *s = avctx->priv_data; | UltimotionDecodeContext *s = avctx->priv_data; | ||||
| @@ -232,7 +225,6 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| int i; | int i; | ||||
| int skip; | int skip; | ||||
| int tmp; | int tmp; | ||||
| const uint8_t *buf_end = buf + buf_size; | |||||
| s->frame.reference = 3; | s->frame.reference = 3; | ||||
| s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; | ||||
| @@ -241,18 +233,20 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| bytestream2_init(&s->gb, buf, buf_size); | |||||
| while(!done) { | while(!done) { | ||||
| int idx; | int idx; | ||||
| if(blocks >= s->blocks || y >= s->height) | if(blocks >= s->blocks || y >= s->height) | ||||
| break;//all blocks decoded | break;//all blocks decoded | ||||
| CHECK_OVERREAD_SIZE(1); | |||||
| idx = *buf++; | |||||
| if (bytestream2_get_bytes_left(&s->gb) < 1) | |||||
| goto err; | |||||
| idx = bytestream2_get_byteu(&s->gb); | |||||
| if((idx & 0xF8) == 0x70) { | if((idx & 0xF8) == 0x70) { | ||||
| switch(idx) { | switch(idx) { | ||||
| case 0x70: //change modifier | case 0x70: //change modifier | ||||
| CHECK_OVERREAD_SIZE(1); | |||||
| modifier = *buf++; | |||||
| modifier = bytestream2_get_byte(&s->gb); | |||||
| if(modifier>1) | if(modifier>1) | ||||
| av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier); | av_log(avctx, AV_LOG_INFO, "warning: modifier must be 0 or 1, got %i\n", modifier); | ||||
| break; | break; | ||||
| @@ -266,8 +260,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| done = 1; | done = 1; | ||||
| break; | break; | ||||
| case 0x74: //skip some blocks | case 0x74: //skip some blocks | ||||
| CHECK_OVERREAD_SIZE(1); | |||||
| skip = *buf++; | |||||
| skip = bytestream2_get_byte(&s->gb); | |||||
| if ((blocks + skip) >= s->blocks) | if ((blocks + skip) >= s->blocks) | ||||
| break; | break; | ||||
| blocks += skip; | blocks += skip; | ||||
| @@ -294,8 +287,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| } else { | } else { | ||||
| cf = 0; | cf = 0; | ||||
| if (idx) { | if (idx) { | ||||
| CHECK_OVERREAD_SIZE(1); | |||||
| chroma = *buf++; | |||||
| chroma = bytestream2_get_byte(&s->gb); | |||||
| } | } | ||||
| } | } | ||||
| for (i = 0; i < 4; i++) { // for every subblock | for (i = 0; i < 4; i++) { // for every subblock | ||||
| @@ -303,15 +295,13 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| if(!code) //skip subblock | if(!code) //skip subblock | ||||
| continue; | continue; | ||||
| if(cf) { | if(cf) { | ||||
| CHECK_OVERREAD_SIZE(1); | |||||
| chroma = *buf++; | |||||
| chroma = bytestream2_get_byte(&s->gb); | |||||
| } | } | ||||
| tx = x + block_coords[i * 2]; | tx = x + block_coords[i * 2]; | ||||
| ty = y + block_coords[(i * 2) + 1]; | ty = y + block_coords[(i * 2) + 1]; | ||||
| switch(code) { | switch(code) { | ||||
| case 1: | case 1: | ||||
| CHECK_OVERREAD_SIZE(1); | |||||
| tmp = *buf++; | |||||
| tmp = bytestream2_get_byte(&s->gb); | |||||
| angle = angle_by_index[(tmp >> 6) & 0x3]; | angle = angle_by_index[(tmp >> 6) & 0x3]; | ||||
| @@ -331,8 +321,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| case 2: | case 2: | ||||
| if (modifier) { // unpack four luma samples | if (modifier) { // unpack four luma samples | ||||
| CHECK_OVERREAD_SIZE(3); | |||||
| tmp = bytestream_get_be24(&buf); | |||||
| tmp = bytestream2_get_be24(&s->gb); | |||||
| Y[0] = (tmp >> 18) & 0x3F; | Y[0] = (tmp >> 18) & 0x3F; | ||||
| Y[1] = (tmp >> 12) & 0x3F; | Y[1] = (tmp >> 12) & 0x3F; | ||||
| @@ -340,8 +329,7 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| Y[3] = tmp & 0x3F; | Y[3] = tmp & 0x3F; | ||||
| angle = 16; | angle = 16; | ||||
| } else { // retrieve luma samples from codebook | } else { // retrieve luma samples from codebook | ||||
| CHECK_OVERREAD_SIZE(2); | |||||
| tmp = bytestream_get_be16(&buf); | |||||
| tmp = bytestream2_get_be16(&s->gb); | |||||
| angle = (tmp >> 12) & 0xF; | angle = (tmp >> 12) & 0xF; | ||||
| tmp &= 0xFFF; | tmp &= 0xFFF; | ||||
| @@ -357,27 +345,27 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| if (modifier) { // all 16 luma samples | if (modifier) { // all 16 luma samples | ||||
| uint8_t Luma[16]; | uint8_t Luma[16]; | ||||
| CHECK_OVERREAD_SIZE(12); | |||||
| tmp = bytestream_get_be24(&buf); | |||||
| if (bytestream2_get_bytes_left(&s->gb) < 12) | |||||
| goto err; | |||||
| tmp = bytestream2_get_be24u(&s->gb); | |||||
| Luma[0] = (tmp >> 18) & 0x3F; | Luma[0] = (tmp >> 18) & 0x3F; | ||||
| Luma[1] = (tmp >> 12) & 0x3F; | Luma[1] = (tmp >> 12) & 0x3F; | ||||
| Luma[2] = (tmp >> 6) & 0x3F; | Luma[2] = (tmp >> 6) & 0x3F; | ||||
| Luma[3] = tmp & 0x3F; | Luma[3] = tmp & 0x3F; | ||||
| tmp = bytestream_get_be24(&buf); | |||||
| tmp = bytestream2_get_be24u(&s->gb); | |||||
| Luma[4] = (tmp >> 18) & 0x3F; | Luma[4] = (tmp >> 18) & 0x3F; | ||||
| Luma[5] = (tmp >> 12) & 0x3F; | Luma[5] = (tmp >> 12) & 0x3F; | ||||
| Luma[6] = (tmp >> 6) & 0x3F; | Luma[6] = (tmp >> 6) & 0x3F; | ||||
| Luma[7] = tmp & 0x3F; | Luma[7] = tmp & 0x3F; | ||||
| tmp = bytestream_get_be24(&buf); | |||||
| tmp = bytestream2_get_be24u(&s->gb); | |||||
| Luma[8] = (tmp >> 18) & 0x3F; | Luma[8] = (tmp >> 18) & 0x3F; | ||||
| Luma[9] = (tmp >> 12) & 0x3F; | Luma[9] = (tmp >> 12) & 0x3F; | ||||
| Luma[10] = (tmp >> 6) & 0x3F; | Luma[10] = (tmp >> 6) & 0x3F; | ||||
| Luma[11] = tmp & 0x3F; | Luma[11] = tmp & 0x3F; | ||||
| tmp = bytestream_get_be24(&buf); | |||||
| tmp = bytestream2_get_be24u(&s->gb); | |||||
| Luma[12] = (tmp >> 18) & 0x3F; | Luma[12] = (tmp >> 18) & 0x3F; | ||||
| Luma[13] = (tmp >> 12) & 0x3F; | Luma[13] = (tmp >> 12) & 0x3F; | ||||
| Luma[14] = (tmp >> 6) & 0x3F; | Luma[14] = (tmp >> 6) & 0x3F; | ||||
| @@ -385,22 +373,23 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma); | ulti_convert_yuv(&s->frame, tx, ty, Luma, chroma); | ||||
| } else { | } else { | ||||
| CHECK_OVERREAD_SIZE(4); | |||||
| tmp = *buf++; | |||||
| if (bytestream2_get_bytes_left(&s->gb) < 4) | |||||
| goto err; | |||||
| tmp = bytestream2_get_byteu(&s->gb); | |||||
| if(tmp & 0x80) { | if(tmp & 0x80) { | ||||
| angle = (tmp >> 4) & 0x7; | angle = (tmp >> 4) & 0x7; | ||||
| tmp = (tmp << 8) + *buf++; | |||||
| tmp = (tmp << 8) + bytestream2_get_byteu(&s->gb); | |||||
| Y[0] = (tmp >> 6) & 0x3F; | Y[0] = (tmp >> 6) & 0x3F; | ||||
| Y[1] = tmp & 0x3F; | Y[1] = tmp & 0x3F; | ||||
| Y[2] = (*buf++) & 0x3F; | |||||
| Y[3] = (*buf++) & 0x3F; | |||||
| Y[2] = bytestream2_get_byteu(&s->gb) & 0x3F; | |||||
| Y[3] = bytestream2_get_byteu(&s->gb) & 0x3F; | |||||
| ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block | ulti_grad(&s->frame, tx, ty, Y, chroma, angle); //draw block | ||||
| } else { // some patterns | } else { // some patterns | ||||
| int f0, f1; | int f0, f1; | ||||
| f0 = *buf++; | |||||
| f0 = bytestream2_get_byteu(&s->gb); | |||||
| f1 = tmp; | f1 = tmp; | ||||
| Y[0] = (*buf++) & 0x3F; | |||||
| Y[1] = (*buf++) & 0x3F; | |||||
| Y[0] = bytestream2_get_byteu(&s->gb) & 0x3F; | |||||
| Y[1] = bytestream2_get_byteu(&s->gb) & 0x3F; | |||||
| ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma); | ulti_pattern(&s->frame, tx, ty, f1, f0, Y[0], Y[1], chroma); | ||||
| } | } | ||||
| } | } | ||||
| @@ -422,6 +411,11 @@ static int ulti_decode_frame(AVCodecContext *avctx, | |||||
| *(AVFrame*)data= s->frame; | *(AVFrame*)data= s->frame; | ||||
| return buf_size; | return buf_size; | ||||
| err: | |||||
| av_log(avctx, AV_LOG_ERROR, | |||||
| "Insufficient data\n"); | |||||
| return AVERROR_INVALIDDATA; | |||||
| } | } | ||||
| AVCodec ff_ulti_decoder = { | AVCodec ff_ulti_decoder = { | ||||
| @@ -568,6 +568,7 @@ static void vc1_mc_1mv(VC1Context *v, int dir) | |||||
| } | } | ||||
| if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) | if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) | ||||
| || s->h_edge_pos < 22 || v_edge_pos < 22 | |||||
| || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 16 - s->mspel * 3 | || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx&3) - 16 - s->mspel * 3 | ||||
| || (unsigned)(src_y - s->mspel) > v_edge_pos - (my&3) - 16 - s->mspel * 3) { | || (unsigned)(src_y - s->mspel) > v_edge_pos - (my&3) - 16 - s->mspel * 3) { | ||||
| uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; | uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; | ||||
| @@ -799,6 +800,7 @@ static void vc1_mc_4mv_luma(VC1Context *v, int n, int dir) | |||||
| if (fieldmv && (src_y & 1) && src_y < 4) | if (fieldmv && (src_y & 1) && src_y < 4) | ||||
| src_y--; | src_y--; | ||||
| if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) | if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) | ||||
| || s->h_edge_pos < 13 || v_edge_pos < 23 | |||||
| || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 8 - s->mspel * 2 | || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 8 - s->mspel * 2 | ||||
| || (unsigned)(src_y - (s->mspel << fieldmv)) > v_edge_pos - (my & 3) - ((8 + s->mspel * 2) << fieldmv)) { | || (unsigned)(src_y - (s->mspel << fieldmv)) > v_edge_pos - (my & 3) - ((8 + s->mspel * 2) << fieldmv)) { | ||||
| srcY -= s->mspel * (1 + (s->linesize << fieldmv)); | srcY -= s->mspel * (1 + (s->linesize << fieldmv)); | ||||
| @@ -998,6 +1000,7 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) | |||||
| } | } | ||||
| if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) | if (v->rangeredfrm || (v->mv_mode == MV_PMODE_INTENSITY_COMP) | ||||
| || s->h_edge_pos < 18 || v_edge_pos < 18 | |||||
| || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 9 | || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 9 | ||||
| || (unsigned)uvsrc_y > (v_edge_pos >> 1) - 9) { | || (unsigned)uvsrc_y > (v_edge_pos >> 1) - 9) { | ||||
| s->dsp.emulated_edge_mc(s->edge_emu_buffer , srcU, s->uvlinesize, | s->dsp.emulated_edge_mc(s->edge_emu_buffer , srcU, s->uvlinesize, | ||||
| @@ -1102,6 +1105,7 @@ static void vc1_mc_4mv_chroma4(VC1Context *v) | |||||
| if (fieldmv && (uvsrc_y & 1) && uvsrc_y < 2) | if (fieldmv && (uvsrc_y & 1) && uvsrc_y < 2) | ||||
| uvsrc_y--; | uvsrc_y--; | ||||
| if ((v->mv_mode == MV_PMODE_INTENSITY_COMP) | if ((v->mv_mode == MV_PMODE_INTENSITY_COMP) | ||||
| || s->h_edge_pos < 10 || v_edge_pos < (5 << fieldmv) | |||||
| || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 5 | || (unsigned)uvsrc_x > (s->h_edge_pos >> 1) - 5 | ||||
| || (unsigned)uvsrc_y > v_edge_pos - (5 << fieldmv)) { | || (unsigned)uvsrc_y > v_edge_pos - (5 << fieldmv)) { | ||||
| s->dsp.emulated_edge_mc(s->edge_emu_buffer, srcU, s->uvlinesize, | s->dsp.emulated_edge_mc(s->edge_emu_buffer, srcU, s->uvlinesize, | ||||
| @@ -2006,7 +2010,7 @@ static void vc1_interp_mc(VC1Context *v) | |||||
| srcV = s->edge_emu_buffer + 18 * s->linesize; | srcV = s->edge_emu_buffer + 18 * s->linesize; | ||||
| } | } | ||||
| if (v->rangeredfrm | |||||
| if (v->rangeredfrm || s->h_edge_pos < 22 || v_edge_pos < 22 | |||||
| || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 16 - s->mspel * 3 | || (unsigned)(src_x - s->mspel) > s->h_edge_pos - (mx & 3) - 16 - s->mspel * 3 | ||||
| || (unsigned)(src_y - s->mspel) > v_edge_pos - (my & 3) - 16 - s->mspel * 3) { | || (unsigned)(src_y - s->mspel) > v_edge_pos - (my & 3) - 16 - s->mspel * 3) { | ||||
| uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; | uint8_t *uvbuf = s->edge_emu_buffer + 19 * s->linesize; | ||||
| @@ -69,19 +69,17 @@ | |||||
| static const int desired_video_buffers = 256; | static const int desired_video_buffers = 256; | ||||
| enum io_method { | |||||
| io_read, | |||||
| io_mmap, | |||||
| io_userptr | |||||
| }; | |||||
| #define V4L_ALLFORMATS 3 | |||||
| #define V4L_RAWFORMATS 1 | |||||
| #define V4L_COMPFORMATS 2 | |||||
| struct video_data { | struct video_data { | ||||
| AVClass *class; | AVClass *class; | ||||
| int fd; | int fd; | ||||
| int frame_format; /* V4L2_PIX_FMT_* */ | int frame_format; /* V4L2_PIX_FMT_* */ | ||||
| enum io_method io_method; | |||||
| int width, height; | int width, height; | ||||
| int frame_size; | int frame_size; | ||||
| int interlaced; | |||||
| int top_field_first; | int top_field_first; | ||||
| int buffers; | int buffers; | ||||
| @@ -89,8 +87,10 @@ struct video_data { | |||||
| unsigned int *buf_len; | unsigned int *buf_len; | ||||
| char *standard; | char *standard; | ||||
| int channel; | int channel; | ||||
| char *video_size; /**< String describing video size, set by a private option. */ | |||||
| char *video_size; /**< String describing video size, | |||||
| set by a private option. */ | |||||
| char *pixel_format; /**< Set by a private option. */ | char *pixel_format; /**< Set by a private option. */ | ||||
| int list_format; /**< Set by a private option. */ | |||||
| char *framerate; /**< Set by a private option. */ | char *framerate; /**< Set by a private option. */ | ||||
| }; | }; | ||||
| @@ -124,7 +124,7 @@ static struct fmt_map fmt_conversion_table[] = { | |||||
| { PIX_FMT_NONE, CODEC_ID_MJPEG, V4L2_PIX_FMT_JPEG }, | { PIX_FMT_NONE, CODEC_ID_MJPEG, V4L2_PIX_FMT_JPEG }, | ||||
| }; | }; | ||||
| static int device_open(AVFormatContext *ctx, uint32_t *capabilities) | |||||
| static int device_open(AVFormatContext *ctx) | |||||
| { | { | ||||
| struct v4l2_capability cap; | struct v4l2_capability cap; | ||||
| int fd; | int fd; | ||||
| @@ -137,11 +137,15 @@ static int device_open(AVFormatContext *ctx, uint32_t *capabilities) | |||||
| if (ctx->flags & AVFMT_FLAG_NONBLOCK) { | if (ctx->flags & AVFMT_FLAG_NONBLOCK) { | ||||
| flags |= O_NONBLOCK; | flags |= O_NONBLOCK; | ||||
| } | } | ||||
| fd = v4l2_open(ctx->filename, flags, 0); | fd = v4l2_open(ctx->filename, flags, 0); | ||||
| if (fd < 0) { | if (fd < 0) { | ||||
| err = errno; | |||||
| av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n", | av_log(ctx, AV_LOG_ERROR, "Cannot open video device %s : %s\n", | ||||
| ctx->filename, strerror(errno)); | |||||
| return AVERROR(errno); | |||||
| ctx->filename, strerror(err)); | |||||
| return AVERROR(err); | |||||
| } | } | ||||
| #if CONFIG_LIBV4L2 | #if CONFIG_LIBV4L2 | ||||
| fd_libv4l = v4l2_fd_open(fd, 0); | fd_libv4l = v4l2_fd_open(fd, 0); | ||||
| @@ -155,53 +159,80 @@ static int device_open(AVFormatContext *ctx, uint32_t *capabilities) | |||||
| #endif | #endif | ||||
| res = v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap); | res = v4l2_ioctl(fd, VIDIOC_QUERYCAP, &cap); | ||||
| // ENOIOCTLCMD definition only availble on __KERNEL__ | |||||
| if (res < 0 && ((err = errno) == 515)) { | |||||
| av_log(ctx, AV_LOG_ERROR, "QUERYCAP not implemented, probably V4L device but not supporting V4L2\n"); | |||||
| v4l2_close(fd); | |||||
| return AVERROR(515); | |||||
| } | |||||
| if (res < 0) { | if (res < 0) { | ||||
| err = errno; | |||||
| av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", | av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QUERYCAP): %s\n", | ||||
| strerror(errno)); | |||||
| v4l2_close(fd); | |||||
| return AVERROR(err); | |||||
| strerror(err)); | |||||
| goto fail; | |||||
| } | |||||
| av_log(ctx, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n", | |||||
| fd, cap.capabilities); | |||||
| if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { | |||||
| av_log(ctx, AV_LOG_ERROR, "Not a video capture device.\n"); | |||||
| err = ENODEV; | |||||
| goto fail; | |||||
| } | } | ||||
| if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { | |||||
| av_log(ctx, AV_LOG_ERROR, "Not a video capture device\n"); | |||||
| v4l2_close(fd); | |||||
| return AVERROR(ENODEV); | |||||
| if (!(cap.capabilities & V4L2_CAP_STREAMING)) { | |||||
| av_log(ctx, AV_LOG_ERROR, | |||||
| "The device does not support the streaming I/O method.\n"); | |||||
| err = ENOSYS; | |||||
| goto fail; | |||||
| } | } | ||||
| *capabilities = cap.capabilities; | |||||
| return fd; | return fd; | ||||
| fail: | |||||
| v4l2_close(fd); | |||||
| return AVERROR(err); | |||||
| } | } | ||||
| static int device_init(AVFormatContext *ctx, int *width, int *height, uint32_t pix_fmt) | |||||
| static int device_init(AVFormatContext *ctx, int *width, int *height, | |||||
| uint32_t pix_fmt) | |||||
| { | { | ||||
| struct video_data *s = ctx->priv_data; | struct video_data *s = ctx->priv_data; | ||||
| int fd = s->fd; | int fd = s->fd; | ||||
| struct v4l2_format fmt = {0}; | |||||
| struct v4l2_format fmt; | |||||
| struct v4l2_pix_format *pix = &fmt.fmt.pix; | |||||
| int res; | int res; | ||||
| memset(&fmt, 0, sizeof(struct v4l2_format)); | |||||
| fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| fmt.fmt.pix.width = *width; | |||||
| fmt.fmt.pix.height = *height; | |||||
| fmt.fmt.pix.pixelformat = pix_fmt; | |||||
| fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; | |||||
| pix->width = *width; | |||||
| pix->height = *height; | |||||
| pix->pixelformat = pix_fmt; | |||||
| pix->field = V4L2_FIELD_ANY; | |||||
| res = v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt); | res = v4l2_ioctl(fd, VIDIOC_S_FMT, &fmt); | ||||
| if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) { | if ((*width != fmt.fmt.pix.width) || (*height != fmt.fmt.pix.height)) { | ||||
| av_log(ctx, AV_LOG_INFO, "The V4L2 driver changed the video from %dx%d to %dx%d\n", *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height); | |||||
| av_log(ctx, AV_LOG_INFO, | |||||
| "The V4L2 driver changed the video from %dx%d to %dx%d\n", | |||||
| *width, *height, fmt.fmt.pix.width, fmt.fmt.pix.height); | |||||
| *width = fmt.fmt.pix.width; | *width = fmt.fmt.pix.width; | ||||
| *height = fmt.fmt.pix.height; | *height = fmt.fmt.pix.height; | ||||
| } | } | ||||
| if (pix_fmt != fmt.fmt.pix.pixelformat) { | if (pix_fmt != fmt.fmt.pix.pixelformat) { | ||||
| av_log(ctx, AV_LOG_DEBUG, "The V4L2 driver changed the pixel format from 0x%08X to 0x%08X\n", pix_fmt, fmt.fmt.pix.pixelformat); | |||||
| av_log(ctx, AV_LOG_DEBUG, | |||||
| "The V4L2 driver changed the pixel format " | |||||
| "from 0x%08X to 0x%08X\n", | |||||
| pix_fmt, fmt.fmt.pix.pixelformat); | |||||
| res = -1; | res = -1; | ||||
| } | } | ||||
| if (fmt.fmt.pix.field == V4L2_FIELD_INTERLACED) { | |||||
| av_log(ctx, AV_LOG_DEBUG, "The V4L2 driver using the interlaced mode"); | |||||
| s->interlaced = 1; | |||||
| } | |||||
| return res; | return res; | ||||
| } | } | ||||
| @@ -264,6 +295,71 @@ static enum CodecID fmt_v4l2codec(uint32_t v4l2_fmt) | |||||
| return CODEC_ID_NONE; | return CODEC_ID_NONE; | ||||
| } | } | ||||
| #if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE | |||||
| static void list_framesizes(AVFormatContext *ctx, int fd, uint32_t pixelformat) | |||||
| { | |||||
| struct v4l2_frmsizeenum vfse = { .pixel_format = pixelformat }; | |||||
| while(!ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &vfse)) { | |||||
| switch (vfse.type) { | |||||
| case V4L2_FRMSIZE_TYPE_DISCRETE: | |||||
| av_log(ctx, AV_LOG_INFO, " %ux%u", | |||||
| vfse.discrete.width, vfse.discrete.height); | |||||
| break; | |||||
| case V4L2_FRMSIZE_TYPE_CONTINUOUS: | |||||
| case V4L2_FRMSIZE_TYPE_STEPWISE: | |||||
| av_log(ctx, AV_LOG_INFO, " {%u-%u, %u}x{%u-%u, %u}", | |||||
| vfse.stepwise.min_width, | |||||
| vfse.stepwise.max_width, | |||||
| vfse.stepwise.step_width, | |||||
| vfse.stepwise.min_height, | |||||
| vfse.stepwise.max_height, | |||||
| vfse.stepwise.step_height); | |||||
| } | |||||
| vfse.index++; | |||||
| } | |||||
| } | |||||
| #endif | |||||
| static void list_formats(AVFormatContext *ctx, int fd, int type) | |||||
| { | |||||
| struct v4l2_fmtdesc vfd = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; | |||||
| while(!ioctl(fd, VIDIOC_ENUM_FMT, &vfd)) { | |||||
| enum CodecID codec_id = fmt_v4l2codec(vfd.pixelformat); | |||||
| enum PixelFormat pix_fmt = fmt_v4l2ff(vfd.pixelformat, codec_id); | |||||
| vfd.index++; | |||||
| if (!(vfd.flags & V4L2_FMT_FLAG_COMPRESSED) && | |||||
| type & V4L_RAWFORMATS) { | |||||
| const char *fmt_name = av_get_pix_fmt_name(pix_fmt); | |||||
| av_log(ctx, AV_LOG_INFO, "R : %9s : %20s :", | |||||
| fmt_name ? fmt_name : "Unsupported", | |||||
| vfd.description); | |||||
| } else if (vfd.flags & V4L2_FMT_FLAG_COMPRESSED && | |||||
| type & V4L_COMPFORMATS) { | |||||
| AVCodec *codec = avcodec_find_encoder(codec_id); | |||||
| av_log(ctx, AV_LOG_INFO, "C : %9s : %20s :", | |||||
| codec ? codec->name : "Unsupported", | |||||
| vfd.description); | |||||
| } else { | |||||
| continue; | |||||
| } | |||||
| #ifdef V4L2_FMT_FLAG_EMULATED | |||||
| if (vfd.flags & V4L2_FMT_FLAG_EMULATED) { | |||||
| av_log(ctx, AV_LOG_WARNING, "%s", "Emulated"); | |||||
| continue; | |||||
| } | |||||
| #endif | |||||
| #if HAVE_STRUCT_V4L2_FRMIVALENUM_DISCRETE | |||||
| list_framesizes(ctx, fd, vfd.pixelformat); | |||||
| #endif | |||||
| av_log(ctx, AV_LOG_INFO, "\n"); | |||||
| } | |||||
| } | |||||
| static int mmap_init(AVFormatContext *ctx) | static int mmap_init(AVFormatContext *ctx) | ||||
| { | { | ||||
| struct video_data *s = ctx->priv_data; | struct video_data *s = ctx->priv_data; | ||||
| @@ -314,12 +410,16 @@ static int mmap_init(AVFormatContext *ctx) | |||||
| s->buf_len[i] = buf.length; | s->buf_len[i] = buf.length; | ||||
| if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) { | if (s->frame_size > 0 && s->buf_len[i] < s->frame_size) { | ||||
| av_log(ctx, AV_LOG_ERROR, "Buffer len [%d] = %d != %d\n", i, s->buf_len[i], s->frame_size); | |||||
| av_log(ctx, AV_LOG_ERROR, | |||||
| "Buffer len [%d] = %d != %d\n", | |||||
| i, s->buf_len[i], s->frame_size); | |||||
| return -1; | return -1; | ||||
| } | } | ||||
| s->buf_start[i] = v4l2_mmap(NULL, buf.length, | s->buf_start[i] = v4l2_mmap(NULL, buf.length, | ||||
| PROT_READ | PROT_WRITE, MAP_SHARED, s->fd, buf.m.offset); | |||||
| PROT_READ | PROT_WRITE, MAP_SHARED, | |||||
| s->fd, buf.m.offset); | |||||
| if (s->buf_start[i] == MAP_FAILED) { | if (s->buf_start[i] == MAP_FAILED) { | ||||
| av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno)); | av_log(ctx, AV_LOG_ERROR, "mmap: %s\n", strerror(errno)); | ||||
| return AVERROR(errno); | return AVERROR(errno); | ||||
| @@ -329,20 +429,14 @@ static int mmap_init(AVFormatContext *ctx) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| static int read_init(AVFormatContext *ctx) | |||||
| { | |||||
| return -1; | |||||
| } | |||||
| static void mmap_release_buffer(AVPacket *pkt) | static void mmap_release_buffer(AVPacket *pkt) | ||||
| { | { | ||||
| struct v4l2_buffer buf = {0}; | struct v4l2_buffer buf = {0}; | ||||
| int res, fd; | int res, fd; | ||||
| struct buff_data *buf_descriptor = pkt->priv; | struct buff_data *buf_descriptor = pkt->priv; | ||||
| if (pkt->data == NULL) { | |||||
| return; | |||||
| } | |||||
| if (pkt->data == NULL) | |||||
| return; | |||||
| buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| buf.memory = V4L2_MEMORY_MMAP; | buf.memory = V4L2_MEMORY_MMAP; | ||||
| @@ -351,9 +445,10 @@ static void mmap_release_buffer(AVPacket *pkt) | |||||
| av_free(buf_descriptor); | av_free(buf_descriptor); | ||||
| res = v4l2_ioctl(fd, VIDIOC_QBUF, &buf); | res = v4l2_ioctl(fd, VIDIOC_QBUF, &buf); | ||||
| if (res < 0) { | |||||
| av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno)); | |||||
| } | |||||
| if (res < 0) | |||||
| av_log(NULL, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", | |||||
| strerror(errno)); | |||||
| pkt->data = NULL; | pkt->data = NULL; | ||||
| pkt->size = 0; | pkt->size = 0; | ||||
| } | } | ||||
| @@ -375,13 +470,17 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) | |||||
| pkt->size = 0; | pkt->size = 0; | ||||
| return AVERROR(EAGAIN); | return AVERROR(EAGAIN); | ||||
| } | } | ||||
| av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", strerror(errno)); | |||||
| av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_DQBUF): %s\n", | |||||
| strerror(errno)); | |||||
| return AVERROR(errno); | return AVERROR(errno); | ||||
| } | } | ||||
| assert(buf.index < s->buffers); | assert(buf.index < s->buffers); | ||||
| if (s->frame_size > 0 && buf.bytesused != s->frame_size) { | if (s->frame_size > 0 && buf.bytesused != s->frame_size) { | ||||
| av_log(ctx, AV_LOG_ERROR, "The v4l2 frame is %d bytes, but %d bytes are expected\n", buf.bytesused, s->frame_size); | |||||
| av_log(ctx, AV_LOG_ERROR, | |||||
| "The v4l2 frame is %d bytes, but %d bytes are expected\n", | |||||
| buf.bytesused, s->frame_size); | |||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| @@ -407,11 +506,6 @@ static int mmap_read_frame(AVFormatContext *ctx, AVPacket *pkt) | |||||
| return s->buf_len[buf.index]; | return s->buf_len[buf.index]; | ||||
| } | } | ||||
| static int read_frame(AVFormatContext *ctx, AVPacket *pkt) | |||||
| { | |||||
| return -1; | |||||
| } | |||||
| static int mmap_start(AVFormatContext *ctx) | static int mmap_start(AVFormatContext *ctx) | ||||
| { | { | ||||
| struct video_data *s = ctx->priv_data; | struct video_data *s = ctx->priv_data; | ||||
| @@ -427,7 +521,9 @@ static int mmap_start(AVFormatContext *ctx) | |||||
| res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); | res = v4l2_ioctl(s->fd, VIDIOC_QBUF, &buf); | ||||
| if (res < 0) { | if (res < 0) { | ||||
| av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", strerror(errno)); | |||||
| av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_QBUF): %s\n", | |||||
| strerror(errno)); | |||||
| return AVERROR(errno); | return AVERROR(errno); | ||||
| } | } | ||||
| } | } | ||||
| @@ -435,7 +531,9 @@ static int mmap_start(AVFormatContext *ctx) | |||||
| type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| res = v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type); | res = v4l2_ioctl(s->fd, VIDIOC_STREAMON, &type); | ||||
| if (res < 0) { | if (res < 0) { | ||||
| av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", strerror(errno)); | |||||
| av_log(ctx, AV_LOG_ERROR, "ioctl(VIDIOC_STREAMON): %s\n", | |||||
| strerror(errno)); | |||||
| return AVERROR(errno); | return AVERROR(errno); | ||||
| } | } | ||||
| @@ -471,8 +569,10 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) | |||||
| streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| if (s->framerate && (ret = av_parse_video_rate(&framerate_q, s->framerate)) < 0) { | |||||
| av_log(s1, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", s->framerate); | |||||
| if (s->framerate && | |||||
| (ret = av_parse_video_rate(&framerate_q, s->framerate)) < 0) { | |||||
| av_log(s1, AV_LOG_ERROR, "Could not parse framerate '%s'.\n", | |||||
| s->framerate); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -486,7 +586,8 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) | |||||
| av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n", | av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set input_id: %d, input: %s\n", | ||||
| s->channel, input.name); | s->channel, input.name); | ||||
| if (v4l2_ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) { | if (v4l2_ioctl(s->fd, VIDIOC_S_INPUT, &input.index) < 0) { | ||||
| av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set input(%d) failed\n", | |||||
| av_log(s1, AV_LOG_ERROR, | |||||
| "The V4L2 driver ioctl set input(%d) failed\n", | |||||
| s->channel); | s->channel); | ||||
| return AVERROR(EIO); | return AVERROR(EIO); | ||||
| } | } | ||||
| @@ -506,10 +607,12 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| av_log(s1, AV_LOG_DEBUG, "The V4L2 driver set standard: %s, id: %"PRIu64"\n", | |||||
| av_log(s1, AV_LOG_DEBUG, | |||||
| "The V4L2 driver set standard: %s, id: %"PRIu64"\n", | |||||
| s->standard, (uint64_t)standard.id); | s->standard, (uint64_t)standard.id); | ||||
| if (v4l2_ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) { | if (v4l2_ioctl(s->fd, VIDIOC_S_STD, &standard.id) < 0) { | ||||
| av_log(s1, AV_LOG_ERROR, "The V4L2 driver ioctl set standard(%s) failed\n", | |||||
| av_log(s1, AV_LOG_ERROR, | |||||
| "The V4L2 driver ioctl set standard(%s) failed\n", | |||||
| s->standard); | s->standard); | ||||
| return AVERROR(EIO); | return AVERROR(EIO); | ||||
| } | } | ||||
| @@ -520,6 +623,7 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) | |||||
| framerate_q.den, framerate_q.num); | framerate_q.den, framerate_q.num); | ||||
| tpf->numerator = framerate_q.den; | tpf->numerator = framerate_q.den; | ||||
| tpf->denominator = framerate_q.num; | tpf->denominator = framerate_q.num; | ||||
| if (v4l2_ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) { | if (v4l2_ioctl(s->fd, VIDIOC_S_PARM, &streamparm) != 0) { | ||||
| av_log(s1, AV_LOG_ERROR, | av_log(s1, AV_LOG_ERROR, | ||||
| "ioctl set time per frame(%d/%d) failed\n", | "ioctl set time per frame(%d/%d) failed\n", | ||||
| @@ -530,14 +634,15 @@ static int v4l2_set_parameters(AVFormatContext *s1, AVFormatParameters *ap) | |||||
| if (framerate_q.num != tpf->denominator || | if (framerate_q.num != tpf->denominator || | ||||
| framerate_q.den != tpf->numerator) { | framerate_q.den != tpf->numerator) { | ||||
| av_log(s1, AV_LOG_INFO, | av_log(s1, AV_LOG_INFO, | ||||
| "The driver changed the time per frame from %d/%d to %d/%d\n", | |||||
| "The driver changed the time per frame from " | |||||
| "%d/%d to %d/%d\n", | |||||
| framerate_q.den, framerate_q.num, | framerate_q.den, framerate_q.num, | ||||
| tpf->numerator, tpf->denominator); | tpf->numerator, tpf->denominator); | ||||
| } | } | ||||
| } else { | } else { | ||||
| /* if timebase value is not set, read the timebase value from the driver */ | |||||
| if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) { | if (v4l2_ioctl(s->fd, VIDIOC_G_PARM, &streamparm) != 0) { | ||||
| av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", strerror(errno)); | |||||
| av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_PARM): %s\n", | |||||
| strerror(errno)); | |||||
| return AVERROR(errno); | return AVERROR(errno); | ||||
| } | } | ||||
| } | } | ||||
| @@ -571,6 +676,7 @@ static uint32_t device_try_init(AVFormatContext *s1, | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (desired_format != 0) { | if (desired_format != 0) { | ||||
| *codec_id = fmt_v4l2codec(desired_format); | *codec_id = fmt_v4l2codec(desired_format); | ||||
| assert(*codec_id != CODEC_ID_NONE); | assert(*codec_id != CODEC_ID_NONE); | ||||
| @@ -584,7 +690,7 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) | |||||
| struct video_data *s = s1->priv_data; | struct video_data *s = s1->priv_data; | ||||
| AVStream *st; | AVStream *st; | ||||
| int res = 0; | int res = 0; | ||||
| uint32_t desired_format, capabilities; | |||||
| uint32_t desired_format; | |||||
| enum CodecID codec_id; | enum CodecID codec_id; | ||||
| enum PixelFormat pix_fmt = PIX_FMT_NONE; | enum PixelFormat pix_fmt = PIX_FMT_NONE; | ||||
| @@ -593,42 +699,62 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) | |||||
| res = AVERROR(ENOMEM); | res = AVERROR(ENOMEM); | ||||
| goto out; | goto out; | ||||
| } | } | ||||
| avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ | |||||
| if (s->video_size && (res = av_parse_video_size(&s->width, &s->height, s->video_size)) < 0) { | |||||
| av_log(s1, AV_LOG_ERROR, "Could not parse video size '%s'.\n", s->video_size); | |||||
| s->fd = device_open(s1); | |||||
| if (s->fd < 0) { | |||||
| res = s->fd; | |||||
| goto out; | goto out; | ||||
| } | } | ||||
| if (s->pixel_format && (pix_fmt = av_get_pix_fmt(s->pixel_format)) == PIX_FMT_NONE) { | |||||
| av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", s->pixel_format); | |||||
| res = AVERROR(EINVAL); | |||||
| if (s->list_format) { | |||||
| list_formats(s1, s->fd, s->list_format); | |||||
| res = AVERROR_EXIT; | |||||
| goto out; | goto out; | ||||
| } | } | ||||
| capabilities = 0; | |||||
| s->fd = device_open(s1, &capabilities); | |||||
| if (s->fd < 0) { | |||||
| res = AVERROR(EIO); | |||||
| avpriv_set_pts_info(st, 64, 1, 1000000); /* 64 bits pts in us */ | |||||
| if (s->video_size && | |||||
| (res = av_parse_video_size(&s->width, &s->height, s->video_size)) < 0) { | |||||
| av_log(s1, AV_LOG_ERROR, "Could not parse video size '%s'.\n", | |||||
| s->video_size); | |||||
| goto out; | goto out; | ||||
| } | } | ||||
| av_log(s1, AV_LOG_VERBOSE, "[%d]Capabilities: %x\n", s->fd, capabilities); | |||||
| if (s->pixel_format) { | |||||
| pix_fmt = av_get_pix_fmt(s->pixel_format); | |||||
| if (pix_fmt == PIX_FMT_NONE) { | |||||
| av_log(s1, AV_LOG_ERROR, "No such pixel format: %s.\n", | |||||
| s->pixel_format); | |||||
| res = AVERROR(EINVAL); | |||||
| goto out; | |||||
| } | |||||
| } | |||||
| if (!s->width && !s->height) { | if (!s->width && !s->height) { | ||||
| struct v4l2_format fmt; | struct v4l2_format fmt; | ||||
| av_log(s1, AV_LOG_VERBOSE, "Querying the device for the current frame size\n"); | |||||
| av_log(s1, AV_LOG_VERBOSE, | |||||
| "Querying the device for the current frame size\n"); | |||||
| fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| if (v4l2_ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) { | if (v4l2_ioctl(s->fd, VIDIOC_G_FMT, &fmt) < 0) { | ||||
| av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", strerror(errno)); | |||||
| av_log(s1, AV_LOG_ERROR, "ioctl(VIDIOC_G_FMT): %s\n", | |||||
| strerror(errno)); | |||||
| res = AVERROR(errno); | res = AVERROR(errno); | ||||
| goto out; | goto out; | ||||
| } | } | ||||
| s->width = fmt.fmt.pix.width; | s->width = fmt.fmt.pix.width; | ||||
| s->height = fmt.fmt.pix.height; | s->height = fmt.fmt.pix.height; | ||||
| av_log(s1, AV_LOG_VERBOSE, "Setting frame size to %dx%d\n", s->width, s->height); | |||||
| av_log(s1, AV_LOG_VERBOSE, | |||||
| "Setting frame size to %dx%d\n", s->width, s->height); | |||||
| } | } | ||||
| desired_format = device_try_init(s1, pix_fmt, &s->width, &s->height, &codec_id); | |||||
| desired_format = device_try_init(s1, pix_fmt, &s->width, &s->height, | |||||
| &codec_id); | |||||
| if (desired_format == 0) { | if (desired_format == 0) { | ||||
| av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for " | av_log(s1, AV_LOG_ERROR, "Cannot find a proper format for " | ||||
| "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, pix_fmt); | "codec_id %d, pix_fmt %d.\n", s1->video_codec_id, pix_fmt); | ||||
| @@ -639,32 +765,29 @@ static int v4l2_read_header(AVFormatContext *s1, AVFormatParameters *ap) | |||||
| } | } | ||||
| if ((res = av_image_check_size(s->width, s->height, 0, s1)) < 0) | if ((res = av_image_check_size(s->width, s->height, 0, s1)) < 0) | ||||
| goto out; | goto out; | ||||
| s->frame_format = desired_format; | s->frame_format = desired_format; | ||||
| if ((res = v4l2_set_parameters(s1, ap)) < 0) | if ((res = v4l2_set_parameters(s1, ap)) < 0) | ||||
| goto out; | goto out; | ||||
| st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id); | st->codec->pix_fmt = fmt_v4l2ff(desired_format, codec_id); | ||||
| s->frame_size = avpicture_get_size(st->codec->pix_fmt, s->width, s->height); | |||||
| if (capabilities & V4L2_CAP_STREAMING) { | |||||
| s->io_method = io_mmap; | |||||
| res = mmap_init(s1); | |||||
| if (res == 0) { | |||||
| res = mmap_start(s1); | |||||
| } | |||||
| } else { | |||||
| s->io_method = io_read; | |||||
| res = read_init(s1); | |||||
| } | |||||
| if (res < 0) { | |||||
| s->frame_size = | |||||
| avpicture_get_size(st->codec->pix_fmt, s->width, s->height); | |||||
| if ((res = mmap_init(s1)) || | |||||
| (res = mmap_start(s1)) < 0) { | |||||
| v4l2_close(s->fd); | v4l2_close(s->fd); | ||||
| res = AVERROR(EIO); | |||||
| goto out; | goto out; | ||||
| } | } | ||||
| s->top_field_first = first_field(s->fd); | s->top_field_first = first_field(s->fd); | ||||
| st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | st->codec->codec_type = AVMEDIA_TYPE_VIDEO; | ||||
| st->codec->codec_id = codec_id; | st->codec->codec_id = codec_id; | ||||
| if (codec_id == CODEC_ID_RAWVIDEO) | |||||
| st->codec->codec_tag = | |||||
| avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt); | |||||
| st->codec->width = s->width; | st->codec->width = s->width; | ||||
| st->codec->height = s->height; | st->codec->height = s->height; | ||||
| st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8; | st->codec->bit_rate = s->frame_size * 1/av_q2d(st->codec->time_base) * 8; | ||||
| @@ -676,26 +799,17 @@ out: | |||||
| static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt) | static int v4l2_read_packet(AVFormatContext *s1, AVPacket *pkt) | ||||
| { | { | ||||
| struct video_data *s = s1->priv_data; | struct video_data *s = s1->priv_data; | ||||
| AVFrame *frame = s1->streams[0]->codec->coded_frame; | |||||
| int res; | int res; | ||||
| if (s->io_method == io_mmap) { | |||||
| av_init_packet(pkt); | |||||
| res = mmap_read_frame(s1, pkt); | |||||
| } else if (s->io_method == io_read) { | |||||
| if (av_new_packet(pkt, s->frame_size) < 0) | |||||
| return AVERROR(EIO); | |||||
| res = read_frame(s1, pkt); | |||||
| } else { | |||||
| return AVERROR(EIO); | |||||
| } | |||||
| if (res < 0) { | |||||
| av_init_packet(pkt); | |||||
| if ((res = mmap_read_frame(s1, pkt)) < 0) { | |||||
| return res; | return res; | ||||
| } | } | ||||
| if (s1->streams[0]->codec->coded_frame) { | |||||
| s1->streams[0]->codec->coded_frame->interlaced_frame = 1; | |||||
| s1->streams[0]->codec->coded_frame->top_field_first = s->top_field_first; | |||||
| if (frame && s->interlaced) { | |||||
| frame->interlaced_frame = 1; | |||||
| frame->top_field_first = s->top_field_first; | |||||
| } | } | ||||
| return pkt->size; | return pkt->size; | ||||
| @@ -705,9 +819,7 @@ static int v4l2_read_close(AVFormatContext *s1) | |||||
| { | { | ||||
| struct video_data *s = s1->priv_data; | struct video_data *s = s1->priv_data; | ||||
| if (s->io_method == io_mmap) { | |||||
| mmap_close(s); | |||||
| } | |||||
| mmap_close(s); | |||||
| v4l2_close(s->fd); | v4l2_close(s->fd); | ||||
| return 0; | return 0; | ||||
| @@ -717,11 +829,15 @@ static int v4l2_read_close(AVFormatContext *s1) | |||||
| #define DEC AV_OPT_FLAG_DECODING_PARAM | #define DEC AV_OPT_FLAG_DECODING_PARAM | ||||
| static const AVOption options[] = { | static const AVOption options[] = { | ||||
| { "standard", "", OFFSET(standard), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, AV_OPT_FLAG_DECODING_PARAM }, | |||||
| { "channel", "", OFFSET(channel), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, | |||||
| { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, | |||||
| { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, | |||||
| { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, | |||||
| { "standard", "TV standard, used only by analog frame grabber", OFFSET(standard), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC }, | |||||
| { "channel", "TV channel, used only by frame grabber", OFFSET(channel), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC }, | |||||
| { "video_size", "A string describing frame size, such as 640x480 or hd720.", OFFSET(video_size), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, | |||||
| { "pixel_format", "", OFFSET(pixel_format), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, | |||||
| { "framerate", "", OFFSET(framerate), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, DEC }, | |||||
| { "list_formats", "List available formats and exit", OFFSET(list_format), AV_OPT_TYPE_INT, {.dbl = 0 }, 0, INT_MAX, DEC, "list_formats" }, | |||||
| { "all", "Show all available formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_ALLFORMATS }, 0, INT_MAX, DEC, "list_formats" }, | |||||
| { "raw", "Show only non-compressed formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_RAWFORMATS }, 0, INT_MAX, DEC, "list_formats" }, | |||||
| { "compressed", "Show only compressed formats", OFFSET(list_format), AV_OPT_TYPE_CONST, {.dbl = V4L_COMPFORMATS }, 0, INT_MAX, DEC, "list_formats" }, | |||||
| { NULL }, | { NULL }, | ||||
| }; | }; | ||||
| @@ -26,6 +26,7 @@ OBJS-$(CONFIG_AC3_MUXER) += rawenc.o | |||||
| OBJS-$(CONFIG_ACT_DEMUXER) += act.o | OBJS-$(CONFIG_ACT_DEMUXER) += act.o | ||||
| OBJS-$(CONFIG_ADF_DEMUXER) += bintext.o sauce.o | OBJS-$(CONFIG_ADF_DEMUXER) += bintext.o sauce.o | ||||
| OBJS-$(CONFIG_ADX_DEMUXER) += adxdec.o | OBJS-$(CONFIG_ADX_DEMUXER) += adxdec.o | ||||
| OBJS-$(CONFIG_ADX_MUXER) += rawenc.o | |||||
| OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o | OBJS-$(CONFIG_ADTS_MUXER) += adtsenc.o | ||||
| OBJS-$(CONFIG_AEA_DEMUXER) += aea.o pcm.o | OBJS-$(CONFIG_AEA_DEMUXER) += aea.o pcm.o | ||||
| OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o riff.o pcm.o isom.o | OBJS-$(CONFIG_AIFF_DEMUXER) += aiffdec.o riff.o pcm.o isom.o | ||||
| @@ -109,4 +109,5 @@ AVInputFormat ff_adx_demuxer = { | |||||
| .read_packet = adx_read_packet, | .read_packet = adx_read_packet, | ||||
| .extensions = "adx", | .extensions = "adx", | ||||
| .value = CODEC_ID_ADPCM_ADX, | .value = CODEC_ID_ADPCM_ADX, | ||||
| .flags = AVFMT_GENERIC_INDEX, | |||||
| }; | }; | ||||
| @@ -54,7 +54,7 @@ void av_register_all(void) | |||||
| REGISTER_DEMUXER (ACT, act); | REGISTER_DEMUXER (ACT, act); | ||||
| REGISTER_DEMUXER (ADF, adf); | REGISTER_DEMUXER (ADF, adf); | ||||
| REGISTER_MUXER (ADTS, adts); | REGISTER_MUXER (ADTS, adts); | ||||
| REGISTER_DEMUXER (ADX, adx); | |||||
| REGISTER_MUXDEMUX (ADX, adx); | |||||
| REGISTER_DEMUXER (AEA, aea); | REGISTER_DEMUXER (AEA, aea); | ||||
| REGISTER_MUXDEMUX (AIFF, aiff); | REGISTER_MUXDEMUX (AIFF, aiff); | ||||
| REGISTER_MUXDEMUX (AMR, amr); | REGISTER_MUXDEMUX (AMR, amr); | ||||
| @@ -574,6 +574,10 @@ static void fill_buffer(AVIOContext *s) | |||||
| int len= s->buffer_size - (dst - s->buffer); | int len= s->buffer_size - (dst - s->buffer); | ||||
| int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; | int max_buffer_size = s->max_packet_size ? s->max_packet_size : IO_BUFFER_SIZE; | ||||
| /* can't fill the buffer without read_packet, just set EOF if appropiate */ | |||||
| if (!s->read_packet && s->buf_ptr >= s->buf_end) | |||||
| s->eof_reached = 1; | |||||
| /* no need to do anything if EOF already reached */ | /* no need to do anything if EOF already reached */ | ||||
| if (s->eof_reached) | if (s->eof_reached) | ||||
| return; | return; | ||||
| @@ -112,10 +112,12 @@ static int mtv_read_header(AVFormatContext *s, AVFormatParameters *ap) | |||||
| avio_skip(pb, 4); | avio_skip(pb, 4); | ||||
| audio_subsegments = avio_rl16(pb); | audio_subsegments = avio_rl16(pb); | ||||
| if(!audio_subsegments){ | |||||
| av_log(s, AV_LOG_ERROR, "audio_subsegments is 0\n"); | |||||
| return AVERROR(EINVAL); | |||||
| if (audio_subsegments == 0) { | |||||
| av_log_ask_for_sample(s, "MTV files without audio are not supported\n"); | |||||
| return AVERROR_INVALIDDATA; | |||||
| } | } | ||||
| mtv->full_segment_size = | mtv->full_segment_size = | ||||
| audio_subsegments * (MTV_AUDIO_PADDING_SIZE + MTV_ASUBCHUNK_DATA_SIZE) + | audio_subsegments * (MTV_AUDIO_PADDING_SIZE + MTV_ASUBCHUNK_DATA_SIZE) + | ||||
| mtv->img_segment_size; | mtv->img_segment_size; | ||||
| @@ -45,6 +45,18 @@ AVOutputFormat ff_ac3_muxer = { | |||||
| }; | }; | ||||
| #endif | #endif | ||||
| #if CONFIG_ADX_MUXER | |||||
| AVOutputFormat ff_adx_muxer = { | |||||
| .name = "adx", | |||||
| .long_name = NULL_IF_CONFIG_SMALL("CRI ADX"), | |||||
| .extensions = "adx", | |||||
| .audio_codec = CODEC_ID_ADPCM_ADX, | |||||
| .video_codec = CODEC_ID_NONE, | |||||
| .write_packet = ff_raw_write_packet, | |||||
| .flags = AVFMT_NOTIMESTAMPS, | |||||
| }; | |||||
| #endif | |||||
| #if CONFIG_DIRAC_MUXER | #if CONFIG_DIRAC_MUXER | ||||
| AVOutputFormat ff_dirac_muxer = { | AVOutputFormat ff_dirac_muxer = { | ||||
| .name = "dirac", | .name = "dirac", | ||||
| @@ -2470,7 +2470,7 @@ static av_always_inline void RENAME(do_a_deblock)(uint8_t *src, int step, int st | |||||
| int64_t dc_mask, eq_mask, both_masks; | int64_t dc_mask, eq_mask, both_masks; | ||||
| int64_t sums[10*8*2]; | int64_t sums[10*8*2]; | ||||
| src+= step*3; // src points to begin of the 8x8 Block | src+= step*3; // src points to begin of the 8x8 Block | ||||
| //START_TIMER | |||||
| //{ START_TIMER | |||||
| __asm__ volatile( | __asm__ volatile( | ||||
| "movq %0, %%mm7 \n\t" | "movq %0, %%mm7 \n\t" | ||||
| "movq %1, %%mm6 \n\t" | "movq %1, %%mm6 \n\t" | ||||
| @@ -2995,7 +2995,8 @@ static av_always_inline void RENAME(do_a_deblock)(uint8_t *src, int step, int st | |||||
| STOP_TIMER("step16") | STOP_TIMER("step16") | ||||
| }else{ | }else{ | ||||
| STOP_TIMER("stepX") | STOP_TIMER("stepX") | ||||
| }*/ | |||||
| } | |||||
| } */ | |||||
| } | } | ||||
| #endif //HAVE_MMX | #endif //HAVE_MMX | ||||
| @@ -19,7 +19,8 @@ OBJS-$(HAVE_MMX) += x86/rgb2rgb.o \ | |||||
| x86/swscale_mmx.o \ | x86/swscale_mmx.o \ | ||||
| x86/yuv2rgb_mmx.o | x86/yuv2rgb_mmx.o | ||||
| OBJS-$(HAVE_VIS) += sparc/yuv2rgb_vis.o | OBJS-$(HAVE_VIS) += sparc/yuv2rgb_vis.o | ||||
| OBJS-$(HAVE_YASM) += x86/scale.o | |||||
| MMX-OBJS-$(HAVE_YASM) += x86/output.o \ | |||||
| x86/scale.o | |||||
| $(SUBDIR)x86/swscale_mmx.o: CFLAGS += $(NOREDZONE_FLAGS) | $(SUBDIR)x86/swscale_mmx.o: CFLAGS += $(NOREDZONE_FLAGS) | ||||
| @@ -21,8 +21,8 @@ | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
| */ | */ | ||||
| #ifndef PPC_YUV2RGB_ALTIVEC_H | |||||
| #define PPC_YUV2RGB_ALTIVEC_H 1 | |||||
| #ifndef SWSCALE_PPC_YUV2RGB_ALTIVEC_H | |||||
| #define SWSCALE_PPC_YUV2RGB_ALTIVEC_H | |||||
| #define YUV2PACKEDX_HEADER(suffix) \ | #define YUV2PACKEDX_HEADER(suffix) \ | ||||
| void ff_yuv2 ## suffix ## _X_altivec(SwsContext *c, const int16_t *lumFilter, \ | void ff_yuv2 ## suffix ## _X_altivec(SwsContext *c, const int16_t *lumFilter, \ | ||||
| @@ -39,4 +39,4 @@ YUV2PACKEDX_HEADER(rgba); | |||||
| YUV2PACKEDX_HEADER(rgb24); | YUV2PACKEDX_HEADER(rgb24); | ||||
| YUV2PACKEDX_HEADER(bgr24); | YUV2PACKEDX_HEADER(bgr24); | ||||
| #endif /* PPC_YUV2RGB_ALTIVEC_H */ | |||||
| #endif /* SWSCALE_PPC_YUV2RGB_ALTIVEC_H */ | |||||
| @@ -18,39 +18,6 @@ | |||||
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||||
| */ | */ | ||||
| /* | |||||
| supported Input formats: YV12, I420/IYUV, YUY2, UYVY, BGR32, BGR32_1, BGR24, BGR16, BGR15, RGB32, RGB32_1, RGB24, Y8/Y800, YVU9/IF09, PAL8 | |||||
| supported output formats: YV12, I420/IYUV, YUY2, UYVY, {BGR,RGB}{1,4,8,15,16,24,32}, Y8/Y800, YVU9/IF09 | |||||
| {BGR,RGB}{1,4,8,15,16} support dithering | |||||
| unscaled special converters (YV12=I420=IYUV, Y800=Y8) | |||||
| YV12 -> {BGR,RGB}{1,4,8,12,15,16,24,32} | |||||
| x -> x | |||||
| YUV9 -> YV12 | |||||
| YUV9/YV12 -> Y800 | |||||
| Y800 -> YUV9/YV12 | |||||
| BGR24 -> BGR32 & RGB24 -> RGB32 | |||||
| BGR32 -> BGR24 & RGB32 -> RGB24 | |||||
| BGR15 -> BGR16 | |||||
| */ | |||||
| /* | |||||
| tested special converters (most are tested actually, but I did not write it down ...) | |||||
| YV12 -> BGR12/BGR16 | |||||
| YV12 -> YV12 | |||||
| BGR15 -> BGR16 | |||||
| BGR16 -> BGR16 | |||||
| YVU9 -> YV12 | |||||
| untested special converters | |||||
| YV12/I420 -> BGR15/BGR24/BGR32 (it is the yuv2rgb stuff, so it should be OK) | |||||
| YV12/I420 -> YV12/I420 | |||||
| YUY2/BGR15/BGR24/BGR32/RGB24/RGB32 -> same format | |||||
| BGR24 -> BGR32 & RGB24 -> RGB32 | |||||
| BGR32 -> BGR24 & RGB32 -> RGB24 | |||||
| BGR24 -> YV12 | |||||
| */ | |||||
| #include <inttypes.h> | #include <inttypes.h> | ||||
| #include <string.h> | #include <string.h> | ||||
| #include <math.h> | #include <math.h> | ||||
| @@ -2371,36 +2338,6 @@ find_c_packed_planar_out_funcs(SwsContext *c, | |||||
| } else { | } else { | ||||
| YUV_PACKED: | YUV_PACKED: | ||||
| switch (dstFormat) { | switch (dstFormat) { | ||||
| case PIX_FMT_GRAY16BE: | |||||
| *yuv2packed1 = yuv2gray16BE_1_c; | |||||
| *yuv2packed2 = yuv2gray16BE_2_c; | |||||
| *yuv2packedX = yuv2gray16BE_X_c; | |||||
| break; | |||||
| case PIX_FMT_GRAY16LE: | |||||
| *yuv2packed1 = yuv2gray16LE_1_c; | |||||
| *yuv2packed2 = yuv2gray16LE_2_c; | |||||
| *yuv2packedX = yuv2gray16LE_X_c; | |||||
| break; | |||||
| case PIX_FMT_MONOWHITE: | |||||
| *yuv2packed1 = yuv2monowhite_1_c; | |||||
| *yuv2packed2 = yuv2monowhite_2_c; | |||||
| *yuv2packedX = yuv2monowhite_X_c; | |||||
| break; | |||||
| case PIX_FMT_MONOBLACK: | |||||
| *yuv2packed1 = yuv2monoblack_1_c; | |||||
| *yuv2packed2 = yuv2monoblack_2_c; | |||||
| *yuv2packedX = yuv2monoblack_X_c; | |||||
| break; | |||||
| case PIX_FMT_YUYV422: | |||||
| *yuv2packed1 = yuv2yuyv422_1_c; | |||||
| *yuv2packed2 = yuv2yuyv422_2_c; | |||||
| *yuv2packedX = yuv2yuyv422_X_c; | |||||
| break; | |||||
| case PIX_FMT_UYVY422: | |||||
| *yuv2packed1 = yuv2uyvy422_1_c; | |||||
| *yuv2packed2 = yuv2uyvy422_2_c; | |||||
| *yuv2packedX = yuv2uyvy422_X_c; | |||||
| break; | |||||
| case PIX_FMT_RGB48LE: | case PIX_FMT_RGB48LE: | ||||
| *yuv2packed1 = yuv2rgb48le_1_c; | *yuv2packed1 = yuv2rgb48le_1_c; | ||||
| *yuv2packed2 = yuv2rgb48le_2_c; | *yuv2packed2 = yuv2rgb48le_2_c; | ||||
| @@ -2517,6 +2454,38 @@ find_c_packed_planar_out_funcs(SwsContext *c, | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| switch (dstFormat) { | |||||
| case PIX_FMT_GRAY16BE: | |||||
| *yuv2packed1 = yuv2gray16BE_1_c; | |||||
| *yuv2packed2 = yuv2gray16BE_2_c; | |||||
| *yuv2packedX = yuv2gray16BE_X_c; | |||||
| break; | |||||
| case PIX_FMT_GRAY16LE: | |||||
| *yuv2packed1 = yuv2gray16LE_1_c; | |||||
| *yuv2packed2 = yuv2gray16LE_2_c; | |||||
| *yuv2packedX = yuv2gray16LE_X_c; | |||||
| break; | |||||
| case PIX_FMT_MONOWHITE: | |||||
| *yuv2packed1 = yuv2monowhite_1_c; | |||||
| *yuv2packed2 = yuv2monowhite_2_c; | |||||
| *yuv2packedX = yuv2monowhite_X_c; | |||||
| break; | |||||
| case PIX_FMT_MONOBLACK: | |||||
| *yuv2packed1 = yuv2monoblack_1_c; | |||||
| *yuv2packed2 = yuv2monoblack_2_c; | |||||
| *yuv2packedX = yuv2monoblack_X_c; | |||||
| break; | |||||
| case PIX_FMT_YUYV422: | |||||
| *yuv2packed1 = yuv2yuyv422_1_c; | |||||
| *yuv2packed2 = yuv2yuyv422_2_c; | |||||
| *yuv2packedX = yuv2yuyv422_X_c; | |||||
| break; | |||||
| case PIX_FMT_UYVY422: | |||||
| *yuv2packed1 = yuv2uyvy422_1_c; | |||||
| *yuv2packed2 = yuv2uyvy422_2_c; | |||||
| *yuv2packedX = yuv2uyvy422_X_c; | |||||
| break; | |||||
| } | |||||
| } | } | ||||
| #define DEBUG_SWSCALE_BUFFERS 0 | #define DEBUG_SWSCALE_BUFFERS 0 | ||||
| @@ -0,0 +1,409 @@ | |||||
| ;****************************************************************************** | |||||
| ;* x86-optimized vertical line scaling functions | |||||
| ;* Copyright (c) 2011 Ronald S. Bultje <rsbultje@gmail.com> | |||||
| ;* Kieran Kunhya <kieran@kunhya.com> | |||||
| ;* | |||||
| ;* 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 | |||||
| ;****************************************************************************** | |||||
| %include "x86inc.asm" | |||||
| %include "x86util.asm" | |||||
| SECTION_RODATA | |||||
| minshort: times 8 dw 0x8000 | |||||
| yuv2yuvX_16_start: times 4 dd 0x4000 - 0x40000000 | |||||
| yuv2yuvX_10_start: times 4 dd 0x10000 | |||||
| yuv2yuvX_9_start: times 4 dd 0x20000 | |||||
| yuv2yuvX_10_upper: times 8 dw 0x3ff | |||||
| yuv2yuvX_9_upper: times 8 dw 0x1ff | |||||
| pd_4: times 4 dd 4 | |||||
| pd_4min0x40000:times 4 dd 4 - (0x40000) | |||||
| pw_16: times 8 dw 16 | |||||
| pw_32: times 8 dw 32 | |||||
| pw_512: times 8 dw 512 | |||||
| pw_1024: times 8 dw 1024 | |||||
| SECTION .text | |||||
| ;----------------------------------------------------------------------------- | |||||
| ; vertical line scaling | |||||
| ; | |||||
| ; void yuv2plane1_<output_size>_<opt>(const int16_t *src, uint8_t *dst, int dstW, | |||||
| ; const uint8_t *dither, int offset) | |||||
| ; and | |||||
| ; void yuv2planeX_<output_size>_<opt>(const int16_t *filter, int filterSize, | |||||
| ; const int16_t **src, uint8_t *dst, int dstW, | |||||
| ; const uint8_t *dither, int offset) | |||||
| ; | |||||
| ; Scale one or $filterSize lines of source data to generate one line of output | |||||
| ; data. The input is 15-bit in int16_t if $output_size is [8,10] and 19-bit in | |||||
| ; int32_t if $output_size is 16. $filter is 12-bits. $filterSize is a multiple | |||||
| ; of 2. $offset is either 0 or 3. $dither holds 8 values. | |||||
| ;----------------------------------------------------------------------------- | |||||
| %macro yuv2planeX_fn 4 | |||||
| %ifdef ARCH_X86_32 | |||||
| %define cntr_reg r1 | |||||
| %define movsx mov | |||||
| %else | |||||
| %define cntr_reg r11 | |||||
| %define movsx movsxd | |||||
| %endif | |||||
| cglobal yuv2planeX_%2_%1, %4, 7, %3 | |||||
| %if %2 == 8 || %2 == 9 || %2 == 10 | |||||
| pxor m6, m6 | |||||
| %endif ; %2 == 8/9/10 | |||||
| %if %2 == 8 | |||||
| %ifdef ARCH_X86_32 | |||||
| %assign pad 0x2c - (stack_offset & 15) | |||||
| SUB rsp, pad | |||||
| %define m_dith m7 | |||||
| %else ; x86-64 | |||||
| %define m_dith m9 | |||||
| %endif ; x86-32 | |||||
| ; create registers holding dither | |||||
| movq m_dith, [r5] ; dither | |||||
| test r6d, r6d | |||||
| jz .no_rot | |||||
| %if mmsize == 16 | |||||
| punpcklqdq m_dith, m_dith | |||||
| %endif ; mmsize == 16 | |||||
| PALIGNR m_dith, m_dith, 3, m0 | |||||
| .no_rot: | |||||
| %if mmsize == 16 | |||||
| punpcklbw m_dith, m6 | |||||
| %ifdef ARCH_X86_64 | |||||
| punpcklwd m8, m_dith, m6 | |||||
| pslld m8, 12 | |||||
| %else ; x86-32 | |||||
| punpcklwd m5, m_dith, m6 | |||||
| pslld m5, 12 | |||||
| %endif ; x86-32/64 | |||||
| punpckhwd m_dith, m6 | |||||
| pslld m_dith, 12 | |||||
| %ifdef ARCH_X86_32 | |||||
| mova [rsp+ 0], m5 | |||||
| mova [rsp+16], m_dith | |||||
| %endif | |||||
| %else ; mmsize == 8 | |||||
| punpcklbw m5, m_dith, m6 | |||||
| punpckhbw m_dith, m6 | |||||
| punpcklwd m4, m5, m6 | |||||
| punpckhwd m5, m6 | |||||
| punpcklwd m3, m_dith, m6 | |||||
| punpckhwd m_dith, m6 | |||||
| pslld m4, 12 | |||||
| pslld m5, 12 | |||||
| pslld m3, 12 | |||||
| pslld m_dith, 12 | |||||
| mova [rsp+ 0], m4 | |||||
| mova [rsp+ 8], m5 | |||||
| mova [rsp+16], m3 | |||||
| mova [rsp+24], m_dith | |||||
| %endif ; mmsize == 8/16 | |||||
| %endif ; %2 == 8 | |||||
| xor r5, r5 | |||||
| .pixelloop: | |||||
| %assign %%i 0 | |||||
| ; the rep here is for the 8bit output mmx case, where dither covers | |||||
| ; 8 pixels but we can only handle 2 pixels per register, and thus 4 | |||||
| ; pixels per iteration. In order to not have to keep track of where | |||||
| ; we are w.r.t. dithering, we unroll the mmx/8bit loop x2. | |||||
| %if %2 == 8 | |||||
| %rep 16/mmsize | |||||
| %endif ; %2 == 8 | |||||
| %if %2 == 8 | |||||
| %ifdef ARCH_X86_32 | |||||
| mova m2, [rsp+mmsize*(0+%%i)] | |||||
| mova m1, [rsp+mmsize*(1+%%i)] | |||||
| %else ; x86-64 | |||||
| mova m2, m8 | |||||
| mova m1, m_dith | |||||
| %endif ; x86-32/64 | |||||
| %else ; %2 == 9/10/16 | |||||
| mova m1, [yuv2yuvX_%2_start] | |||||
| mova m2, m1 | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| movsx cntr_reg, r1m | |||||
| .filterloop_ %+ %%i: | |||||
| ; input pixels | |||||
| mov r6, [r2+gprsize*cntr_reg-2*gprsize] | |||||
| %if %2 == 16 | |||||
| mova m3, [r6+r5*4] | |||||
| mova m5, [r6+r5*4+mmsize] | |||||
| %else ; %2 == 8/9/10 | |||||
| mova m3, [r6+r5*2] | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| mov r6, [r2+gprsize*cntr_reg-gprsize] | |||||
| %if %2 == 16 | |||||
| mova m4, [r6+r5*4] | |||||
| mova m6, [r6+r5*4+mmsize] | |||||
| %else ; %2 == 8/9/10 | |||||
| mova m4, [r6+r5*2] | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| ; coefficients | |||||
| movd m0, [r0+2*cntr_reg-4]; coeff[0], coeff[1] | |||||
| %if %2 == 16 | |||||
| pshuflw m7, m0, 0 ; coeff[0] | |||||
| pshuflw m0, m0, 0x55 ; coeff[1] | |||||
| pmovsxwd m7, m7 ; word -> dword | |||||
| pmovsxwd m0, m0 ; word -> dword | |||||
| pmulld m3, m7 | |||||
| pmulld m5, m7 | |||||
| pmulld m4, m0 | |||||
| pmulld m6, m0 | |||||
| paddd m2, m3 | |||||
| paddd m1, m5 | |||||
| paddd m2, m4 | |||||
| paddd m1, m6 | |||||
| %else ; %2 == 10/9/8 | |||||
| punpcklwd m5, m3, m4 | |||||
| punpckhwd m3, m4 | |||||
| SPLATD m0, m0 | |||||
| pmaddwd m5, m0 | |||||
| pmaddwd m3, m0 | |||||
| paddd m2, m5 | |||||
| paddd m1, m3 | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| sub cntr_reg, 2 | |||||
| jg .filterloop_ %+ %%i | |||||
| %if %2 == 16 | |||||
| psrad m2, 31 - %2 | |||||
| psrad m1, 31 - %2 | |||||
| %else ; %2 == 10/9/8 | |||||
| psrad m2, 27 - %2 | |||||
| psrad m1, 27 - %2 | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| %if %2 == 8 | |||||
| packssdw m2, m1 | |||||
| packuswb m2, m2 | |||||
| movh [r3+r5*1], m2 | |||||
| %else ; %2 == 9/10/16 | |||||
| %if %2 == 16 | |||||
| packssdw m2, m1 | |||||
| paddw m2, [minshort] | |||||
| %else ; %2 == 9/10 | |||||
| %ifidn %1, sse4 | |||||
| packusdw m2, m1 | |||||
| %elifidn %1, avx | |||||
| packusdw m2, m1 | |||||
| %else ; mmx2/sse2 | |||||
| packssdw m2, m1 | |||||
| pmaxsw m2, m6 | |||||
| %endif ; mmx2/sse2/sse4/avx | |||||
| pminsw m2, [yuv2yuvX_%2_upper] | |||||
| %endif ; %2 == 9/10/16 | |||||
| mova [r3+r5*2], m2 | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| add r5, mmsize/2 | |||||
| sub r4d, mmsize/2 | |||||
| %if %2 == 8 | |||||
| %assign %%i %%i+2 | |||||
| %endrep | |||||
| %endif ; %2 == 8 | |||||
| jg .pixelloop | |||||
| %if %2 == 8 | |||||
| %ifdef ARCH_X86_32 | |||||
| ADD rsp, pad | |||||
| RET | |||||
| %else ; x86-64 | |||||
| REP_RET | |||||
| %endif ; x86-32/64 | |||||
| %else ; %2 == 9/10/16 | |||||
| REP_RET | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| %endmacro | |||||
| %define PALIGNR PALIGNR_MMX | |||||
| %ifdef ARCH_X86_32 | |||||
| INIT_MMX | |||||
| yuv2planeX_fn mmx2, 8, 0, 7 | |||||
| yuv2planeX_fn mmx2, 9, 0, 5 | |||||
| yuv2planeX_fn mmx2, 10, 0, 5 | |||||
| %endif | |||||
| INIT_XMM | |||||
| yuv2planeX_fn sse2, 8, 10, 7 | |||||
| yuv2planeX_fn sse2, 9, 7, 5 | |||||
| yuv2planeX_fn sse2, 10, 7, 5 | |||||
| %define PALIGNR PALIGNR_SSSE3 | |||||
| yuv2planeX_fn sse4, 8, 10, 7 | |||||
| yuv2planeX_fn sse4, 9, 7, 5 | |||||
| yuv2planeX_fn sse4, 10, 7, 5 | |||||
| yuv2planeX_fn sse4, 16, 8, 5 | |||||
| INIT_AVX | |||||
| yuv2planeX_fn avx, 8, 10, 7 | |||||
| yuv2planeX_fn avx, 9, 7, 5 | |||||
| yuv2planeX_fn avx, 10, 7, 5 | |||||
| ; %1=outout-bpc, %2=alignment (u/a) | |||||
| %macro yuv2plane1_mainloop 2 | |||||
| .loop_%2: | |||||
| %if %1 == 8 | |||||
| paddsw m0, m2, [r0+r2*2+mmsize*0] | |||||
| paddsw m1, m3, [r0+r2*2+mmsize*1] | |||||
| psraw m0, 7 | |||||
| psraw m1, 7 | |||||
| packuswb m0, m1 | |||||
| mov%2 [r1+r2], m0 | |||||
| %elif %1 == 16 | |||||
| paddd m0, m4, [r0+r2*4+mmsize*0] | |||||
| paddd m1, m4, [r0+r2*4+mmsize*1] | |||||
| paddd m2, m4, [r0+r2*4+mmsize*2] | |||||
| paddd m3, m4, [r0+r2*4+mmsize*3] | |||||
| psrad m0, 3 | |||||
| psrad m1, 3 | |||||
| psrad m2, 3 | |||||
| psrad m3, 3 | |||||
| %if cpuflag(sse4) ; avx/sse4 | |||||
| packusdw m0, m1 | |||||
| packusdw m2, m3 | |||||
| %else ; mmx/sse2 | |||||
| packssdw m0, m1 | |||||
| packssdw m2, m3 | |||||
| paddw m0, m5 | |||||
| paddw m2, m5 | |||||
| %endif ; mmx/sse2/sse4/avx | |||||
| mov%2 [r1+r2*2], m0 | |||||
| mov%2 [r1+r2*2+mmsize], m2 | |||||
| %else | |||||
| paddsw m0, m2, [r0+r2*2+mmsize*0] | |||||
| paddsw m1, m2, [r0+r2*2+mmsize*1] | |||||
| psraw m0, 15 - %1 | |||||
| psraw m1, 15 - %1 | |||||
| pmaxsw m0, m4 | |||||
| pmaxsw m1, m4 | |||||
| pminsw m0, m3 | |||||
| pminsw m1, m3 | |||||
| mov%2 [r1+r2*2], m0 | |||||
| mov%2 [r1+r2*2+mmsize], m1 | |||||
| %endif | |||||
| add r2, mmsize | |||||
| jl .loop_%2 | |||||
| %endmacro | |||||
| %macro yuv2plane1_fn 3 | |||||
| cglobal yuv2plane1_%1, %3, %3, %2 | |||||
| add r2, mmsize - 1 | |||||
| and r2, ~(mmsize - 1) | |||||
| %if %1 == 8 | |||||
| add r1, r2 | |||||
| %else ; %1 != 8 | |||||
| lea r1, [r1+r2*2] | |||||
| %endif ; %1 == 8 | |||||
| %if %1 == 16 | |||||
| lea r0, [r0+r2*4] | |||||
| %else ; %1 != 16 | |||||
| lea r0, [r0+r2*2] | |||||
| %endif ; %1 == 16 | |||||
| neg r2 | |||||
| %if %1 == 8 | |||||
| pxor m4, m4 ; zero | |||||
| ; create registers holding dither | |||||
| movq m3, [r3] ; dither | |||||
| test r4d, r4d | |||||
| jz .no_rot | |||||
| %if mmsize == 16 | |||||
| punpcklqdq m3, m3 | |||||
| %endif ; mmsize == 16 | |||||
| PALIGNR_MMX m3, m3, 3, m2 | |||||
| .no_rot: | |||||
| %if mmsize == 8 | |||||
| mova m2, m3 | |||||
| punpckhbw m3, m4 ; byte->word | |||||
| punpcklbw m2, m4 ; byte->word | |||||
| %else | |||||
| punpcklbw m3, m4 | |||||
| mova m2, m3 | |||||
| %endif | |||||
| %elif %1 == 9 | |||||
| pxor m4, m4 | |||||
| mova m3, [pw_512] | |||||
| mova m2, [pw_32] | |||||
| %elif %1 == 10 | |||||
| pxor m4, m4 | |||||
| mova m3, [pw_1024] | |||||
| mova m2, [pw_16] | |||||
| %else ; %1 == 16 | |||||
| %if cpuflag(sse4) ; sse4/avx | |||||
| mova m4, [pd_4] | |||||
| %else ; mmx/sse2 | |||||
| mova m4, [pd_4min0x40000] | |||||
| mova m5, [minshort] | |||||
| %endif ; mmx/sse2/sse4/avx | |||||
| %endif ; %1 == .. | |||||
| ; actual pixel scaling | |||||
| %if mmsize == 8 | |||||
| yuv2plane1_mainloop %1, a | |||||
| %else ; mmsize == 16 | |||||
| test r1, 15 | |||||
| jnz .unaligned | |||||
| yuv2plane1_mainloop %1, a | |||||
| REP_RET | |||||
| .unaligned: | |||||
| yuv2plane1_mainloop %1, u | |||||
| %endif ; mmsize == 8/16 | |||||
| REP_RET | |||||
| %endmacro | |||||
| %ifdef ARCH_X86_32 | |||||
| INIT_MMX mmx | |||||
| yuv2plane1_fn 8, 0, 5 | |||||
| yuv2plane1_fn 16, 0, 3 | |||||
| INIT_MMX mmx2 | |||||
| yuv2plane1_fn 9, 0, 3 | |||||
| yuv2plane1_fn 10, 0, 3 | |||||
| %endif | |||||
| INIT_XMM sse2 | |||||
| yuv2plane1_fn 8, 5, 5 | |||||
| yuv2plane1_fn 9, 5, 3 | |||||
| yuv2plane1_fn 10, 5, 3 | |||||
| yuv2plane1_fn 16, 6, 3 | |||||
| INIT_XMM sse4 | |||||
| yuv2plane1_fn 16, 5, 3 | |||||
| INIT_XMM avx | |||||
| yuv2plane1_fn 8, 5, 5 | |||||
| yuv2plane1_fn 9, 5, 3 | |||||
| yuv2plane1_fn 10, 5, 3 | |||||
| yuv2plane1_fn 16, 5, 3 | |||||
| @@ -1,7 +1,6 @@ | |||||
| ;****************************************************************************** | ;****************************************************************************** | ||||
| ;* x86-optimized horizontal/vertical line scaling functions | |||||
| ;* x86-optimized horizontal line scaling functions | |||||
| ;* Copyright (c) 2011 Ronald S. Bultje <rsbultje@gmail.com> | ;* Copyright (c) 2011 Ronald S. Bultje <rsbultje@gmail.com> | ||||
| ;* Kieran Kunhya <kieran@kunhya.com> | |||||
| ;* | ;* | ||||
| ;* This file is part of Libav. | ;* This file is part of Libav. | ||||
| ;* | ;* | ||||
| @@ -29,17 +28,6 @@ max_19bit_int: times 4 dd 0x7ffff | |||||
| max_19bit_flt: times 4 dd 524287.0 | max_19bit_flt: times 4 dd 524287.0 | ||||
| minshort: times 8 dw 0x8000 | minshort: times 8 dw 0x8000 | ||||
| unicoeff: times 4 dd 0x20000000 | unicoeff: times 4 dd 0x20000000 | ||||
| yuv2yuvX_16_start: times 4 dd 0x4000 - 0x40000000 | |||||
| yuv2yuvX_10_start: times 4 dd 0x10000 | |||||
| yuv2yuvX_9_start: times 4 dd 0x20000 | |||||
| yuv2yuvX_10_upper: times 8 dw 0x3ff | |||||
| yuv2yuvX_9_upper: times 8 dw 0x1ff | |||||
| pd_4: times 4 dd 4 | |||||
| pd_4min0x40000:times 4 dd 4 - (0x40000) | |||||
| pw_16: times 8 dw 16 | |||||
| pw_32: times 8 dw 32 | |||||
| pw_512: times 8 dw 512 | |||||
| pw_1024: times 8 dw 1024 | |||||
| SECTION .text | SECTION .text | ||||
| @@ -441,371 +429,3 @@ INIT_XMM | |||||
| SCALE_FUNCS2 sse2, 6, 7, 8 | SCALE_FUNCS2 sse2, 6, 7, 8 | ||||
| SCALE_FUNCS2 ssse3, 6, 6, 8 | SCALE_FUNCS2 ssse3, 6, 6, 8 | ||||
| SCALE_FUNCS2 sse4, 6, 6, 8 | SCALE_FUNCS2 sse4, 6, 6, 8 | ||||
| ;----------------------------------------------------------------------------- | |||||
| ; vertical line scaling | |||||
| ; | |||||
| ; void yuv2plane1_<output_size>_<opt>(const int16_t *src, uint8_t *dst, int dstW, | |||||
| ; const uint8_t *dither, int offset) | |||||
| ; and | |||||
| ; void yuv2planeX_<output_size>_<opt>(const int16_t *filter, int filterSize, | |||||
| ; const int16_t **src, uint8_t *dst, int dstW, | |||||
| ; const uint8_t *dither, int offset) | |||||
| ; | |||||
| ; Scale one or $filterSize lines of source data to generate one line of output | |||||
| ; data. The input is 15-bit in int16_t if $output_size is [8,10] and 19-bit in | |||||
| ; int32_t if $output_size is 16. $filter is 12-bits. $filterSize is a multiple | |||||
| ; of 2. $offset is either 0 or 3. $dither holds 8 values. | |||||
| ;----------------------------------------------------------------------------- | |||||
| %macro yuv2planeX_fn 4 | |||||
| %ifdef ARCH_X86_32 | |||||
| %define cntr_reg r1 | |||||
| %define movsx mov | |||||
| %else | |||||
| %define cntr_reg r11 | |||||
| %define movsx movsxd | |||||
| %endif | |||||
| cglobal yuv2planeX_%2_%1, %4, 7, %3 | |||||
| %if %2 == 8 || %2 == 9 || %2 == 10 | |||||
| pxor m6, m6 | |||||
| %endif ; %2 == 8/9/10 | |||||
| %if %2 == 8 | |||||
| %ifdef ARCH_X86_32 | |||||
| %assign pad 0x2c - (stack_offset & 15) | |||||
| SUB rsp, pad | |||||
| %define m_dith m7 | |||||
| %else ; x86-64 | |||||
| %define m_dith m9 | |||||
| %endif ; x86-32 | |||||
| ; create registers holding dither | |||||
| movq m_dith, [r5] ; dither | |||||
| test r6d, r6d | |||||
| jz .no_rot | |||||
| %if mmsize == 16 | |||||
| punpcklqdq m_dith, m_dith | |||||
| %endif ; mmsize == 16 | |||||
| PALIGNR m_dith, m_dith, 3, m0 | |||||
| .no_rot: | |||||
| %if mmsize == 16 | |||||
| punpcklbw m_dith, m6 | |||||
| %ifdef ARCH_X86_64 | |||||
| punpcklwd m8, m_dith, m6 | |||||
| pslld m8, 12 | |||||
| %else ; x86-32 | |||||
| punpcklwd m5, m_dith, m6 | |||||
| pslld m5, 12 | |||||
| %endif ; x86-32/64 | |||||
| punpckhwd m_dith, m6 | |||||
| pslld m_dith, 12 | |||||
| %ifdef ARCH_X86_32 | |||||
| mova [rsp+ 0], m5 | |||||
| mova [rsp+16], m_dith | |||||
| %endif | |||||
| %else ; mmsize == 8 | |||||
| punpcklbw m5, m_dith, m6 | |||||
| punpckhbw m_dith, m6 | |||||
| punpcklwd m4, m5, m6 | |||||
| punpckhwd m5, m6 | |||||
| punpcklwd m3, m_dith, m6 | |||||
| punpckhwd m_dith, m6 | |||||
| pslld m4, 12 | |||||
| pslld m5, 12 | |||||
| pslld m3, 12 | |||||
| pslld m_dith, 12 | |||||
| mova [rsp+ 0], m4 | |||||
| mova [rsp+ 8], m5 | |||||
| mova [rsp+16], m3 | |||||
| mova [rsp+24], m_dith | |||||
| %endif ; mmsize == 8/16 | |||||
| %endif ; %2 == 8 | |||||
| xor r5, r5 | |||||
| .pixelloop: | |||||
| %assign %%i 0 | |||||
| ; the rep here is for the 8bit output mmx case, where dither covers | |||||
| ; 8 pixels but we can only handle 2 pixels per register, and thus 4 | |||||
| ; pixels per iteration. In order to not have to keep track of where | |||||
| ; we are w.r.t. dithering, we unroll the mmx/8bit loop x2. | |||||
| %if %2 == 8 | |||||
| %rep 16/mmsize | |||||
| %endif ; %2 == 8 | |||||
| %if %2 == 8 | |||||
| %ifdef ARCH_X86_32 | |||||
| mova m2, [rsp+mmsize*(0+%%i)] | |||||
| mova m1, [rsp+mmsize*(1+%%i)] | |||||
| %else ; x86-64 | |||||
| mova m2, m8 | |||||
| mova m1, m_dith | |||||
| %endif ; x86-32/64 | |||||
| %else ; %2 == 9/10/16 | |||||
| mova m1, [yuv2yuvX_%2_start] | |||||
| mova m2, m1 | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| movsx cntr_reg, r1m | |||||
| .filterloop_ %+ %%i: | |||||
| ; input pixels | |||||
| mov r6, [r2+gprsize*cntr_reg-2*gprsize] | |||||
| %if %2 == 16 | |||||
| mova m3, [r6+r5*4] | |||||
| mova m5, [r6+r5*4+mmsize] | |||||
| %else ; %2 == 8/9/10 | |||||
| mova m3, [r6+r5*2] | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| mov r6, [r2+gprsize*cntr_reg-gprsize] | |||||
| %if %2 == 16 | |||||
| mova m4, [r6+r5*4] | |||||
| mova m6, [r6+r5*4+mmsize] | |||||
| %else ; %2 == 8/9/10 | |||||
| mova m4, [r6+r5*2] | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| ; coefficients | |||||
| movd m0, [r0+2*cntr_reg-4]; coeff[0], coeff[1] | |||||
| %if %2 == 16 | |||||
| pshuflw m7, m0, 0 ; coeff[0] | |||||
| pshuflw m0, m0, 0x55 ; coeff[1] | |||||
| pmovsxwd m7, m7 ; word -> dword | |||||
| pmovsxwd m0, m0 ; word -> dword | |||||
| pmulld m3, m7 | |||||
| pmulld m5, m7 | |||||
| pmulld m4, m0 | |||||
| pmulld m6, m0 | |||||
| paddd m2, m3 | |||||
| paddd m1, m5 | |||||
| paddd m2, m4 | |||||
| paddd m1, m6 | |||||
| %else ; %2 == 10/9/8 | |||||
| punpcklwd m5, m3, m4 | |||||
| punpckhwd m3, m4 | |||||
| SPLATD m0, m0 | |||||
| pmaddwd m5, m0 | |||||
| pmaddwd m3, m0 | |||||
| paddd m2, m5 | |||||
| paddd m1, m3 | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| sub cntr_reg, 2 | |||||
| jg .filterloop_ %+ %%i | |||||
| %if %2 == 16 | |||||
| psrad m2, 31 - %2 | |||||
| psrad m1, 31 - %2 | |||||
| %else ; %2 == 10/9/8 | |||||
| psrad m2, 27 - %2 | |||||
| psrad m1, 27 - %2 | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| %if %2 == 8 | |||||
| packssdw m2, m1 | |||||
| packuswb m2, m2 | |||||
| movh [r3+r5*1], m2 | |||||
| %else ; %2 == 9/10/16 | |||||
| %if %2 == 16 | |||||
| packssdw m2, m1 | |||||
| paddw m2, [minshort] | |||||
| %else ; %2 == 9/10 | |||||
| %ifidn %1, sse4 | |||||
| packusdw m2, m1 | |||||
| %elifidn %1, avx | |||||
| packusdw m2, m1 | |||||
| %else ; mmx2/sse2 | |||||
| packssdw m2, m1 | |||||
| pmaxsw m2, m6 | |||||
| %endif ; mmx2/sse2/sse4/avx | |||||
| pminsw m2, [yuv2yuvX_%2_upper] | |||||
| %endif ; %2 == 9/10/16 | |||||
| mova [r3+r5*2], m2 | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| add r5, mmsize/2 | |||||
| sub r4d, mmsize/2 | |||||
| %if %2 == 8 | |||||
| %assign %%i %%i+2 | |||||
| %endrep | |||||
| %endif ; %2 == 8 | |||||
| jg .pixelloop | |||||
| %if %2 == 8 | |||||
| %ifdef ARCH_X86_32 | |||||
| ADD rsp, pad | |||||
| RET | |||||
| %else ; x86-64 | |||||
| REP_RET | |||||
| %endif ; x86-32/64 | |||||
| %else ; %2 == 9/10/16 | |||||
| REP_RET | |||||
| %endif ; %2 == 8/9/10/16 | |||||
| %endmacro | |||||
| %define PALIGNR PALIGNR_MMX | |||||
| %ifdef ARCH_X86_32 | |||||
| INIT_MMX | |||||
| yuv2planeX_fn mmx2, 8, 0, 7 | |||||
| yuv2planeX_fn mmx2, 9, 0, 5 | |||||
| yuv2planeX_fn mmx2, 10, 0, 5 | |||||
| %endif | |||||
| INIT_XMM | |||||
| yuv2planeX_fn sse2, 8, 10, 7 | |||||
| yuv2planeX_fn sse2, 9, 7, 5 | |||||
| yuv2planeX_fn sse2, 10, 7, 5 | |||||
| %define PALIGNR PALIGNR_SSSE3 | |||||
| yuv2planeX_fn sse4, 8, 10, 7 | |||||
| yuv2planeX_fn sse4, 9, 7, 5 | |||||
| yuv2planeX_fn sse4, 10, 7, 5 | |||||
| yuv2planeX_fn sse4, 16, 8, 5 | |||||
| INIT_AVX | |||||
| yuv2planeX_fn avx, 8, 10, 7 | |||||
| yuv2planeX_fn avx, 9, 7, 5 | |||||
| yuv2planeX_fn avx, 10, 7, 5 | |||||
| ; %1=outout-bpc, %2=alignment (u/a) | |||||
| %macro yuv2plane1_mainloop 2 | |||||
| .loop_%2: | |||||
| %if %1 == 8 | |||||
| paddsw m0, m2, [r0+r2*2+mmsize*0] | |||||
| paddsw m1, m3, [r0+r2*2+mmsize*1] | |||||
| psraw m0, 7 | |||||
| psraw m1, 7 | |||||
| packuswb m0, m1 | |||||
| mov%2 [r1+r2], m0 | |||||
| %elif %1 == 16 | |||||
| paddd m0, m4, [r0+r2*4+mmsize*0] | |||||
| paddd m1, m4, [r0+r2*4+mmsize*1] | |||||
| paddd m2, m4, [r0+r2*4+mmsize*2] | |||||
| paddd m3, m4, [r0+r2*4+mmsize*3] | |||||
| psrad m0, 3 | |||||
| psrad m1, 3 | |||||
| psrad m2, 3 | |||||
| psrad m3, 3 | |||||
| %if cpuflag(sse4) ; avx/sse4 | |||||
| packusdw m0, m1 | |||||
| packusdw m2, m3 | |||||
| %else ; mmx/sse2 | |||||
| packssdw m0, m1 | |||||
| packssdw m2, m3 | |||||
| paddw m0, m5 | |||||
| paddw m2, m5 | |||||
| %endif ; mmx/sse2/sse4/avx | |||||
| mov%2 [r1+r2*2], m0 | |||||
| mov%2 [r1+r2*2+mmsize], m2 | |||||
| %else | |||||
| paddsw m0, m2, [r0+r2*2+mmsize*0] | |||||
| paddsw m1, m2, [r0+r2*2+mmsize*1] | |||||
| psraw m0, 15 - %1 | |||||
| psraw m1, 15 - %1 | |||||
| pmaxsw m0, m4 | |||||
| pmaxsw m1, m4 | |||||
| pminsw m0, m3 | |||||
| pminsw m1, m3 | |||||
| mov%2 [r1+r2*2], m0 | |||||
| mov%2 [r1+r2*2+mmsize], m1 | |||||
| %endif | |||||
| add r2, mmsize | |||||
| jl .loop_%2 | |||||
| %endmacro | |||||
| %macro yuv2plane1_fn 3 | |||||
| cglobal yuv2plane1_%1, %3, %3, %2 | |||||
| add r2, mmsize - 1 | |||||
| and r2, ~(mmsize - 1) | |||||
| %if %1 == 8 | |||||
| add r1, r2 | |||||
| %else ; %1 != 8 | |||||
| lea r1, [r1+r2*2] | |||||
| %endif ; %1 == 8 | |||||
| %if %1 == 16 | |||||
| lea r0, [r0+r2*4] | |||||
| %else ; %1 != 16 | |||||
| lea r0, [r0+r2*2] | |||||
| %endif ; %1 == 16 | |||||
| neg r2 | |||||
| %if %1 == 8 | |||||
| pxor m4, m4 ; zero | |||||
| ; create registers holding dither | |||||
| movq m3, [r3] ; dither | |||||
| test r4d, r4d | |||||
| jz .no_rot | |||||
| %if mmsize == 16 | |||||
| punpcklqdq m3, m3 | |||||
| %endif ; mmsize == 16 | |||||
| PALIGNR_MMX m3, m3, 3, m2 | |||||
| .no_rot: | |||||
| %if mmsize == 8 | |||||
| mova m2, m3 | |||||
| punpckhbw m3, m4 ; byte->word | |||||
| punpcklbw m2, m4 ; byte->word | |||||
| %else | |||||
| punpcklbw m3, m4 | |||||
| mova m2, m3 | |||||
| %endif | |||||
| %elif %1 == 9 | |||||
| pxor m4, m4 | |||||
| mova m3, [pw_512] | |||||
| mova m2, [pw_32] | |||||
| %elif %1 == 10 | |||||
| pxor m4, m4 | |||||
| mova m3, [pw_1024] | |||||
| mova m2, [pw_16] | |||||
| %else ; %1 == 16 | |||||
| %if cpuflag(sse4) ; sse4/avx | |||||
| mova m4, [pd_4] | |||||
| %else ; mmx/sse2 | |||||
| mova m4, [pd_4min0x40000] | |||||
| mova m5, [minshort] | |||||
| %endif ; mmx/sse2/sse4/avx | |||||
| %endif ; %1 == .. | |||||
| ; actual pixel scaling | |||||
| %if mmsize == 8 | |||||
| yuv2plane1_mainloop %1, a | |||||
| %else ; mmsize == 16 | |||||
| test r1, 15 | |||||
| jnz .unaligned | |||||
| yuv2plane1_mainloop %1, a | |||||
| REP_RET | |||||
| .unaligned: | |||||
| yuv2plane1_mainloop %1, u | |||||
| %endif ; mmsize == 8/16 | |||||
| REP_RET | |||||
| %endmacro | |||||
| %ifdef ARCH_X86_32 | |||||
| INIT_MMX mmx | |||||
| yuv2plane1_fn 8, 0, 5 | |||||
| yuv2plane1_fn 16, 0, 3 | |||||
| INIT_MMX mmx2 | |||||
| yuv2plane1_fn 9, 0, 3 | |||||
| yuv2plane1_fn 10, 0, 3 | |||||
| %endif | |||||
| INIT_XMM sse2 | |||||
| yuv2plane1_fn 8, 5, 5 | |||||
| yuv2plane1_fn 9, 5, 3 | |||||
| yuv2plane1_fn 10, 5, 3 | |||||
| yuv2plane1_fn 16, 6, 3 | |||||
| INIT_XMM sse4 | |||||
| yuv2plane1_fn 16, 5, 3 | |||||
| INIT_XMM avx | |||||
| yuv2plane1_fn 8, 5, 5 | |||||
| yuv2plane1_fn 9, 5, 3 | |||||
| yuv2plane1_fn 10, 5, 3 | |||||
| yuv2plane1_fn 16, 5, 3 | |||||
| @@ -369,6 +369,11 @@ do_audio_encoding g726.wav "-b:a 32k -ac 1 -ar 8000 -acodec g726" | |||||
| do_audio_decoding | do_audio_decoding | ||||
| fi | fi | ||||
| if [ -n "$do_adpcm_adx" ] ; then | |||||
| do_audio_encoding adpcm_adx.adx "-acodec adpcm_adx" | |||||
| do_audio_decoding | |||||
| fi | |||||
| if [ -n "$do_adpcm_ima_wav" ] ; then | if [ -n "$do_adpcm_ima_wav" ] ; then | ||||
| do_audio_encoding adpcm_ima.wav "-acodec adpcm_ima_wav" | do_audio_encoding adpcm_ima.wav "-acodec adpcm_ima_wav" | ||||
| do_audio_decoding | do_audio_decoding | ||||
| @@ -0,0 +1,4 @@ | |||||
| 0a30509d9296b857e134b762b76dbc31 *./tests/data/acodec/adpcm_adx.adx | |||||
| 297720 ./tests/data/acodec/adpcm_adx.adx | |||||
| 2dbc601ed5259f4d74dc48ccd8da7eaf *./tests/data/adpcm_adx.acodec.out.wav | |||||
| stddev: 6989.46 PSNR: 19.44 MAXDIFF:65398 bytes: 1058432/ 1058400 | |||||