1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-23 12:43:46 +02:00

Merge remote-tracking branch 'qatar/master'

* qatar/master: (25 commits)
  rv40dsp x86: MMX/MMX2/3DNow/SSE2/SSSE3 implementations of MC
  ape: Use unsigned integer maths
  arm: dsputil: fix overreads in put/avg_pixels functions
  h264: K&R formatting cosmetics for header files (part II/II)
  h264: K&R formatting cosmetics for header files (part I/II)
  rtmp: Implement check bandwidth notification.
  rtmp: Support 'rtmp_swfurl', an option which specifies the URL of the SWF player.
  rtmp: Support 'rtmp_flashver', an option which overrides the version of the Flash plugin.
  rtmp: Support 'rtmp_tcurl', an option which overrides the URL of the target stream.
  cmdutils: Add fallback case to switch in check_stream_specifier().
  sctp: be consistent with socket option level
  configure: Add _XOPEN_SOURCE=600 to Solaris preprocessor flags.
  vcr1enc: drop pointless empty encode_init() wrapper function
  vcr1: drop pointless write-only AVCodecContext member from VCR1Context
  vcr1: group encoder code together to save #ifdefs
  vcr1: cosmetics: K&R prettyprinting, typos, parentheses, dead code, comments
  mov: make one comment slightly more specific
  lavr: replace the SSE version of ff_conv_fltp_to_flt_6ch() with SSE4 and AVX
  lavfi: move audio-related functions to a separate file.
  lavfi: remove some audio-related function from public API.
  ...

Conflicts:
	cmdutils.c
	libavcodec/h264.h
	libavcodec/h264_mvpred.h
	libavcodec/vcr1.c
	libavfilter/avfilter.c
	libavfilter/avfilter.h
	libavfilter/defaults.c
	libavfilter/internal.h

Merged-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
Michael Niedermayer 2012-05-10 22:41:29 +02:00
commit 015903294c
44 changed files with 2249 additions and 1422 deletions

View File

@ -38,6 +38,7 @@
#if CONFIG_POSTPROC #if CONFIG_POSTPROC
#include "libpostproc/postprocess.h" #include "libpostproc/postprocess.h"
#endif #endif
#include "libavutil/avassert.h"
#include "libavutil/avstring.h" #include "libavutil/avstring.h"
#include "libavutil/mathematics.h" #include "libavutil/mathematics.h"
#include "libavutil/parseutils.h" #include "libavutil/parseutils.h"
@ -1075,7 +1076,7 @@ int check_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
case 's': type = AVMEDIA_TYPE_SUBTITLE; break; case 's': type = AVMEDIA_TYPE_SUBTITLE; break;
case 'd': type = AVMEDIA_TYPE_DATA; break; case 'd': type = AVMEDIA_TYPE_DATA; break;
case 't': type = AVMEDIA_TYPE_ATTACHMENT; break; case 't': type = AVMEDIA_TYPE_ATTACHMENT; break;
default: abort(); // never reached, silence warning default: av_assert0(0);
} }
if (type != st->codec->codec_type) if (type != st->codec->codec_type)
return 0; return 0;

2
configure vendored
View File

@ -2662,7 +2662,7 @@ case $target_os in
SHFLAGS='-shared -Wl,-h,$$(@F)' SHFLAGS='-shared -Wl,-h,$$(@F)'
enabled x86 && SHFLAGS="-mimpure-text $SHFLAGS" enabled x86 && SHFLAGS="-mimpure-text $SHFLAGS"
network_extralibs="-lsocket -lnsl" network_extralibs="-lsocket -lnsl"
add_cppflags -D__EXTENSIONS__ add_cppflags -D__EXTENSIONS__ -D_XOPEN_SOURCE=600
# When using suncc to build, the Solaris linker will mark # When using suncc to build, the Solaris linker will mark
# an executable with each instruction set encountered by # an executable with each instruction set encountered by
# the Solaris assembler. As our libraries contain their own # the Solaris assembler. As our libraries contain their own

View File

