| @@ -921,34 +921,6 @@ WRAPPER8_16_SQ(quant_psnr8x8_c, quant_psnr16_c) | |||
| WRAPPER8_16_SQ(rd8x8_c, rd16_c) | |||
| WRAPPER8_16_SQ(bit8x8_c, bit16_c) | |||
| /* draw the edges of width 'w' of an image of size width, height */ | |||
| // FIXME: Check that this is OK for MPEG-4 interlaced. | |||
| static void draw_edges_8_c(uint8_t *buf, int wrap, int width, int height, | |||
| int w, int h, int sides) | |||
| { | |||
| uint8_t *ptr = buf, *last_line; | |||
| int i; | |||
| /* left and right */ | |||
| for (i = 0; i < height; i++) { | |||
| memset(ptr - w, ptr[0], w); | |||
| memset(ptr + width, ptr[width - 1], w); | |||
| ptr += wrap; | |||
| } | |||
| /* top and bottom + corners */ | |||
| buf -= w; | |||
| last_line = buf + (height - 1) * wrap; | |||
| if (sides & EDGE_TOP) | |||
| for (i = 0; i < h; i++) | |||
| // top | |||
| memcpy(buf - (i + 1) * wrap, buf, width + w + w); | |||
| if (sides & EDGE_BOTTOM) | |||
| for (i = 0; i < h; i++) | |||
| // bottom | |||
| memcpy(last_line + (i + 1) * wrap, last_line, width + w + w); | |||
| } | |||
| /* init static data */ | |||
| av_cold void ff_dsputil_static_init(void) | |||
| { | |||
| @@ -1023,8 +995,6 @@ av_cold void ff_dsputil_init(DSPContext *c, AVCodecContext *avctx) | |||
| c->nsse[0] = nsse16_c; | |||
| c->nsse[1] = nsse8_c; | |||
| c->draw_edges = draw_edges_8_c; | |||
| switch (avctx->bits_per_raw_sample) { | |||
| case 9: | |||
| case 10: | |||
| @@ -83,12 +83,6 @@ typedef struct DSPContext { | |||
| /* (I)DCT */ | |||
| void (*fdct)(int16_t *block /* align 16 */); | |||
| void (*fdct248)(int16_t *block /* align 16 */); | |||
| void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, | |||
| int w, int h, int sides); | |||
| #define EDGE_WIDTH 16 | |||
| #define EDGE_TOP 1 | |||
| #define EDGE_BOTTOM 2 | |||
| } DSPContext; | |||
| void ff_dsputil_static_init(void); | |||
| @@ -80,6 +80,8 @@ enum OutputFormat { | |||
| #define INPLACE_OFFSET 16 | |||
| #define EDGE_WIDTH 16 | |||
| /* Start codes. */ | |||
| #define SEQ_END_CODE 0x000001b7 | |||
| #define SEQ_START_CODE 0x000001b3 | |||
| @@ -1391,18 +1391,22 @@ static void frame_end(MpegEncContext *s) | |||
| const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(s->avctx->pix_fmt); | |||
| int hshift = desc->log2_chroma_w; | |||
| int vshift = desc->log2_chroma_h; | |||
| s->dsp.draw_edges(s->current_picture.f->data[0], s->linesize, | |||
| s->h_edge_pos, s->v_edge_pos, | |||
| EDGE_WIDTH, EDGE_WIDTH, | |||
| EDGE_TOP | EDGE_BOTTOM); | |||
| s->dsp.draw_edges(s->current_picture.f->data[1], s->uvlinesize, | |||
| s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, | |||
| EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, | |||
| EDGE_TOP | EDGE_BOTTOM); | |||
| s->dsp.draw_edges(s->current_picture.f->data[2], s->uvlinesize, | |||
| s->h_edge_pos >> hshift, s->v_edge_pos >> vshift, | |||
| EDGE_WIDTH >> hshift, EDGE_WIDTH >> vshift, | |||
| EDGE_TOP | EDGE_BOTTOM); | |||
| s->mpvencdsp.draw_edges(s->current_picture.f->data[0], s->linesize, | |||
| s->h_edge_pos, s->v_edge_pos, | |||
| EDGE_WIDTH, EDGE_WIDTH, | |||
| EDGE_TOP | EDGE_BOTTOM); | |||
| s->mpvencdsp.draw_edges(s->current_picture.f->data[1], s->uvlinesize, | |||
| s->h_edge_pos >> hshift, | |||
| s->v_edge_pos >> vshift, | |||
| EDGE_WIDTH >> hshift, | |||
| EDGE_WIDTH >> vshift, | |||
| EDGE_TOP | EDGE_BOTTOM); | |||
| s->mpvencdsp.draw_edges(s->current_picture.f->data[2], s->uvlinesize, | |||
| s->h_edge_pos >> hshift, | |||
| s->v_edge_pos >> vshift, | |||
| EDGE_WIDTH >> hshift, | |||
| EDGE_WIDTH >> vshift, | |||
| EDGE_TOP | EDGE_BOTTOM); | |||
| } | |||
| emms_c(); | |||
| @@ -18,6 +18,7 @@ | |||
| #include <assert.h> | |||
| #include <stdint.h> | |||
| #include <string.h> | |||
| #include "config.h" | |||
| #include "libavutil/attributes.h" | |||
| @@ -124,6 +125,34 @@ static int pix_norm1_c(uint8_t *pix, int line_size) | |||
| return s; | |||
| } | |||
| /* draw the edges of width 'w' of an image of size width, height */ | |||
| // FIXME: Check that this is OK for MPEG-4 interlaced. | |||
| static void draw_edges_8_c(uint8_t *buf, int wrap, int width, int height, | |||
| int w, int h, int sides) | |||
| { | |||
| uint8_t *ptr = buf, *last_line; | |||
| int i; | |||
| /* left and right */ | |||
| for (i = 0; i < height; i++) { | |||
| memset(ptr - w, ptr[0], w); | |||
| memset(ptr + width, ptr[width - 1], w); | |||
| ptr += wrap; | |||
| } | |||
| /* top and bottom + corners */ | |||
| buf -= w; | |||
| last_line = buf + (height - 1) * wrap; | |||
| if (sides & EDGE_TOP) | |||
| for (i = 0; i < h; i++) | |||
| // top | |||
| memcpy(buf - (i + 1) * wrap, buf, width + w + w); | |||
| if (sides & EDGE_BOTTOM) | |||
| for (i = 0; i < h; i++) | |||
| // bottom | |||
| memcpy(last_line + (i + 1) * wrap, last_line, width + w + w); | |||
| } | |||
| av_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, | |||
| AVCodecContext *avctx) | |||
| { | |||
| @@ -138,6 +167,8 @@ av_cold void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, | |||
| c->pix_sum = pix_sum_c; | |||
| c->pix_norm1 = pix_norm1_c; | |||
| c->draw_edges = draw_edges_8_c; | |||
| if (ARCH_ARM) | |||
| ff_mpegvideoencdsp_init_arm(c, avctx); | |||
| if (ARCH_PPC) | |||
| @@ -26,6 +26,9 @@ | |||
| #define BASIS_SHIFT 16 | |||
| #define RECON_SHIFT 6 | |||
| #define EDGE_TOP 1 | |||
| #define EDGE_BOTTOM 2 | |||
| typedef struct MpegvideoEncDSPContext { | |||
| int (*try_8x8basis)(int16_t rem[64], int16_t weight[64], | |||
| int16_t basis[64], int scale); | |||
| @@ -36,6 +39,9 @@ typedef struct MpegvideoEncDSPContext { | |||
| void (*shrink[4])(uint8_t *dst, int dst_wrap, const uint8_t *src, | |||
| int src_wrap, int width, int height); | |||
| void (*draw_edges)(uint8_t *buf, int wrap, int width, int height, | |||
| int w, int h, int sides); | |||
| } MpegvideoEncDSPContext; | |||
| void ff_mpegvideoencdsp_init(MpegvideoEncDSPContext *c, | |||
| @@ -41,6 +41,7 @@ | |||
| #include "avcodec.h" | |||
| #include "dsputil.h" | |||
| #include "libavutil/opt.h" | |||
| #include "mpegvideo.h" | |||
| #include "thread.h" | |||
| #include "internal.h" | |||
| #include "bytestream.h" | |||
| @@ -51,7 +51,6 @@ OBJS-$(CONFIG_VP8_DECODER) += x86/vp8dsp_init.o | |||
| OBJS-$(CONFIG_VP9_DECODER) += x86/vp9dsp_init.o | |||
| MMX-OBJS-$(CONFIG_AUDIODSP) += x86/audiodsp_mmx.o | |||
| MMX-OBJS-$(CONFIG_DSPUTIL) += x86/dsputil_mmx.o | |||
| MMX-OBJS-$(CONFIG_ENCODERS) += x86/fdct.o | |||
| MMX-OBJS-$(CONFIG_HPELDSP) += x86/fpel_mmx.o \ | |||
| x86/hpeldsp_mmx.o | |||
| @@ -24,24 +24,9 @@ | |||
| #include "libavcodec/dsputil.h" | |||
| #include "dsputil_x86.h" | |||
| static av_cold void dsputil_init_mmx(DSPContext *c, AVCodecContext *avctx, | |||
| int cpu_flags, unsigned high_bit_depth) | |||
| { | |||
| #if HAVE_MMX_INLINE | |||
| if (!high_bit_depth) { | |||
| c->draw_edges = ff_draw_edges_mmx; | |||
| } | |||
| #endif /* HAVE_MMX_INLINE */ | |||
| } | |||
| av_cold void ff_dsputil_init_x86(DSPContext *c, AVCodecContext *avctx, | |||
| unsigned high_bit_depth) | |||
| { | |||
| int cpu_flags = av_get_cpu_flags(); | |||
| if (X86_MMX(cpu_flags)) | |||
| dsputil_init_mmx(c, avctx, cpu_flags, high_bit_depth); | |||
| if (CONFIG_ENCODERS) | |||
| ff_dsputilenc_init_mmx(c, avctx, high_bit_depth); | |||
| } | |||
| @@ -1,128 +0,0 @@ | |||
| /* | |||
| * MMX optimized DSP utils | |||
| * Copyright (c) 2000, 2001 Fabrice Bellard | |||
| * Copyright (c) 2002-2004 Michael Niedermayer <michaelni@gmx.at> | |||
| * | |||
| * MMX optimization by Nick Kurshev <nickols_k@mail.ru> | |||
| * | |||
| * 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 "config.h" | |||
| #include "libavutil/cpu.h" | |||
| #include "libavutil/x86/asm.h" | |||
| #include "dsputil_x86.h" | |||
| #include "inline_asm.h" | |||
| #if HAVE_INLINE_ASM | |||
| /* Draw the edges of width 'w' of an image of size width, height | |||
| * this MMX version can only handle w == 8 || w == 16. */ | |||
| void ff_draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, | |||
| int w, int h, int sides) | |||
| { | |||
| uint8_t *ptr, *last_line; | |||
| int i; | |||
| last_line = buf + (height - 1) * wrap; | |||
| /* left and right */ | |||
| ptr = buf; | |||
| if (w == 8) { | |||
| __asm__ volatile ( | |||
| "1: \n\t" | |||
| "movd (%0), %%mm0 \n\t" | |||
| "punpcklbw %%mm0, %%mm0 \n\t" | |||
| "punpcklwd %%mm0, %%mm0 \n\t" | |||
| "punpckldq %%mm0, %%mm0 \n\t" | |||
| "movq %%mm0, -8(%0) \n\t" | |||
| "movq -8(%0, %2), %%mm1 \n\t" | |||
| "punpckhbw %%mm1, %%mm1 \n\t" | |||
| "punpckhwd %%mm1, %%mm1 \n\t" | |||
| "punpckhdq %%mm1, %%mm1 \n\t" | |||
| "movq %%mm1, (%0, %2) \n\t" | |||
| "add %1, %0 \n\t" | |||
| "cmp %3, %0 \n\t" | |||
| "jb 1b \n\t" | |||
| : "+r" (ptr) | |||
| : "r" ((x86_reg) wrap), "r" ((x86_reg) width), | |||
| "r" (ptr + wrap * height)); | |||
| } else { | |||
| __asm__ volatile ( | |||
| "1: \n\t" | |||
| "movd (%0), %%mm0 \n\t" | |||
| "punpcklbw %%mm0, %%mm0 \n\t" | |||
| "punpcklwd %%mm0, %%mm0 \n\t" | |||
| "punpckldq %%mm0, %%mm0 \n\t" | |||
| "movq %%mm0, -8(%0) \n\t" | |||
| "movq %%mm0, -16(%0) \n\t" | |||
| "movq -8(%0, %2), %%mm1 \n\t" | |||
| "punpckhbw %%mm1, %%mm1 \n\t" | |||
| "punpckhwd %%mm1, %%mm1 \n\t" | |||
| "punpckhdq %%mm1, %%mm1 \n\t" | |||
| "movq %%mm1, (%0, %2) \n\t" | |||
| "movq %%mm1, 8(%0, %2) \n\t" | |||
| "add %1, %0 \n\t" | |||
| "cmp %3, %0 \n\t" | |||
| "jb 1b \n\t" | |||
| : "+r" (ptr) | |||
| : "r" ((x86_reg) wrap), "r" ((x86_reg) width), | |||
| "r" (ptr + wrap * height)); | |||
| } | |||
| /* top and bottom (and hopefully also the corners) */ | |||
| if (sides & EDGE_TOP) { | |||
| for (i = 0; i < h; i += 4) { | |||
| ptr = buf - (i + 1) * wrap - w; | |||
| __asm__ volatile ( | |||
| "1: \n\t" | |||
| "movq (%1, %0), %%mm0 \n\t" | |||
| "movq %%mm0, (%0) \n\t" | |||
| "movq %%mm0, (%0, %2) \n\t" | |||
| "movq %%mm0, (%0, %2, 2) \n\t" | |||
| "movq %%mm0, (%0, %3) \n\t" | |||
| "add $8, %0 \n\t" | |||
| "cmp %4, %0 \n\t" | |||
| "jb 1b \n\t" | |||
| : "+r" (ptr) | |||
| : "r" ((x86_reg) buf - (x86_reg) ptr - w), | |||
| "r" ((x86_reg) - wrap), "r" ((x86_reg) - wrap * 3), | |||
| "r" (ptr + width + 2 * w)); | |||
| } | |||
| } | |||
| if (sides & EDGE_BOTTOM) { | |||
| for (i = 0; i < h; i += 4) { | |||
| ptr = last_line + (i + 1) * wrap - w; | |||
| __asm__ volatile ( | |||
| "1: \n\t" | |||
| "movq (%1, %0), %%mm0 \n\t" | |||
| "movq %%mm0, (%0) \n\t" | |||
| "movq %%mm0, (%0, %2) \n\t" | |||
| "movq %%mm0, (%0, %2, 2) \n\t" | |||
| "movq %%mm0, (%0, %3) \n\t" | |||
| "add $8, %0 \n\t" | |||
| "cmp %4, %0 \n\t" | |||
| "jb 1b \n\t" | |||
| : "+r" (ptr) | |||
| : "r" ((x86_reg) last_line - (x86_reg) ptr - w), | |||
| "r" ((x86_reg) wrap), "r" ((x86_reg) wrap * 3), | |||
| "r" (ptr + width + 2 * w)); | |||
| } | |||
| } | |||
| } | |||
| #endif /* HAVE_INLINE_ASM */ | |||
| @@ -31,7 +31,4 @@ void ff_dsputilenc_init_mmx(DSPContext *c, AVCodecContext *avctx, | |||
| unsigned high_bit_depth); | |||
| void ff_dsputil_init_pix_mmx(DSPContext *c, AVCodecContext *avctx); | |||
| void ff_draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, | |||
| int w, int h, int sides); | |||
| #endif /* AVCODEC_X86_DSPUTIL_X86_H */ | |||
| @@ -93,6 +93,101 @@ int ff_pix_norm1_mmx(uint8_t *pix, int line_size); | |||
| #undef PHADDD | |||
| #endif /* HAVE_SSSE3_INLINE */ | |||
| /* Draw the edges of width 'w' of an image of size width, height | |||
| * this MMX version can only handle w == 8 || w == 16. */ | |||
| static void draw_edges_mmx(uint8_t *buf, int wrap, int width, int height, | |||
| int w, int h, int sides) | |||
| { | |||
| uint8_t *ptr, *last_line; | |||
| int i; | |||
| last_line = buf + (height - 1) * wrap; | |||
| /* left and right */ | |||
| ptr = buf; | |||
| if (w == 8) { | |||
| __asm__ volatile ( | |||
| "1: \n\t" | |||
| "movd (%0), %%mm0 \n\t" | |||
| "punpcklbw %%mm0, %%mm0 \n\t" | |||
| "punpcklwd %%mm0, %%mm0 \n\t" | |||
| "punpckldq %%mm0, %%mm0 \n\t" | |||
| "movq %%mm0, -8(%0) \n\t" | |||
| "movq -8(%0, %2), %%mm1 \n\t" | |||
| "punpckhbw %%mm1, %%mm1 \n\t" | |||
| "punpckhwd %%mm1, %%mm1 \n\t" | |||
| "punpckhdq %%mm1, %%mm1 \n\t" | |||
| "movq %%mm1, (%0, %2) \n\t" | |||
| "add %1, %0 \n\t" | |||
| "cmp %3, %0 \n\t" | |||
| "jb 1b \n\t" | |||
| : "+r" (ptr) | |||
| : "r" ((x86_reg) wrap), "r" ((x86_reg) width), | |||
| "r" (ptr + wrap * height)); | |||
| } else { | |||
| __asm__ volatile ( | |||
| "1: \n\t" | |||
| "movd (%0), %%mm0 \n\t" | |||
| "punpcklbw %%mm0, %%mm0 \n\t" | |||
| "punpcklwd %%mm0, %%mm0 \n\t" | |||
| "punpckldq %%mm0, %%mm0 \n\t" | |||
| "movq %%mm0, -8(%0) \n\t" | |||
| "movq %%mm0, -16(%0) \n\t" | |||
| "movq -8(%0, %2), %%mm1 \n\t" | |||
| "punpckhbw %%mm1, %%mm1 \n\t" | |||
| "punpckhwd %%mm1, %%mm1 \n\t" | |||
| "punpckhdq %%mm1, %%mm1 \n\t" | |||
| "movq %%mm1, (%0, %2) \n\t" | |||
| "movq %%mm1, 8(%0, %2) \n\t" | |||
| "add %1, %0 \n\t" | |||
| "cmp %3, %0 \n\t" | |||
| "jb 1b \n\t" | |||
| : "+r" (ptr) | |||
| : "r" ((x86_reg) wrap), "r" ((x86_reg) width), | |||
| "r" (ptr + wrap * height)); | |||
| } | |||
| /* top and bottom (and hopefully also the corners) */ | |||
| if (sides & EDGE_TOP) { | |||
| for (i = 0; i < h; i += 4) { | |||
| ptr = buf - (i + 1) * wrap - w; | |||
| __asm__ volatile ( | |||
| "1: \n\t" | |||
| "movq (%1, %0), %%mm0 \n\t" | |||
| "movq %%mm0, (%0) \n\t" | |||
| "movq %%mm0, (%0, %2) \n\t" | |||
| "movq %%mm0, (%0, %2, 2) \n\t" | |||
| "movq %%mm0, (%0, %3) \n\t" | |||
| "add $8, %0 \n\t" | |||
| "cmp %4, %0 \n\t" | |||
| "jb 1b \n\t" | |||
| : "+r" (ptr) | |||
| : "r" ((x86_reg) buf - (x86_reg) ptr - w), | |||
| "r" ((x86_reg) - wrap), "r" ((x86_reg) - wrap * 3), | |||
| "r" (ptr + width + 2 * w)); | |||
| } | |||
| } | |||
| if (sides & EDGE_BOTTOM) { | |||
| for (i = 0; i < h; i += 4) { | |||
| ptr = last_line + (i + 1) * wrap - w; | |||
| __asm__ volatile ( | |||
| "1: \n\t" | |||
| "movq (%1, %0), %%mm0 \n\t" | |||
| "movq %%mm0, (%0) \n\t" | |||
| "movq %%mm0, (%0, %2) \n\t" | |||
| "movq %%mm0, (%0, %2, 2) \n\t" | |||
| "movq %%mm0, (%0, %3) \n\t" | |||
| "add $8, %0 \n\t" | |||
| "cmp %4, %0 \n\t" | |||
| "jb 1b \n\t" | |||
| : "+r" (ptr) | |||
| : "r" ((x86_reg) last_line - (x86_reg) ptr - w), | |||
| "r" ((x86_reg) wrap), "r" ((x86_reg) wrap * 3), | |||
| "r" (ptr + width + 2 * w)); | |||
| } | |||
| } | |||
| } | |||
| #endif /* HAVE_INLINE_ASM */ | |||
| av_cold void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c, | |||
| @@ -112,6 +207,10 @@ av_cold void ff_mpegvideoencdsp_init_x86(MpegvideoEncDSPContext *c, | |||
| c->try_8x8basis = try_8x8basis_mmx; | |||
| } | |||
| c->add_8x8basis = add_8x8basis_mmx; | |||
| if (avctx->bits_per_raw_sample <= 8) { | |||
| c->draw_edges = draw_edges_mmx; | |||
| } | |||
| } | |||
| if (INLINE_AMD3DNOW(cpu_flags)) { | |||