mpeg4_encoder_select="h263_encoder"
mpeg4_vaapi_hwaccel_select="vaapi mpeg4_decoder"
mpeg4_vdpau_decoder_select="vdpau mpeg4_decoder"
+ mpegvideo_select="videodsp"
+msmpeg4_crystalhd_decoder_select="crystalhd"
msmpeg4v1_decoder_select="h263_decoder"
msmpeg4v1_encoder_select="h263_encoder"
msmpeg4v2_decoder_select="h263_decoder"
void ff_simple_idct_put_armv5te(uint8_t *dest, int line_size, DCTELEM *data);
void ff_simple_idct_add_armv5te(uint8_t *dest, int line_size, DCTELEM *data);
- void ff_prefetch_arm(void *mem, int stride, int h);
-
av_cold void ff_dsputil_init_armv5te(DSPContext *c, AVCodecContext *avctx)
{
- if (avctx->bits_per_raw_sample <= 8 &&
+ if (!avctx->lowres && avctx->bits_per_raw_sample <= 8 &&
(avctx->idct_algo == FF_IDCT_AUTO ||
avctx->idct_algo == FF_IDCT_SIMPLEARMV5TE)) {
c->idct_put = ff_simple_idct_put_armv5te;
--- /dev/null
+ /*
+ * Copyright (C) 2012 Ronald S. Bultje
+ *
+ * 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 "libavutil/arm/cpu.h"
+ #include <libavcodec/videodsp.h>
+ #include "videodsp_arm.h"
+
+ void ff_prefetch_arm(uint8_t *mem, ptrdiff_t stride, int h);
+
+ void ff_videodsp_init_armv5te(VideoDSPContext *ctx, int bpc)
+ {
++#if HAVE_ARMV5TE_EXTERNAL
+ ctx->prefetch = ff_prefetch_arm;
++#endif
+ }
add_pixels_clamped_c(block, dest, line_size);
}
- static void just_return(void *mem av_unused, int stride av_unused, int h av_unused) { return; }
-
+static void ff_jref_idct4_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_j_rev_dct4 (block);
+ put_pixels_clamped4_c(block, dest, line_size);
+}
+static void ff_jref_idct4_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_j_rev_dct4 (block);
+ add_pixels_clamped4_c(block, dest, line_size);
+}
+
+static void ff_jref_idct2_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_j_rev_dct2 (block);
+ put_pixels_clamped2_c(block, dest, line_size);
+}
+static void ff_jref_idct2_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ ff_j_rev_dct2 (block);
+ add_pixels_clamped2_c(block, dest, line_size);
+}
+
+static void ff_jref_idct1_put(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ dest[0] = av_clip_uint8((block[0] + 4)>>3);
+}
+static void ff_jref_idct1_add(uint8_t *dest, int line_size, DCTELEM *block)
+{
+ dest[0] = av_clip_uint8(dest[0] + ((block[0] + 4)>>3));
+}
+
/* init static data */
av_cold void ff_dsputil_static_init(void)
{
void ff_init_scantable_permutation(uint8_t *idct_permutation,
int idct_permutation_type);
- void ff_emulated_edge_mc_ ## depth (uint8_t *buf, const uint8_t *src, int linesize,\
+#define EMULATED_EDGE(depth) \
- EMULATED_EDGE(9)
- EMULATED_EDGE(10)
- EMULATED_EDGE(12)
- EMULATED_EDGE(14)
++void ff_emulated_edge_mc_ ## depth (uint8_t *buf, const uint8_t *src, ptrdiff_t linesize,\
+ int block_w, int block_h,\
+ int src_x, int src_y, int w, int h);
+
+EMULATED_EDGE(8)
++EMULATED_EDGE(16)
+
/**
* DSPContext.
*/
memcpy(last_line + (i + 1) * wrap, last_line, (width + w + w) * sizeof(pixel)); // bottom
}
- /**
- * Copy a rectangular area of samples to a temporary buffer and replicate the border samples.
- * @param buf destination buffer
- * @param src source buffer
- * @param linesize number of bytes between 2 vertically adjacent samples in both the source and destination buffers
- * @param block_w width of block
- * @param block_h height of block
- * @param src_x x coordinate of the top left sample of the block in the source buffer
- * @param src_y y coordinate of the top left sample of the block in the source buffer
- * @param w width of the source buffer
- * @param h height of the source buffer
- */
- void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src, int linesize, int block_w, int block_h,
- int src_x, int src_y, int w, int h){
- int x, y;
- int start_y, start_x, end_y, end_x;
-
- if(!w || !h)
- return;
-
- if(src_y>= h){
- src-= src_y*linesize;
- src+= (h-1)*linesize;
- src_y=h-1;
- }else if(src_y<=-block_h){
- src-= src_y*linesize;
- src+= (1-block_h)*linesize;
- src_y=1-block_h;
- }
- if(src_x>= w){
- src+= (w-1-src_x)*sizeof(pixel);
- src_x=w-1;
- }else if(src_x<=-block_w){
- src+= (1-block_w-src_x)*sizeof(pixel);
- src_x=1-block_w;
- }
-
- start_y= FFMAX(0, -src_y);
- start_x= FFMAX(0, -src_x);
- end_y= FFMIN(block_h, h-src_y);
- end_x= FFMIN(block_w, w-src_x);
- av_assert2(start_y < end_y && block_h);
- av_assert2(start_x < end_x && block_w);
-
- w = end_x - start_x;
- src += start_y*linesize + start_x*sizeof(pixel);
- buf += start_x*sizeof(pixel);
-
- //top
- for(y=0; y<start_y; y++){
- memcpy(buf, src, w*sizeof(pixel));
- buf += linesize;
- }
-
- // copy existing part
- for(; y<end_y; y++){
- memcpy(buf, src, w*sizeof(pixel));
- src += linesize;
- buf += linesize;
- }
-
- //bottom
- src -= linesize;
- for(; y<block_h; y++){
- memcpy(buf, src, w*sizeof(pixel));
- buf += linesize;
- }
-
- buf -= block_h * linesize + start_x*sizeof(pixel);
- while (block_h--){
- pixel *bufp = (pixel*)buf;
- //left
- for(x=0; x<start_x; x++){
- bufp[x] = bufp[start_x];
- }
-
- //right
- for(x=end_x; x<block_w; x++){
- bufp[x] = bufp[end_x - 1];
- }
- buf += linesize;
- }
- }
-
#define DCTELEM_FUNCS(dctcoef, suffix) \
-static void FUNCC(get_pixels ## suffix)(DCTELEM *restrict _block, \
+static void FUNCC(get_pixels ## suffix)(DCTELEM *av_restrict _block, \
const uint8_t *_pixels, \
int line_size) \
{ \
int off = (mx << pixel_shift) +
(my + (s->mb_x & 3) * 4) * h->mb_linesize +
(64 << pixel_shift);
- s->dsp.prefetch(src[0] + off, s->linesize, 4);
+ s->vdsp.prefetch(src[0] + off, s->linesize, 4);
if (chroma_idc == 3 /* yuv444 */) {
- s->dsp.prefetch(src[1] + off, s->linesize, 4);
- s->dsp.prefetch(src[2] + off, s->linesize, 4);
+ s->vdsp.prefetch(src[1] + off, s->linesize, 4);
+ s->vdsp.prefetch(src[2] + off, s->linesize, 4);
} else {
- off = ((mx >> 1) << pixel_shift) +
- ((my >> 1) + (s->mb_x & 7)) * s->uvlinesize +
- (64 << pixel_shift);
+ off= (((mx>>1)+64)<<pixel_shift) + ((my>>1) + (s->mb_x&7))*s->uvlinesize;
- s->dsp.prefetch(src[1] + off, src[2] - src[1], 2);
+ s->vdsp.prefetch(src[1] + off, src[2] - src[1], 2);
}
}
}
h->dequant_coeff_pps = -1;
s->unrestricted_mv = 1;
+ s->dsp.dct_bits = 16;
/* needed so that IDCT permutation is known early */
ff_dsputil_init(&s->dsp, s->avctx);
+ ff_videodsp_init(&s->vdsp, 8);
memset(h->pps.scaling_matrix4, 16, 6 * 16 * sizeof(uint8_t));
memset(h->pps.scaling_matrix8, 16, 2 * 64 * sizeof(uint8_t));
av_cold int ff_dct_common_init(MpegEncContext *s)
{
ff_dsputil_init(&s->dsp, s->avctx);
- ff_videodsp_init(&s->vdsp, 8);
++ ff_videodsp_init(&s->vdsp, s->avctx->bits_per_raw_sample > 8 ? 16 : 8);
s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_c;
s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_c;
}
}
- s->dsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w + 1,
+static inline int hpel_motion_lowres(MpegEncContext *s,
+ uint8_t *dest, uint8_t *src,
+ int field_based, int field_select,
+ int src_x, int src_y,
+ int width, int height, int stride,
+ int h_edge_pos, int v_edge_pos,
+ int w, int h, h264_chroma_mc_func *pix_op,
+ int motion_x, int motion_y)
+{
+ const int lowres = s->avctx->lowres;
+ const int op_index = FFMIN(lowres, 2);
+ const int s_mask = (2 << lowres) - 1;
+ int emu = 0;
+ int sx, sy;
+
+ if (s->quarter_sample) {
+ motion_x /= 2;
+ motion_y /= 2;
+ }
+
+ sx = motion_x & s_mask;
+ sy = motion_y & s_mask;
+ src_x += motion_x >> lowres + 1;
+ src_y += motion_y >> lowres + 1;
+
+ src += src_y * stride + src_x;
+
+ if ((unsigned)src_x > FFMAX( h_edge_pos - (!!sx) - w, 0) ||
+ (unsigned)src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) {
- s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y,
++ s->vdsp.emulated_edge_mc(s->edge_emu_buffer, src, s->linesize, w + 1,
+ (h + 1) << field_based, src_x,
+ src_y << field_based,
+ h_edge_pos,
+ v_edge_pos);
+ src = s->edge_emu_buffer;
+ emu = 1;
+ }
+
+ sx = (sx << 2) >> lowres;
+ sy = (sy << 2) >> lowres;
+ if (field_select)
+ src += s->linesize;
+ pix_op[op_index](dest, src, stride, h, sx, sy);
+ return emu;
+}
+
+/* apply one mpeg motion vector to the three components */
+static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
+ uint8_t *dest_y,
+ uint8_t *dest_cb,
+ uint8_t *dest_cr,
+ int field_based,
+ int bottom_field,
+ int field_select,
+ uint8_t **ref_picture,
+ h264_chroma_mc_func *pix_op,
+ int motion_x, int motion_y,
+ int h, int mb_y)
+{
+ uint8_t *ptr_y, *ptr_cb, *ptr_cr;
+ int mx, my, src_x, src_y, uvsrc_x, uvsrc_y, uvlinesize, linesize, sx, sy,
+ uvsx, uvsy;
+ const int lowres = s->avctx->lowres;
+ const int op_index = FFMIN(lowres-1+s->chroma_x_shift, 2);
+ const int block_s = 8>>lowres;
+ const int s_mask = (2 << lowres) - 1;
+ const int h_edge_pos = s->h_edge_pos >> lowres;
+ const int v_edge_pos = s->v_edge_pos >> lowres;
+ linesize = s->current_picture.f.linesize[0] << field_based;
+ uvlinesize = s->current_picture.f.linesize[1] << field_based;
+
+ // FIXME obviously not perfect but qpel will not work in lowres anyway
+ if (s->quarter_sample) {
+ motion_x /= 2;
+ motion_y /= 2;
+ }
+
+ if(field_based){
+ motion_y += (bottom_field - field_select)*((1 << lowres)-1);
+ }
+
+ sx = motion_x & s_mask;
+ sy = motion_y & s_mask;
+ src_x = s->mb_x * 2 * block_s + (motion_x >> lowres + 1);
+ src_y = (mb_y * 2 * block_s >> field_based) + (motion_y >> lowres + 1);
+
+ if (s->out_format == FMT_H263) {
+ uvsx = ((motion_x >> 1) & s_mask) | (sx & 1);
+ uvsy = ((motion_y >> 1) & s_mask) | (sy & 1);
+ uvsrc_x = src_x >> 1;
+ uvsrc_y = src_y >> 1;
+ } else if (s->out_format == FMT_H261) {
+ // even chroma mv's are full pel in H261
+ mx = motion_x / 4;
+ my = motion_y / 4;
+ uvsx = (2 * mx) & s_mask;
+ uvsy = (2 * my) & s_mask;
+ uvsrc_x = s->mb_x * block_s + (mx >> lowres);
+ uvsrc_y = mb_y * block_s + (my >> lowres);
+ } else {
+ if(s->chroma_y_shift){
+ mx = motion_x / 2;
+ my = motion_y / 2;
+ uvsx = mx & s_mask;
+ uvsy = my & s_mask;
+ uvsrc_x = s->mb_x * block_s + (mx >> lowres + 1);
+ uvsrc_y = (mb_y * block_s >> field_based) + (my >> lowres + 1);
+ } else {
+ if(s->chroma_x_shift){
+ //Chroma422
+ mx = motion_x / 2;
+ uvsx = mx & s_mask;
+ uvsy = motion_y & s_mask;
+ uvsrc_y = src_y;
+ uvsrc_x = s->mb_x*block_s + (mx >> (lowres+1));
+ } else {
+ //Chroma444
+ uvsx = motion_x & s_mask;
+ uvsy = motion_y & s_mask;
+ uvsrc_x = src_x;
+ uvsrc_y = src_y;
+ }
+ }
+ }
+
+ ptr_y = ref_picture[0] + src_y * linesize + src_x;
+ ptr_cb = ref_picture[1] + uvsrc_y * uvlinesize + uvsrc_x;
+ ptr_cr = ref_picture[2] + uvsrc_y * uvlinesize + uvsrc_x;
+
+ if ((unsigned) src_x > FFMAX( h_edge_pos - (!!sx) - 2 * block_s, 0) ||
+ (unsigned) src_y > FFMAX((v_edge_pos >> field_based) - (!!sy) - h, 0)) {
- s->dsp.emulated_edge_mc(uvbuf , ptr_cb, uvlinesize >> field_based, 9,
++ s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr_y,
+ linesize >> field_based, 17, 17 + field_based,
+ src_x, src_y << field_based, h_edge_pos,
+ v_edge_pos);
+ ptr_y = s->edge_emu_buffer;
+ if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
+ uint8_t *uvbuf = s->edge_emu_buffer + 18 * s->linesize;
- s->dsp.emulated_edge_mc(uvbuf + 16, ptr_cr, uvlinesize >> field_based, 9,
++ s->vdsp.emulated_edge_mc(uvbuf , ptr_cb, uvlinesize >> field_based, 9,
+ 9 + field_based,
+ uvsrc_x, uvsrc_y << field_based,
+ h_edge_pos >> 1, v_edge_pos >> 1);
- s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
++ s->vdsp.emulated_edge_mc(uvbuf + 16, ptr_cr, uvlinesize >> field_based, 9,
+ 9 + field_based,
+ uvsrc_x, uvsrc_y << field_based,
+ h_edge_pos >> 1, v_edge_pos >> 1);
+ ptr_cb = uvbuf;
+ ptr_cr = uvbuf + 16;
+ }
+ }
+
+ // FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data
+ if (bottom_field) {
+ dest_y += s->linesize;
+ dest_cb += s->uvlinesize;
+ dest_cr += s->uvlinesize;
+ }
+
+ if (field_select) {
+ ptr_y += s->linesize;
+ ptr_cb += s->uvlinesize;
+ ptr_cr += s->uvlinesize;
+ }
+
+ sx = (sx << 2) >> lowres;
+ sy = (sy << 2) >> lowres;
+ pix_op[lowres - 1](dest_y, ptr_y, linesize, h, sx, sy);
+
+ if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY)) {
+ uvsx = (uvsx << 2) >> lowres;
+ uvsy = (uvsy << 2) >> lowres;
+ if (h >> s->chroma_y_shift) {
+ pix_op[op_index](dest_cb, ptr_cb, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
+ pix_op[op_index](dest_cr, ptr_cr, uvlinesize, h >> s->chroma_y_shift, uvsx, uvsy);
+ }
+ }
+ // FIXME h261 lowres loop filter
+}
+
+static inline void chroma_4mv_motion_lowres(MpegEncContext *s,
+ uint8_t *dest_cb, uint8_t *dest_cr,
+ uint8_t **ref_picture,
+ h264_chroma_mc_func * pix_op,
+ int mx, int my)
+{
+ const int lowres = s->avctx->lowres;
+ const int op_index = FFMIN(lowres, 2);
+ const int block_s = 8 >> lowres;
+ const int s_mask = (2 << lowres) - 1;
+ const int h_edge_pos = s->h_edge_pos >> lowres + 1;
+ const int v_edge_pos = s->v_edge_pos >> lowres + 1;
+ int emu = 0, src_x, src_y, offset, sx, sy;
+ uint8_t *ptr;
+
+ if (s->quarter_sample) {
+ mx /= 2;
+ my /= 2;
+ }
+
+ /* In case of 8X8, we construct a single chroma motion vector
+ with a special rounding */
+ mx = ff_h263_round_chroma(mx);
+ my = ff_h263_round_chroma(my);
+
+ sx = mx & s_mask;
+ sy = my & s_mask;
+ src_x = s->mb_x * block_s + (mx >> lowres + 1);
+ src_y = s->mb_y * block_s + (my >> lowres + 1);
+
+ offset = src_y * s->uvlinesize + src_x;
+ ptr = ref_picture[1] + offset;
+ if (s->flags & CODEC_FLAG_EMU_EDGE) {
+ if ((unsigned) src_x > FFMAX(h_edge_pos - (!!sx) - block_s, 0) ||
+ (unsigned) src_y > FFMAX(v_edge_pos - (!!sy) - block_s, 0)) {
- s->dsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9,
++ s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize,
+ 9, 9, src_x, src_y, h_edge_pos, v_edge_pos);
+ ptr = s->edge_emu_buffer;
+ emu = 1;
+ }
+ }
+ sx = (sx << 2) >> lowres;
+ sy = (sy << 2) >> lowres;
+ pix_op[op_index](dest_cb, ptr, s->uvlinesize, block_s, sx, sy);
+
+ ptr = ref_picture[2] + offset;
+ if (emu) {
++ s->vdsp.emulated_edge_mc(s->edge_emu_buffer, ptr, s->uvlinesize, 9, 9,
+ src_x, src_y, h_edge_pos, v_edge_pos);
+ ptr = s->edge_emu_buffer;
+ }
+ pix_op[op_index](dest_cr, ptr, s->uvlinesize, block_s, sx, sy);
+}
+
+/**
+ * motion compensation of a single macroblock
+ * @param s context
+ * @param dest_y luma destination pointer
+ * @param dest_cb chroma cb/u destination pointer
+ * @param dest_cr chroma cr/v destination pointer
+ * @param dir direction (0->forward, 1->backward)
+ * @param ref_picture array[3] of pointers to the 3 planes of the reference picture
+ * @param pix_op halfpel motion compensation function (average or put normally)
+ * the motion vectors are taken from s->mv and the MV type from s->mv_type
+ */
+static inline void MPV_motion_lowres(MpegEncContext *s,
+ uint8_t *dest_y, uint8_t *dest_cb,
+ uint8_t *dest_cr,
+ int dir, uint8_t **ref_picture,
+ h264_chroma_mc_func *pix_op)
+{
+ int mx, my;
+ int mb_x, mb_y, i;
+ const int lowres = s->avctx->lowres;
+ const int block_s = 8 >>lowres;
+
+ mb_x = s->mb_x;
+ mb_y = s->mb_y;
+
+ switch (s->mv_type) {
+ case MV_TYPE_16X16:
+ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
+ 0, 0, 0,
+ ref_picture, pix_op,
+ s->mv[dir][0][0], s->mv[dir][0][1],
+ 2 * block_s, mb_y);
+ break;
+ case MV_TYPE_8X8:
+ mx = 0;
+ my = 0;
+ for (i = 0; i < 4; i++) {
+ hpel_motion_lowres(s, dest_y + ((i & 1) + (i >> 1) *
+ s->linesize) * block_s,
+ ref_picture[0], 0, 0,
+ (2 * mb_x + (i & 1)) * block_s,
+ (2 * mb_y + (i >> 1)) * block_s,
+ s->width, s->height, s->linesize,
+ s->h_edge_pos >> lowres, s->v_edge_pos >> lowres,
+ block_s, block_s, pix_op,
+ s->mv[dir][i][0], s->mv[dir][i][1]);
+
+ mx += s->mv[dir][i][0];
+ my += s->mv[dir][i][1];
+ }
+
+ if (!CONFIG_GRAY || !(s->flags & CODEC_FLAG_GRAY))
+ chroma_4mv_motion_lowres(s, dest_cb, dest_cr, ref_picture,
+ pix_op, mx, my);
+ break;
+ case MV_TYPE_FIELD:
+ if (s->picture_structure == PICT_FRAME) {
+ /* top field */
+ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
+ 1, 0, s->field_select[dir][0],
+ ref_picture, pix_op,
+ s->mv[dir][0][0], s->mv[dir][0][1],
+ block_s, mb_y);
+ /* bottom field */
+ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
+ 1, 1, s->field_select[dir][1],
+ ref_picture, pix_op,
+ s->mv[dir][1][0], s->mv[dir][1][1],
+ block_s, mb_y);
+ } else {
+ if (s->picture_structure != s->field_select[dir][0] + 1 &&
+ s->pict_type != AV_PICTURE_TYPE_B && !s->first_field) {
+ ref_picture = s->current_picture_ptr->f.data;
+
+ }
+ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
+ 0, 0, s->field_select[dir][0],
+ ref_picture, pix_op,
+ s->mv[dir][0][0],
+ s->mv[dir][0][1], 2 * block_s, mb_y >> 1);
+ }
+ break;
+ case MV_TYPE_16X8:
+ for (i = 0; i < 2; i++) {
+ uint8_t **ref2picture;
+
+ if (s->picture_structure == s->field_select[dir][i] + 1 ||
+ s->pict_type == AV_PICTURE_TYPE_B || s->first_field) {
+ ref2picture = ref_picture;
+ } else {
+ ref2picture = s->current_picture_ptr->f.data;
+ }
+
+ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
+ 0, 0, s->field_select[dir][i],
+ ref2picture, pix_op,
+ s->mv[dir][i][0], s->mv[dir][i][1] +
+ 2 * block_s * i, block_s, mb_y >> 1);
+
+ dest_y += 2 * block_s * s->linesize;
+ dest_cb += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize;
+ dest_cr += (2 * block_s >> s->chroma_y_shift) * s->uvlinesize;
+ }
+ break;
+ case MV_TYPE_DMV:
+ if (s->picture_structure == PICT_FRAME) {
+ for (i = 0; i < 2; i++) {
+ int j;
+ for (j = 0; j < 2; j++) {
+ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
+ 1, j, j ^ i,
+ ref_picture, pix_op,
+ s->mv[dir][2 * i + j][0],
+ s->mv[dir][2 * i + j][1],
+ block_s, mb_y);
+ }
+ pix_op = s->dsp.avg_h264_chroma_pixels_tab;
+ }
+ } else {
+ for (i = 0; i < 2; i++) {
+ mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
+ 0, 0, s->picture_structure != i + 1,
+ ref_picture, pix_op,
+ s->mv[dir][2 * i][0],s->mv[dir][2 * i][1],
+ 2 * block_s, mb_y >> 1);
+
+ // after put we make avg of the same block
+ pix_op = s->dsp.avg_h264_chroma_pixels_tab;
+
+ // opposite parity is always in the same
+ // frame if this is second field
+ if (!s->first_field) {
+ ref_picture = s->current_picture_ptr->f.data;
+ }
+ }
+ }
+ break;
+ default:
+ av_assert2(0);
+ }
+}
+
/**
* find the lowest MB row referenced in the MVs
*/
#include "parser.h"
#include "mpeg12data.h"
#include "rl.h"
- #include "libavutil/timecode.h"
+ #include "videodsp.h"
#include "libavutil/opt.h"
++#include "libavutil/timecode.h"
#define FRAME_SKIPPED 100 ///< return value for header parsers if frame is not coded
ptr_y = s->new_picture.f.data[0] +
(mb_y * 16 * wrap_y) + mb_x * 16;
ptr_cb = s->new_picture.f.data[1] +
- (mb_y * mb_block_height * wrap_c) + mb_x * 8;
+ (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width;
ptr_cr = s->new_picture.f.data[2] +
- (mb_y * mb_block_height * wrap_c) + mb_x * 8;
+ (mb_y * mb_block_height * wrap_c) + mb_x * mb_block_width;
- if (mb_x * 16 + 16 > s->width || mb_y * 16 + 16 > s->height) {
+ if((mb_x*16+16 > s->width || mb_y*16+16 > s->height) && s->codec_id != AV_CODEC_ID_AMV){
uint8_t *ebuf = s->edge_emu_buffer + 32;
- s->dsp.emulated_edge_mc(ebuf, ptr_y, wrap_y, 16, 16, mb_x * 16,
- mb_y * 16, s->width, s->height);
+ s->vdsp.emulated_edge_mc(ebuf, ptr_y, wrap_y, 16, 16, mb_x * 16,
+ mb_y * 16, s->width, s->height);
ptr_y = ebuf;
- s->dsp.emulated_edge_mc(ebuf + 18 * wrap_y, ptr_cb, wrap_c, mb_block_width,
- mb_block_height, mb_x * 8, mb_y * 8,
- (s->width+1) >> 1, (s->height+1) >> 1);
- s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y, ptr_cb, wrap_c, 8,
++ s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y, ptr_cb, wrap_c, mb_block_width,
+ mb_block_height, mb_x * 8, mb_y * 8,
- s->width >> 1, s->height >> 1);
++ (s->width+1) >> 1, (s->height+1) >> 1);
ptr_cb = ebuf + 18 * wrap_y;
- s->dsp.emulated_edge_mc(ebuf + 18 * wrap_y + 8, ptr_cr, wrap_c, mb_block_width,
- mb_block_height, mb_x * 8, mb_y * 8,
- (s->width+1) >> 1, (s->height+1) >> 1);
- s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y + 8, ptr_cr, wrap_c, 8,
++ s->vdsp.emulated_edge_mc(ebuf + 18 * wrap_y + 8, ptr_cr, wrap_c, mb_block_width,
+ mb_block_height, mb_x * 8, mb_y * 8,
- s->width >> 1, s->height >> 1);
++ (s->width+1) >> 1, (s->height+1) >> 1);
ptr_cr = ebuf + 18 * wrap_y + 8;
}
void ff_dsputil_init_ppc(DSPContext* c, AVCodecContext *avctx)
{
const int high_bit_depth = avctx->bits_per_raw_sample > 8;
+ int mm_flags = av_get_cpu_flags();
+
+ if (avctx->dsp_mask) {
+ if (avctx->dsp_mask & AV_CPU_FLAG_FORCE)
+ mm_flags |= (avctx->dsp_mask & 0xffff);
+ else
+ mm_flags &= ~(avctx->dsp_mask & 0xffff);
+ }
// Common optimizations whether AltiVec is available or not
- c->prefetch = prefetch_ppc;
if (!high_bit_depth) {
switch (check_dcbzl_effect()) {
case 32:
sx += (mx>>4) - (HTAPS_MAX/2-1);
sy += (my>>4) - (HTAPS_MAX/2-1);
src += sx + sy*stride;
- if( (unsigned)sx >= w - b_w - (HTAPS_MAX-2)
- || (unsigned)sy >= h - b_h - (HTAPS_MAX-2)){
- s->dsp.emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1, sx, sy, w, h);
+ if( (unsigned)sx >= FFMAX(w - b_w - (HTAPS_MAX-2), 0)
+ || (unsigned)sy >= FFMAX(h - b_h - (HTAPS_MAX-2), 0)){
- s->dsp.emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1, sx, sy, w, h);
++ s->vdsp.emulated_edge_mc(tmp + MB_SIZE, src, stride, b_w+HTAPS_MAX-1, b_h+HTAPS_MAX-1, sx, sy, w, h);
src= tmp + MB_SIZE;
}
+
+ av_assert2(s->chroma_h_shift == s->chroma_v_shift); // only one mv_scale
+
// assert(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h);
// assert(!(b_w&(b_w-1)));
- assert(b_w>1 && b_h>1);
- assert((tab_index>=0 && tab_index<4) || b_w==32);
+ av_assert2(b_w>1 && b_h>1);
+ av_assert2((tab_index>=0 && tab_index<4) || b_w==32);
if((dx&3) || (dy&3) || !(b_w == b_h || 2*b_w == b_h || b_w == 2*b_h) || (b_w&(b_w-1)) || !s->plane[plane_index].fast_mc )
mc_block(&s->plane[plane_index], dst, src, stride, b_w, b_h, dx, dy);
else if(b_w==32){
s->max_ref_frames=1; //just make sure its not an invalid value in case of no initial keyframe
ff_dsputil_init(&s->dsp, avctx);
++ ff_videodsp_init(&s->vdsp, 8);
ff_dwt_init(&s->dwt);
#define mcf(dx,dy)\
AVCodecContext *avctx;
RangeCoder c;
DSPContext dsp;
++ VideoDSPContext vdsp;
DWTContext dwt;
AVFrame new_picture;
AVFrame input_picture; ///< new_picture with the internal linesizes
--- /dev/null
+ /*
+ * Copyright (C) 2012 Ronald S. Bultje
+ *
+ * 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 "libavutil/avassert.h"
+ #include "libavutil/common.h"
+ #include "videodsp.h"
+
+ #define BIT_DEPTH 8
+ #include "videodsp_template.c"
+ #undef BIT_DEPTH
+
+ #define BIT_DEPTH 16
+ #include "videodsp_template.c"
+ #undef BIT_DEPTH
+
+ static void just_return(uint8_t *buf, ptrdiff_t stride, int h)
+ {
+ }
+
+ void ff_videodsp_init(VideoDSPContext *ctx, int bpc)
+ {
+ ctx->prefetch = just_return;
+ if (bpc <= 8) {
+ ctx->emulated_edge_mc = ff_emulated_edge_mc_8;
+ } else {
+ ctx->emulated_edge_mc = ff_emulated_edge_mc_16;
+ }
+
+ if (ARCH_ARM)
+ ff_videodsp_init_arm(ctx, bpc);
+ if (ARCH_PPC)
+ ff_videodsp_init_ppc(ctx, bpc);
+ if (ARCH_X86)
+ ff_videodsp_init_x86(ctx, bpc);
+ }
--- /dev/null
-
-static void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src,
- ptrdiff_t linesize,
+ /*
+ * Copyright (c) 2002-2004 Michael Niedermayer
+ * Copyright (C) 2012 Ronald S. Bultje
+ *
+ * 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 "bit_depth_template.c"
- src += (h - 1 - src_y) * linesize;
++void FUNC(ff_emulated_edge_mc)(uint8_t *buf, const uint8_t *src,
++ ptrdiff_t linesize_arg,
+ int block_w, int block_h,
+ int src_x, int src_y, int w, int h)
+ {
+ int x, y;
+ int start_y, start_x, end_y, end_x;
++ int linesize = linesize_arg;
++
++ if (!w || !h)
++ return;
+
+ if (src_y >= h) {
- src += (1 - block_h - src_y) * linesize;
++ src -= src_y * linesize;
++ src += (h - 1) * linesize;
+ src_y = h - 1;
+ } else if (src_y <= -block_h) {
- assert(start_y < end_y && block_h);
- assert(start_x < end_x && block_w);
++ src -= src_y * linesize;
++ src += (1 - block_h) * linesize;
+ src_y = 1 - block_h;
+ }
+ if (src_x >= w) {
+ src += (w - 1 - src_x) * sizeof(pixel);
+ src_x = w - 1;
+ } else if (src_x <= -block_w) {
+ src += (1 - block_w - src_x) * sizeof(pixel);
+ src_x = 1 - block_w;
+ }
+
+ start_y = FFMAX(0, -src_y);
+ start_x = FFMAX(0, -src_x);
+ end_y = FFMIN(block_h, h-src_y);
+ end_x = FFMIN(block_w, w-src_x);
++ av_assert2(start_y < end_y && block_h);
++ av_assert2(start_x < end_x && block_w);
+
+ w = end_x - start_x;
+ src += start_y * linesize + start_x * sizeof(pixel);
+ buf += start_x * sizeof(pixel);
+
+ // top
+ for (y = 0; y < start_y; y++) {
+ memcpy(buf, src, w * sizeof(pixel));
+ buf += linesize;
+ }
+
+ // copy existing part
+ for (; y < end_y; y++) {
+ memcpy(buf, src, w * sizeof(pixel));
+ src += linesize;
+ buf += linesize;
+ }
+
+ // bottom
+ src -= linesize;
+ for (; y < block_h; y++) {
+ memcpy(buf, src, w * sizeof(pixel));
+ buf += linesize;
+ }
+
+ buf -= block_h * linesize + start_x * sizeof(pixel);
+ while (block_h--) {
+ pixel *bufp = (pixel *) buf;
+
+ // left
+ for(x = 0; x < start_x; x++) {
+ bufp[x] = bufp[start_x];
+ }
+
+ // right
+ for (x = end_x; x < block_w; x++) {
+ bufp[x] = bufp[end_x - 1];
+ }
+ buf += linesize;
+ }
+ }
OBJS-$(CONFIG_RV30_DECODER) += x86/rv34dsp_init.o
OBJS-$(CONFIG_RV40_DECODER) += x86/rv34dsp_init.o \
x86/rv40dsp_init.o
+OBJS-$(CONFIG_V210_DECODER) += x86/v210-init.o
OBJS-$(CONFIG_TRUEHD_DECODER) += x86/mlpdsp.o
OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_init.o
+ OBJS-$(CONFIG_VIDEODSP) += x86/videodsp_init.o
OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp_init.o
OBJS-$(CONFIG_VP5_DECODER) += x86/vp56dsp_init.o
OBJS-$(CONFIG_VP6_DECODER) += x86/vp56dsp_init.o
YASM-OBJS-$(CONFIG_RV30_DECODER) += x86/rv34dsp.o
YASM-OBJS-$(CONFIG_RV40_DECODER) += x86/rv34dsp.o \
x86/rv40dsp.o
+YASM-OBJS-$(CONFIG_V210_DECODER) += x86/v210.o
YASM-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp.o
+ YASM-OBJS-$(CONFIG_VIDEODSP) += x86/videodsp.o
YASM-OBJS-$(CONFIG_VP3DSP) += x86/vp3dsp.o
YASM-OBJS-$(CONFIG_VP6_DECODER) += x86/vp56dsp.o
YASM-OBJS-$(CONFIG_VP8_DECODER) += x86/vp8dsp.o
avg_pixels16_xy2_mmx(dst, src, stride, 16);
}
- #endif /* HAVE_INLINE_ASM */
-
- #if HAVE_YASM
- typedef void emu_edge_core_func(uint8_t *buf, const uint8_t *src,
- x86_reg linesize, x86_reg start_y,
- x86_reg end_y, x86_reg block_h,
- x86_reg start_x, x86_reg end_x,
- x86_reg block_w);
- extern emu_edge_core_func ff_emu_edge_core_mmx;
- extern emu_edge_core_func ff_emu_edge_core_sse;
-
- static av_always_inline void emulated_edge_mc(uint8_t *buf, const uint8_t *src,
- int linesize,
- int block_w, int block_h,
- int src_x, int src_y,
- int w, int h,
- emu_edge_core_func *core_fn)
- {
- int start_y, start_x, end_y, end_x, src_y_add = 0;
-
- if(!w || !h)
- return;
-
- if (src_y >= h) {
- src -= src_y*linesize;
- src_y_add = h - 1;
- src_y = h - 1;
- } else if (src_y <= -block_h) {
- src -= src_y*linesize;
- src_y_add = 1 - block_h;
- src_y = 1 - block_h;
- }
- if (src_x >= w) {
- src += w - 1 - src_x;
- src_x = w - 1;
- } else if (src_x <= -block_w) {
- src += 1 - block_w - src_x;
- src_x = 1 - block_w;
- }
-
- start_y = FFMAX(0, -src_y);
- start_x = FFMAX(0, -src_x);
- end_y = FFMIN(block_h, h-src_y);
- end_x = FFMIN(block_w, w-src_x);
- av_assert2(start_x < end_x && block_w > 0);
- av_assert2(start_y < end_y && block_h > 0);
-
- // fill in the to-be-copied part plus all above/below
- src += (src_y_add + start_y) * linesize + start_x;
- buf += start_x;
- core_fn(buf, src, linesize, start_y, end_y,
- block_h, start_x, end_x, block_w);
- }
-
- #if ARCH_X86_32
- static av_noinline void emulated_edge_mc_mmx(uint8_t *buf, const uint8_t *src,
- int linesize,
- int block_w, int block_h,
- int src_x, int src_y, int w, int h)
- {
- emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y,
- w, h, &ff_emu_edge_core_mmx);
- }
- #endif
-
- static av_noinline void emulated_edge_mc_sse(uint8_t *buf, const uint8_t *src,
- int linesize,
- int block_w, int block_h,
- int src_x, int src_y, int w, int h)
- {
- emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y,
- w, h, &ff_emu_edge_core_sse);
- }
- #endif /* HAVE_YASM */
-
- #if HAVE_INLINE_ASM
-
-static void gmc_mmx(uint8_t *dst, uint8_t *src,
- int stride, int h, int ox, int oy,
- int dxx, int dxy, int dyx, int dyy,
- int shift, int r, int width, int height)
+typedef void emulated_edge_mc_func(uint8_t *dst, const uint8_t *src,
+ int linesize, int block_w, int block_h,
+ int src_x, int src_y, int w, int h);
+
+static av_always_inline void gmc(uint8_t *dst, uint8_t *src,
+ int stride, int h, int ox, int oy,
+ int dxx, int dxy, int dyx, int dyy,
+ int shift, int r, int width, int height,
+ emulated_edge_mc_func *emu_edge_fn)
{
const int w = 8;
const int ix = ox >> (16 + shift);
src += 4 - h * stride;
}
}
- width, height, &emulated_edge_mc_mmx);
+
+#if HAVE_YASM
+#if ARCH_X86_32
+static void gmc_mmx(uint8_t *dst, uint8_t *src,
+ int stride, int h, int ox, int oy,
+ int dxx, int dxy, int dyx, int dyy,
+ int shift, int r, int width, int height)
+{
+ gmc(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, shift, r,
- width, height, &emulated_edge_mc_sse);
++ width, height, &ff_emulated_edge_mc_8);
+}
+#endif
+static void gmc_sse(uint8_t *dst, uint8_t *src,
+ int stride, int h, int ox, int oy,
+ int dxx, int dxy, int dyx, int dyy,
+ int shift, int r, int width, int height)
+{
+ gmc(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, shift, r,
- #define PREFETCH(name, op) \
- static void name(void *mem, int stride, int h) \
- { \
- const uint8_t *p = mem; \
- do { \
- __asm__ volatile (#op" %0" :: "m"(*p)); \
- p += stride; \
- } while (--h); \
- }
-
- PREFETCH(prefetch_mmxext, prefetcht0)
- PREFETCH(prefetch_3dnow, prefetch)
- #undef PREFETCH
-
++ width, height, &ff_emulated_edge_mc_8);
+}
+#else
+static void gmc_mmx(uint8_t *dst, uint8_t *src,
+ int stride, int h, int ox, int oy,
+ int dxx, int dxy, int dyx, int dyy,
+ int shift, int r, int width, int height)
+{
+ gmc(dst, src, stride, h, ox, oy, dxx, dxy, dyx, dyy, shift, r,
+ width, height, &ff_emulated_edge_mc_8);
+}
+#endif
+
#endif /* HAVE_INLINE_ASM */
#include "h264_qpel.c"
c->scalarproduct_float = ff_scalarproduct_float_sse;
c->butterflies_float_interleave = ff_butterflies_float_interleave_sse;
- if (!high_bit_depth)
- c->emulated_edge_mc = emulated_edge_mc_sse;
+
+#if HAVE_INLINE_ASM
+ c->gmc = gmc_sse;
+#endif
#endif /* HAVE_YASM */
}
--- /dev/null
- ptrdiff_t linesize,
+ /*
+ * Copyright (C) 2012 Ronald S. Bultje
+ *
+ * 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/avassert.h"
+ #include "libavutil/common.h"
+ #include "libavutil/cpu.h"
+ #include "libavutil/mem.h"
+ #include "libavutil/x86/asm.h"
+ #include "libavcodec/videodsp.h"
+
+ #if HAVE_YASM
+ typedef void emu_edge_core_func(uint8_t *buf, const uint8_t *src,
+ x86_reg linesize, x86_reg start_y,
+ x86_reg end_y, x86_reg block_h,
+ x86_reg start_x, x86_reg end_x,
+ x86_reg block_w);
+ extern emu_edge_core_func ff_emu_edge_core_mmx;
+ extern emu_edge_core_func ff_emu_edge_core_sse;
+
+ static av_always_inline void emulated_edge_mc(uint8_t *buf, const uint8_t *src,
- src_y_add = h - 1 - src_y;
++ ptrdiff_t linesize_arg,
+ int block_w, int block_h,
+ int src_x, int src_y,
+ int w, int h,
+ emu_edge_core_func *core_fn)
+ {
+ int start_y, start_x, end_y, end_x, src_y_add = 0;
++ int linesize = linesize_arg;
++
++ if(!w || !h)
++ return;
+
+ if (src_y >= h) {
- src_y_add = 1 - block_h - src_y;
++ src -= src_y*linesize;
++ src_y_add = h - 1;
+ src_y = h - 1;
+ } else if (src_y <= -block_h) {
- assert(start_x < end_x && block_w > 0);
- assert(start_y < end_y && block_h > 0);
++ src -= src_y*linesize;
++ src_y_add = 1 - block_h;
+ src_y = 1 - block_h;
+ }
+ if (src_x >= w) {
+ src += w - 1 - src_x;
+ src_x = w - 1;
+ } else if (src_x <= -block_w) {
+ src += 1 - block_w - src_x;
+ src_x = 1 - block_w;
+ }
+
+ start_y = FFMAX(0, -src_y);
+ start_x = FFMAX(0, -src_x);
+ end_y = FFMIN(block_h, h-src_y);
+ end_x = FFMIN(block_w, w-src_x);
++ av_assert2(start_x < end_x && block_w > 0);
++ av_assert2(start_y < end_y && block_h > 0);
+
+ // fill in the to-be-copied part plus all above/below
+ src += (src_y_add + start_y) * linesize + start_x;
+ buf += start_x;
+ core_fn(buf, src, linesize, start_y, end_y,
+ block_h, start_x, end_x, block_w);
+ }
+
+ #if ARCH_X86_32
+ static av_noinline void emulated_edge_mc_mmx(uint8_t *buf, const uint8_t *src,
+ ptrdiff_t linesize,
+ int block_w, int block_h,
+ int src_x, int src_y, int w, int h)
+ {
+ emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y,
+ w, h, &ff_emu_edge_core_mmx);
+ }
+ #endif
+
+ static av_noinline void emulated_edge_mc_sse(uint8_t *buf, const uint8_t *src,
+ ptrdiff_t linesize,
+ int block_w, int block_h,
+ int src_x, int src_y, int w, int h)
+ {
+ emulated_edge_mc(buf, src, linesize, block_w, block_h, src_x, src_y,
+ w, h, &ff_emu_edge_core_sse);
+ }
+ #endif /* HAVE_YASM */
+
+ void ff_prefetch_mmxext(uint8_t *buf, ptrdiff_t stride, int h);
+ void ff_prefetch_3dnow(uint8_t *buf, ptrdiff_t stride, int h);
+
+ void ff_videodsp_init_x86(VideoDSPContext *ctx, int bpc)
+ {
+ #if HAVE_YASM
+ int mm_flags = av_get_cpu_flags();
+
+ #if ARCH_X86_32
+ if (bpc <= 8 && mm_flags & AV_CPU_FLAG_MMX) {
+ ctx->emulated_edge_mc = emulated_edge_mc_mmx;
+ }
+ if (mm_flags & AV_CPU_FLAG_3DNOW) {
+ ctx->prefetch = ff_prefetch_3dnow;
+ }
+ #endif /* ARCH_X86_32 */
+ if (mm_flags & AV_CPU_FLAG_MMXEXT) {
+ ctx->prefetch = ff_prefetch_mmxext;
+ }
+ if (bpc <= 8 && mm_flags & AV_CPU_FLAG_SSE) {
+ ctx->emulated_edge_mc = emulated_edge_mc_sse;
+ }
+ #endif /* HAVE_YASM */
+ }