@ -393,7 +393,7 @@ static inline int range_get_symbol(APEContext *ctx,
} }
/** @} */ // group rangecoder /** @} */ // group rangecoder
static inline void update_rice(APERice *rice, int x) static inline void update_rice(APERice *rice, unsigned int x)
{ {
int lim = rice->k ? (1 << (rice->k + 4)) : 0; int lim = rice->k ? (1 << (rice->k + 4)) : 0;
rice->ksum += ((x + 1) / 2) - ((rice->ksum + 16) >> 5); rice->ksum += ((x + 1) / 2) - ((rice->ksum + 16) >> 5);
@ -406,7 +406,7 @@ static inline void update_rice(APERice *rice, int x)
static inline int ape_decode_value(APEContext *ctx, APERice *rice) static inline int ape_decode_value(APEContext *ctx, APERice *rice)
{ {
int x, overflow; unsigned int x, overflow;
if (ctx->fileversion < 3990) { if (ctx->fileversion < 3990) {
int tmpk; int tmpk;

View File

@ -95,6 +95,7 @@ endfunc
.endm .endm
.macro pixels16_y2 rnd=1, avg=0 .macro pixels16_y2 rnd=1, avg=0
sub r3, r3, #2
vld1.64 {q0}, [r1], r2 vld1.64 {q0}, [r1], r2
vld1.64 {q1}, [r1], r2 vld1.64 {q1}, [r1], r2
1: subs r3, r3, #2 1: subs r3, r3, #2
@ -114,10 +115,25 @@ endfunc
vst1.64 {q2}, [r0,:128], r2 vst1.64 {q2}, [r0,:128], r2
vst1.64 {q3}, [r0,:128], r2 vst1.64 {q3}, [r0,:128], r2
bne 1b bne 1b
avg q2, q0, q1
vld1.64 {q0}, [r1], r2
avg q3, q0, q1
.if \avg
vld1.8 {q8}, [r0,:128], r2
vld1.8 {q9}, [r0,:128]
vrhadd.u8 q2, q2, q8
vrhadd.u8 q3, q3, q9
sub r0, r0, r2
.endif
vst1.64 {q2}, [r0,:128], r2
vst1.64 {q3}, [r0,:128], r2
bx lr bx lr
.endm .endm
.macro pixels16_xy2 rnd=1, avg=0 .macro pixels16_xy2 rnd=1, avg=0
sub r3, r3, #2
vld1.64 {d0-d2}, [r1], r2 vld1.64 {d0-d2}, [r1], r2
vld1.64 {d4-d6}, [r1], r2 vld1.64 {d4-d6}, [r1], r2
.ifeq \rnd .ifeq \rnd
@ -173,6 +189,42 @@ endfunc
vaddl.u8 q11, d3, d5 vaddl.u8 q11, d3, d5
vst1.64 {q15}, [r0,:128], r2 vst1.64 {q15}, [r0,:128], r2
bgt 1b bgt 1b
vld1.64 {d0-d2}, [r1], r2
vadd.u16 q12, q8, q9
.ifeq \rnd
vadd.u16 q12, q12, q13
.endif
vext.8 q15, q0, q1, #1
vadd.u16 q1 , q10, q11
shrn d28, q12, #2
.ifeq \rnd
vadd.u16 q1, q1, q13
.endif
shrn d29, q1, #2
.if \avg
vld1.8 {q8}, [r0,:128]
vrhadd.u8 q14, q14, q8
.endif
vaddl.u8 q8, d0, d30
vaddl.u8 q10, d1, d31
vst1.64 {q14}, [r0,:128], r2
vadd.u16 q12, q8, q9
.ifeq \rnd
vadd.u16 q12, q12, q13
.endif
vadd.u16 q0, q10, q11
shrn d30, q12, #2
.ifeq \rnd
vadd.u16 q0, q0, q13
.endif
shrn d31, q0, #2
.if \avg
vld1.8 {q9}, [r0,:128]
vrhadd.u8 q15, q15, q9
.endif
vst1.64 {q15}, [r0,:128], r2
bx lr bx lr
.endm .endm
@ -228,6 +280,7 @@ endfunc
.endm .endm
.macro pixels8_y2 rnd=1, avg=0 .macro pixels8_y2 rnd=1, avg=0
sub r3, r3, #2
vld1.64 {d0}, [r1], r2 vld1.64 {d0}, [r1], r2
vld1.64 {d1}, [r1], r2 vld1.64 {d1}, [r1], r2
1: subs r3, r3, #2 1: subs r3, r3, #2
@ -246,10 +299,24 @@ endfunc
vst1.64 {d4}, [r0,:64], r2 vst1.64 {d4}, [r0,:64], r2
vst1.64 {d5}, [r0,:64], r2 vst1.64 {d5}, [r0,:64], r2
bne 1b bne 1b
avg d4, d0, d1
vld1.64 {d0}, [r1], r2
avg d5, d0, d1
.if \avg
vld1.8 {d2}, [r0,:64], r2
vld1.8 {d3}, [r0,:64]
vrhadd.u8 q2, q2, q1
sub r0, r0, r2
.endif
vst1.64 {d4}, [r0,:64], r2
vst1.64 {d5}, [r0,:64], r2
bx lr bx lr
.endm .endm
.macro pixels8_xy2 rnd=1, avg=0 .macro pixels8_xy2 rnd=1, avg=0
sub r3, r3, #2
vld1.64 {q0}, [r1], r2 vld1.64 {q0}, [r1], r2
vld1.64 {q1}, [r1], r2 vld1.64 {q1}, [r1], r2
.ifeq \rnd .ifeq \rnd
@ -291,6 +358,31 @@ endfunc
vaddl.u8 q9, d2, d6 vaddl.u8 q9, d2, d6
vst1.64 {d7}, [r0,:64], r2 vst1.64 {d7}, [r0,:64], r2
bgt 1b bgt 1b
vld1.64 {q0}, [r1], r2
vadd.u16 q10, q8, q9
vext.8 d4, d0, d1, #1
.ifeq \rnd
vadd.u16 q10, q10, q11
.endif
vaddl.u8 q8, d0, d4
shrn d5, q10, #2
vadd.u16 q10, q8, q9
.if \avg
vld1.8 {d7}, [r0,:64]
vrhadd.u8 d5, d5, d7
.endif
.ifeq \rnd
vadd.u16 q10, q10, q11
.endif
vst1.64 {d5}, [r0,:64], r2
shrn d7, q10, #2
.if \avg
vld1.8 {d5}, [r0,:64]
vrhadd.u8 d7, d7, d5
.endif
vst1.64 {d7}, [r0,:64], r2
bx lr bx lr
.endm .endm

View File

@ -153,7 +153,6 @@ typedef enum {
* Sequence parameter set * Sequence parameter set
*/ */
typedef struct SPS { typedef struct SPS {
int profile_idc; int profile_idc;
int level_idc; int level_idc;
int chroma_format_idc; int chroma_format_idc;
@ -379,12 +378,12 @@ typedef struct H264Context{
/** /**
* num_ref_idx_l0/1_active_minus1 + 1 * num_ref_idx_l0/1_active_minus1 + 1
*/ */
uint8_t *list_counts; ///< Array of list_count per MB specifying the slice type
unsigned int ref_count[2]; ///< counts frames or fields, depending on current mb mode unsigned int ref_count[2]; ///< counts frames or fields, depending on current mb mode
unsigned int list_count; unsigned int list_count;
uint8_t *list_counts; ///< Array of list_count per MB specifying the slice type
Picture ref_list[2][48]; /**< 0..15: frame refs, 16..47: mbaff field refs. Picture ref_list[2][48]; /**< 0..15: frame refs, 16..47: mbaff field refs.
Reordered version of default_ref_list * Reordered version of default_ref_list
according to picture reordering in slice header */ * according to picture reordering in slice header */
int ref2frm[MAX_SLICES][2][64]; ///< reference to frame number lists, used in the loop filter, the first 2 are for -2,-1 int ref2frm[MAX_SLICES][2][64]; ///< reference to frame number lists, used in the loop filter, the first 2 are for -2,-1
// data partitioning // data partitioning
@ -462,7 +461,6 @@ typedef struct H264Context{
uint16_t *slice_table_base; uint16_t *slice_table_base;
// POC stuff // POC stuff
int poc_lsb; int poc_lsb;
int poc_msb; int poc_msb;
@ -600,7 +598,6 @@ typedef struct H264Context{
int parse_last_mb; int parse_last_mb;
} H264Context; } H264Context;
extern const uint8_t ff_h264_chroma_qp[5][QP_MAX_NUM + 1]; ///< One chroma qp table for each possible bit depth (8-12). extern const uint8_t ff_h264_chroma_qp[5][QP_MAX_NUM + 1]; ///< One chroma qp table for each possible bit depth (8-12).
extern const uint16_t ff_h264_mb_sizes[4]; extern const uint16_t ff_h264_mb_sizes[4];
@ -628,13 +625,16 @@ int ff_h264_decode_picture_parameter_set(H264Context *h, int bit_length);
* Decode a network abstraction layer unit. * Decode a network abstraction layer unit.
* @param consumed is the number of bytes used as input * @param consumed is the number of bytes used as input
* @param length is the length of the array * @param length is the length of the array
* @param dst_length is the number of decoded bytes FIXME here or a decode rbsp tailing? * @param dst_length is the number of decoded bytes FIXME here
* or a decode rbsp tailing?
* @return decoded bytes, might be src+1 if no escapes * @return decoded bytes, might be src+1 if no escapes
*/ */
const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src, int *dst_length, int *consumed, int length); const uint8_t *ff_h264_decode_nal(H264Context *h, const uint8_t *src,
int *dst_length, int *consumed, int length);
/** /**
* Free any data that may have been allocated in the H264 context like SPS, PPS etc. * Free any data that may have been allocated in the H264 context
* like SPS, PPS etc.
*/ */
av_cold void ff_h264_free_context(H264Context *h); av_cold void ff_h264_free_context(H264Context *h);
@ -667,12 +667,16 @@ int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb);
void ff_generate_sliding_window_mmcos(H264Context *h); void ff_generate_sliding_window_mmcos(H264Context *h);
/** /**
* Check if the top & left blocks are available if needed & change the dc mode so it only uses the available blocks. * Check if the top & left blocks are available if needed & change the
* dc mode so it only uses the available blocks.
*/ */
int ff_h264_check_intra4x4_pred_mode(H264Context *h); int ff_h264_check_intra4x4_pred_mode(H264Context *h);
/**
* Check if the top & left blocks are available if needed & change the
* dc mode so it only uses the available blocks.
*/
int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma); int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma);
void ff_h264_hl_decode_mb(H264Context *h); void ff_h264_hl_decode_mb(H264Context *h);
@ -683,13 +687,13 @@ av_cold void ff_h264_decode_init_vlc(void);
/** /**
* Decode a macroblock * Decode a macroblock
* @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR if an error is noticed * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR on error
*/ */
int ff_h264_decode_mb_cavlc(H264Context *h); int ff_h264_decode_mb_cavlc(H264Context *h);
/** /**
* Decode a CABAC coded macroblock * Decode a CABAC coded macroblock
* @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR if an error is noticed * @return 0 if OK, ER_AC_ERROR / ER_DC_ERROR / ER_MV_ERROR on error
*/ */
int ff_h264_decode_mb_cabac(H264Context *h); int ff_h264_decode_mb_cabac(H264Context *h);
@ -699,8 +703,12 @@ void ff_h264_direct_dist_scale_factor(H264Context * const h);
void ff_h264_direct_ref_list_init(H264Context *const h); void ff_h264_direct_ref_list_init(H264Context *const h);
void ff_h264_pred_direct_motion(H264Context *const h, int *mb_type); void ff_h264_pred_direct_motion(H264Context *const h, int *mb_type);
void ff_h264_filter_mb_fast( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize); void ff_h264_filter_mb_fast(H264Context *h, int mb_x, int mb_y,
void ff_h264_filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize); uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr,
unsigned int linesize, unsigned int uvlinesize);
void ff_h264_filter_mb(H264Context *h, int mb_x, int mb_y,
uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr,
unsigned int linesize, unsigned int uvlinesize);
/** /**
* Reset SEI values at the beginning of the frame. * Reset SEI values at the beginning of the frame.
@ -709,15 +717,14 @@ void ff_h264_filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint
*/ */
void ff_h264_reset_sei(H264Context *h); void ff_h264_reset_sei(H264Context *h);
/* /*
o-o o-o * o-o o-o
/ / / * / / /
o-o o-o * o-o o-o
,---' * ,---'
o-o o-o * o-o o-o
/ / / * / / /
o-o o-o * o-o o-o
*/ */
/* Scan8 organization: /* Scan8 organization:
@ -760,7 +767,8 @@ static const uint8_t scan8[16*3 + 3]={
0 + 0 * 8, 0 + 5 * 8, 0 + 10 * 8 0 + 0 * 8, 0 + 5 * 8, 0 + 10 * 8
}; };
static av_always_inline uint32_t pack16to32(int a, int b){ static av_always_inline uint32_t pack16to32(int a, int b)
{
#if HAVE_BIGENDIAN #if HAVE_BIGENDIAN
return (b & 0xFFFF) + (a << 16); return (b & 0xFFFF) + (a << 16);
#else #else
@ -768,7 +776,8 @@ static av_always_inline uint32_t pack16to32(int a, int b){
#endif #endif
} }
static av_always_inline uint16_t pack8to16(int a, int b){ static av_always_inline uint16_t pack8to16(int a, int b)
{
#if HAVE_BIGENDIAN #if HAVE_BIGENDIAN
return (b & 0xFF) + (a << 8); return (b & 0xFF) + (a << 8);
#else #else
@ -779,14 +788,16 @@ static av_always_inline uint16_t pack8to16(int a, int b){
/** /**
* Get the chroma qp. * Get the chroma qp.
*/ */
static av_always_inline int get_chroma_qp(H264Context *h, int t, int qscale){ static av_always_inline int get_chroma_qp(H264Context *h, int t, int qscale)
{
return h->pps.chroma_qp_table[t][qscale]; return h->pps.chroma_qp_table[t][qscale];
} }
/** /**
* Get the predicted intra4x4 prediction mode. * Get the predicted intra4x4 prediction mode.
*/ */
static av_always_inline int pred_intra_mode(H264Context *h, int n){ static av_always_inline int pred_intra_mode(H264Context *h, int n)
{
const int index8 = scan8[n]; const int index8 = scan8[n];
const int left = h->intra4x4_pred_mode_cache[index8 - 1]; const int left = h->intra4x4_pred_mode_cache[index8 - 1];
const int top = h->intra4x4_pred_mode_cache[index8 - 8]; const int top = h->intra4x4_pred_mode_cache[index8 - 8];
@ -794,11 +805,14 @@ static av_always_inline int pred_intra_mode(H264Context *h, int n){
tprintf(h->s.avctx, "mode:%d %d min:%d\n", left, top, min); tprintf(h->s.avctx, "mode:%d %d min:%d\n", left, top, min);
if(min<0) return DC_PRED; if (min < 0)
else return min; return DC_PRED;
else
return min;
} }
static av_always_inline void write_back_intra_pred_mode(H264Context *h){ static av_always_inline void write_back_intra_pred_mode(H264Context *h)
{
int8_t *i4x4 = h->intra4x4_pred_mode + h->mb2br_xy[h->mb_xy]; int8_t *i4x4 = h->intra4x4_pred_mode + h->mb2br_xy[h->mb_xy];
int8_t *i4x4_cache = h->intra4x4_pred_mode_cache; int8_t *i4x4_cache = h->intra4x4_pred_mode_cache;
@ -808,7 +822,8 @@ static av_always_inline void write_back_intra_pred_mode(H264Context *h){
i4x4[6] = i4x4_cache[7 + 8 * 1]; i4x4[6] = i4x4_cache[7 + 8 * 1];
} }
static av_always_inline void write_back_non_zero_count(H264Context *h){ static av_always_inline void write_back_non_zero_count(H264Context *h)
{
const int mb_xy = h->mb_xy; const int mb_xy = h->mb_xy;
uint8_t *nnz = h->non_zero_count[mb_xy]; uint8_t *nnz = h->non_zero_count[mb_xy];
uint8_t *nnz_cache = h->non_zero_count_cache; uint8_t *nnz_cache = h->non_zero_count_cache;
@ -830,8 +845,11 @@ static av_always_inline void write_back_non_zero_count(H264Context *h){
} }
} }
static av_always_inline void write_back_motion_list(H264Context *h, MpegEncContext * const s, int b_stride, static av_always_inline void write_back_motion_list(H264Context *h,
int b_xy, int b8_xy, int mb_type, int list ) MpegEncContext *const s,
int b_stride,
int b_xy, int b8_xy,
int mb_type, int list)
{ {
int16_t(*mv_dst)[2] = &s->current_picture.f.motion_val[list][b_xy]; int16_t(*mv_dst)[2] = &s->current_picture.f.motion_val[list][b_xy];
int16_t(*mv_src)[2] = &h->mv_cache[list][scan8[0]]; int16_t(*mv_src)[2] = &h->mv_cache[list][scan8[0]];
@ -840,11 +858,12 @@ static av_always_inline void write_back_motion_list(H264Context *h, MpegEncConte
AV_COPY128(mv_dst + 2 * b_stride, mv_src + 8 * 2); AV_COPY128(mv_dst + 2 * b_stride, mv_src + 8 * 2);
AV_COPY128(mv_dst + 3 * b_stride, mv_src + 8 * 3); AV_COPY128(mv_dst + 3 * b_stride, mv_src + 8 * 3);
if (CABAC) { if (CABAC) {
uint8_t (*mvd_dst)[2] = &h->mvd_table[list][FMO ? 8*h->mb_xy : h->mb2br_xy[h->mb_xy]]; uint8_t (*mvd_dst)[2] = &h->mvd_table[list][FMO ? 8 * h->mb_xy
: h->mb2br_xy[h->mb_xy]];
uint8_t(*mvd_src)[2] = &h->mvd_cache[list][scan8[0]]; uint8_t(*mvd_src)[2] = &h->mvd_cache[list][scan8[0]];
if(IS_SKIP(mb_type)) if (IS_SKIP(mb_type)) {
AV_ZERO128(mvd_dst); AV_ZERO128(mvd_dst);
else{ } else {
AV_COPY64(mvd_dst, mvd_src + 8 * 3); AV_COPY64(mvd_dst, mvd_src + 8 * 3);
AV_COPY16(mvd_dst + 3 + 3, mvd_src + 3 + 8 * 0); AV_COPY16(mvd_dst + 3 + 3, mvd_src + 3 + 8 * 0);
AV_COPY16(mvd_dst + 3 + 2, mvd_src + 3 + 8 * 1); AV_COPY16(mvd_dst + 3 + 2, mvd_src + 3 + 8 * 1);
@ -862,7 +881,8 @@ static av_always_inline void write_back_motion_list(H264Context *h, MpegEncConte
} }
} }
static av_always_inline void write_back_motion(H264Context *h, int mb_type){ static av_always_inline void write_back_motion(H264Context *h, int mb_type)
{
MpegEncContext *const s = &h->s; MpegEncContext *const s = &h->s;
const int b_stride = h->b_stride; const int b_stride = h->b_stride;
const int b_xy = 4 * s->mb_x + 4 * s->mb_y * h->b_stride; // try mb2b(8)_xy const int b_xy = 4 * s->mb_x + 4 * s->mb_y * h->b_stride; // try mb2b(8)_xy
@ -874,9 +894,8 @@ static av_always_inline void write_back_motion(H264Context *h, int mb_type){
fill_rectangle(&s->current_picture.f.ref_index[0][b8_xy], fill_rectangle(&s->current_picture.f.ref_index[0][b8_xy],
2, 2, 2, (uint8_t)LIST_NOT_USED, 1); 2, 2, 2, (uint8_t)LIST_NOT_USED, 1);
} }
if(USES_LIST(mb_type, 1)){ if (USES_LIST(mb_type, 1))
write_back_motion_list(h, s, b_stride, b_xy, b8_xy, mb_type, 1); write_back_motion_list(h, s, b_stride, b_xy, b8_xy, mb_type, 1);
}
if (h->slice_type_nos == AV_PICTURE_TYPE_B && CABAC) { if (h->slice_type_nos == AV_PICTURE_TYPE_B && CABAC) {
if (IS_8X8(mb_type)) { if (IS_8X8(mb_type)) {
@ -888,11 +907,16 @@ static av_always_inline void write_back_motion(H264Context *h, int mb_type){
} }
} }
static av_always_inline int get_dct8x8_allowed(H264Context *h){ static av_always_inline int get_dct8x8_allowed(H264Context *h)
{
if (h->sps.direct_8x8_inference_flag) if (h->sps.direct_8x8_inference_flag)
return !(AV_RN64A(h->sub_mb_type) & ((MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_8x8 )*0x0001000100010001ULL)); return !(AV_RN64A(h->sub_mb_type) &
((MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_8x8) *
0x0001000100010001ULL));
else else
return !(AV_RN64A(h->sub_mb_type) & ((MB_TYPE_16x8|MB_TYPE_8x16|MB_TYPE_8x8|MB_TYPE_DIRECT2)*0x0001000100010001ULL)); return !(AV_RN64A(h->sub_mb_type) &
((MB_TYPE_16x8 | MB_TYPE_8x16 | MB_TYPE_8x8 | MB_TYPE_DIRECT2) *
0x0001000100010001ULL));
} }
#endif /* AVCODEC_H264_H */ #endif /* AVCODEC_H264_H */

View File

@ -35,14 +35,15 @@
//#undef NDEBUG //#undef NDEBUG
#include <assert.h> #include <assert.h>
static av_always_inline int fetch_diagonal_mv(H264Context *h, const int16_t **C, int i, int list, int part_width){ static av_always_inline int fetch_diagonal_mv(H264Context *h, const int16_t **C,
int i, int list, int part_width)
{
const int topright_ref = h->ref_cache[list][i - 8 + part_width]; const int topright_ref = h->ref_cache[list][i - 8 + part_width];
MpegEncContext *s = &h->s; MpegEncContext *s = &h->s;
/* there is no consistent mapping of mvs to neighboring locations that will /* there is no consistent mapping of mvs to neighboring locations that will
* make mbaff happy, so we can't move all this logic to fill_caches */ * make mbaff happy, so we can't move all this logic to fill_caches */
if (FRAME_MBAFF) { if (FRAME_MBAFF) {
#define SET_DIAG_MV(MV_OP, REF_OP, XY, Y4) \ #define SET_DIAG_MV(MV_OP, REF_OP, XY, Y4) \
const int xy = XY, y4 = Y4; \ const int xy = XY, y4 = Y4; \
const int mb_type = mb_types[xy + (y4 >> 2) * s->mb_stride]; \ const int mb_type = mb_types[xy + (y4 >> 2) * s->mb_stride]; \
@ -61,12 +62,11 @@ static av_always_inline int fetch_diagonal_mv(H264Context *h, const int16_t **C,
AV_ZERO32(h->mv_cache[list][scan8[0] - 2]); AV_ZERO32(h->mv_cache[list][scan8[0] - 2]);
*C = h->mv_cache[list][scan8[0] - 2]; *C = h->mv_cache[list][scan8[0] - 2];
if(!MB_FIELD if (!MB_FIELD && IS_INTERLACED(h->left_type[0])) {
&& IS_INTERLACED(h->left_type[0])){ SET_DIAG_MV(* 2, >> 1, h->left_mb_xy[0] + s->mb_stride,
SET_DIAG_MV(*2, >>1, h->left_mb_xy[0]+s->mb_stride, (s->mb_y&1)*2+(i>>5)); (s->mb_y & 1) * 2 + (i >> 5));
} }
if(MB_FIELD if (MB_FIELD && !IS_INTERLACED(h->left_type[0])) {
&& !IS_INTERLACED(h->left_type[0])){
// left shift will turn LIST_NOT_USED into PART_NOT_AVAILABLE, but that's OK. // left shift will turn LIST_NOT_USED into PART_NOT_AVAILABLE, but that's OK.
SET_DIAG_MV(/ 2, << 1, h->left_mb_xy[i >= 36], ((i >> 2)) & 3); SET_DIAG_MV(/ 2, << 1, h->left_mb_xy[i >= 36], ((i >> 2)) & 3);
} }
@ -92,7 +92,10 @@ static av_always_inline int fetch_diagonal_mv(H264Context *h, const int16_t **C,
* @param mx the x component of the predicted motion vector * @param mx the x component of the predicted motion vector
* @param my the y component of the predicted motion vector * @param my the y component of the predicted motion vector
*/ */
static av_always_inline void pred_motion(H264Context * const h, int n, int part_width, int list, int ref, int * const mx, int * const my){ static av_always_inline void pred_motion(H264Context *const h, int n,
int part_width, int list, int ref,
int *const mx, int *const my)
{
const int index8 = scan8[n]; const int index8 = scan8[n];
const int top_ref = h->ref_cache[list][index8 - 8]; const int top_ref = h->ref_cache[list][index8 - 8];
const int left_ref = h->ref_cache[list][index8 - 1]; const int left_ref = h->ref_cache[list][index8 - 1];
@ -104,11 +107,11 @@ static av_always_inline void pred_motion(H264Context * const h, int n, int part_
assert(part_width == 1 || part_width == 2 || part_width == 4); assert(part_width == 1 || part_width == 2 || part_width == 4);
/* mv_cache /* mv_cache
B . . A T T T T * B . . A T T T T
U . . L . . , . * U . . L . . , .
U . . L . . . . * U . . L . . . .
U . . L . . , . * U . . L . . , .
. . . L . . . . * . . . L . . . .
*/ */
diagonal_ref = fetch_diagonal_mv(h, &C, index8, list, part_width); diagonal_ref = fetch_diagonal_mv(h, &C, index8, list, part_width);
@ -129,7 +132,9 @@ static av_always_inline void pred_motion(H264Context * const h, int n, int part_
*my = C[1]; *my = C[1];
} }
} else { } else {
if(top_ref == PART_NOT_AVAILABLE && diagonal_ref == PART_NOT_AVAILABLE && left_ref != PART_NOT_AVAILABLE){ if (top_ref == PART_NOT_AVAILABLE &&
diagonal_ref == PART_NOT_AVAILABLE &&
left_ref != PART_NOT_AVAILABLE) {
*mx = A[0]; *mx = A[0];
*my = A[1]; *my = A[1];
} else { } else {
@ -138,7 +143,10 @@ static av_always_inline void pred_motion(H264Context * const h, int n, int part_
} }
} }
tprintf(h->s.avctx, "pred_motion (%2d %2d %2d) (%2d %2d %2d) (%2d %2d %2d) -> (%2d %2d %2d) at %2d %2d %d list %d\n", top_ref, B[0], B[1], diagonal_ref, C[0], C[1], left_ref, A[0], A[1], ref, *mx, *my, h->s.mb_x, h->s.mb_y, n, list); tprintf(h->s.avctx,
"pred_motion (%2d %2d %2d) (%2d %2d %2d) (%2d %2d %2d) -> (%2d %2d %2d) at %2d %2d %d list %d\n",
top_ref, B[0], B[1], diagonal_ref, C[0], C[1], left_ref,
A[0], A[1], ref, *mx, *my, h->s.mb_x, h->s.mb_y, n, list);
} }
/** /**
@ -147,12 +155,16 @@ static av_always_inline void pred_motion(H264Context * const h, int n, int part_
* @param mx the x component of the predicted motion vector * @param mx the x component of the predicted motion vector
* @param my the y component of the predicted motion vector * @param my the y component of the predicted motion vector
*/ */
static av_always_inline void pred_16x8_motion(H264Context * const h, int n, int list, int ref, int * const mx, int * const my){ static av_always_inline void pred_16x8_motion(H264Context *const h,
int n, int list, int ref,
int *const mx, int *const my)
{
if (n == 0) { if (n == 0) {
const int top_ref = h->ref_cache[list][scan8[0] - 8]; const int top_ref = h->ref_cache[list][scan8[0] - 8];
const int16_t *const B = h->mv_cache[list][scan8[0] - 8]; const int16_t *const B = h->mv_cache[list][scan8[0] - 8];
tprintf(h->s.avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", top_ref, B[0], B[1], h->s.mb_x, h->s.mb_y, n, list); tprintf(h->s.avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n",
top_ref, B[0], B[1], h->s.mb_x, h->s.mb_y, n, list);
if (top_ref == ref) { if (top_ref == ref) {
*mx = B[0]; *mx = B[0];
@ -163,7 +175,8 @@ static av_always_inline void pred_16x8_motion(H264Context * const h, int n, int
const int left_ref = h->ref_cache[list][scan8[8] - 1]; const int left_ref = h->ref_cache[list][scan8[8] - 1];
const int16_t *const A = h->mv_cache[list][scan8[8] - 1]; const int16_t *const A = h->mv_cache[list][scan8[8] - 1];
tprintf(h->s.avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n", left_ref, A[0], A[1], h->s.mb_x, h->s.mb_y, n, list); tprintf(h->s.avctx, "pred_16x8: (%2d %2d %2d) at %2d %2d %d list %d\n",
left_ref, A[0], A[1], h->s.mb_x, h->s.mb_y, n, list);
if (left_ref == ref) { if (left_ref == ref) {
*mx = A[0]; *mx = A[0];
@ -182,12 +195,16 @@ static av_always_inline void pred_16x8_motion(H264Context * const h, int n, int
* @param mx the x component of the predicted motion vector * @param mx the x component of the predicted motion vector
* @param my the y component of the predicted motion vector * @param my the y component of the predicted motion vector
*/ */
static av_always_inline void pred_8x16_motion(H264Context * const h, int n, int list, int ref, int * const mx, int * const my){ static av_always_inline void pred_8x16_motion(H264Context *const h,
int n, int list, int ref,
int *const mx, int *const my)
{
if (n == 0) { if (n == 0) {
const int left_ref = h->ref_cache[list][scan8[0] - 1]; const int left_ref = h->ref_cache[list][scan8[0] - 1];
const int16_t *const A = h->mv_cache[list][scan8[0] - 1]; const int16_t *const A = h->mv_cache[list][scan8[0] - 1];
tprintf(h->s.avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", left_ref, A[0], A[1], h->s.mb_x, h->s.mb_y, n, list); tprintf(h->s.avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n",
left_ref, A[0], A[1], h->s.mb_x, h->s.mb_y, n, list);
if (left_ref == ref) { if (left_ref == ref) {
*mx = A[0]; *mx = A[0];
@ -200,7 +217,8 @@ static av_always_inline void pred_8x16_motion(H264Context * const h, int n, int
diagonal_ref = fetch_diagonal_mv(h, &C, scan8[4], list, 2); diagonal_ref = fetch_diagonal_mv(h, &C, scan8[4], list, 2);
tprintf(h->s.avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n", diagonal_ref, C[0], C[1], h->s.mb_x, h->s.mb_y, n, list); tprintf(h->s.avctx, "pred_8x16: (%2d %2d %2d) at %2d %2d %d list %d\n",
diagonal_ref, C[0], C[1], h->s.mb_x, h->s.mb_y, n, list);
if (diagonal_ref == ref) { if (diagonal_ref == ref) {
*mx = C[0]; *mx = C[0];
@ -232,7 +250,8 @@ static av_always_inline void pred_8x16_motion(H264Context * const h, int n, int
} \ } \
} }
static av_always_inline void pred_pskip_motion(H264Context * const h){ static av_always_inline void pred_pskip_motion(H264Context *const h)
{
DECLARE_ALIGNED(4, static const int16_t, zeromv)[2] = { 0 }; DECLARE_ALIGNED(4, static const int16_t, zeromv)[2] = { 0 };
DECLARE_ALIGNED(4, int16_t, mvbuf)[3][2]; DECLARE_ALIGNED(4, int16_t, mvbuf)[3][2];
MpegEncContext *const s = &h->s; MpegEncContext *const s = &h->s;
@ -244,17 +263,17 @@ static av_always_inline void pred_pskip_motion(H264Context * const h){
fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1); fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, 0, 1);
/* To avoid doing an entire fill_decode_caches, we inline the relevant parts here. /* To avoid doing an entire fill_decode_caches, we inline the relevant
* FIXME: this is a partial duplicate of the logic in fill_decode_caches, but it's * parts here.
* faster this way. Is there a way to avoid this duplication? * FIXME: this is a partial duplicate of the logic in fill_decode_caches,
* but it's faster this way. Is there a way to avoid this duplication?
*/ */
if (USES_LIST(h->left_type[LTOP], 0)) { if (USES_LIST(h->left_type[LTOP], 0)) {
left_ref = ref[4 * h->left_mb_xy[LTOP] + 1 + (h->left_block[0] & ~1)]; left_ref = ref[4 * h->left_mb_xy[LTOP] + 1 + (h->left_block[0] & ~1)];
A = mv[h->mb2b_xy[h->left_mb_xy[LTOP]] + 3 + b_stride * h->left_block[0]]; A = mv[h->mb2b_xy[h->left_mb_xy[LTOP]] + 3 + b_stride * h->left_block[0]];
FIX_MV_MBAFF(h->left_type[LTOP], left_ref, A, 0); FIX_MV_MBAFF(h->left_type[LTOP], left_ref, A, 0);
if(!(left_ref | AV_RN32A(A))){ if (!(left_ref | AV_RN32A(A)))
goto zeromv; goto zeromv;
}
} else if (h->left_type[LTOP]) { } else if (h->left_type[LTOP]) {
left_ref = LIST_NOT_USED; left_ref = LIST_NOT_USED;
A = zeromv; A = zeromv;
@ -266,9 +285,8 @@ static av_always_inline void pred_pskip_motion(H264Context * const h){
top_ref = ref[4 * h->top_mb_xy + 2]; top_ref = ref[4 * h->top_mb_xy + 2];
B = mv[h->mb2b_xy[h->top_mb_xy] + 3 * b_stride]; B = mv[h->mb2b_xy[h->top_mb_xy] + 3 * b_stride];
FIX_MV_MBAFF(h->top_type, top_ref, B, 1); FIX_MV_MBAFF(h->top_type, top_ref, B, 1);
if(!(top_ref | AV_RN32A(B))){ if (!(top_ref | AV_RN32A(B)))
goto zeromv; goto zeromv;
}
} else if (h->top_type) { } else if (h->top_type) {
top_ref = LIST_NOT_USED; top_ref = LIST_NOT_USED;
B = zeromv; B = zeromv;
@ -276,7 +294,8 @@ static av_always_inline void pred_pskip_motion(H264Context * const h){
goto zeromv; goto zeromv;
} }
tprintf(h->s.avctx, "pred_pskip: (%d) (%d) at %2d %2d\n", top_ref, left_ref, h->s.mb_x, h->s.mb_y); tprintf(h->s.avctx, "pred_pskip: (%d) (%d) at %2d %2d\n",
top_ref, left_ref, h->s.mb_x, h->s.mb_y);
if (USES_LIST(h->topright_type, 0)) { if (USES_LIST(h->topright_type, 0)) {
diagonal_ref = ref[4 * h->topright_mb_xy + 2]; diagonal_ref = ref[4 * h->topright_mb_xy + 2];
@ -287,8 +306,10 @@ static av_always_inline void pred_pskip_motion(H264Context * const h){
C = zeromv; C = zeromv;
} else { } else {
if (USES_LIST(h->topleft_type, 0)) { if (USES_LIST(h->topleft_type, 0)) {
diagonal_ref = ref[4*h->topleft_mb_xy + 1 + (h->topleft_partition & 2)]; diagonal_ref = ref[4 * h->topleft_mb_xy + 1 +
C = mv[h->mb2b_xy[h->topleft_mb_xy] + 3 + b_stride + (h->topleft_partition & 2*b_stride)]; (h->topleft_partition & 2)];
C = mv[h->mb2b_xy[h->topleft_mb_xy] + 3 + b_stride +
(h->topleft_partition & 2 * b_stride)];
FIX_MV_MBAFF(h->topleft_type, diagonal_ref, C, 2); FIX_MV_MBAFF(h->topleft_type, diagonal_ref, C, 2);
} else if (h->topleft_type) { } else if (h->topleft_type) {
diagonal_ref = LIST_NOT_USED; diagonal_ref = LIST_NOT_USED;
@ -322,12 +343,14 @@ static av_always_inline void pred_pskip_motion(H264Context * const h){
fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx, my), 4); fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, pack16to32(mx, my), 4);
return; return;
zeromv: zeromv:
fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4); fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8, 0, 4);
return; return;
} }
static void fill_decode_neighbors(H264Context *h, int mb_type){ static void fill_decode_neighbors(H264Context *h, int mb_type)
{
MpegEncContext *const s = &h->s; MpegEncContext *const s = &h->s;
const int mb_xy = h->mb_xy; const int mb_xy = h->mb_xy;
int topleft_xy, top_xy, topright_xy, left_xy[LEFT_MBS]; int topleft_xy, top_xy, topright_xy, left_xy[LEFT_MBS];
@ -360,7 +383,8 @@ static void fill_decode_neighbors(H264Context *h, int mb_type){
h->left_block = left_block_options[3]; h->left_block = left_block_options[3];
} else { } else {
topleft_xy += s->mb_stride; topleft_xy += s->mb_stride;
// take top left mv from the middle of the mb, as opposed to all other modes which use the bottom right partition /* take top left mv from the middle of the mb, as opposed
* to all other modes which use the bottom right partition */
h->topleft_partition = 0; h->topleft_partition = 0;
h->left_block = left_block_options[1]; h->left_block = left_block_options[1];
} }
@ -396,20 +420,27 @@ static void fill_decode_neighbors(H264Context *h, int mb_type){
h->left_type[LBOT] = s->current_picture.f.mb_type[left_xy[LBOT]]; h->left_type[LBOT] = s->current_picture.f.mb_type[left_xy[LBOT]];
if (FMO) { if (FMO) {
if(h->slice_table[topleft_xy ] != h->slice_num) h->topleft_type = 0; if (h->slice_table[topleft_xy] != h->slice_num)
if(h->slice_table[top_xy ] != h->slice_num) h->top_type = 0; h->topleft_type = 0;
if(h->slice_table[left_xy[LTOP] ] != h->slice_num) h->left_type[LTOP] = h->left_type[LBOT] = 0; if (h->slice_table[top_xy] != h->slice_num)
h->top_type = 0;
if (h->slice_table[left_xy[LTOP]] != h->slice_num)
h->left_type[LTOP] = h->left_type[LBOT] = 0;
} else { } else {
if (h->slice_table[topleft_xy] != h->slice_num) { if (h->slice_table[topleft_xy] != h->slice_num) {
h->topleft_type = 0; h->topleft_type = 0;
if(h->slice_table[top_xy ] != h->slice_num) h->top_type = 0; if (h->slice_table[top_xy] != h->slice_num)
if(h->slice_table[left_xy[LTOP] ] != h->slice_num) h->left_type[LTOP] = h->left_type[LBOT] = 0; h->top_type = 0;
if (h->slice_table[left_xy[LTOP]] != h->slice_num)
h->left_type[LTOP] = h->left_type[LBOT] = 0;
} }
} }
if(h->slice_table[topright_xy] != h->slice_num) h->topright_type= 0; if (h->slice_table[topright_xy] != h->slice_num)
h->topright_type = 0;
} }
static void fill_decode_caches(H264Context *h, int mb_type){ static void fill_decode_caches(H264Context *h, int mb_type)
{
MpegEncContext *const s = &h->s; MpegEncContext *const s = &h->s;
int topleft_xy, top_xy, topright_xy, left_xy[LEFT_MBS]; int topleft_xy, top_xy, topright_xy, left_xy[LEFT_MBS];
int topleft_type, top_type, topright_type, left_type[LEFT_MBS]; int topleft_type, top_type, topright_type, left_type[LEFT_MBS];
@ -496,16 +527,16 @@ static void fill_decode_caches(H264Context *h, int mb_type){
} }
} }
/* /*
0 . T T. T T T T * 0 . T T. T T T T
1 L . .L . . . . * 1 L . .L . . . .
2 L . .L . . . . * 2 L . .L . . . .
3 . T TL . . . . * 3 . T TL . . . .
4 L . .L . . . . * 4 L . .L . . . .
5 L . .. . . . . * 5 L . .. . . . .
*/ */
//FIXME constraint_intra_pred & partitioning & nnz (let us hope this is just a typo in the spec) /* FIXME: constraint_intra_pred & partitioning & nnz
* (let us hope this is just a typo in the spec) */
nnz_cache = h->non_zero_count_cache; nnz_cache = h->non_zero_count_cache;
if (top_type) { if (top_type) {
nnz = h->non_zero_count[top_xy]; nnz = h->non_zero_count[top_xy];
@ -555,16 +586,15 @@ static void fill_decode_caches(H264Context *h, int mb_type){
if (CABAC) { if (CABAC) {
// top_cbp // top_cbp
if(top_type) { if (top_type)
h->top_cbp = h->cbp_table[top_xy]; h->top_cbp = h->cbp_table[top_xy];
} else { else
h->top_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F; h->top_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F;
}
// left_cbp // left_cbp
if (left_type[LTOP]) { if (left_type[LTOP]) {
h->left_cbp = (h->cbp_table[left_xy[LTOP]] & 0x7F0) h->left_cbp = (h->cbp_table[left_xy[LTOP]] & 0x7F0) |
| ((h->cbp_table[left_xy[LTOP]]>>(left_block[0]&(~1)))&2) ((h->cbp_table[left_xy[LTOP]] >> (left_block[0] & (~1))) & 2) |
| (((h->cbp_table[left_xy[LBOT]]>>(left_block[2]&(~1)))&2) << 2); (((h->cbp_table[left_xy[LBOT]] >> (left_block[2] & (~1))) & 2) << 2);
} else { } else {
h->left_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F; h->left_cbp = IS_INTRA(mb_type) ? 0x7CF : 0x00F;
} }
@ -579,9 +609,8 @@ static void fill_decode_caches(H264Context *h, int mb_type){
int8_t *ref = s->current_picture.f.ref_index[list]; int8_t *ref = s->current_picture.f.ref_index[list];
int16_t(*mv_cache)[2] = &h->mv_cache[list][scan8[0]]; int16_t(*mv_cache)[2] = &h->mv_cache[list][scan8[0]];
int16_t(*mv)[2] = s->current_picture.f.motion_val[list]; int16_t(*mv)[2] = s->current_picture.f.motion_val[list];
if(!USES_LIST(mb_type, list)){ if (!USES_LIST(mb_type, list))
continue; continue;
}
assert(!(IS_DIRECT(mb_type) && !h->direct_spatial_mv_pred)); assert(!(IS_DIRECT(mb_type) && !h->direct_spatial_mv_pred));
if (USES_LIST(top_type, list)) { if (USES_LIST(top_type, list)) {
@ -593,7 +622,8 @@ static void fill_decode_caches(H264Context *h, int mb_type){
ref_cache[3 - 1 * 8] = ref[4 * top_xy + 3]; ref_cache[3 - 1 * 8] = ref[4 * top_xy + 3];
} else { } else {
AV_ZERO128(mv_cache[0 - 1 * 8]); AV_ZERO128(mv_cache[0 - 1 * 8]);
AV_WN32A(&ref_cache[0 - 1*8], ((top_type ? LIST_NOT_USED : PART_NOT_AVAILABLE)&0xFF)*0x01010101u); AV_WN32A(&ref_cache[0 - 1 * 8],
((top_type ? LIST_NOT_USED : PART_NOT_AVAILABLE) & 0xFF) * 0x01010101u);
} }
if (mb_type & (MB_TYPE_16x8 | MB_TYPE_8x8)) { if (mb_type & (MB_TYPE_16x8 | MB_TYPE_8x8)) {
@ -602,15 +632,18 @@ static void fill_decode_caches(H264Context *h, int mb_type){
if (USES_LIST(left_type[LEFT(i)], list)) { if (USES_LIST(left_type[LEFT(i)], list)) {
const int b_xy = h->mb2b_xy[left_xy[LEFT(i)]] + 3; const int b_xy = h->mb2b_xy[left_xy[LEFT(i)]] + 3;
const int b8_xy = 4 * left_xy[LEFT(i)] + 1; const int b8_xy = 4 * left_xy[LEFT(i)] + 1;
AV_COPY32(mv_cache[cache_idx ], mv[b_xy + b_stride*left_block[0+i*2]]); AV_COPY32(mv_cache[cache_idx],
AV_COPY32(mv_cache[cache_idx+8], mv[b_xy + b_stride*left_block[1+i*2]]); mv[b_xy + b_stride * left_block[0 + i * 2]]);
AV_COPY32(mv_cache[cache_idx + 8],
mv[b_xy + b_stride * left_block[1 + i * 2]]);
ref_cache[cache_idx] = ref[b8_xy + (left_block[0 + i * 2] & ~1)]; ref_cache[cache_idx] = ref[b8_xy + (left_block[0 + i * 2] & ~1)];
ref_cache[cache_idx + 8] = ref[b8_xy + (left_block[1 + i * 2] & ~1)]; ref_cache[cache_idx + 8] = ref[b8_xy + (left_block[1 + i * 2] & ~1)];
} else { } else {
AV_ZERO32(mv_cache[cache_idx]); AV_ZERO32(mv_cache[cache_idx]);
AV_ZERO32(mv_cache[cache_idx + 8]); AV_ZERO32(mv_cache[cache_idx + 8]);
ref_cache[cache_idx] = ref_cache[cache_idx] =
ref_cache[cache_idx+8]= (left_type[LEFT(i)]) ? LIST_NOT_USED : PART_NOT_AVAILABLE; ref_cache[cache_idx + 8] = (left_type[LEFT(i)]) ? LIST_NOT_USED
: PART_NOT_AVAILABLE;
} }
} }
} else { } else {
@ -621,7 +654,8 @@ static void fill_decode_caches(H264Context *h, int mb_type){
ref_cache[-1] = ref[b8_xy + (left_block[0] & ~1)]; ref_cache[-1] = ref[b8_xy + (left_block[0] & ~1)];
} else { } else {
AV_ZERO32(mv_cache[-1]); AV_ZERO32(mv_cache[-1]);
ref_cache[-1]= left_type[LTOP] ? LIST_NOT_USED : PART_NOT_AVAILABLE; ref_cache[-1] = left_type[LTOP] ? LIST_NOT_USED
: PART_NOT_AVAILABLE;
} }
} }
@ -631,17 +665,20 @@ static void fill_decode_caches(H264Context *h, int mb_type){
ref_cache[4 - 1 * 8] = ref[4 * topright_xy + 2]; ref_cache[4 - 1 * 8] = ref[4 * topright_xy + 2];
} else { } else {
AV_ZERO32(mv_cache[4 - 1 * 8]); AV_ZERO32(mv_cache[4 - 1 * 8]);
ref_cache[4 - 1*8]= topright_type ? LIST_NOT_USED : PART_NOT_AVAILABLE; ref_cache[4 - 1 * 8] = topright_type ? LIST_NOT_USED
: PART_NOT_AVAILABLE;
} }
if(ref_cache[2 - 1*8] < 0 || ref_cache[4 - 1*8] < 0){ if(ref_cache[2 - 1*8] < 0 || ref_cache[4 - 1*8] < 0){
if (USES_LIST(topleft_type, list)) { if (USES_LIST(topleft_type, list)) {
const int b_xy = h->mb2b_xy[topleft_xy] + 3 + b_stride + (h->topleft_partition & 2*b_stride); const int b_xy = h->mb2b_xy[topleft_xy] + 3 + b_stride +
(h->topleft_partition & 2 * b_stride);
const int b8_xy = 4 * topleft_xy + 1 + (h->topleft_partition & 2); const int b8_xy = 4 * topleft_xy + 1 + (h->topleft_partition & 2);
AV_COPY32(mv_cache[-1 - 1 * 8], mv[b_xy]); AV_COPY32(mv_cache[-1 - 1 * 8], mv[b_xy]);
ref_cache[-1 - 1 * 8] = ref[b8_xy]; ref_cache[-1 - 1 * 8] = ref[b8_xy];
} else { } else {
AV_ZERO32(mv_cache[-1 - 1 * 8]); AV_ZERO32(mv_cache[-1 - 1 * 8]);
ref_cache[-1 - 1*8]= topleft_type ? LIST_NOT_USED : PART_NOT_AVAILABLE; ref_cache[-1 - 1 * 8] = topleft_type ? LIST_NOT_USED
: PART_NOT_AVAILABLE;
} }
} }
@ -687,13 +724,15 @@ static void fill_decode_caches(H264Context *h, int mb_type){
fill_rectangle(direct_cache, 4, 4, 8, MB_TYPE_16x16 >> 1, 1); fill_rectangle(direct_cache, 4, 4, 8, MB_TYPE_16x16 >> 1, 1);
if (IS_DIRECT(top_type)) { if (IS_DIRECT(top_type)) {
AV_WN32A(&direct_cache[-1*8], 0x01010101u*(MB_TYPE_DIRECT2>>1)); AV_WN32A(&direct_cache[-1 * 8],
0x01010101u * (MB_TYPE_DIRECT2 >> 1));
} else if (IS_8X8(top_type)) { } else if (IS_8X8(top_type)) {
int b8_xy = 4 * top_xy; int b8_xy = 4 * top_xy;
direct_cache[0 - 1 * 8] = direct_table[b8_xy + 2]; direct_cache[0 - 1 * 8] = direct_table[b8_xy + 2];
direct_cache[2 - 1 * 8] = direct_table[b8_xy + 3]; direct_cache[2 - 1 * 8] = direct_table[b8_xy + 3];
} else { } else {
AV_WN32A(&direct_cache[-1*8], 0x01010101*(MB_TYPE_16x16>>1)); AV_WN32A(&direct_cache[-1 * 8],
0x01010101 * (MB_TYPE_16x16 >> 1));
} }
if (IS_DIRECT(left_type[LTOP])) if (IS_DIRECT(left_type[LTOP]))
@ -712,7 +751,7 @@ static void fill_decode_caches(H264Context *h, int mb_type){
} }
} }
} }
if(FRAME_MBAFF){
#define MAP_MVS \ #define MAP_MVS \
MAP_F2F(scan8[0] - 1 - 1 * 8, topleft_type) \ MAP_F2F(scan8[0] - 1 - 1 * 8, topleft_type) \
MAP_F2F(scan8[0] + 0 - 1 * 8, top_type) \ MAP_F2F(scan8[0] + 0 - 1 * 8, top_type) \
@ -724,22 +763,28 @@ static void fill_decode_caches(H264Context *h, int mb_type){
MAP_F2F(scan8[0] - 1 + 1 * 8, left_type[LTOP]) \ MAP_F2F(scan8[0] - 1 + 1 * 8, left_type[LTOP]) \
MAP_F2F(scan8[0] - 1 + 2 * 8, left_type[LBOT]) \ MAP_F2F(scan8[0] - 1 + 2 * 8, left_type[LBOT]) \
MAP_F2F(scan8[0] - 1 + 3 * 8, left_type[LBOT]) MAP_F2F(scan8[0] - 1 + 3 * 8, left_type[LBOT])
if (FRAME_MBAFF) {
if (MB_FIELD) { if (MB_FIELD) {
#define MAP_F2F(idx, mb_type) \ #define MAP_F2F(idx, mb_type) \
if (!IS_INTERLACED(mb_type) && h->ref_cache[list][idx] >= 0) { \ if (!IS_INTERLACED(mb_type) && h->ref_cache[list][idx] >= 0) { \
h->ref_cache[list][idx] <<= 1; \ h->ref_cache[list][idx] <<= 1; \
h->mv_cache[list][idx][1] /= 2; \ h->mv_cache[list][idx][1] /= 2; \
h->mvd_cache[list][idx][1] >>= 1; \ h->mvd_cache[list][idx][1] >>= 1; \
} }
MAP_MVS MAP_MVS
#undef MAP_F2F
} else { } else {
#undef MAP_F2F
#define MAP_F2F(idx, mb_type) \ #define MAP_F2F(idx, mb_type) \
if (IS_INTERLACED(mb_type) && h->ref_cache[list][idx] >= 0) { \ if (IS_INTERLACED(mb_type) && h->ref_cache[list][idx] >= 0) { \
h->ref_cache[list][idx] >>= 1; \ h->ref_cache[list][idx] >>= 1; \
h->mv_cache[list][idx][1] <<= 1; \ h->mv_cache[list][idx][1] <<= 1; \
h->mvd_cache[list][idx][1] <<= 1; \ h->mvd_cache[list][idx][1] <<= 1; \
} }
MAP_MVS MAP_MVS
#undef MAP_F2F #undef MAP_F2F
} }
@ -753,7 +798,8 @@ static void fill_decode_caches(H264Context *h, int mb_type){
/** /**
* decodes a P_SKIP or B_SKIP macroblock * decodes a P_SKIP or B_SKIP macroblock
*/ */
static void av_unused decode_mb_skip(H264Context *h){ static void av_unused decode_mb_skip(H264Context *h)
{
MpegEncContext *const s = &h->s; MpegEncContext *const s = &h->s;
const int mb_xy = h->mb_xy; const int mb_xy = h->mb_xy;
int mb_type = 0; int mb_type = 0;
@ -763,8 +809,7 @@ static void av_unused decode_mb_skip(H264Context *h){
if (MB_FIELD) if (MB_FIELD)
mb_type |= MB_TYPE_INTERLACED; mb_type |= MB_TYPE_INTERLACED;
if( h->slice_type_nos == AV_PICTURE_TYPE_B ) if (h->slice_type_nos == AV_PICTURE_TYPE_B) {
{
// just for fill_caches. pred_direct_motion will set the real mb_type // just for fill_caches. pred_direct_motion will set the real mb_type
mb_type |= MB_TYPE_L0L1 | MB_TYPE_DIRECT2 | MB_TYPE_SKIP; mb_type |= MB_TYPE_L0L1 | MB_TYPE_DIRECT2 | MB_TYPE_SKIP;
if (h->direct_spatial_mv_pred) { if (h->direct_spatial_mv_pred) {
@ -773,9 +818,7 @@ static void av_unused decode_mb_skip(H264Context *h){
} }
ff_h264_pred_direct_motion(h, &mb_type); ff_h264_pred_direct_motion(h, &mb_type);
mb_type |= MB_TYPE_SKIP; mb_type |= MB_TYPE_SKIP;
} } else {
else
{
mb_type |= MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_SKIP; mb_type |= MB_TYPE_16x16 | MB_TYPE_P0L0 | MB_TYPE_P1L0 | MB_TYPE_SKIP;
fill_decode_neighbors(h, mb_type); fill_decode_neighbors(h, mb_type);

View File

@ -30,13 +30,15 @@
#define AVCODEC_H264DATA_H #define AVCODEC_H264DATA_H
#include <stdint.h> #include <stdint.h>
#include "libavutil/rational.h" #include "libavutil/rational.h"
#include "mpegvideo.h" #include "mpegvideo.h"
#include "h264.h" #include "h264.h"
static const uint8_t golomb_to_pict_type[5] = {
static const uint8_t golomb_to_pict_type[5]= AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, AV_PICTURE_TYPE_I,
{AV_PICTURE_TYPE_P, AV_PICTURE_TYPE_B, AV_PICTURE_TYPE_I, AV_PICTURE_TYPE_SP, AV_PICTURE_TYPE_SI}; AV_PICTURE_TYPE_SP, AV_PICTURE_TYPE_SI
};
static const uint8_t golomb_to_intra4x4_cbp[48] = { static const uint8_t golomb_to_intra4x4_cbp[48] = {
47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46, 47, 31, 15, 0, 23, 27, 29, 30, 7, 11, 13, 14, 39, 43, 45, 46,
@ -257,6 +259,7 @@ static const uint8_t dequant4_coeff_init[6][3]={
static const uint8_t dequant8_coeff_init_scan[16] = { static const uint8_t dequant8_coeff_init_scan[16] = {
0, 3, 4, 3, 3, 1, 5, 1, 4, 5, 2, 5, 3, 1, 5, 1 0, 3, 4, 3, 3, 1, 5, 1, 4, 5, 2, 5, 3, 1, 5, 1
}; };
static const uint8_t dequant8_coeff_init[6][6] = { static const uint8_t dequant8_coeff_init[6][6] = {
{ 20, 18, 32, 19, 25, 24 }, { 20, 18, 32, 19, 25, 24 },
{ 22, 19, 35, 21, 28, 26 }, { 22, 19, 35, 21, 28, 26 },

View File

@ -28,12 +28,14 @@
#define AVCODEC_H264DSP_H #define AVCODEC_H264DSP_H
#include <stdint.h> #include <stdint.h>
#include "dsputil.h" #include "dsputil.h"
typedef void (*h264_weight_func)(uint8_t *block, int stride, int height, typedef void (*h264_weight_func)(uint8_t *block, int stride, int height,
int log2_denom, int weight, int offset); int log2_denom, int weight, int offset);
typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src, int stride, int height, typedef void (*h264_biweight_func)(uint8_t *dst, uint8_t *src,
int log2_denom, int weightd, int weights, int offset); int stride, int height, int log2_denom,
int weightd, int weights, int offset);
/** /**
* Context for storing H.264 DSP functions * Context for storing H.264 DSP functions
@ -44,40 +46,72 @@ typedef struct H264DSPContext{
h264_biweight_func biweight_h264_pixels_tab[4]; h264_biweight_func biweight_h264_pixels_tab[4];
/* loop filter */ /* loop filter */
void (*h264_v_loop_filter_luma)(uint8_t *pix/*align 16*/, int stride, int alpha, int beta, int8_t *tc0); void (*h264_v_loop_filter_luma)(uint8_t *pix /*align 16*/, int stride,
void (*h264_h_loop_filter_luma)(uint8_t *pix/*align 4 */, int stride, int alpha, int beta, int8_t *tc0); int alpha, int beta, int8_t *tc0);
void (*h264_h_loop_filter_luma_mbaff)(uint8_t *pix/*align 16*/, int stride, int alpha, int beta, int8_t *tc0); void (*h264_h_loop_filter_luma)(uint8_t *pix /*align 4 */, int stride,
int alpha, int beta, int8_t *tc0);
void (*h264_h_loop_filter_luma_mbaff)(uint8_t *pix /*align 16*/, int stride,
int alpha, int beta, int8_t *tc0);
/* v/h_loop_filter_luma_intra: align 16 */ /* v/h_loop_filter_luma_intra: align 16 */
void (*h264_v_loop_filter_luma_intra)(uint8_t *pix, int stride, int alpha, int beta); void (*h264_v_loop_filter_luma_intra)(uint8_t *pix, int stride,
void (*h264_h_loop_filter_luma_intra)(uint8_t *pix, int stride, int alpha, int beta); int alpha, int beta);
void (*h264_h_loop_filter_luma_mbaff_intra)(uint8_t *pix/*align 16*/, int stride, int alpha, int beta); void (*h264_h_loop_filter_luma_intra)(uint8_t *pix, int stride,
void (*h264_v_loop_filter_chroma)(uint8_t *pix/*align 8*/, int stride, int alpha, int beta, int8_t *tc0); int alpha, int beta);
void (*h264_h_loop_filter_chroma)(uint8_t *pix/*align 4*/, int stride, int alpha, int beta, int8_t *tc0); void (*h264_h_loop_filter_luma_mbaff_intra)(uint8_t *pix /*align 16*/,
void (*h264_h_loop_filter_chroma_mbaff)(uint8_t *pix/*align 8*/, int stride, int alpha, int beta, int8_t *tc0); int stride, int alpha, int beta);
void (*h264_v_loop_filter_chroma_intra)(uint8_t *pix/*align 8*/, int stride, int alpha, int beta); void (*h264_v_loop_filter_chroma)(uint8_t *pix /*align 8*/, int stride,
void (*h264_h_loop_filter_chroma_intra)(uint8_t *pix/*align 8*/, int stride, int alpha, int beta); int alpha, int beta, int8_t *tc0);
void (*h264_h_loop_filter_chroma_mbaff_intra)(uint8_t *pix/*align 8*/, int stride, int alpha, int beta); void (*h264_h_loop_filter_chroma)(uint8_t *pix /*align 4*/, int stride,
int alpha, int beta, int8_t *tc0);
void (*h264_h_loop_filter_chroma_mbaff)(uint8_t *pix /*align 8*/,
int stride, int alpha, int beta,
int8_t *tc0);
void (*h264_v_loop_filter_chroma_intra)(uint8_t *pix /*align 8*/,
int stride, int alpha, int beta);
void (*h264_h_loop_filter_chroma_intra)(uint8_t *pix /*align 8*/,
int stride, int alpha, int beta);
void (*h264_h_loop_filter_chroma_mbaff_intra)(uint8_t *pix /*align 8*/,
int stride, int alpha, int beta);
// h264_loop_filter_strength: simd only. the C version is inlined in h264.c // h264_loop_filter_strength: simd only. the C version is inlined in h264.c
void (*h264_loop_filter_strength)(int16_t bS[2][4][4], uint8_t nnz[40], int8_t ref[2][40], int16_t mv[2][40][2], void (*h264_loop_filter_strength)(int16_t bS[2][4][4], uint8_t nnz[40],
int bidir, int edges, int step, int mask_mv0, int mask_mv1, int field); int8_t ref[2][40], int16_t mv[2][40][2],
int bidir, int edges, int step,
int mask_mv0, int mask_mv1, int field);
/* IDCT */ /* IDCT */
void (*h264_idct_add)(uint8_t *dst/*align 4*/, DCTELEM *block/*align 16*/, int stride); void (*h264_idct_add)(uint8_t *dst /*align 4*/,
void (*h264_idct8_add)(uint8_t *dst/*align 8*/, DCTELEM *block/*align 16*/, int stride); DCTELEM *block /*align 16*/, int stride);
void (*h264_idct_dc_add)(uint8_t *dst/*align 4*/, DCTELEM *block/*align 16*/, int stride); void (*h264_idct8_add)(uint8_t *dst /*align 8*/,
void (*h264_idct8_dc_add)(uint8_t *dst/*align 8*/, DCTELEM *block/*align 16*/, int stride); DCTELEM *block /*align 16*/, int stride);
void (*h264_idct_dc_add)(uint8_t *dst /*align 4*/,
DCTELEM *block /*align 16*/, int stride);
void (*h264_idct8_dc_add)(uint8_t *dst /*align 8*/,
DCTELEM *block /*align 16*/, int stride);
void (*h264_idct_add16)(uint8_t *dst/*align 16*/, const int *blockoffset, DCTELEM *block/*align 16*/, int stride, const uint8_t nnzc[15*8]); void (*h264_idct_add16)(uint8_t *dst /*align 16*/, const int *blockoffset,
void (*h264_idct8_add4)(uint8_t *dst/*align 16*/, const int *blockoffset, DCTELEM *block/*align 16*/, int stride, const uint8_t nnzc[15*8]); DCTELEM *block /*align 16*/, int stride,
void (*h264_idct_add8)(uint8_t **dst/*align 16*/, const int *blockoffset, DCTELEM *block/*align 16*/, int stride, const uint8_t nnzc[15*8]); const uint8_t nnzc[15 * 8]);
void (*h264_idct_add16intra)(uint8_t *dst/*align 16*/, const int *blockoffset, DCTELEM *block/*align 16*/, int stride, const uint8_t nnzc[15*8]); void (*h264_idct8_add4)(uint8_t *dst /*align 16*/, const int *blockoffset,
void (*h264_luma_dc_dequant_idct)(DCTELEM *output, DCTELEM *input/*align 16*/, int qmul); DCTELEM *block /*align 16*/, int stride,
const uint8_t nnzc[15 * 8]);
void (*h264_idct_add8)(uint8_t **dst /*align 16*/, const int *blockoffset,
DCTELEM *block /*align 16*/, int stride,
const uint8_t nnzc[15 * 8]);
void (*h264_idct_add16intra)(uint8_t *dst /*align 16*/, const int *blockoffset,
DCTELEM *block /*align 16*/,
int stride, const uint8_t nnzc[15 * 8]);
void (*h264_luma_dc_dequant_idct)(DCTELEM *output,
DCTELEM *input /*align 16*/, int qmul);
void (*h264_chroma_dc_dequant_idct)(DCTELEM *block, int qmul); void (*h264_chroma_dc_dequant_idct)(DCTELEM *block, int qmul);
} H264DSPContext; } H264DSPContext;
void ff_h264dsp_init(H264DSPContext *c, const int bit_depth, const int chroma_format_idc); void ff_h264dsp_init(H264DSPContext *c, const int bit_depth,
void ff_h264dsp_init_arm(H264DSPContext *c, const int bit_depth, const int chroma_format_idc); const int chroma_format_idc);
void ff_h264dsp_init_ppc(H264DSPContext *c, const int bit_depth, const int chroma_format_idc); void ff_h264dsp_init_arm(H264DSPContext *c, const int bit_depth,
void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth, const int chroma_format_idc); const int chroma_format_idc);
void ff_h264dsp_init_ppc(H264DSPContext *c, const int bit_depth,
const int chroma_format_idc);
void ff_h264dsp_init_x86(H264DSPContext *c, const int bit_depth,
const int chroma_format_idc);
#endif /* AVCODEC_H264DSP_H */ #endif /* AVCODEC_H264DSP_H */

View File

@ -95,14 +95,23 @@ typedef struct H264PredContext{
void(*pred8x8[4 + 3 + 4])(uint8_t *src, int stride); void(*pred8x8[4 + 3 + 4])(uint8_t *src, int stride);
void(*pred16x16[4 + 3 + 2])(uint8_t *src, int stride); void(*pred16x16[4 + 3 + 2])(uint8_t *src, int stride);
void (*pred4x4_add [2])(uint8_t *pix/*align 4*/, const DCTELEM *block/*align 16*/, int stride); void(*pred4x4_add[2])(uint8_t *pix /*align 4*/,
void (*pred8x8l_add [2])(uint8_t *pix/*align 8*/, const DCTELEM *block/*align 16*/, int stride); const DCTELEM *block /*align 16*/, int stride);
void (*pred8x8_add [3])(uint8_t *pix/*align 8*/, const int *block_offset, const DCTELEM *block/*align 16*/, int stride); void(*pred8x8l_add[2])(uint8_t *pix /*align 8*/,
void (*pred16x16_add[3])(uint8_t *pix/*align 16*/, const int *block_offset, const DCTELEM *block/*align 16*/, int stride); const DCTELEM *block /*align 16*/, int stride);
void(*pred8x8_add[3])(uint8_t *pix /*align 8*/,
const int *block_offset,
const DCTELEM *block /*align 16*/, int stride);
void(*pred16x16_add[3])(uint8_t *pix /*align 16*/,
const int *block_offset,
const DCTELEM *block /*align 16*/, int stride);
} H264PredContext; } H264PredContext;
void ff_h264_pred_init(H264PredContext *h, int codec_id, const int bit_depth, const int chroma_format_idc); void ff_h264_pred_init(H264PredContext *h, int codec_id,
void ff_h264_pred_init_arm(H264PredContext *h, int codec_id, const int bit_depth, const int chroma_format_idc); const int bit_depth, const int chroma_format_idc);
void ff_h264_pred_init_x86(H264PredContext *h, int codec_id, const int bit_depth, const int chroma_format_idc); void ff_h264_pred_init_arm(H264PredContext *h, int codec_id,
const int bit_depth, const int chroma_format_idc);
void ff_h264_pred_init_x86(H264PredContext *h, int codec_id,
const int bit_depth, const int chroma_format_idc);
#endif /* AVCODEC_H264PRED_H */ #endif /* AVCODEC_H264PRED_H */

View File

@ -21,29 +21,47 @@
/** /**
* @file * @file
* ati vcr1 codec. * ATI VCR1 codec
*/ */
#include "avcodec.h" #include "avcodec.h"
#include "dsputil.h" #include "dsputil.h"
//#undef NDEBUG
//#include <assert.h>
/* Disable the encoder. */
#undef CONFIG_VCR1_ENCODER
#define CONFIG_VCR1_ENCODER 0
typedef struct VCR1Context { typedef struct VCR1Context {
AVCodecContext *avctx;
AVFrame picture; AVFrame picture;
int delta[16]; int delta[16];
int offset[4]; int offset[4];
} VCR1Context; } VCR1Context;
static int decode_frame(AVCodecContext *avctx, static av_cold void common_init(AVCodecContext *avctx)
void *data, int *data_size, {
AVPacket *avpkt) VCR1Context *const a = avctx->priv_data;
avctx->coded_frame = &a->picture;
avcodec_get_frame_defaults(&a->picture);
}
static av_cold int decode_init(AVCodecContext *avctx)
{
common_init(avctx);
avctx->pix_fmt = PIX_FMT_YUV410P;
return 0;
}
static av_cold int decode_end(AVCodecContext *avctx)
{
VCR1Context *s = avctx->priv_data;
if (s->picture.data[0])
avctx->release_buffer(avctx, &s->picture);
return 0;
}
static int decode_frame(AVCodecContext *avctx, void *data,
int *data_size, AVPacket *avpkt)
{ {
const uint8_t *buf = avpkt->data; const uint8_t *buf = avpkt->data;
int buf_size = avpkt->size; int buf_size = avpkt->size;
@ -70,7 +88,7 @@ static int decode_frame(AVCodecContext *avctx,
p->key_frame = 1; p->key_frame = 1;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
a->delta[i]= *(bytestream++); a->delta[i] = *bytestream++;
bytestream++; bytestream++;
} }
@ -83,18 +101,18 @@ static int decode_frame(AVCodecContext *avctx,
uint8_t *cr = &a->picture.data[2][(y >> 2) * a->picture.linesize[2]]; uint8_t *cr = &a->picture.data[2][(y >> 2) * a->picture.linesize[2]];
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
a->offset[i]= *(bytestream++); a->offset[i] = *bytestream++;
offset = a->offset[0] - a->delta[bytestream[2] & 0xF]; offset = a->offset[0] - a->delta[bytestream[2] & 0xF];
for (x = 0; x < avctx->width; x += 4) { for (x = 0; x < avctx->width; x += 4) {
luma[0]=( offset += a->delta[ bytestream[2]&0xF ]); luma[0] = offset += a->delta[bytestream[2] & 0xF];
luma[1]=( offset += a->delta[ bytestream[2]>>4 ]); luma[1] = offset += a->delta[bytestream[2] >> 4];
luma[2]=( offset += a->delta[ bytestream[0]&0xF ]); luma[2] = offset += a->delta[bytestream[0] & 0xF];
luma[3]=( offset += a->delta[ bytestream[0]>>4 ]); luma[3] = offset += a->delta[bytestream[0] >> 4];
luma += 4; luma += 4;
*(cb++) = bytestream[3]; *cb++ = bytestream[3];
*(cr++) = bytestream[1]; *cr++ = bytestream[1];
bytestream += 4; bytestream += 4;
} }
@ -102,14 +120,14 @@ static int decode_frame(AVCodecContext *avctx,
offset = a->offset[y & 3] - a->delta[bytestream[2] & 0xF]; offset = a->offset[y & 3] - a->delta[bytestream[2] & 0xF];
for (x = 0; x < avctx->width; x += 8) { for (x = 0; x < avctx->width; x += 8) {
luma[0]=( offset += a->delta[ bytestream[2]&0xF ]); luma[0] = offset += a->delta[bytestream[2] & 0xF];
luma[1]=( offset += a->delta[ bytestream[2]>>4 ]); luma[1] = offset += a->delta[bytestream[2] >> 4];
luma[2]=( offset += a->delta[ bytestream[3]&0xF ]); luma[2] = offset += a->delta[bytestream[3] & 0xF];
luma[3]=( offset += a->delta[ bytestream[3]>>4 ]); luma[3] = offset += a->delta[bytestream[3] >> 4];
luma[4]=( offset += a->delta[ bytestream[0]&0xF ]); luma[4] = offset += a->delta[bytestream[0] & 0xF];
luma[5]=( offset += a->delta[ bytestream[0]>>4 ]); luma[5] = offset += a->delta[bytestream[0] >> 4];
luma[6]=( offset += a->delta[ bytestream[1]&0xF ]); luma[6] = offset += a->delta[bytestream[1] & 0xF];
luma[7]=( offset += a->delta[ bytestream[1]>>4 ]); luma[7] = offset += a->delta[bytestream[1] >> 4];
luma += 8; luma += 8;
bytestream += 4; bytestream += 4;
} }
@ -122,8 +140,26 @@ static int decode_frame(AVCodecContext *avctx,
return buf_size; return buf_size;
} }
AVCodec ff_vcr1_decoder = {
.name = "vcr1",
.type = AVMEDIA_TYPE_VIDEO,
.id = CODEC_ID_VCR1,
.priv_data_size = sizeof(VCR1Context),
.init = decode_init,
.close = decode_end,
.decode = decode_frame,
.capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"),
};
/* Disable the encoder. */
#undef CONFIG_VCR1_ENCODER
#define CONFIG_VCR1_ENCODER 0
#if CONFIG_VCR1_ENCODER #if CONFIG_VCR1_ENCODER
static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ static int encode_frame(AVCodecContext *avctx, unsigned char *buf,
int buf_size, void *data)
{
VCR1Context *const a = avctx->priv_data; VCR1Context *const a = avctx->priv_data;
AVFrame *pict = data; AVFrame *pict = data;
AVFrame *const p = &a->picture; AVFrame *const p = &a->picture;
@ -141,63 +177,14 @@ static int encode_frame(AVCodecContext *avctx, unsigned char *buf, int buf_size,
return size * 4; return size * 4;
} }
#endif
static av_cold void common_init(AVCodecContext *avctx){
VCR1Context * const a = avctx->priv_data;
avctx->coded_frame = &a->picture;
avcodec_get_frame_defaults(&a->picture);
a->avctx= avctx;
}
static av_cold int decode_init(AVCodecContext *avctx){
common_init(avctx);
avctx->pix_fmt= PIX_FMT_YUV410P;
return 0;
}
static av_cold int decode_end(AVCodecContext *avctx){
VCR1Context *s = avctx->priv_data;
if (s->picture.data[0])
avctx->release_buffer(avctx, &s->picture);
return 0;
}
#if CONFIG_VCR1_ENCODER
static av_cold int encode_init(AVCodecContext *avctx){
common_init(avctx);
return 0;
}
#endif
AVCodec ff_vcr1_decoder = {
.name = "vcr1",
.type = AVMEDIA_TYPE_VIDEO,
.id = CODEC_ID_VCR1,
.priv_data_size = sizeof(VCR1Context),
.init = decode_init,
.close = decode_end,
.decode = decode_frame,
.capabilities = CODEC_CAP_DR1,
.long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"),
};
#if CONFIG_VCR1_ENCODER
AVCodec ff_vcr1_encoder = { AVCodec ff_vcr1_encoder = {
.name = "vcr1", .name = "vcr1",
.type = AVMEDIA_TYPE_VIDEO, .type = AVMEDIA_TYPE_VIDEO,
.id = CODEC_ID_VCR1, .id = CODEC_ID_VCR1,
.priv_data_size = sizeof(VCR1Context), .priv_data_size = sizeof(VCR1Context),
.init = encode_init, .init = common_init,
.encode = encode_frame, .encode = encode_frame,
.long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"), .long_name = NULL_IF_CONFIG_SMALL("ATI VCR1"),
}; };
#endif #endif /* CONFIG_VCR1_ENCODER */

View File

@ -1792,6 +1792,22 @@ QPEL_2TAP(avg_, 16, 3dnow)
QPEL_2TAP(put_, 8, 3dnow) QPEL_2TAP(put_, 8, 3dnow)
QPEL_2TAP(avg_, 8, 3dnow) QPEL_2TAP(avg_, 8, 3dnow)
void ff_put_rv40_qpel8_mc33_mmx(uint8_t *dst, uint8_t *src, int stride)
{
put_pixels8_xy2_mmx(dst, src, stride, 8);
}
void ff_put_rv40_qpel16_mc33_mmx(uint8_t *dst, uint8_t *src, int stride)
{
put_pixels16_xy2_mmx(dst, src, stride, 16);
}
void ff_avg_rv40_qpel8_mc33_mmx(uint8_t *dst, uint8_t *src, int stride)
{
avg_pixels8_xy2_mmx(dst, src, stride, 8);
}
void ff_avg_rv40_qpel16_mc33_mmx(uint8_t *dst, uint8_t *src, int stride)
{
avg_pixels16_xy2_mmx(dst, src, stride, 16);
}
#if HAVE_YASM #if HAVE_YASM
typedef void emu_edge_core_func(uint8_t *buf, const uint8_t *src, typedef void emu_edge_core_func(uint8_t *buf, const uint8_t *src,

View File

@ -199,6 +199,11 @@ void ff_avg_cavs_qpel16_mc00_mmx2(uint8_t *dst, uint8_t *src, int stride);
void ff_put_vc1_mspel_mc00_mmx(uint8_t *dst, const uint8_t *src, int stride, int rnd); void ff_put_vc1_mspel_mc00_mmx(uint8_t *dst, const uint8_t *src, int stride, int rnd);
void ff_avg_vc1_mspel_mc00_mmx2(uint8_t *dst, const uint8_t *src, int stride, int rnd); void ff_avg_vc1_mspel_mc00_mmx2(uint8_t *dst, const uint8_t *src, int stride, int rnd);
void ff_put_rv40_qpel8_mc33_mmx(uint8_t *block, uint8_t *pixels, int line_size);
void ff_put_rv40_qpel16_mc33_mmx(uint8_t *block, uint8_t *pixels, int line_size);
void ff_avg_rv40_qpel8_mc33_mmx(uint8_t *block, uint8_t *pixels, int line_size);
void ff_avg_rv40_qpel16_mc33_mmx(uint8_t *block, uint8_t *pixels, int line_size);
void ff_mmx_idct(DCTELEM *block); void ff_mmx_idct(DCTELEM *block);
void ff_mmxext_idct(DCTELEM *block); void ff_mmxext_idct(DCTELEM *block);

View File

@ -1,5 +1,7 @@
;****************************************************************************** ;******************************************************************************
;* MMX/SSE2-optimized functions for the RV40 decoder ;* MMX/SSE2-optimized functions for the RV40 decoder
;* Copyright (c) 2010 Ronald S. Bultje <rsbultje@gmail.com>
;* Copyright (c) 2010 Jason Garrett-Glaser <darkshikari@gmail.com>
;* Copyright (C) 2012 Christophe Gisquet <christophe.gisquet@gmail.com> ;* Copyright (C) 2012 Christophe Gisquet <christophe.gisquet@gmail.com>
;* ;*
;* This file is part of Libav. ;* This file is part of Libav.
@ -25,11 +27,319 @@
SECTION_RODATA SECTION_RODATA
align 16 align 16
shift_round: times 8 dw 1 << (16 - 6) pw_1024: times 8 dw 1 << (16 - 6) ; pw_1024
sixtap_filter_hb_m: times 8 db 1, -5
times 8 db 52, 20
; multiplied by 2 to have the same shift
times 8 db 2, -10
times 8 db 40, 40
; back to normal
times 8 db 1, -5
times 8 db 20, 52
sixtap_filter_v_m: times 8 dw 1
times 8 dw -5
times 8 dw 52
times 8 dw 20
; multiplied by 2 to have the same shift
times 8 dw 2
times 8 dw -10
times 8 dw 40
times 8 dw 40
; back to normal
times 8 dw 1
times 8 dw -5
times 8 dw 20
times 8 dw 52
%ifdef PIC
%define sixtap_filter_hw picregq
%define sixtap_filter_hb picregq
%define sixtap_filter_v picregq
%define npicregs 1
%else
%define sixtap_filter_hw sixtap_filter_hw_m
%define sixtap_filter_hb sixtap_filter_hb_m
%define sixtap_filter_v sixtap_filter_v_m
%define npicregs 0
%endif
filter_h6_shuf1: db 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8
filter_h6_shuf2: db 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10
filter_h6_shuf3: db 5, 4, 6, 5, 7, 6, 8, 7, 9, 8, 10, 9, 11, 10, 12, 11
cextern pw_32
cextern pw_16 cextern pw_16
cextern pw_512
SECTION .text SECTION .text
;-----------------------------------------------------------------------------
; subpel MC functions:
;
; void [put|rv40]_rv40_qpel_[h|v]_<opt>(uint8_t *dst, int deststride,
; uint8_t *src, int srcstride,
; int len, int m);
;----------------------------------------------------------------------
%macro LOAD 2
%if WIN64
movsxd %1q, %1d
%endif
%ifdef PIC
add %1q, picregq
%else
add %1q, %2
%endif
%endmacro
%macro STORE 3
%ifidn %3, avg
movh %2, [dstq]
%endif
packuswb %1, %1
%ifidn %3, avg
%if cpuflag(3dnow)
pavgusb %1, %2
%else
pavgb %1, %2
%endif
%endif
movh [dstq], %1
%endmacro
%macro FILTER_V 1
cglobal %1_rv40_qpel_v, 6,6+npicregs,12, dst, dststride, src, srcstride, height, my, picreg
%ifdef PIC
lea picregq, [sixtap_filter_v_m]
%endif
pxor m7, m7
LOAD my, sixtap_filter_v
; read 5 lines
sub srcq, srcstrideq
sub srcq, srcstrideq
movh m0, [srcq]
movh m1, [srcq+srcstrideq]
movh m2, [srcq+srcstrideq*2]
lea srcq, [srcq+srcstrideq*2]
add srcq, srcstrideq
movh m3, [srcq]
movh m4, [srcq+srcstrideq]
punpcklbw m0, m7
punpcklbw m1, m7
punpcklbw m2, m7
punpcklbw m3, m7
punpcklbw m4, m7
%ifdef m8
mova m8, [myq+ 0]
mova m9, [myq+16]
mova m10, [myq+32]
mova m11, [myq+48]
%define COEFF05 m8
%define COEFF14 m9
%define COEFF2 m10
%define COEFF3 m11
%else
%define COEFF05 [myq+ 0]
%define COEFF14 [myq+16]
%define COEFF2 [myq+32]
%define COEFF3 [myq+48]
%endif
.nextrow:
mova m6, m1
movh m5, [srcq+2*srcstrideq] ; read new row
paddw m6, m4
punpcklbw m5, m7
pmullw m6, COEFF14
paddw m0, m5
pmullw m0, COEFF05
paddw m6, m0
mova m0, m1
paddw m6, [pw_32]
mova m1, m2
pmullw m2, COEFF2
paddw m6, m2
mova m2, m3
pmullw m3, COEFF3
paddw m6, m3
; round/clip/store
mova m3, m4
psraw m6, 6
mova m4, m5
STORE m6, m5, %1
; go to next line
add dstq, dststrideq
add srcq, srcstrideq
dec heightd ; next row
jg .nextrow
REP_RET
%endmacro
%macro FILTER_H 1
cglobal %1_rv40_qpel_h, 6, 6+npicregs, 12, dst, dststride, src, srcstride, height, mx, picreg
%ifdef PIC
lea picregq, [sixtap_filter_v_m]
%endif
pxor m7, m7
LOAD mx, sixtap_filter_v
mova m6, [pw_32]
%ifdef m8
mova m8, [mxq+ 0]
mova m9, [mxq+16]
mova m10, [mxq+32]
mova m11, [mxq+48]
%define COEFF05 m8
%define COEFF14 m9
%define COEFF2 m10
%define COEFF3 m11
%else
%define COEFF05 [mxq+ 0]
%define COEFF14 [mxq+16]
%define COEFF2 [mxq+32]
%define COEFF3 [mxq+48]
%endif
.nextrow:
movq m0, [srcq-2]
movq m5, [srcq+3]
movq m1, [srcq-1]
movq m4, [srcq+2]
punpcklbw m0, m7
punpcklbw m5, m7
punpcklbw m1, m7
punpcklbw m4, m7
movq m2, [srcq-0]
movq m3, [srcq+1]
paddw m0, m5
paddw m1, m4
punpcklbw m2, m7
punpcklbw m3, m7
pmullw m0, COEFF05
pmullw m1, COEFF14
pmullw m2, COEFF2
pmullw m3, COEFF3
paddw m0, m6
paddw m1, m2
paddw m0, m3
paddw m0, m1
psraw m0, 6
STORE m0, m1, %1
; go to next line
add dstq, dststrideq
add srcq, srcstrideq
dec heightd ; next row
jg .nextrow
REP_RET
%endmacro
%if ARCH_X86_32
INIT_MMX mmx
FILTER_V put
FILTER_H put
INIT_MMX mmx2
FILTER_V avg
FILTER_H avg
INIT_MMX 3dnow
FILTER_V avg
FILTER_H avg
%endif
INIT_XMM sse2
FILTER_H put
FILTER_H avg
FILTER_V put
FILTER_V avg
%macro FILTER_SSSE3 1
cglobal %1_rv40_qpel_v, 6,6+npicregs,8, dst, dststride, src, srcstride, height, my, picreg
%ifdef PIC
lea picregq, [sixtap_filter_hb_m]
%endif
; read 5 lines
sub srcq, srcstrideq
LOAD my, sixtap_filter_hb
sub srcq, srcstrideq
movh m0, [srcq]
movh m1, [srcq+srcstrideq]
movh m2, [srcq+srcstrideq*2]
lea srcq, [srcq+srcstrideq*2]
add srcq, srcstrideq
mova m5, [myq]
movh m3, [srcq]
movh m4, [srcq+srcstrideq]
lea srcq, [srcq+2*srcstrideq]
.nextrow:
mova m6, m2
punpcklbw m0, m1
punpcklbw m6, m3
pmaddubsw m0, m5
pmaddubsw m6, [myq+16]
movh m7, [srcq] ; read new row
paddw m6, m0
mova m0, m1
mova m1, m2
mova m2, m3
mova m3, m4
mova m4, m7
punpcklbw m7, m3
pmaddubsw m7, m5
paddw m6, m7
pmulhrsw m6, [pw_512]
STORE m6, m7, %1
; go to next line
add dstq, dststrideq
add srcq, srcstrideq
dec heightd ; next row
jg .nextrow
REP_RET
cglobal %1_rv40_qpel_h, 6,6+npicregs,8, dst, dststride, src, srcstride, height, mx, picreg
%ifdef PIC
lea picregq, [sixtap_filter_hb_m]
%endif
mova m3, [filter_h6_shuf2]
mova m4, [filter_h6_shuf3]
LOAD mx, sixtap_filter_hb
mova m5, [mxq] ; set up 6tap filter in bytes
mova m6, [mxq+16]
mova m7, [filter_h6_shuf1]
.nextrow:
movu m0, [srcq-2]
mova m1, m0
mova m2, m0
pshufb m0, m7
pshufb m1, m3
pshufb m2, m4
pmaddubsw m0, m5
pmaddubsw m1, m6
pmaddubsw m2, m5
paddw m0, m1
paddw m0, m2
pmulhrsw m0, [pw_512]
STORE m0, m1, %1
; go to next line
add dstq, dststrideq
add srcq, srcstrideq
dec heightd ; next row
jg .nextrow
REP_RET
%endmacro
INIT_XMM ssse3
FILTER_SSSE3 put
FILTER_SSSE3 avg
; %1=5bits weights?, %2=dst %3=src1 %4=src3 %5=stride if sse2 ; %1=5bits weights?, %2=dst %3=src1 %4=src3 %5=stride if sse2
%macro RV40_WCORE 4-5 %macro RV40_WCORE 4-5
movh m4, [%3 + r6 + 0] movh m4, [%3 + r6 + 0]
@ -143,7 +453,7 @@ SECTION .text
%macro RV40_WEIGHT 3 %macro RV40_WEIGHT 3
cglobal rv40_weight_func_%1_%2, 6, 7, 8 cglobal rv40_weight_func_%1_%2, 6, 7, 8
%if cpuflag(ssse3) %if cpuflag(ssse3)
mova m1, [shift_round] mova m1, [pw_1024]
%else %else
mova m1, [pw_16] mova m1, [pw_16]
%endif %endif

View File

@ -22,8 +22,11 @@
/** /**
* @file * @file
* RV40 decoder motion compensation functions x86-optimised * RV40 decoder motion compensation functions x86-optimised
* 2,0 and 0,2 have h264 equivalents.
* 3,3 is bugged in the rv40 format and maps to _xy2 version
*/ */
#include "libavcodec/x86/dsputil_mmx.h"
#include "libavcodec/rv34dsp.h" #include "libavcodec/rv34dsp.h"
void ff_put_rv40_chroma_mc8_mmx (uint8_t *dst, uint8_t *src, void ff_put_rv40_chroma_mc8_mmx (uint8_t *dst, uint8_t *src,
@ -53,6 +56,132 @@ DECLARE_WEIGHT(mmx)
DECLARE_WEIGHT(sse2) DECLARE_WEIGHT(sse2)
DECLARE_WEIGHT(ssse3) DECLARE_WEIGHT(ssse3)
/** @{ */
/**
* Define one qpel function.
* LOOPSIZE must be already set to the number of pixels processed per
* iteration in the inner loop of the called functions.
* COFF(x) must be already defined so as to provide the offset into any
* array of coeffs used by the called function for the qpel position x.
*/
#define QPEL_FUNC_DECL(OP, SIZE, PH, PV, OPT) \
static void OP ## rv40_qpel ##SIZE ##_mc ##PH ##PV ##OPT(uint8_t *dst, \
uint8_t *src, \
int stride) \
{ \
int i; \
if (PH && PV) { \
DECLARE_ALIGNED(16, uint8_t, tmp)[SIZE * (SIZE + 5)]; \
uint8_t *tmpptr = tmp + SIZE * 2; \
src -= stride * 2; \
\
for (i = 0; i < SIZE; i += LOOPSIZE) \
ff_put_rv40_qpel_h ##OPT(tmp + i, SIZE, src + i, stride, \
SIZE + 5, HCOFF(PH)); \
for (i = 0; i < SIZE; i += LOOPSIZE) \
ff_ ##OP ##rv40_qpel_v ##OPT(dst + i, stride, tmpptr + i, \
SIZE, SIZE, VCOFF(PV)); \
} else if (PV) { \
for (i = 0; i < SIZE; i += LOOPSIZE) \
ff_ ##OP ##rv40_qpel_v ## OPT(dst + i, stride, src + i, \
stride, SIZE, VCOFF(PV)); \
} else { \
for (i = 0; i < SIZE; i += LOOPSIZE) \
ff_ ##OP ##rv40_qpel_h ## OPT(dst + i, stride, src + i, \
stride, SIZE, HCOFF(PH)); \
} \
};
/** Declare functions for sizes 8 and 16 and given operations
* and qpel position. */
#define QPEL_FUNCS_DECL(OP, PH, PV, OPT) \
QPEL_FUNC_DECL(OP, 8, PH, PV, OPT) \
QPEL_FUNC_DECL(OP, 16, PH, PV, OPT)
/** Declare all functions for all sizes and qpel positions */
#define QPEL_MC_DECL(OP, OPT) \
void ff_ ##OP ##rv40_qpel_h ##OPT(uint8_t *dst, ptrdiff_t dstStride, \
const uint8_t *src, \
ptrdiff_t srcStride, \
int len, int m); \
void ff_ ##OP ##rv40_qpel_v ##OPT(uint8_t *dst, ptrdiff_t dstStride, \
const uint8_t *src, \
ptrdiff_t srcStride, \
int len, int m); \
QPEL_FUNCS_DECL(OP, 0, 1, OPT) \
QPEL_FUNCS_DECL(OP, 0, 3, OPT) \
QPEL_FUNCS_DECL(OP, 1, 0, OPT) \
QPEL_FUNCS_DECL(OP, 1, 1, OPT) \
QPEL_FUNCS_DECL(OP, 1, 2, OPT) \
QPEL_FUNCS_DECL(OP, 1, 3, OPT) \
QPEL_FUNCS_DECL(OP, 2, 1, OPT) \
QPEL_FUNCS_DECL(OP, 2, 2, OPT) \
QPEL_FUNCS_DECL(OP, 2, 3, OPT) \
QPEL_FUNCS_DECL(OP, 3, 0, OPT) \
QPEL_FUNCS_DECL(OP, 3, 1, OPT) \
QPEL_FUNCS_DECL(OP, 3, 2, OPT)
/** @} */
#define LOOPSIZE 8
#define HCOFF(x) (32 * (x - 1))
#define VCOFF(x) (32 * (x - 1))
QPEL_MC_DECL(put_, _ssse3)
QPEL_MC_DECL(avg_, _ssse3)
#undef LOOPSIZE
#undef HCOFF
#undef VCOFF
#define LOOPSIZE 8
#define HCOFF(x) (64 * (x - 1))
#define VCOFF(x) (64 * (x - 1))
QPEL_MC_DECL(put_, _sse2)
QPEL_MC_DECL(avg_, _sse2)
#if ARCH_X86_32
#undef LOOPSIZE
#undef HCOFF
#undef VCOFF
#define LOOPSIZE 4
#define HCOFF(x) (64 * (x - 1))
#define VCOFF(x) (64 * (x - 1))
QPEL_MC_DECL(put_, _mmx)
#define ff_put_rv40_qpel_h_mmx2 ff_put_rv40_qpel_h_mmx
#define ff_put_rv40_qpel_v_mmx2 ff_put_rv40_qpel_v_mmx
QPEL_MC_DECL(avg_, _mmx2)
#define ff_put_rv40_qpel_h_3dnow ff_put_rv40_qpel_h_mmx
#define ff_put_rv40_qpel_v_3dnow ff_put_rv40_qpel_v_mmx
QPEL_MC_DECL(avg_, _3dnow)
#endif
/** @{ */
/** Set one function */
#define QPEL_FUNC_SET(OP, SIZE, PH, PV, OPT) \
c-> OP ## pixels_tab[2 - SIZE / 8][4 * PV + PH] = OP ## rv40_qpel ##SIZE ## _mc ##PH ##PV ##OPT;
/** Set functions put and avg for sizes 8 and 16 and a given qpel position */
#define QPEL_FUNCS_SET(OP, PH, PV, OPT) \
QPEL_FUNC_SET(OP, 8, PH, PV, OPT) \
QPEL_FUNC_SET(OP, 16, PH, PV, OPT)
/** Set all functions for all sizes and qpel positions */
#define QPEL_MC_SET(OP, OPT) \
QPEL_FUNCS_SET (OP, 0, 1, OPT) \
QPEL_FUNCS_SET (OP, 0, 3, OPT) \
QPEL_FUNCS_SET (OP, 1, 0, OPT) \
QPEL_FUNCS_SET (OP, 1, 1, OPT) \
QPEL_FUNCS_SET (OP, 1, 2, OPT) \
QPEL_FUNCS_SET (OP, 1, 3, OPT) \
QPEL_FUNCS_SET (OP, 2, 1, OPT) \
QPEL_FUNCS_SET (OP, 2, 2, OPT) \
QPEL_FUNCS_SET (OP, 2, 3, OPT) \
QPEL_FUNCS_SET (OP, 3, 0, OPT) \
QPEL_FUNCS_SET (OP, 3, 1, OPT) \
QPEL_FUNCS_SET (OP, 3, 2, OPT)
/** @} */
void ff_rv40dsp_init_x86(RV34DSPContext *c, DSPContext *dsp) void ff_rv40dsp_init_x86(RV34DSPContext *c, DSPContext *dsp)
{ {
#if HAVE_YASM #if HAVE_YASM
@ -65,25 +194,42 @@ void ff_rv40dsp_init_x86(RV34DSPContext *c, DSPContext *dsp)
c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_mmx; c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_mmx;
c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_mmx; c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_mmx;
c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_mmx; c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_mmx;
c->put_pixels_tab[0][15] = ff_put_rv40_qpel16_mc33_mmx;
c->put_pixels_tab[1][15] = ff_put_rv40_qpel8_mc33_mmx;
c->avg_pixels_tab[0][15] = ff_avg_rv40_qpel16_mc33_mmx;
c->avg_pixels_tab[1][15] = ff_avg_rv40_qpel8_mc33_mmx;
#if ARCH_X86_32
QPEL_MC_SET(put_, _mmx)
#endif
} }
if (mm_flags & AV_CPU_FLAG_MMX2) { if (mm_flags & AV_CPU_FLAG_MMX2) {
c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_mmx2; c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_mmx2;
c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_mmx2; c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_mmx2;
#if ARCH_X86_32
QPEL_MC_SET(avg_, _mmx2)
#endif
} else if (mm_flags & AV_CPU_FLAG_3DNOW) { } else if (mm_flags & AV_CPU_FLAG_3DNOW) {
c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_3dnow; c->avg_chroma_pixels_tab[0] = ff_avg_rv40_chroma_mc8_3dnow;
c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_3dnow; c->avg_chroma_pixels_tab[1] = ff_avg_rv40_chroma_mc4_3dnow;
#if ARCH_X86_32
QPEL_MC_SET(avg_, _3dnow)
#endif
} }
if (mm_flags & AV_CPU_FLAG_SSE2) { if (mm_flags & AV_CPU_FLAG_SSE2) {
c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_sse2; c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_sse2;
c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_sse2; c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_sse2;
c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_sse2; c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_sse2;
c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_sse2; c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_sse2;
QPEL_MC_SET(put_, _sse2)
QPEL_MC_SET(avg_, _sse2)
} }
if (mm_flags & AV_CPU_FLAG_SSSE3) { if (mm_flags & AV_CPU_FLAG_SSSE3) {
c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_ssse3; c->rv40_weight_pixels_tab[0][0] = ff_rv40_weight_func_rnd_16_ssse3;
c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_ssse3; c->rv40_weight_pixels_tab[0][1] = ff_rv40_weight_func_rnd_8_ssse3;
c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_ssse3; c->rv40_weight_pixels_tab[1][0] = ff_rv40_weight_func_nornd_16_ssse3;
c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_ssse3; c->rv40_weight_pixels_tab[1][1] = ff_rv40_weight_func_nornd_8_ssse3;
QPEL_MC_SET(put_, _ssse3)
QPEL_MC_SET(avg_, _ssse3)
} }
#endif #endif
} }

View File

@ -21,6 +21,7 @@ HEADERS = asrc_abuffer.h \
vsrc_buffer.h \ vsrc_buffer.h \
OBJS = allfilters.o \ OBJS = allfilters.o \
audio.o \
avfilter.o \ avfilter.o \
avfiltergraph.o \ avfiltergraph.o \
buffersink.o \ buffersink.o \

View File

@ -144,7 +144,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref
AConvertContext *aconvert = inlink->dst->priv; AConvertContext *aconvert = inlink->dst->priv;
const int n = insamplesref->audio->nb_samples; const int n = insamplesref->audio->nb_samples;
AVFilterLink *const outlink = inlink->dst->outputs[0]; AVFilterLink *const outlink = inlink->dst->outputs[0];
AVFilterBufferRef *outsamplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, n); AVFilterBufferRef *outsamplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n);
swr_convert(aconvert->swr, outsamplesref->data, n, swr_convert(aconvert->swr, outsamplesref->data, n,
(void *)insamplesref->data, n); (void *)insamplesref->data, n);
@ -153,7 +153,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref
outsamplesref->audio->channel_layout = outlink->channel_layout; outsamplesref->audio->channel_layout = outlink->channel_layout;
outsamplesref->audio->planar = outlink->planar; outsamplesref->audio->planar = outlink->planar;
avfilter_filter_samples(outlink, outsamplesref); ff_filter_samples(outlink, outsamplesref);
avfilter_unref_buffer(insamplesref); avfilter_unref_buffer(insamplesref);
} }

View File

@ -89,7 +89,7 @@ static int query_formats(AVFilterContext *ctx)
static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref) static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref)
{ {
avfilter_filter_samples(inlink->dst->outputs[0], insamplesref); ff_filter_samples(inlink->dst->outputs[0], insamplesref);
} }
AVFilter avfilter_af_aformat = { AVFilter avfilter_af_aformat = {

View File

@ -208,7 +208,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
nb_samples = FFMIN(am->queue[0].nb_samples, nb_samples = FFMIN(am->queue[0].nb_samples,
am->queue[1].nb_samples); am->queue[1].nb_samples);
outbuf = avfilter_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE, outbuf = ff_get_audio_buffer(ctx->outputs[0], AV_PERM_WRITE,
nb_samples); nb_samples);
outs = outbuf->data[0]; outs = outbuf->data[0];
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
@ -264,7 +264,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
am->queue[i].nb_buf * sizeof(**inbuf)); am->queue[i].nb_buf * sizeof(**inbuf));
} }
} }
avfilter_filter_samples(ctx->outputs[0], outbuf); ff_filter_samples(ctx->outputs[0], outbuf);
} }
AVFilter avfilter_af_amerge = { AVFilter avfilter_af_amerge = {

View File

@ -21,6 +21,7 @@
* null audio filter * null audio filter
*/ */
#include "audio.h"
#include "avfilter.h" #include "avfilter.h"
AVFilter avfilter_af_anull = { AVFilter avfilter_af_anull = {
@ -31,8 +32,8 @@ AVFilter avfilter_af_anull = {
.inputs = (const AVFilterPad[]) {{ .name = "default", .inputs = (const AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_AUDIO, .type = AVMEDIA_TYPE_AUDIO,
.get_audio_buffer = avfilter_null_get_audio_buffer, .get_audio_buffer = ff_null_get_audio_buffer,
.filter_samples = avfilter_null_filter_samples }, .filter_samples = ff_null_filter_samples },
{ .name = NULL}}, { .name = NULL}},
.outputs = (const AVFilterPad[]) {{ .name = "default", .outputs = (const AVFilterPad[]) {{ .name = "default",

View File

@ -92,7 +92,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref
const int n_in = insamplesref->audio->nb_samples; const int n_in = insamplesref->audio->nb_samples;
int n_out = n_in * aresample->ratio; int n_out = n_in * aresample->ratio;
AVFilterLink *const outlink = inlink->dst->outputs[0]; AVFilterLink *const outlink = inlink->dst->outputs[0];
AVFilterBufferRef *outsamplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, n_out); AVFilterBufferRef *outsamplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n_out);
n_out = swr_convert(aresample->swr, outsamplesref->data, n_out, n_out = swr_convert(aresample->swr, outsamplesref->data, n_out,
(void *)insamplesref->data, n_in); (void *)insamplesref->data, n_in);
@ -103,7 +103,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamplesref
outsamplesref->pts = insamplesref->pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE : outsamplesref->pts = insamplesref->pts == AV_NOPTS_VALUE ? AV_NOPTS_VALUE :
av_rescale(outlink->sample_rate, insamplesref->pts, inlink ->sample_rate); av_rescale(outlink->sample_rate, insamplesref->pts, inlink ->sample_rate);
avfilter_filter_samples(outlink, outsamplesref); ff_filter_samples(outlink, outsamplesref);
avfilter_unref_buffer(insamplesref); avfilter_unref_buffer(insamplesref);
} }

View File

@ -83,7 +83,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
av_log(ctx, AV_LOG_INFO, "]\n"); av_log(ctx, AV_LOG_INFO, "]\n");
showinfo->frame++; showinfo->frame++;
avfilter_filter_samples(inlink->dst->outputs[0], samplesref); ff_filter_samples(inlink->dst->outputs[0], samplesref);
} }
AVFilter avfilter_af_ashowinfo = { AVFilter avfilter_af_ashowinfo = {
@ -95,7 +95,7 @@ AVFilter avfilter_af_ashowinfo = {
.inputs = (const AVFilterPad[]) {{ .name = "default", .inputs = (const AVFilterPad[]) {{ .name = "default",
.type = AVMEDIA_TYPE_AUDIO, .type = AVMEDIA_TYPE_AUDIO,
.get_audio_buffer = avfilter_null_get_audio_buffer, .get_audio_buffer = ff_null_get_audio_buffer,
.filter_samples = filter_samples, .filter_samples = filter_samples,
.min_perms = AV_PERM_READ, }, .min_perms = AV_PERM_READ, },
{ .name = NULL}}, { .name = NULL}},

View File

@ -27,9 +27,9 @@
static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples) static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
{ {
avfilter_filter_samples(inlink->dst->outputs[0], ff_filter_samples(inlink->dst->outputs[0],
avfilter_ref_buffer(insamples, ~AV_PERM_WRITE)); avfilter_ref_buffer(insamples, ~AV_PERM_WRITE));
avfilter_filter_samples(inlink->dst->outputs[1], ff_filter_samples(inlink->dst->outputs[1],
avfilter_ref_buffer(insamples, ~AV_PERM_WRITE)); avfilter_ref_buffer(insamples, ~AV_PERM_WRITE));
avfilter_unref_buffer(insamples); avfilter_unref_buffer(insamples);
} }
@ -41,7 +41,7 @@ AVFilter avfilter_af_asplit = {
.inputs = (const AVFilterPad[]) { .inputs = (const AVFilterPad[]) {
{ .name = "default", { .name = "default",
.type = AVMEDIA_TYPE_AUDIO, .type = AVMEDIA_TYPE_AUDIO,
.get_audio_buffer = avfilter_null_get_audio_buffer, .get_audio_buffer = ff_null_get_audio_buffer,
.filter_samples = filter_samples, }, .filter_samples = filter_samples, },
{ .name = NULL} { .name = NULL}
}, },

View File

@ -119,7 +119,7 @@ static void send_out(AVFilterContext *ctx, int out_id)
av_q2d(ctx->outputs[out_id]->time_base) * buf->pts; av_q2d(ctx->outputs[out_id]->time_base) * buf->pts;
as->var_values[VAR_T1 + out_id] += buf->audio->nb_samples / as->var_values[VAR_T1 + out_id] += buf->audio->nb_samples /
(double)ctx->inputs[out_id]->sample_rate; (double)ctx->inputs[out_id]->sample_rate;
avfilter_filter_samples(ctx->outputs[out_id], buf); ff_filter_samples(ctx->outputs[out_id], buf);
queue->nb--; queue->nb--;
queue->tail = (queue->tail + 1) % QUEUE_SIZE; queue->tail = (queue->tail + 1) % QUEUE_SIZE;
if (as->req[out_id]) if (as->req[out_id])

View File

@ -122,7 +122,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
AVFilterLink *outlink = inlink->dst->outputs[0]; AVFilterLink *outlink = inlink->dst->outputs[0];
int16_t *taps, *endin, *in, *out; int16_t *taps, *endin, *in, *out;
AVFilterBufferRef *outsamples = AVFilterBufferRef *outsamples =
avfilter_get_audio_buffer(inlink, AV_PERM_WRITE, ff_get_audio_buffer(inlink, AV_PERM_WRITE,
insamples->audio->nb_samples); insamples->audio->nb_samples);
avfilter_copy_buffer_ref_props(outsamples, insamples); avfilter_copy_buffer_ref_props(outsamples, insamples);
@ -141,7 +141,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
// save part of input for next round // save part of input for next round
memcpy(taps, endin, NUMTAPS * sizeof(*taps)); memcpy(taps, endin, NUMTAPS * sizeof(*taps));
avfilter_filter_samples(outlink, outsamples); ff_filter_samples(outlink, outsamples);
avfilter_unref_buffer(insamples); avfilter_unref_buffer(insamples);
} }

View File

@ -340,7 +340,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
{ {
int n = insamples->audio->nb_samples; int n = insamples->audio->nb_samples;
AVFilterLink *const outlink = inlink->dst->outputs[0]; AVFilterLink *const outlink = inlink->dst->outputs[0];
AVFilterBufferRef *outsamples = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, n); AVFilterBufferRef *outsamples = ff_get_audio_buffer(outlink, AV_PERM_WRITE, n);
PanContext *pan = inlink->dst->priv; PanContext *pan = inlink->dst->priv;
swr_convert(pan->swr, outsamples->data, n, (void *)insamples->data, n); swr_convert(pan->swr, outsamples->data, n, (void *)insamples->data, n);
@ -348,7 +348,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
outsamples->audio->channel_layout = outlink->channel_layout; outsamples->audio->channel_layout = outlink->channel_layout;
outsamples->audio->planar = outlink->planar; outsamples->audio->planar = outlink->planar;
avfilter_filter_samples(outlink, outsamples); ff_filter_samples(outlink, outsamples);
avfilter_unref_buffer(insamples); avfilter_unref_buffer(insamples);
} }

View File

@ -123,7 +123,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
} }
} }
avfilter_filter_samples(inlink->dst->outputs[0], insamples); ff_filter_samples(inlink->dst->outputs[0], insamples);
} }
static int query_formats(AVFilterContext *ctx) static int query_formats(AVFilterContext *ctx)
@ -163,7 +163,7 @@ AVFilter avfilter_af_silencedetect = {
.inputs = (const AVFilterPad[]) { .inputs = (const AVFilterPad[]) {
{ .name = "default", { .name = "default",
.type = AVMEDIA_TYPE_AUDIO, .type = AVMEDIA_TYPE_AUDIO,
.get_audio_buffer = avfilter_null_get_audio_buffer, .get_audio_buffer = ff_null_get_audio_buffer,
.filter_samples = filter_samples, }, .filter_samples = filter_samples, },
{ .name = NULL } { .name = NULL }
}, },

View File

@ -167,7 +167,7 @@ static void filter_samples(AVFilterLink *inlink, AVFilterBufferRef *insamples)
} }
} }
} }
avfilter_filter_samples(outlink, insamples); ff_filter_samples(outlink, insamples);
} }
AVFilter avfilter_af_volume = { AVFilter avfilter_af_volume = {

View File

@ -205,7 +205,7 @@ static int request_frame(AVFilterLink *outlink)
if (eval->duration >= 0 && t > eval->duration) if (eval->duration >= 0 && t > eval->duration)
return AVERROR_EOF; return AVERROR_EOF;
samplesref = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, eval->nb_samples); samplesref = ff_get_audio_buffer(outlink, AV_PERM_WRITE, eval->nb_samples);
/* evaluate expression for each single sample and for each channel */ /* evaluate expression for each single sample and for each channel */
for (i = 0; i < eval->nb_samples; i++, eval->n++) { for (i = 0; i < eval->nb_samples; i++, eval->n++) {
@ -223,7 +223,7 @@ static int request_frame(AVFilterLink *outlink)
samplesref->audio->sample_rate = eval->sample_rate; samplesref->audio->sample_rate = eval->sample_rate;
eval->pts += eval->nb_samples; eval->pts += eval->nb_samples;
avfilter_filter_samples(outlink, samplesref); ff_filter_samples(outlink, samplesref);
return 0; return 0;
} }

View File

@ -108,13 +108,13 @@ static int request_frame(AVFilterLink *outlink)
AVFilterBufferRef *samplesref; AVFilterBufferRef *samplesref;
samplesref = samplesref =
avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, null->nb_samples); ff_get_audio_buffer(outlink, AV_PERM_WRITE, null->nb_samples);
samplesref->pts = null->pts; samplesref->pts = null->pts;
samplesref->pos = -1; samplesref->pos = -1;
samplesref->audio->channel_layout = null->channel_layout; samplesref->audio->channel_layout = null->channel_layout;
samplesref->audio->sample_rate = outlink->sample_rate; samplesref->audio->sample_rate = outlink->sample_rate;
avfilter_filter_samples(outlink, avfilter_ref_buffer(samplesref, ~0)); ff_filter_samples(outlink, avfilter_ref_buffer(samplesref, ~0));
avfilter_unref_buffer(samplesref); avfilter_unref_buffer(samplesref);
null->pts += null->nb_samples; null->pts += null->nb_samples;

291
libavfilter/audio.c Normal file
View File

@ -0,0 +1,291 @@
/*
* Copyright (c) Stefano Sabatini | stefasab at gmail.com
* Copyright (c) S.N. Hemanth Meenakshisundaram | smeenaks at ucsd.edu
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "libavutil/avassert.h"
#include "libavutil/audioconvert.h"
#include "audio.h"
#include "avfilter.h"
#include "internal.h"
AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples)
{
return ff_get_audio_buffer(link->dst->outputs[0], perms, nb_samples);
}
AVFilterBufferRef *ff_default_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples)
{
AVFilterBufferRef *samplesref = NULL;
int linesize[8] = {0};
uint8_t *data[8] = {0};
int ch, nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
/* right now we don't support more than 8 channels */
av_assert0(nb_channels <= 8);
/* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */
if (av_samples_alloc(data, linesize,
nb_channels, nb_samples,
av_get_alt_sample_fmt(link->format, link->planar),
16) < 0)
return NULL;
for (ch = 1; link->planar && ch < nb_channels; ch++)
linesize[ch] = linesize[0];
samplesref =
avfilter_get_audio_buffer_ref_from_arrays(data, linesize, perms,
nb_samples, link->format,
link->channel_layout, link->planar);
if (!samplesref) {
av_free(data[0]);
return NULL;
}
return samplesref;
}
static AVFilterBufferRef *ff_default_get_audio_buffer_alt(AVFilterLink *link, int perms,
int nb_samples)
{
AVFilterBufferRef *samplesref = NULL;
uint8_t **data;
int planar = av_sample_fmt_is_planar(link->format);
int nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
int planes = planar ? nb_channels : 1;
int linesize;
if (!(data = av_mallocz(sizeof(*data) * planes)))
goto fail;
if (av_samples_alloc(data, &linesize, nb_channels, nb_samples, link->format, 0) < 0)
goto fail;
samplesref = avfilter_get_audio_buffer_ref_from_arrays_alt(data, linesize, perms,
nb_samples, link->format,
link->channel_layout);
if (!samplesref)
goto fail;
av_freep(&data);
fail:
if (data)
av_freep(&data[0]);
av_freep(&data);
return samplesref;
}
AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples)
{
AVFilterBufferRef *ret = NULL;
if (link->dstpad->get_audio_buffer)
ret = link->dstpad->get_audio_buffer(link, perms, nb_samples);
if (!ret)
ret = ff_default_get_audio_buffer(link, perms, nb_samples);
if (ret)
ret->type = AVMEDIA_TYPE_AUDIO;
return ret;
}
AVFilterBufferRef *
avfilter_get_audio_buffer_ref_from_arrays(uint8_t *data[8], int linesize[8], int perms,
int nb_samples, enum AVSampleFormat sample_fmt,
uint64_t channel_layout, int planar)
{
AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer));
AVFilterBufferRef *samplesref = av_mallocz(sizeof(AVFilterBufferRef));
if (!samples || !samplesref)
goto fail;
samplesref->buf = samples;
samplesref->buf->free = ff_avfilter_default_free_buffer;
if (!(samplesref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps))))
goto fail;
samplesref->audio->nb_samples = nb_samples;
samplesref->audio->channel_layout = channel_layout;
samplesref->audio->planar = planar;
/* make sure the buffer gets read permission or it's useless for output */
samplesref->perms = perms | AV_PERM_READ;
samples->refcount = 1;
samplesref->type = AVMEDIA_TYPE_AUDIO;
samplesref->format = sample_fmt;
memcpy(samples->data, data, sizeof(samples->data));
memcpy(samples->linesize, linesize, sizeof(samples->linesize));
memcpy(samplesref->data, data, sizeof(samplesref->data));
memcpy(samplesref->linesize, linesize, sizeof(samplesref->linesize));
return samplesref;
fail:
if (samplesref && samplesref->audio)
av_freep(&samplesref->audio);
av_freep(&samplesref);
av_freep(&samples);
return NULL;
}
AVFilterBufferRef* avfilter_get_audio_buffer_ref_from_arrays_alt(uint8_t **data,
int linesize,int perms,
int nb_samples,
enum AVSampleFormat sample_fmt,
uint64_t channel_layout)
{
int planes;
AVFilterBuffer *samples = av_mallocz(sizeof(*samples));
AVFilterBufferRef *samplesref = av_mallocz(sizeof(*samplesref));
if (!samples || !samplesref)
goto fail;
samplesref->buf = samples;
samplesref->buf->free = ff_avfilter_default_free_buffer;
if (!(samplesref->audio = av_mallocz(sizeof(*samplesref->audio))))
goto fail;
samplesref->audio->nb_samples = nb_samples;
samplesref->audio->channel_layout = channel_layout;
samplesref->audio->planar = av_sample_fmt_is_planar(sample_fmt);
planes = samplesref->audio->planar ? av_get_channel_layout_nb_channels(channel_layout) : 1;
/* make sure the buffer gets read permission or it's useless for output */
samplesref->perms = perms | AV_PERM_READ;
samples->refcount = 1;
samplesref->type = AVMEDIA_TYPE_AUDIO;
samplesref->format = sample_fmt;
memcpy(samples->data, data,
FFMIN(FF_ARRAY_ELEMS(samples->data), planes)*sizeof(samples->data[0]));
memcpy(samplesref->data, samples->data, sizeof(samples->data));
samples->linesize[0] = samplesref->linesize[0] = linesize;
if (planes > FF_ARRAY_ELEMS(samples->data)) {
samples-> extended_data = av_mallocz(sizeof(*samples->extended_data) *
planes);
samplesref->extended_data = av_mallocz(sizeof(*samplesref->extended_data) *
planes);
if (!samples->extended_data || !samplesref->extended_data)
goto fail;
memcpy(samples-> extended_data, data, sizeof(*data)*planes);
memcpy(samplesref->extended_data, data, sizeof(*data)*planes);
} else {
samples->extended_data = samples->data;
samplesref->extended_data = samplesref->data;
}
return samplesref;
fail:
if (samples && samples->extended_data != samples->data)
av_freep(&samples->extended_data);
if (samplesref) {
av_freep(&samplesref->audio);
if (samplesref->extended_data != samplesref->data)
av_freep(&samplesref->extended_data);
}
av_freep(&samplesref);
av_freep(&samples);
return NULL;
}
void ff_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
{
ff_filter_samples(link->dst->outputs[0], samplesref);
}
/* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */
void ff_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
{
AVFilterLink *outlink = NULL;
if (inlink->dst->output_count)
outlink = inlink->dst->outputs[0];
if (outlink) {
outlink->out_buf = ff_default_get_audio_buffer(inlink, AV_PERM_WRITE,
samplesref->audio->nb_samples);
outlink->out_buf->pts = samplesref->pts;
outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate;
ff_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
avfilter_unref_buffer(outlink->out_buf);
outlink->out_buf = NULL;
}
avfilter_unref_buffer(samplesref);
inlink->cur_buf = NULL;
}
void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
{
void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
AVFilterPad *dst = link->dstpad;
int64_t pts;
FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1);
if (!(filter_samples = dst->filter_samples))
filter_samples = ff_default_filter_samples;
/* prepare to copy the samples if the buffer has insufficient permissions */
if ((dst->min_perms & samplesref->perms) != dst->min_perms ||
dst->rej_perms & samplesref->perms) {
int i, planar = av_sample_fmt_is_planar(samplesref->format);
int planes = !planar ? 1:
av_get_channel_layout_nb_channels(samplesref->audio->channel_layout);
av_log(link->dst, AV_LOG_DEBUG,
"Copying audio data in avfilter (have perms %x, need %x, reject %x)\n",
samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms);
link->cur_buf = ff_default_get_audio_buffer(link, dst->min_perms,
samplesref->audio->nb_samples);
link->cur_buf->pts = samplesref->pts;
link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate;
/* Copy actual data into new samples buffer */
for (i = 0; samplesref->data[i] && i < 8; i++)
memcpy(link->cur_buf->data[i], samplesref->data[i], samplesref->linesize[0]);
for (i = 0; i < planes; i++)
memcpy(link->cur_buf->extended_data[i], samplesref->extended_data[i], samplesref->linesize[0]);
avfilter_unref_buffer(samplesref);
} else
link->cur_buf = samplesref;
pts = link->cur_buf->pts;
filter_samples(link, link->cur_buf);
ff_update_link_current_pts(link, pts);
}

65
libavfilter/audio.h Normal file
View File

@ -0,0 +1,65 @@
/*
* Copyright (c) Stefano Sabatini | stefasab at gmail.com
* Copyright (c) S.N. Hemanth Meenakshisundaram | smeenaks at ucsd.edu
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef AVFILTER_AUDIO_H
#define AVFILTER_AUDIO_H
#include "avfilter.h"
/** default handler for get_audio_buffer() for audio inputs */
AVFilterBufferRef *ff_default_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples);
/** get_audio_buffer() handler for filters which simply pass audio along */
AVFilterBufferRef *ff_null_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples);
/**
* Request an audio samples buffer with a specific set of permissions.
*
* @param link the output link to the filter from which the buffer will
* be requested
* @param perms the required access permissions
* @param nb_samples the number of samples per channel
* @return A reference to the samples. This must be unreferenced with
* avfilter_unref_buffer when you are finished with it.
*/
AVFilterBufferRef *ff_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples);
/** default handler for filter_samples() for audio inputs */
void ff_default_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
/** filter_samples() handler for filters which simply pass audio along */
void ff_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
/**
* Send a buffer of audio samples to the next filter.
*
* @param link the output link over which the audio samples are being sent
* @param samplesref a reference to the buffer of audio samples being sent. The
* receiving filter will free this reference when it no longer
* needs it or pass it on to the next filter.
*/
void ff_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
#endif /* AVFILTER_AUDIO_H */

View File

@ -27,6 +27,7 @@
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/avassert.h" #include "libavutil/avassert.h"
#include "libavutil/avstring.h" #include "libavutil/avstring.h"
#include "avfilter.h" #include "avfilter.h"
#include "internal.h" #include "internal.h"
@ -410,7 +411,7 @@ static void ff_dlog_ref(void *ctx, AVFilterBufferRef *ref, int end)
av_dlog(ctx, "]%s", end ? "\n" : ""); av_dlog(ctx, "]%s", end ? "\n" : "");
} }
static void ff_dlog_link(void *ctx, AVFilterLink *link, int end) void ff_dlog_link(void *ctx, AVFilterLink *link, int end)
{ {
if (link->type == AVMEDIA_TYPE_VIDEO) { if (link->type == AVMEDIA_TYPE_VIDEO) {
av_dlog(ctx, av_dlog(ctx,
@ -434,8 +435,6 @@ static void ff_dlog_link(void *ctx, AVFilterLink *link, int end)
} }
} }
#define FF_DPRINTF_START(ctx, func) av_dlog(NULL, "%-16s: ", #func)
AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h) AVFilterBufferRef *avfilter_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
{ {
AVFilterBufferRef *ret = NULL; AVFilterBufferRef *ret = NULL;
@ -501,133 +500,6 @@ fail:
return NULL; return NULL;
} }
AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link,
int perms, int nb_samples)
{
AVFilterBufferRef *ret = NULL;
if (link->dstpad->get_audio_buffer)
ret = link->dstpad->get_audio_buffer(link, perms, nb_samples);
if (!ret)
ret = avfilter_default_get_audio_buffer(link, perms, nb_samples);
if (ret)
ret->type = AVMEDIA_TYPE_AUDIO;
return ret;
}
AVFilterBufferRef *
avfilter_get_audio_buffer_ref_from_arrays(uint8_t *data[8], int linesize[8], int perms,
int nb_samples, enum AVSampleFormat sample_fmt,
uint64_t channel_layout, int planar)
{
AVFilterBuffer *samples = av_mallocz(sizeof(AVFilterBuffer));
AVFilterBufferRef *samplesref = av_mallocz(sizeof(AVFilterBufferRef));
if (!samples || !samplesref)
goto fail;
samplesref->buf = samples;
samplesref->buf->free = ff_avfilter_default_free_buffer;
if (!(samplesref->audio = av_mallocz(sizeof(AVFilterBufferRefAudioProps))))
goto fail;
samplesref->audio->nb_samples = nb_samples;
samplesref->audio->channel_layout = channel_layout;
samplesref->audio->planar = planar;
/* make sure the buffer gets read permission or it's useless for output */
samplesref->perms = perms | AV_PERM_READ;
samples->refcount = 1;
samplesref->type = AVMEDIA_TYPE_AUDIO;
samplesref->format = sample_fmt;
memcpy(samples->data, data, sizeof(samples->data));
memcpy(samples->linesize, linesize, sizeof(samples->linesize));
memcpy(samplesref->data, data, sizeof(samplesref->data));
memcpy(samplesref->linesize, linesize, sizeof(samplesref->linesize));
return samplesref;
fail:
if (samplesref && samplesref->audio)
av_freep(&samplesref->audio);
av_freep(&samplesref);
av_freep(&samples);
return NULL;
}
AVFilterBufferRef *avfilter_get_audio_buffer_ref_from_arrays_alt(uint8_t **data,
int linesize, int perms,
int nb_samples,
enum AVSampleFormat sample_fmt,
uint64_t channel_layout)
{
int planes;
AVFilterBuffer *samples = av_mallocz(sizeof(*samples));
AVFilterBufferRef *samplesref = av_mallocz(sizeof(*samplesref));
if (!samples || !samplesref)
goto fail;
samplesref->buf = samples;
samplesref->buf->free = ff_avfilter_default_free_buffer;
if (!(samplesref->audio = av_mallocz(sizeof(*samplesref->audio))))
goto fail;
samplesref->audio->nb_samples = nb_samples;
samplesref->audio->channel_layout = channel_layout;
samplesref->audio->planar = av_sample_fmt_is_planar(sample_fmt);
planes = samplesref->audio->planar ? av_get_channel_layout_nb_channels(channel_layout) : 1;
/* make sure the buffer gets read permission or it's useless for output */
samplesref->perms = perms | AV_PERM_READ;
samples->refcount = 1;
samplesref->type = AVMEDIA_TYPE_AUDIO;
samplesref->format = sample_fmt;
memcpy(samples->data, data,
FFMIN(FF_ARRAY_ELEMS(samples->data), planes)*sizeof(samples->data[0]));
memcpy(samplesref->data, samples->data, sizeof(samples->data));
samples->linesize[0] = samplesref->linesize[0] = linesize;
if (planes > FF_ARRAY_ELEMS(samples->data)) {
samples-> extended_data = av_mallocz(sizeof(*samples->extended_data) *
planes);
samplesref->extended_data = av_mallocz(sizeof(*samplesref->extended_data) *
planes);
if (!samples->extended_data || !samplesref->extended_data)
goto fail;
memcpy(samples-> extended_data, data, sizeof(*data)*planes);
memcpy(samplesref->extended_data, data, sizeof(*data)*planes);
} else {
samples->extended_data = samples->data;
samplesref->extended_data = samplesref->data;
}
return samplesref;
fail:
if (samples && samples->extended_data != samples->data)
av_freep(&samples->extended_data);
if (samplesref) {
av_freep(&samplesref->audio);
if (samplesref->extended_data != samplesref->data)
av_freep(&samplesref->extended_data);
}
av_freep(&samplesref);
av_freep(&samples);
return NULL;
}
int avfilter_request_frame(AVFilterLink *link) int avfilter_request_frame(AVFilterLink *link)
{ {
FF_DPRINTF_START(NULL, request_frame); ff_dlog_link(NULL, link, 1); FF_DPRINTF_START(NULL, request_frame); ff_dlog_link(NULL, link, 1);
@ -657,7 +529,7 @@ int avfilter_poll_frame(AVFilterLink *link)
return min; return min;
} }
static void update_link_current_pts(AVFilterLink *link, int64_t pts) void ff_update_link_current_pts(AVFilterLink *link, int64_t pts)
{ {
if (pts == AV_NOPTS_VALUE) if (pts == AV_NOPTS_VALUE)
return; return;
@ -706,7 +578,7 @@ void avfilter_start_frame(AVFilterLink *link, AVFilterBufferRef *picref)
} }
start_frame(link, link->cur_buf); start_frame(link, link->cur_buf);
update_link_current_pts(link, link->cur_buf->pts); ff_update_link_current_pts(link, link->cur_buf->pts);
} }
void avfilter_end_frame(AVFilterLink *link) void avfilter_end_frame(AVFilterLink *link)
@ -778,44 +650,6 @@ int avfilter_process_command(AVFilterContext *filter, const char *cmd, const cha
return AVERROR(ENOSYS); return AVERROR(ENOSYS);
} }
void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
{
void (*filter_samples)(AVFilterLink *, AVFilterBufferRef *);
AVFilterPad *dst = link->dstpad;
int i;
int64_t pts;
FF_DPRINTF_START(NULL, filter_samples); ff_dlog_link(NULL, link, 1);
if (!(filter_samples = dst->filter_samples))
filter_samples = avfilter_default_filter_samples;
/* prepare to copy the samples if the buffer has insufficient permissions */
if ((dst->min_perms & samplesref->perms) != dst->min_perms ||
dst->rej_perms & samplesref->perms) {
av_log(link->dst, AV_LOG_DEBUG,
"Copying audio data in avfilter (have perms %x, need %x, reject %x)\n",
samplesref->perms, link->dstpad->min_perms, link->dstpad->rej_perms);
link->cur_buf = avfilter_default_get_audio_buffer(link, dst->min_perms,
samplesref->audio->nb_samples);
link->cur_buf->pts = samplesref->pts;
link->cur_buf->audio->sample_rate = samplesref->audio->sample_rate;
/* Copy actual data into new samples buffer */
for (i = 0; samplesref->data[i] && i < 8; i++)
memcpy(link->cur_buf->data[i], samplesref->data[i], samplesref->linesize[0]);
avfilter_unref_buffer(samplesref);
} else
link->cur_buf = samplesref;
pts = link->cur_buf->pts;
filter_samples(link, link->cur_buf);
update_link_current_pts(link, pts);
}
#define MAX_REGISTERED_AVFILTERS_NB 128 #define MAX_REGISTERED_AVFILTERS_NB 128
static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1]; static AVFilter *registered_avfilters[MAX_REGISTERED_AVFILTERS_NB + 1];

View File

@ -430,7 +430,8 @@ struct AVFilterPad {
* *
* Input audio pads only. * Input audio pads only.
*/ */
AVFilterBufferRef *(*get_audio_buffer)(AVFilterLink *link, int perms, int nb_samples); AVFilterBufferRef *(*get_audio_buffer)(AVFilterLink *link, int perms,
int nb_samples);
/** /**
* Callback called after the slices of a frame are completely sent. If * Callback called after the slices of a frame are completely sent. If
@ -508,16 +509,10 @@ void avfilter_default_draw_slice(AVFilterLink *link, int y, int h, int slice_dir
/** default handler for end_frame() for video inputs */ /** default handler for end_frame() for video inputs */
void avfilter_default_end_frame(AVFilterLink *link); void avfilter_default_end_frame(AVFilterLink *link);
/** default handler for filter_samples() for audio inputs */
void avfilter_default_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
/** default handler for get_video_buffer() for video inputs */ /** default handler for get_video_buffer() for video inputs */
AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link,
int perms, int w, int h); int perms, int w, int h);
/** default handler for get_audio_buffer() for audio inputs */
AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link,
int perms, int nb_samples);
/** /**
* Helpers for query_formats() which set all links to the same list of * Helpers for query_formats() which set all links to the same list of
@ -541,17 +536,10 @@ void avfilter_null_draw_slice(AVFilterLink *link, int y, int h, int slice_dir);
/** end_frame() handler for filters which simply pass video along */ /** end_frame() handler for filters which simply pass video along */
void avfilter_null_end_frame(AVFilterLink *link); void avfilter_null_end_frame(AVFilterLink *link);
/** filter_samples() handler for filters which simply pass audio along */
void avfilter_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
/** get_video_buffer() handler for filters which simply pass video along */ /** get_video_buffer() handler for filters which simply pass video along */
AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link,
int perms, int w, int h); int perms, int w, int h);
/** get_audio_buffer() handler for filters which simply pass audio along */
AVFilterBufferRef *avfilter_null_get_audio_buffer(AVFilterLink *link,
int perms, int nb_samples);
/** /**
* Filter definition. This defines the pads a filter contains, and all the * Filter definition. This defines the pads a filter contains, and all the
* callback functions used to interact with the filter. * callback functions used to interact with the filter.
@ -665,7 +653,7 @@ struct AVFilterLink {
AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio AVRational sample_aspect_ratio; ///< agreed upon sample aspect ratio
/* These parameters apply only to audio */ /* These parameters apply only to audio */
uint64_t channel_layout; ///< channel layout of current buffer (see libavutil/audioconvert.h) uint64_t channel_layout; ///< channel layout of current buffer (see libavutil/audioconvert.h)
#if LIBAVFILTER_VERSION_MAJOR < 3 #if FF_API_SAMPLERATE64
int64_t sample_rate; ///< samples per second int64_t sample_rate; ///< samples per second
#else #else
int sample_rate; ///< samples per second int sample_rate; ///< samples per second
@ -790,19 +778,6 @@ AVFilterBufferRef *
avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms, avfilter_get_video_buffer_ref_from_arrays(uint8_t * const data[4], const int linesize[4], int perms,
int w, int h, enum PixelFormat format); int w, int h, enum PixelFormat format);
/**
* Request an audio samples buffer with a specific set of permissions.
*
* @param link the output link to the filter from which the buffer will
* be requested
* @param perms the required access permissions
* @param nb_samples the number of samples per channel
* @return A reference to the samples. This must be unreferenced with
* avfilter_unref_buffer when you are finished with it.
*/
AVFilterBufferRef *avfilter_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples);
/** /**
* Create an audio buffer reference wrapped around an already * Create an audio buffer reference wrapped around an already
* allocated samples buffer. * allocated samples buffer.
@ -904,17 +879,7 @@ void avfilter_draw_slice(AVFilterLink *link, int y, int h, int slice_dir);
*/ */
int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags); int avfilter_process_command(AVFilterContext *filter, const char *cmd, const char *arg, char *res, int res_len, int flags);
/** /** Initialize the filter system. Register all builtin filters. */
* Send a buffer of audio samples to the next filter.
*
* @param link the output link over which the audio samples are being sent
* @param samplesref a reference to the buffer of audio samples being sent. The
* receiving filter will free this reference when it no longer
* needs it or pass it on to the next filter.
*/
void avfilter_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref);
/** Initialize the filter system. Register all built-in filters. */
void avfilter_register_all(void); void avfilter_register_all(void);
/** Uninitialize the filter system. Unregister all filters. */ /** Uninitialize the filter system. Unregister all filters. */
@ -1024,4 +989,6 @@ static inline void avfilter_insert_outpad(AVFilterContext *f, unsigned index,
&f->output_pads, &f->outputs, p); &f->output_pads, &f->outputs, p);
} }
#include "audio.h"
#endif /* AVFILTER_AVFILTER_H */ #endif /* AVFILTER_AVFILTER_H */

View File

@ -23,6 +23,7 @@
#include "libavutil/audioconvert.h" #include "libavutil/audioconvert.h"
#include "libavutil/imgutils.h" #include "libavutil/imgutils.h"
#include "libavutil/samplefmt.h" #include "libavutil/samplefmt.h"
#include "avfilter.h" #include "avfilter.h"
#include "internal.h" #include "internal.h"
@ -87,38 +88,6 @@ AVFilterBufferRef *avfilter_default_get_video_buffer(AVFilterLink *link, int per
return picref; return picref;
} }
AVFilterBufferRef *avfilter_default_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples)
{
AVFilterBufferRef *samplesref = NULL;
int linesize[8] = {0};
uint8_t *data[8] = {0};
int ch, nb_channels = av_get_channel_layout_nb_channels(link->channel_layout);
/* right now we don't support more than 8 channels */
av_assert0(nb_channels <= 8);
/* Calculate total buffer size, round to multiple of 16 to be SIMD friendly */
if (av_samples_alloc(data, linesize,
nb_channels, nb_samples,
av_get_alt_sample_fmt(link->format, link->planar),
16) < 0)
return NULL;
for (ch = 1; link->planar && ch < nb_channels; ch++)
linesize[ch] = linesize[0];
samplesref =
avfilter_get_audio_buffer_ref_from_arrays(data, linesize, perms,
nb_samples, link->format,
link->channel_layout, link->planar);
if (!samplesref) {
av_free(data[0]);
return NULL;
}
return samplesref;
}
void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref) void avfilter_default_start_frame(AVFilterLink *inlink, AVFilterBufferRef *picref)
{ {
AVFilterLink *outlink = NULL; AVFilterLink *outlink = NULL;
@ -163,27 +132,6 @@ void avfilter_default_end_frame(AVFilterLink *inlink)
} }
} }
/* FIXME: samplesref is same as link->cur_buf. Need to consider removing the redundant parameter. */
void avfilter_default_filter_samples(AVFilterLink *inlink, AVFilterBufferRef *samplesref)
{
AVFilterLink *outlink = NULL;
if (inlink->dst->output_count)
outlink = inlink->dst->outputs[0];
if (outlink) {
outlink->out_buf = avfilter_default_get_audio_buffer(inlink, AV_PERM_WRITE,
samplesref->audio->nb_samples);
outlink->out_buf->pts = samplesref->pts;
outlink->out_buf->audio->sample_rate = samplesref->audio->sample_rate;
avfilter_filter_samples(outlink, avfilter_ref_buffer(outlink->out_buf, ~0));
avfilter_unref_buffer(outlink->out_buf);
outlink->out_buf = NULL;
}
avfilter_unref_buffer(samplesref);
inlink->cur_buf = NULL;
}
static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts, static void set_common_formats(AVFilterContext *ctx, AVFilterFormats *fmts,
enum AVMediaType type, int offin, int offout) enum AVMediaType type, int offin, int offout)
{ {
@ -258,18 +206,7 @@ void avfilter_null_end_frame(AVFilterLink *link)
avfilter_end_frame(link->dst->outputs[0]); avfilter_end_frame(link->dst->outputs[0]);
} }
void avfilter_null_filter_samples(AVFilterLink *link, AVFilterBufferRef *samplesref)
{
avfilter_filter_samples(link->dst->outputs[0], samplesref);
}
AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms, int w, int h) AVFilterBufferRef *avfilter_null_get_video_buffer(AVFilterLink *link, int perms, int w, int h)
{ {
return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h); return avfilter_get_video_buffer(link->dst->outputs[0], perms, w, h);
} }
AVFilterBufferRef *avfilter_null_get_audio_buffer(AVFilterLink *link, int perms,
int nb_samples)
{
return avfilter_get_audio_buffer(link->dst->outputs[0], perms, nb_samples);
}

View File

@ -149,4 +149,10 @@ static inline void ff_null_start_frame_keep_ref(AVFilterLink *inlink,
avfilter_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(picref, ~0)); avfilter_start_frame(inlink->dst->outputs[0], avfilter_ref_buffer(picref, ~0));
} }
void ff_update_link_current_pts(AVFilterLink *link, int64_t pts);
#define FF_DPRINTF_START(ctx, func) av_dlog(NULL, "%-16s: ", #func)
void ff_dlog_link(void *ctx, AVFilterLink *link, int end);
#endif /* AVFILTER_INTERNAL_H */ #endif /* AVFILTER_INTERNAL_H */

View File

@ -297,7 +297,7 @@ static AVFilterBufferRef *copy_buffer_ref(AVFilterContext *ctx,
break; break;
case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_AUDIO:
buf = avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, buf = ff_get_audio_buffer(outlink, AV_PERM_WRITE,
ref->audio->nb_samples); ref->audio->nb_samples);
channels = av_get_channel_layout_nb_channels(ref->audio->channel_layout); channels = av_get_channel_layout_nb_channels(ref->audio->channel_layout);
data_size = av_samples_get_buffer_size(NULL, channels, data_size = av_samples_get_buffer_size(NULL, channels,
@ -562,7 +562,7 @@ static int request_frame(AVFilterLink *link)
avfilter_unref_buffer(buf); avfilter_unref_buffer(buf);
break; break;
case AVMEDIA_TYPE_AUDIO: case AVMEDIA_TYPE_AUDIO:
avfilter_filter_samples(link, avfilter_ref_buffer(buf, ~0)); ff_filter_samples(link, avfilter_ref_buffer(buf, ~0));
avfilter_unref_buffer(buf); avfilter_unref_buffer(buf);
break; break;
default: default:

View File

@ -437,7 +437,7 @@ static int amovie_get_samples(AVFilterLink *outlink)
if (data_size < 0) if (data_size < 0)
return data_size; return data_size;
movie->samplesref = movie->samplesref =
avfilter_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples); ff_get_audio_buffer(outlink, AV_PERM_WRITE, nb_samples);
memcpy(movie->samplesref->data[0], movie->frame->data[0], data_size); memcpy(movie->samplesref->data[0], movie->frame->data[0], data_size);
movie->samplesref->pts = movie->pkt.pts; movie->samplesref->pts = movie->pkt.pts;
movie->samplesref->pos = movie->pkt.pos; movie->samplesref->pos = movie->pkt.pos;
@ -463,7 +463,7 @@ static int amovie_request_frame(AVFilterLink *outlink)
return ret; return ret;
} while (!movie->samplesref); } while (!movie->samplesref);
avfilter_filter_samples(outlink, avfilter_ref_buffer(movie->samplesref, ~0)); ff_filter_samples(outlink, avfilter_ref_buffer(movie->samplesref, ~0));
avfilter_unref_buffer(movie->samplesref); avfilter_unref_buffer(movie->samplesref);
movie->samplesref = NULL; movie->samplesref = NULL;

View File

@ -47,5 +47,8 @@
#ifndef FF_API_GRAPH_AVCLASS #ifndef FF_API_GRAPH_AVCLASS
#define FF_API_GRAPH_AVCLASS (LIBAVFILTER_VERSION_MAJOR > 2) #define FF_API_GRAPH_AVCLASS (LIBAVFILTER_VERSION_MAJOR > 2)
#endif #endif
#ifndef FF_API_SAMPLERATE64
#define FF_API_SAMPLERATE64 (LIBAVFILTER_VERSION_MAJOR < 3)
#endif
#endif // AVFILTER_VERSION_H #endif // AVFILTER_VERSION_H

View File

@ -1051,7 +1051,7 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom)
return AVERROR_INVALIDDATA; return AVERROR_INVALIDDATA;
if (atom.size >= 10) { if (atom.size >= 10) {
// Broken files created by legacy versions of Libav and FFmpeg will // Broken files created by legacy versions of libavformat will
// wrap a whole fiel atom inside of a glbl atom. // wrap a whole fiel atom inside of a glbl atom.
unsigned size = avio_rb32(pb); unsigned size = avio_rb32(pb);
unsigned type = avio_rl32(pb); unsigned type = avio_rl32(pb);

View File

@ -44,6 +44,8 @@
#define APP_MAX_LENGTH 128 #define APP_MAX_LENGTH 128
#define PLAYPATH_MAX_LENGTH 256 #define PLAYPATH_MAX_LENGTH 256
#define TCURL_MAX_LENGTH 512
#define FLASHVER_MAX_LENGTH 64
/** RTMP protocol handler state */ /** RTMP protocol handler state */
typedef enum { typedef enum {
@ -82,6 +84,9 @@ typedef struct RTMPContext {
int flv_header_bytes; ///< number of initialized bytes in flv_header int flv_header_bytes; ///< number of initialized bytes in flv_header
int nb_invokes; ///< keeps track of invoke messages int nb_invokes; ///< keeps track of invoke messages
int create_stream_invoke; ///< invoke id for the create stream command int create_stream_invoke; ///< invoke id for the create stream command
char* tcurl; ///< url of the target stream
char* flashver; ///< version of the flash plugin
char* swfurl; ///< url of the swf player
} RTMPContext; } RTMPContext;
#define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
@ -110,35 +115,34 @@ static const uint8_t rtmp_server_key[] = {
/** /**
* Generate 'connect' call and send it to the server. * Generate 'connect' call and send it to the server.
*/ */
static void gen_connect(URLContext *s, RTMPContext *rt, const char *proto, static void gen_connect(URLContext *s, RTMPContext *rt)
const char *host, int port)
{ {
RTMPPacket pkt; RTMPPacket pkt;
uint8_t ver[64], *p; uint8_t *p;
char tcurl[512];
ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096); ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
p = pkt.data; p = pkt.data;
ff_url_join(tcurl, sizeof(tcurl), proto, NULL, host, port, "/%s", rt->app);
ff_amf_write_string(&p, "connect"); ff_amf_write_string(&p, "connect");
ff_amf_write_number(&p, ++rt->nb_invokes); ff_amf_write_number(&p, ++rt->nb_invokes);
ff_amf_write_object_start(&p); ff_amf_write_object_start(&p);
ff_amf_write_field_name(&p, "app"); ff_amf_write_field_name(&p, "app");
ff_amf_write_string(&p, rt->app); ff_amf_write_string(&p, rt->app);
if (rt->is_input) { if (!rt->is_input) {
snprintf(ver, sizeof(ver), "%s %d,%d,%d,%d", RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1,
RTMP_CLIENT_VER2, RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
} else {
snprintf(ver, sizeof(ver), "FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
ff_amf_write_field_name(&p, "type"); ff_amf_write_field_name(&p, "type");
ff_amf_write_string(&p, "nonprivate"); ff_amf_write_string(&p, "nonprivate");
} }
ff_amf_write_field_name(&p, "flashVer"); ff_amf_write_field_name(&p, "flashVer");
ff_amf_write_string(&p, ver); ff_amf_write_string(&p, rt->flashver);
if (rt->swfurl) {
ff_amf_write_field_name(&p, "swfUrl");
ff_amf_write_string(&p, rt->swfurl);
}
ff_amf_write_field_name(&p, "tcUrl"); ff_amf_write_field_name(&p, "tcUrl");
ff_amf_write_string(&p, tcurl); ff_amf_write_string(&p, rt->tcurl);
if (rt->is_input) { if (rt->is_input) {
ff_amf_write_field_name(&p, "fpad"); ff_amf_write_field_name(&p, "fpad");
ff_amf_write_bool(&p, 0); ff_amf_write_bool(&p, 0);
@ -368,6 +372,25 @@ static void gen_server_bw(URLContext *s, RTMPContext *rt)
ff_rtmp_packet_destroy(&pkt); ff_rtmp_packet_destroy(&pkt);
} }
/**
* Generate check bandwidth message and send it to the server.
*/
static void gen_check_bw(URLContext *s, RTMPContext *rt)
{
RTMPPacket pkt;
uint8_t *p;
ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 21);
p = pkt.data;
ff_amf_write_string(&p, "_checkbw");
ff_amf_write_number(&p, ++rt->nb_invokes);
ff_amf_write_null(&p);
ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
ff_rtmp_packet_destroy(&pkt);
}
/** /**
* Generate report on bytes read so far and send it to the server. * Generate report on bytes read so far and send it to the server.
*/ */
@ -687,6 +710,8 @@ static int rtmp_parse_result(URLContext *s, RTMPContext *rt, RTMPPacket *pkt)
if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED; if (!t && !strcmp(tmpstr, "NetStream.Play.Stop")) rt->state = STATE_STOPPED;
if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED; if (!t && !strcmp(tmpstr, "NetStream.Play.UnpublishNotify")) rt->state = STATE_STOPPED;
if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING; if (!t && !strcmp(tmpstr, "NetStream.Publish.Start")) rt->state = STATE_PUBLISHING;
} else if (!memcmp(pkt->data, "\002\000\010onBWDone", 11)) {
gen_check_bw(s, rt);
} }
break; break;
} }
@ -910,13 +935,31 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5); strncat(rt->playpath, fname, PLAYPATH_MAX_LENGTH - 5);
} }
if (!rt->tcurl) {
rt->tcurl = av_malloc(TCURL_MAX_LENGTH);
ff_url_join(rt->tcurl, TCURL_MAX_LENGTH, proto, NULL, hostname,
port, "/%s", rt->app);
}
if (!rt->flashver) {
rt->flashver = av_malloc(FLASHVER_MAX_LENGTH);
if (rt->is_input) {
snprintf(rt->flashver, FLASHVER_MAX_LENGTH, "%s %d,%d,%d,%d",
RTMP_CLIENT_PLATFORM, RTMP_CLIENT_VER1, RTMP_CLIENT_VER2,
RTMP_CLIENT_VER3, RTMP_CLIENT_VER4);
} else {
snprintf(rt->flashver, FLASHVER_MAX_LENGTH,
"FMLE/3.0 (compatible; %s)", LIBAVFORMAT_IDENT);
}
}
rt->client_report_size = 1048576; rt->client_report_size = 1048576;
rt->bytes_read = 0; rt->bytes_read = 0;
rt->last_bytes_read = 0; rt->last_bytes_read = 0;
av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n", av_log(s, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
proto, path, rt->app, rt->playpath); proto, path, rt->app, rt->playpath);
gen_connect(s, rt, proto, hostname, port); gen_connect(s, rt);
do { do {
ret = get_packet(s, 1); ret = get_packet(s, 1);
@ -1052,11 +1095,14 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
static const AVOption rtmp_options[] = { static const AVOption rtmp_options[] = {
{"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, {"rtmp_app", "Name of application to connect to on the RTMP server", OFFSET(app), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
{"rtmp_flashver", "Version of the Flash plugin used to run the SWF player.", OFFSET(flashver), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
{"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"}, {"rtmp_live", "Specify that the media is a live stream.", OFFSET(live), AV_OPT_TYPE_INT, {-2}, INT_MIN, INT_MAX, DEC, "rtmp_live"},
{"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"}, {"any", "both", 0, AV_OPT_TYPE_CONST, {-2}, 0, 0, DEC, "rtmp_live"},
{"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"}, {"live", "live stream", 0, AV_OPT_TYPE_CONST, {-1}, 0, 0, DEC, "rtmp_live"},
{"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"}, {"recorded", "recorded stream", 0, AV_OPT_TYPE_CONST, {0}, 0, 0, DEC, "rtmp_live"},
{"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC}, {"rtmp_playpath", "Stream identifier to play or to publish", OFFSET(playpath), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
{"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
{"rtmp_tcurl", "URL of the target stream. Defaults to rtmp://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
{ NULL }, { NULL },
}; };

View File

@ -227,7 +227,7 @@ static int sctp_open(URLContext *h, const char *uri, int flags)
if (s->max_streams) { if (s->max_streams) {
initparams.sinit_max_instreams = s->max_streams; initparams.sinit_max_instreams = s->max_streams;
initparams.sinit_num_ostreams = s->max_streams; initparams.sinit_num_ostreams = s->max_streams;
if (setsockopt(fd, SOL_SCTP, SCTP_INITMSG, &initparams, if (setsockopt(fd, IPPROTO_SCTP, SCTP_INITMSG, &initparams,
sizeof(initparams)) < 0) sizeof(initparams)) < 0)
av_log(h, AV_LOG_ERROR, av_log(h, AV_LOG_ERROR,
"SCTP ERROR: Unable to initialize socket max streams %d\n", "SCTP ERROR: Unable to initialize socket max streams %d\n",

View File

@ -54,26 +54,24 @@ cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
mova m3, [srcq+src3q] mova m3, [srcq+src3q]
mova m4, [srcq+src4q] mova m4, [srcq+src4q]
mova m5, [srcq+src5q] mova m5, [srcq+src5q]
%if cpuflag(sse) %if cpuflag(sse4)
SBUTTERFLYPS 0, 1, 6 SBUTTERFLYPS 0, 1, 6
SBUTTERFLYPS 2, 3, 6 SBUTTERFLYPS 2, 3, 6
SBUTTERFLYPS 4, 5, 6 SBUTTERFLYPS 4, 5, 6
movaps m6, m4 blendps m6, m4, m0, 1100b
shufps m4, m0, q3210
movlhps m0, m2 movlhps m0, m2
movhlps m6, m2 movhlps m4, m2
movaps [dstq ], m0 blendps m2, m5, m1, 1100b
movaps [dstq+16], m4
movaps [dstq+32], m6
movaps m6, m5
shufps m5, m1, q3210
movlhps m1, m3 movlhps m1, m3
movhlps m6, m3 movhlps m5, m3
movaps [dstq ], m0
movaps [dstq+16], m6
movaps [dstq+32], m4
movaps [dstq+48], m1 movaps [dstq+48], m1
movaps [dstq+64], m5 movaps [dstq+64], m2
movaps [dstq+80], m6 movaps [dstq+80], m5
%else ; mmx %else ; mmx
SBUTTERFLY dq, 0, 1, 6 SBUTTERFLY dq, 0, 1, 6
SBUTTERFLY dq, 2, 3, 6 SBUTTERFLY dq, 2, 3, 6
@ -100,5 +98,9 @@ cglobal conv_fltp_to_flt_6ch, 2,8,7, dst, src, src1, src2, src3, src4, src5, len
INIT_MMX mmx INIT_MMX mmx
CONV_FLTP_TO_FLT_6CH CONV_FLTP_TO_FLT_6CH
INIT_XMM sse INIT_XMM sse4
CONV_FLTP_TO_FLT_6CH CONV_FLTP_TO_FLT_6CH
%if HAVE_AVX
INIT_XMM avx
CONV_FLTP_TO_FLT_6CH
%endif

View File

@ -23,7 +23,8 @@
#include "libavresample/audio_convert.h" #include "libavresample/audio_convert.h"
extern void ff_conv_fltp_to_flt_6ch_mmx (float *dst, float *const *src, int len); extern void ff_conv_fltp_to_flt_6ch_mmx (float *dst, float *const *src, int len);
extern void ff_conv_fltp_to_flt_6ch_sse(float *dst, float *const *src, int len); extern void ff_conv_fltp_to_flt_6ch_sse4(float *dst, float *const *src, int len);
extern void ff_conv_fltp_to_flt_6ch_avx (float *dst, float *const *src, int len);
av_cold void ff_audio_convert_init_x86(AudioConvert *ac) av_cold void ff_audio_convert_init_x86(AudioConvert *ac)
{ {
@ -34,9 +35,13 @@ av_cold void ff_audio_convert_init_x86(AudioConvert *ac)
ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
6, 1, 4, "MMX", ff_conv_fltp_to_flt_6ch_mmx); 6, 1, 4, "MMX", ff_conv_fltp_to_flt_6ch_mmx);
} }
if (mm_flags & AV_CPU_FLAG_SSE && HAVE_SSE) { if (mm_flags & AV_CPU_FLAG_SSE4 && HAVE_SSE) {
ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP, ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
6, 16, 4, "SSE", ff_conv_fltp_to_flt_6ch_sse); 6, 16, 4, "SSE4", ff_conv_fltp_to_flt_6ch_sse4);
}
if (mm_flags & AV_CPU_FLAG_AVX && HAVE_AVX) {
ff_audio_convert_set_func(ac, AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLTP,
6, 16, 4, "AVX", ff_conv_fltp_to_flt_6ch_avx);
} }
#endif #endif
} }

View File

@ -42,10 +42,9 @@
%endmacro %endmacro
%macro SBUTTERFLYPS 3 %macro SBUTTERFLYPS 3
movaps m%3, m%1 unpcklps m%3, m%1, m%2
unpcklps m%1, m%2 unpckhps m%1, m%1, m%2
unpckhps m%3, m%2 SWAP %1, %3, %2
SWAP %2, %3
%endmacro %endmacro
%macro TRANSPOSE4x4B 5 %macro TRANSPOSE4x4B 5