From f7ff0999976c2a00c704a0f9faa2a1801c593910 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 26 Apr 2012 16:43:01 -0400 Subject: [PATCH 01/10] APIchanges: fill in some dates and commit hashes --- doc/APIchanges | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 4d3810a6f7..41cd0a187f 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -6,20 +6,20 @@ libavcodec: 2012-01-27 libavdevice: 2011-04-18 libavfilter: 2011-04-18 libavformat: 2012-01-27 -libavresample: 2012-xx-xx +libavresample: 2012-04-24 libswscale: 2011-06-20 libavutil: 2011-04-18 API changes, most recent first: -2012-04-25 - xxxxxxx - lavu 51.29.0 - cpu.h +2012-04-25 - 3527a73 - lavu 51.29.0 - cpu.h Add av_parse_cpu_flags() -2012-xx-xx - xxxxxxx - lavr 0.0.0 +2012-04-24 - c8af852 - lavr 0.0.0 Add libavresample audio conversion library -2012-xx-xx - xxxxxxx - lavu 51.28.0 - audio_fifo.h +2012-04-20 - 0c0d1bc - lavu 51.28.0 - audio_fifo.h Add audio FIFO functions: av_audio_fifo_free() av_audio_fifo_alloc() @@ -31,14 +31,14 @@ API changes, most recent first: av_audio_fifo_size() av_audio_fifo_space() -2012-xx-xx - xxxxxxx - lavfi 2.16.0 - avfiltergraph.h - Add avfilter_graph_parse2(), avfilter_inout_alloc() and - avfilter_inout_free() functions. +2012-04-14 - lavfi 2.16.0 - avfiltergraph.h + d7bcc71 Add avfilter_graph_parse2(). + 91d3cbe Add avfilter_inout_alloc() and avfilter_inout_free(). -2012-xx-xx - xxxxxxx - lavu 51.27.0 - samplefmt.h +2012-04-08 - 4d693b0 - lavu 51.27.0 - samplefmt.h Add av_get_packed_sample_fmt() and av_get_planar_sample_fmt() -2012-xx-xx - xxxxxxx - lavu 51.26.0 - audioconvert.h +2012-04-05 - 5cc51a5 - lavu 51.26.0 - audioconvert.h Add av_get_default_channel_layout() 2012-03-06 - 4d851f8 - lavu 51.25.0 - cpu.h From c75eca9d37d692dcbd2c80af0f37e33b10ac333b Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 27 Apr 2012 02:25:42 +0100 Subject: [PATCH 02/10] dvenc: do not call dsputil functions with stride not a multiple of 16 Allowing dsputil functions to assume the stride is a multiple of 16 even for smaller block sizes can simplify their implementation. This appears to be the only place this guarantee is not met. Signed-off-by: Mans Rullgard --- libavcodec/dv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/dv.c b/libavcodec/dv.c index 79e73dd125..16be0eddc0 100644 --- a/libavcodec/dv.c +++ b/libavcodec/dv.c @@ -662,7 +662,7 @@ static int dv_encode_video_segment(AVCodecContext *avctx, void *arg) int mb_x, mb_y, c_offset, linesize, y_stride; uint8_t* y_ptr; uint8_t* dif; - LOCAL_ALIGNED_8(uint8_t, scratch, [64]); + LOCAL_ALIGNED_8(uint8_t, scratch, [128]); EncBlockInfo enc_blks[5*DV_MAX_BPM]; PutBitContext pbs[5*DV_MAX_BPM]; PutBitContext* pb; @@ -717,10 +717,10 @@ static int dv_encode_video_segment(AVCodecContext *avctx, void *arg) b[0] = c_ptr[0]; b[1] = c_ptr[1]; b[2] = c_ptr[2]; b[3] = c_ptr[3]; b[4] = d[0]; b[5] = d[1]; b[6] = d[2]; b[7] = d[3]; c_ptr += linesize; - b += 8; + b += 16; } c_ptr = scratch; - linesize = 8; + linesize = 16; } vs_bit_size += dv_init_enc_block( enc_blk++, c_ptr , linesize, s, 1); From 4c387c7070e24fa1d1c6397492fef9e46f9bf7aa Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 27 Apr 2012 02:46:14 +0100 Subject: [PATCH 03/10] ppc: dsputil: do unaligned block accesses correctly To load unaligned vector data in the usual way, explicit vec_ld() should be used rather than dereferencing a pointer to a vector type. When the VSX extension is enabled, gcc may compile vector pointer dereferences using the VSX lxvw4x instruction instead of the lvx instruction typically used with Altivec/VMX. As the behaviour of these instructions with unaligned addresses differs, it is important that only lvx is used here. Signed-off-by: Mans Rullgard --- libavcodec/ppc/dsputil_altivec.c | 174 +++++++++++++++---------------- libavcodec/ppc/int_altivec.c | 24 ++--- 2 files changed, 98 insertions(+), 100 deletions(-) diff --git a/libavcodec/ppc/dsputil_altivec.c b/libavcodec/ppc/dsputil_altivec.c index d27a2bc836..6679359659 100644 --- a/libavcodec/ppc/dsputil_altivec.c +++ b/libavcodec/ppc/dsputil_altivec.c @@ -34,7 +34,9 @@ static int sad16_x2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size int i; int s; const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); - vector unsigned char *tv; + vector unsigned char perm1 = vec_lvsl(0, pix2); + vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1)); + vector unsigned char pix2l, pix2r; vector unsigned char pix1v, pix2v, pix2iv, avgv, t5; vector unsigned int sad; vector signed int sumdiffs; @@ -45,14 +47,11 @@ static int sad16_x2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size /* Read unaligned pixels into our vectors. The vectors are as follows: pix1v: pix1[0]-pix1[15] pix2v: pix2[0]-pix2[15] pix2iv: pix2[1]-pix2[16] */ - tv = (vector unsigned char *) pix1; - pix1v = vec_perm(tv[0], tv[1], vec_lvsl(0, pix1)); - - tv = (vector unsigned char *) &pix2[0]; - pix2v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[0])); - - tv = (vector unsigned char *) &pix2[1]; - pix2iv = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[1])); + pix1v = vec_ld( 0, pix1); + pix2l = vec_ld( 0, pix2); + pix2r = vec_ld(16, pix2); + pix2v = vec_perm(pix2l, pix2r, perm1); + pix2iv = vec_perm(pix2l, pix2r, perm2); /* Calculate the average vector */ avgv = vec_avg(pix2v, pix2iv); @@ -79,7 +78,8 @@ static int sad16_y2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size int i; int s; const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); - vector unsigned char *tv; + vector unsigned char perm = vec_lvsl(0, pix2); + vector unsigned char pix2l, pix2r; vector unsigned char pix1v, pix2v, pix3v, avgv, t5; vector unsigned int sad; vector signed int sumdiffs; @@ -95,18 +95,19 @@ static int sad16_y2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size Read unaligned pixels into our vectors. The vectors are as follows: pix2v: pix2[0]-pix2[15] Split the pixel vectors into shorts */ - tv = (vector unsigned char *) &pix2[0]; - pix2v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[0])); + pix2l = vec_ld( 0, pix2); + pix2r = vec_ld(15, pix2); + pix2v = vec_perm(pix2l, pix2r, perm); for (i = 0; i < h; i++) { /* Read unaligned pixels into our vectors. The vectors are as follows: pix1v: pix1[0]-pix1[15] pix3v: pix3[0]-pix3[15] */ - tv = (vector unsigned char *) pix1; - pix1v = vec_perm(tv[0], tv[1], vec_lvsl(0, pix1)); + pix1v = vec_ld(0, pix1); - tv = (vector unsigned char *) &pix3[0]; - pix3v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix3[0])); + pix2l = vec_ld( 0, pix3); + pix2r = vec_ld(15, pix3); + pix3v = vec_perm(pix2l, pix2r, perm); /* Calculate the average vector */ avgv = vec_avg(pix2v, pix3v); @@ -137,7 +138,10 @@ static int sad16_xy2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_siz uint8_t *pix3 = pix2 + line_size; const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); const vector unsigned short two = (const vector unsigned short)vec_splat_u16(2); - vector unsigned char *tv, avgv, t5; + vector unsigned char avgv, t5; + vector unsigned char perm1 = vec_lvsl(0, pix2); + vector unsigned char perm2 = vec_add(perm1, vec_splat_u8(1)); + vector unsigned char pix2l, pix2r; vector unsigned char pix1v, pix2v, pix3v, pix2iv, pix3iv; vector unsigned short pix2lv, pix2hv, pix2ilv, pix2ihv; vector unsigned short pix3lv, pix3hv, pix3ilv, pix3ihv; @@ -157,11 +161,10 @@ static int sad16_xy2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_siz Read unaligned pixels into our vectors. The vectors are as follows: pix2v: pix2[0]-pix2[15] pix2iv: pix2[1]-pix2[16] Split the pixel vectors into shorts */ - tv = (vector unsigned char *) &pix2[0]; - pix2v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[0])); - - tv = (vector unsigned char *) &pix2[1]; - pix2iv = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix2[1])); + pix2l = vec_ld( 0, pix2); + pix2r = vec_ld(16, pix2); + pix2v = vec_perm(pix2l, pix2r, perm1); + pix2iv = vec_perm(pix2l, pix2r, perm2); pix2hv = (vector unsigned short) vec_mergeh(zero, pix2v); pix2lv = (vector unsigned short) vec_mergel(zero, pix2v); @@ -174,14 +177,12 @@ static int sad16_xy2_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_siz /* Read unaligned pixels into our vectors. The vectors are as follows: pix1v: pix1[0]-pix1[15] pix3v: pix3[0]-pix3[15] pix3iv: pix3[1]-pix3[16] */ - tv = (vector unsigned char *) pix1; - pix1v = vec_perm(tv[0], tv[1], vec_lvsl(0, pix1)); + pix1v = vec_ld(0, pix1); - tv = (vector unsigned char *) &pix3[0]; - pix3v = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix3[0])); - - tv = (vector unsigned char *) &pix3[1]; - pix3iv = vec_perm(tv[0], tv[1], vec_lvsl(0, &pix3[1])); + pix2l = vec_ld( 0, pix3); + pix2r = vec_ld(16, pix3); + pix3v = vec_perm(pix2l, pix2r, perm1); + pix3iv = vec_perm(pix2l, pix2r, perm2); /* Note that AltiVec does have vec_avg, but this works on vector pairs and rounds up. We could do avg(avg(a,b),avg(c,d)), but the rounding @@ -230,7 +231,7 @@ static int sad16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, i int i; int s; const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - vector unsigned char perm1, perm2, pix1v_low, pix1v_high, pix2v_low, pix2v_high; + vector unsigned char perm = vec_lvsl(0, pix2); vector unsigned char t1, t2, t3,t4, t5; vector unsigned int sad; vector signed int sumdiffs; @@ -240,14 +241,10 @@ static int sad16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, i for (i = 0; i < h; i++) { /* Read potentially unaligned pixels into t1 and t2 */ - perm1 = vec_lvsl(0, pix1); - pix1v_high = vec_ld( 0, pix1); - pix1v_low = vec_ld(15, pix1); - perm2 = vec_lvsl(0, pix2); - pix2v_high = vec_ld( 0, pix2); - pix2v_low = vec_ld(15, pix2); - t1 = vec_perm(pix1v_high, pix1v_low, perm1); - t2 = vec_perm(pix2v_high, pix2v_low, perm2); + vector unsigned char pix2l = vec_ld( 0, pix2); + vector unsigned char pix2r = vec_ld(15, pix2); + t1 = vec_ld(0, pix1); + t2 = vec_perm(pix2l, pix2r, perm); /* Calculate a sum of abs differences vector */ t3 = vec_max(t1, t2); @@ -274,25 +271,25 @@ static int sad8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, in int i; int s; const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - vector unsigned char perm1, perm2, permclear, *pix1v, *pix2v; + const vector unsigned char permclear = (vector unsigned char){255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0}; + vector unsigned char perm1 = vec_lvsl(0, pix1); + vector unsigned char perm2 = vec_lvsl(0, pix2); vector unsigned char t1, t2, t3,t4, t5; vector unsigned int sad; vector signed int sumdiffs; sad = (vector unsigned int)vec_splat_u32(0); - permclear = (vector unsigned char){255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0}; - for (i = 0; i < h; i++) { /* Read potentially unaligned pixels into t1 and t2 Since we're reading 16 pixels, and actually only want 8, mask out the last 8 pixels. The 0s don't change the sum. */ - perm1 = vec_lvsl(0, pix1); - pix1v = (vector unsigned char *) pix1; - perm2 = vec_lvsl(0, pix2); - pix2v = (vector unsigned char *) pix2; - t1 = vec_and(vec_perm(pix1v[0], pix1v[1], perm1), permclear); - t2 = vec_and(vec_perm(pix2v[0], pix2v[1], perm2), permclear); + vector unsigned char pix1l = vec_ld( 0, pix1); + vector unsigned char pix1r = vec_ld(15, pix1); + vector unsigned char pix2l = vec_ld( 0, pix2); + vector unsigned char pix2r = vec_ld(15, pix2); + t1 = vec_and(vec_perm(pix1l, pix1r, perm1), permclear); + t2 = vec_and(vec_perm(pix2l, pix2r, perm2), permclear); /* Calculate a sum of abs differences vector */ t3 = vec_max(t1, t2); @@ -319,7 +316,7 @@ static int pix_norm1_altivec(uint8_t *pix, int line_size) int i; int s; const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - vector unsigned char *tv; + vector unsigned char perm = vec_lvsl(0, pix); vector unsigned char pixv; vector unsigned int sv; vector signed int sum; @@ -329,8 +326,9 @@ static int pix_norm1_altivec(uint8_t *pix, int line_size) s = 0; for (i = 0; i < 16; i++) { /* Read in the potentially unaligned pixels */ - tv = (vector unsigned char *) pix; - pixv = vec_perm(tv[0], tv[1], vec_lvsl(0, pix)); + vector unsigned char pixl = vec_ld( 0, pix); + vector unsigned char pixr = vec_ld(15, pix); + pixv = vec_perm(pixl, pixr, perm); /* Square the values, and add them to our sum */ sv = vec_msum(pixv, pixv, sv); @@ -355,26 +353,25 @@ static int sse8_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, in int i; int s; const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - vector unsigned char perm1, perm2, permclear, *pix1v, *pix2v; + const vector unsigned char permclear = (vector unsigned char){255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0}; + vector unsigned char perm1 = vec_lvsl(0, pix1); + vector unsigned char perm2 = vec_lvsl(0, pix2); vector unsigned char t1, t2, t3,t4, t5; vector unsigned int sum; vector signed int sumsqr; sum = (vector unsigned int)vec_splat_u32(0); - permclear = (vector unsigned char){255,255,255,255,255,255,255,255,0,0,0,0,0,0,0,0}; - - for (i = 0; i < h; i++) { /* Read potentially unaligned pixels into t1 and t2 Since we're reading 16 pixels, and actually only want 8, mask out the last 8 pixels. The 0s don't change the sum. */ - perm1 = vec_lvsl(0, pix1); - pix1v = (vector unsigned char *) pix1; - perm2 = vec_lvsl(0, pix2); - pix2v = (vector unsigned char *) pix2; - t1 = vec_and(vec_perm(pix1v[0], pix1v[1], perm1), permclear); - t2 = vec_and(vec_perm(pix2v[0], pix2v[1], perm2), permclear); + vector unsigned char pix1l = vec_ld( 0, pix1); + vector unsigned char pix1r = vec_ld(15, pix1); + vector unsigned char pix2l = vec_ld( 0, pix2); + vector unsigned char pix2r = vec_ld(15, pix2); + t1 = vec_and(vec_perm(pix1l, pix1r, perm1), permclear); + t2 = vec_and(vec_perm(pix2l, pix2r, perm2), permclear); /* Since we want to use unsigned chars, we can take advantage of the fact that abs(a-b)^2 = (a-b)^2. */ @@ -409,7 +406,7 @@ static int sse16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, i int i; int s; const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - vector unsigned char perm1, perm2, *pix1v, *pix2v; + vector unsigned char perm = vec_lvsl(0, pix2); vector unsigned char t1, t2, t3,t4, t5; vector unsigned int sum; vector signed int sumsqr; @@ -418,12 +415,10 @@ static int sse16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, i for (i = 0; i < h; i++) { /* Read potentially unaligned pixels into t1 and t2 */ - perm1 = vec_lvsl(0, pix1); - pix1v = (vector unsigned char *) pix1; - perm2 = vec_lvsl(0, pix2); - pix2v = (vector unsigned char *) pix2; - t1 = vec_perm(pix1v[0], pix1v[1], perm1); - t2 = vec_perm(pix2v[0], pix2v[1], perm2); + vector unsigned char pix2l = vec_ld( 0, pix2); + vector unsigned char pix2r = vec_ld(15, pix2); + t1 = vec_ld(0, pix1); + t2 = vec_perm(pix2l, pix2r, perm); /* Since we want to use unsigned chars, we can take advantage of the fact that abs(a-b)^2 = (a-b)^2. */ @@ -451,7 +446,7 @@ static int sse16_altivec(void *v, uint8_t *pix1, uint8_t *pix2, int line_size, i static int pix_sum_altivec(uint8_t * pix, int line_size) { const vector unsigned int zero = (const vector unsigned int)vec_splat_u32(0); - vector unsigned char perm, *pixv; + vector unsigned char perm = vec_lvsl(0, pix); vector unsigned char t1; vector unsigned int sad; vector signed int sumdiffs; @@ -463,9 +458,9 @@ static int pix_sum_altivec(uint8_t * pix, int line_size) for (i = 0; i < 16; i++) { /* Read the potentially unaligned 16 pixels into t1 */ - perm = vec_lvsl(0, pix); - pixv = (vector unsigned char *) pix; - t1 = vec_perm(pixv[0], pixv[1], perm); + vector unsigned char pixl = vec_ld( 0, pix); + vector unsigned char pixr = vec_ld(15, pix); + t1 = vec_perm(pixl, pixr, perm); /* Add each 4 pixel group together and put 4 results into sad */ sad = vec_sum4s(t1, sad); @@ -484,7 +479,8 @@ static int pix_sum_altivec(uint8_t * pix, int line_size) static void get_pixels_altivec(DCTELEM *restrict block, const uint8_t *pixels, int line_size) { int i; - vector unsigned char perm, bytes, *pixv; + vector unsigned char perm = vec_lvsl(0, pixels); + vector unsigned char bytes; const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); vector signed short shorts; @@ -492,9 +488,9 @@ static void get_pixels_altivec(DCTELEM *restrict block, const uint8_t *pixels, i // Read potentially unaligned pixels. // We're reading 16 pixels, and actually only want 8, // but we simply ignore the extras. - perm = vec_lvsl(0, pixels); - pixv = (vector unsigned char *) pixels; - bytes = vec_perm(pixv[0], pixv[1], perm); + vector unsigned char pixl = vec_ld( 0, pixels); + vector unsigned char pixr = vec_ld(15, pixels); + bytes = vec_perm(pixl, pixr, perm); // convert the bytes into shorts shorts = (vector signed short)vec_mergeh(zero, bytes); @@ -510,7 +506,9 @@ static void diff_pixels_altivec(DCTELEM *restrict block, const uint8_t *s1, const uint8_t *s2, int stride) { int i; - vector unsigned char perm, bytes, *pixv; + vector unsigned char perm1 = vec_lvsl(0, s1); + vector unsigned char perm2 = vec_lvsl(0, s2); + vector unsigned char bytes, pixl, pixr; const vector unsigned char zero = (const vector unsigned char)vec_splat_u8(0); vector signed short shorts1, shorts2; @@ -518,17 +516,17 @@ static void diff_pixels_altivec(DCTELEM *restrict block, const uint8_t *s1, // Read potentially unaligned pixels // We're reading 16 pixels, and actually only want 8, // but we simply ignore the extras. - perm = vec_lvsl(0, s1); - pixv = (vector unsigned char *) s1; - bytes = vec_perm(pixv[0], pixv[1], perm); + pixl = vec_ld( 0, s1); + pixr = vec_ld(15, s1); + bytes = vec_perm(pixl, pixr, perm1); // convert the bytes into shorts shorts1 = (vector signed short)vec_mergeh(zero, bytes); // Do the same for the second block of pixels - perm = vec_lvsl(0, s2); - pixv = (vector unsigned char *) s2; - bytes = vec_perm(pixv[0], pixv[1], perm); + pixl = vec_ld( 0, s2); + pixr = vec_ld(15, s2); + bytes = vec_perm(pixl, pixr, perm2); // convert the bytes into shorts shorts2 = (vector signed short)vec_mergeh(zero, bytes); @@ -550,17 +548,17 @@ static void diff_pixels_altivec(DCTELEM *restrict block, const uint8_t *s1, // Read potentially unaligned pixels // We're reading 16 pixels, and actually only want 8, // but we simply ignore the extras. - perm = vec_lvsl(0, s1); - pixv = (vector unsigned char *) s1; - bytes = vec_perm(pixv[0], pixv[1], perm); + pixl = vec_ld( 0, s1); + pixr = vec_ld(15, s1); + bytes = vec_perm(pixl, pixr, perm1); // convert the bytes into shorts shorts1 = (vector signed short)vec_mergeh(zero, bytes); // Do the same for the second block of pixels - perm = vec_lvsl(0, s2); - pixv = (vector unsigned char *) s2; - bytes = vec_perm(pixv[0], pixv[1], perm); + pixl = vec_ld( 0, s2); + pixr = vec_ld(15, s2); + bytes = vec_perm(pixl, pixr, perm2); // convert the bytes into shorts shorts2 = (vector signed short)vec_mergeh(zero, bytes); diff --git a/libavcodec/ppc/int_altivec.c b/libavcodec/ppc/int_altivec.c index f81b478449..b94b636dec 100644 --- a/libavcodec/ppc/int_altivec.c +++ b/libavcodec/ppc/int_altivec.c @@ -114,31 +114,31 @@ static int32_t scalarproduct_and_madd_int16_altivec(int16_t *v1, const int16_t * { LOAD_ZERO; vec_s16 *pv1 = (vec_s16*)v1; - vec_s16 *pv2 = (vec_s16*)v2; - vec_s16 *pv3 = (vec_s16*)v3; register vec_s16 muls = {mul,mul,mul,mul,mul,mul,mul,mul}; - register vec_s16 t0, t1, i0, i1; - register vec_s16 i2 = pv2[0], i3 = pv3[0]; + register vec_s16 t0, t1, i0, i1, i4; + register vec_s16 i2 = vec_ld(0, v2), i3 = vec_ld(0, v3); register vec_s32 res = zero_s32v; register vec_u8 align = vec_lvsl(0, v2); int32_t ires; order >>= 4; do { - t0 = vec_perm(i2, pv2[1], align); - i2 = pv2[2]; - t1 = vec_perm(pv2[1], i2, align); + i1 = vec_ld(16, v2); + t0 = vec_perm(i2, i1, align); + i2 = vec_ld(32, v2); + t1 = vec_perm(i1, i2, align); i0 = pv1[0]; i1 = pv1[1]; res = vec_msum(t0, i0, res); res = vec_msum(t1, i1, res); - t0 = vec_perm(i3, pv3[1], align); - i3 = pv3[2]; - t1 = vec_perm(pv3[1], i3, align); + i4 = vec_ld(16, v3); + t0 = vec_perm(i3, i4, align); + i3 = vec_ld(32, v3); + t1 = vec_perm(i4, i3, align); pv1[0] = vec_mladd(t0, muls, i0); pv1[1] = vec_mladd(t1, muls, i1); pv1 += 2; - pv2 += 2; - pv3 += 2; + v2 += 8; + v3 += 8; } while(--order); res = vec_splat(vec_sums(res, zero_s32v), 3); vec_ste(res, 0, &ires); From ce82dad7eb66b641ac41cc40deec782227fd4bde Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 27 Apr 2012 10:39:58 +0100 Subject: [PATCH 04/10] ppc: remove shift parameter from scalarproduct_int16_altivec() The shift parameter was removed from this interface in 7e1ce6a. This updates the Altivec implementation to match. Signed-off-by: Mans Rullgard --- libavcodec/ppc/int_altivec.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/libavcodec/ppc/int_altivec.c b/libavcodec/ppc/int_altivec.c index b94b636dec..bbf4e1ddf5 100644 --- a/libavcodec/ppc/int_altivec.c +++ b/libavcodec/ppc/int_altivec.c @@ -80,27 +80,18 @@ static int ssd_int8_vs_int16_altivec(const int8_t *pix1, const int16_t *pix2, } static int32_t scalarproduct_int16_altivec(int16_t *v1, const int16_t *v2, - int order, const int shift) + int order) { int i; LOAD_ZERO; register vec_s16 vec1, *pv; register vec_s32 res = vec_splat_s32(0), t; - register vec_u32 shifts; int32_t ires; - shifts = zero_u32v; - if(shift & 0x10) shifts = vec_add(shifts, vec_sl(vec_splat_u32(0x08), vec_splat_u32(0x1))); - if(shift & 0x08) shifts = vec_add(shifts, vec_splat_u32(0x08)); - if(shift & 0x04) shifts = vec_add(shifts, vec_splat_u32(0x04)); - if(shift & 0x02) shifts = vec_add(shifts, vec_splat_u32(0x02)); - if(shift & 0x01) shifts = vec_add(shifts, vec_splat_u32(0x01)); - for(i = 0; i < order; i += 8){ pv = (vec_s16*)v1; vec1 = vec_perm(pv[0], pv[1], vec_lvsl(0, v1)); t = vec_msum(vec1, vec_ld(0, v2), zero_s32v); - t = vec_sr(t, shifts); res = vec_sums(t, res); v1 += 8; v2 += 8; From c81d1e2390ce7d3182d4176723384e65a771844c Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Fri, 27 Apr 2012 10:43:08 +0100 Subject: [PATCH 05/10] ppc: add const where needed in scalarproduct_int16_altivec() Signed-off-by: Mans Rullgard --- libavcodec/ppc/int_altivec.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libavcodec/ppc/int_altivec.c b/libavcodec/ppc/int_altivec.c index bbf4e1ddf5..3c8b852298 100644 --- a/libavcodec/ppc/int_altivec.c +++ b/libavcodec/ppc/int_altivec.c @@ -79,17 +79,18 @@ static int ssd_int8_vs_int16_altivec(const int8_t *pix1, const int16_t *pix2, return u.score[3]; } -static int32_t scalarproduct_int16_altivec(int16_t *v1, const int16_t *v2, +static int32_t scalarproduct_int16_altivec(const int16_t *v1, const int16_t *v2, int order) { int i; LOAD_ZERO; - register vec_s16 vec1, *pv; + const vec_s16 *pv; + register vec_s16 vec1; register vec_s32 res = vec_splat_s32(0), t; int32_t ires; for(i = 0; i < order; i += 8){ - pv = (vec_s16*)v1; + pv = (const vec_s16*)v1; vec1 = vec_perm(pv[0], pv[1], vec_lvsl(0, v1)); t = vec_msum(vec1, vec_ld(0, v2), zero_s32v); res = vec_sums(t, res); From a812ed003f75ad8f90035ab3b88369ee7f3e1bd1 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sun, 29 Apr 2012 01:17:37 +0100 Subject: [PATCH 06/10] adpcm-thp: fix invalid array indexing Indexing outside array limits is invalid and breaks with gcc 4.8. Signed-off-by: Mans Rullgard --- libavcodec/adpcm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 41d0d98d26..8170e7f416 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -1209,12 +1209,14 @@ static int adpcm_decode_frame(AVCodecContext *avctx, void *data, int prev[2][2]; int ch; - for (i = 0; i < 32; i++) - table[0][i] = sign_extend(bytestream2_get_be16u(&gb), 16); + for (i = 0; i < 2; i++) + for (n = 0; n < 16; n++) + table[i][n] = sign_extend(bytestream2_get_be16u(&gb), 16); /* Initialize the previous sample. */ - for (i = 0; i < 4; i++) - prev[0][i] = sign_extend(bytestream2_get_be16u(&gb), 16); + for (i = 0; i < 2; i++) + for (n = 0; n < 2; n++) + prev[i][n] = sign_extend(bytestream2_get_be16u(&gb), 16); for (ch = 0; ch <= st; ch++) { samples = (short *)c->frame.data[0] + ch; From f92f4523782be96cd80b4d94d2642d12dd42cf00 Mon Sep 17 00:00:00 2001 From: Mashiat Sarker Shakkhar Date: Mon, 30 Apr 2012 08:56:35 -0700 Subject: [PATCH 07/10] WMAL: do not start decoding if frame does not end in current packet This fixes decoding of frames which span more than two packets. Tested with recit24.wma. Signed-off-by: Kostya Shishkov --- libavcodec/wmalosslessdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index 1520a06c45..e86645e225 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -1209,8 +1209,8 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, save_bits(s, gb, num_bits_prev_frame, 1); /* decode the cross packet frame if it is valid */ - if (!s->packet_loss) - decode_frame(s); + if (num_bits_prev_frame < remaining_packet_bits && !s->packet_loss) + decode_frame(s); } else if (s->num_saved_bits - s->frame_offset) { av_dlog(avctx, "ignoring %x previously saved bits\n", s->num_saved_bits - s->frame_offset); From 035a394eac868928dded505fb5ca494350ad2e92 Mon Sep 17 00:00:00 2001 From: Jakub Stachowski Date: Sat, 28 Apr 2012 11:24:19 -0700 Subject: [PATCH 08/10] WMAL: do not output last frame again if nothing was decoded in current packet Reviewed-by: Mashiat Sarker Shakkhar Signed-off-by: Michael Niedermayer Signed-off-by: Kostya Shishkov --- libavcodec/wmalosslessdec.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/wmalosslessdec.c b/libavcodec/wmalosslessdec.c index e86645e225..913271e216 100644 --- a/libavcodec/wmalosslessdec.c +++ b/libavcodec/wmalosslessdec.c @@ -1166,6 +1166,8 @@ static int decode_packet(AVCodecContext *avctx, void *data, int *got_frame_ptr, int buf_size = avpkt->size; int num_bits_prev_frame, packet_sequence_number, spliced_packet; + s->frame.nb_samples = 0; + if (s->packet_done || s->packet_loss) { s->packet_done = 0; From e5b7d7773a07dd80909402939b8f6812cfded903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reimar=20D=C3=B6ffinger?= Date: Sat, 28 Apr 2012 12:51:06 +0200 Subject: [PATCH 09/10] Fix compilation with YASM/NASM without AVX support. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Reimar Döffinger Signed-off-by: Justin Ruggles --- libavresample/x86/audio_mix.asm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavresample/x86/audio_mix.asm b/libavresample/x86/audio_mix.asm index ef30f02486..dbc79e585d 100644 --- a/libavresample/x86/audio_mix.asm +++ b/libavresample/x86/audio_mix.asm @@ -60,5 +60,7 @@ cglobal mix_2_to_1_fltp_flt, 3,4,6, src, matrix, len, src1 INIT_XMM sse MIX_2_TO_1_FLTP_FLT +%if HAVE_AVX INIT_YMM avx MIX_2_TO_1_FLTP_FLT +%endif From f1ffb01ee9fd3a15c395c3cf6ff362ac5cd668d0 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 25 Apr 2012 16:46:22 -0400 Subject: [PATCH 10/10] avplay: use libavresample for sample format conversion and channel mixing SDL only supports s16 sample format and a limited number of channel layouts. Some versions of SDL on some systems support 4-channel and 6-channel output, but it's safer overall to downmix any layout with more than 2 channels to stereo. --- avplay.c | 124 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 86 insertions(+), 38 deletions(-) diff --git a/avplay.c b/avplay.c index 0d72f466f9..e18b2e46f2 100644 --- a/avplay.c +++ b/avplay.c @@ -34,7 +34,7 @@ #include "libavformat/avformat.h" #include "libavdevice/avdevice.h" #include "libswscale/swscale.h" -#include "libavcodec/audioconvert.h" +#include "libavresample/avresample.h" #include "libavutil/opt.h" #include "libavcodec/avfft.h" @@ -159,8 +159,12 @@ typedef struct VideoState { int audio_buf_index; /* in bytes */ AVPacket audio_pkt_temp; AVPacket audio_pkt; - enum AVSampleFormat audio_src_fmt; - AVAudioConvert *reformat_ctx; + enum AVSampleFormat sdl_sample_fmt; + uint64_t sdl_channel_layout; + int sdl_channels; + enum AVSampleFormat resample_sample_fmt; + uint64_t resample_channel_layout; + AVAudioResampleContext *avr; AVFrame *frame; int show_audio; /* if true, display audio samples */ @@ -743,7 +747,7 @@ static void video_audio_display(VideoState *s) nb_freq = 1 << (rdft_bits - 1); /* compute display index : center on currently output samples */ - channels = s->audio_st->codec->channels; + channels = s->sdl_channels; nb_display_channels = channels; if (!s->paused) { int data_used = s->show_audio == 1 ? s->width : (2 * nb_freq); @@ -957,8 +961,8 @@ static double get_audio_clock(VideoState *is) hw_buf_size = audio_write_get_buf_size(is); bytes_per_sec = 0; if (is->audio_st) { - bytes_per_sec = is->audio_st->codec->sample_rate * - 2 * is->audio_st->codec->channels; + bytes_per_sec = is->audio_st->codec->sample_rate * is->sdl_channels * + av_get_bytes_per_sample(is->sdl_sample_fmt); } if (bytes_per_sec) pts -= (double)hw_buf_size / bytes_per_sec; @@ -1937,7 +1941,7 @@ static int synchronize_audio(VideoState *is, short *samples, int n, samples_size; double ref_clock; - n = 2 * is->audio_st->codec->channels; + n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt); samples_size = samples_size1; /* if not master, then we try to remove or add samples to correct the clock */ @@ -2018,6 +2022,8 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) for (;;) { /* NOTE: the audio packet can contain several frames */ while (pkt_temp->size > 0 || (!pkt_temp->data && new_packet)) { + int resample_changed, audio_resample; + if (!is->frame) { if (!(is->frame = avcodec_alloc_frame())) return AVERROR(ENOMEM); @@ -2047,39 +2053,67 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) is->frame->nb_samples, dec->sample_fmt, 1); - if (dec->sample_fmt != is->audio_src_fmt) { - if (is->reformat_ctx) - av_audio_convert_free(is->reformat_ctx); - is->reformat_ctx= av_audio_convert_alloc(AV_SAMPLE_FMT_S16, 1, - dec->sample_fmt, 1, NULL, 0); - if (!is->reformat_ctx) { - fprintf(stderr, "Cannot convert %s sample format to %s sample format\n", - av_get_sample_fmt_name(dec->sample_fmt), - av_get_sample_fmt_name(AV_SAMPLE_FMT_S16)); + audio_resample = dec->sample_fmt != is->sdl_sample_fmt || + dec->channel_layout != is->sdl_channel_layout; + + resample_changed = dec->sample_fmt != is->resample_sample_fmt || + dec->channel_layout != is->resample_channel_layout; + + if ((!is->avr && audio_resample) || resample_changed) { + if (is->avr) + avresample_close(is->avr); + else if (audio_resample) { + int ret; + is->avr = avresample_alloc_context(); + if (!is->avr) { + fprintf(stderr, "error allocating AVAudioResampleContext\n"); break; + } + av_opt_set_int(is->avr, "in_channel_layout", dec->channel_layout, 0); + av_opt_set_int(is->avr, "in_sample_fmt", dec->sample_fmt, 0); + av_opt_set_int(is->avr, "in_sample_rate", dec->sample_rate, 0); + av_opt_set_int(is->avr, "out_channel_layout", is->sdl_channel_layout, 0); + av_opt_set_int(is->avr, "out_sample_fmt", is->sdl_sample_fmt, 0); + av_opt_set_int(is->avr, "out_sample_rate", dec->sample_rate, 0); + if (av_get_bytes_per_sample(dec->sample_fmt) <= 2) + av_opt_set_int(is->avr, "internal_sample_fmt", AV_SAMPLE_FMT_S16P, 0); + + if ((ret = avresample_open(is->avr)) < 0) { + fprintf(stderr, "error initializing libavresample\n"); + break; + } } - is->audio_src_fmt= dec->sample_fmt; + is->resample_sample_fmt = dec->sample_fmt; + is->resample_channel_layout = dec->channel_layout; } - if (is->reformat_ctx) { - const void *ibuf[6] = { is->frame->data[0] }; - void *obuf[6]; - int istride[6] = { av_get_bytes_per_sample(dec->sample_fmt) }; - int ostride[6] = { 2 }; - int len= data_size/istride[0]; - obuf[0] = av_realloc(is->audio_buf1, FFALIGN(len * ostride[0], 32)); - if (!obuf[0]) { + if (audio_resample) { + void *tmp_out; + int out_samples, out_size, out_linesize; + int osize = av_get_bytes_per_sample(is->sdl_sample_fmt); + int nb_samples = is->frame->nb_samples; + + out_size = av_samples_get_buffer_size(&out_linesize, + is->sdl_channels, + nb_samples, + is->sdl_sample_fmt, 0); + tmp_out = av_realloc(is->audio_buf1, out_size); + if (!tmp_out) return AVERROR(ENOMEM); - } - is->audio_buf1 = obuf[0]; - if (av_audio_convert(is->reformat_ctx, obuf, ostride, ibuf, istride, len) < 0) { - printf("av_audio_convert() failed\n"); + is->audio_buf1 = tmp_out; + + out_samples = avresample_convert(is->avr, + (void **)&is->audio_buf1, + out_linesize, nb_samples, + (void **)is->frame->data, + is->frame->linesize[0], + is->frame->nb_samples); + if (out_samples < 0) { + fprintf(stderr, "avresample_convert() failed\n"); break; } is->audio_buf = is->audio_buf1; - /* FIXME: existing code assume that data_size equals framesize*channels*2 - remove this legacy cruft */ - data_size = len * 2; + data_size = out_samples * osize * is->sdl_channels; } else { is->audio_buf = is->frame->data[0]; } @@ -2087,7 +2121,7 @@ static int audio_decode_frame(VideoState *is, double *pts_ptr) /* if no pts, then compute it */ pts = is->audio_clock; *pts_ptr = pts; - n = 2 * dec->channels; + n = is->sdl_channels * av_get_bytes_per_sample(is->sdl_sample_fmt); is->audio_clock += (double)data_size / (double)(n * dec->sample_rate); #ifdef DEBUG @@ -2206,7 +2240,20 @@ static int stream_component_open(VideoState *is, int stream_index) if (avctx->codec_type == AVMEDIA_TYPE_AUDIO) { wanted_spec.freq = avctx->sample_rate; wanted_spec.format = AUDIO_S16SYS; - wanted_spec.channels = avctx->channels; + + if (!avctx->channel_layout) + avctx->channel_layout = av_get_default_channel_layout(avctx->channels); + if (!avctx->channel_layout) { + fprintf(stderr, "unable to guess channel layout\n"); + return -1; + } + if (avctx->channels == 1) + is->sdl_channel_layout = AV_CH_LAYOUT_MONO; + else + is->sdl_channel_layout = AV_CH_LAYOUT_STEREO; + is->sdl_channels = av_get_channel_layout_nb_channels(is->sdl_channel_layout); + + wanted_spec.channels = is->sdl_channels; wanted_spec.silence = 0; wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE; wanted_spec.callback = sdl_audio_callback; @@ -2216,7 +2263,9 @@ static int stream_component_open(VideoState *is, int stream_index) return -1; } is->audio_hw_buf_size = spec.size; - is->audio_src_fmt = AV_SAMPLE_FMT_S16; + is->sdl_sample_fmt = AV_SAMPLE_FMT_S16; + is->resample_sample_fmt = is->sdl_sample_fmt; + is->resample_channel_layout = is->sdl_channel_layout; } ic->streams[stream_index]->discard = AVDISCARD_DEFAULT; @@ -2275,9 +2324,8 @@ static void stream_component_close(VideoState *is, int stream_index) packet_queue_end(&is->audioq); av_free_packet(&is->audio_pkt); - if (is->reformat_ctx) - av_audio_convert_free(is->reformat_ctx); - is->reformat_ctx = NULL; + if (is->avr) + avresample_free(&is->avr); av_freep(&is->audio_buf1); is->audio_buf = NULL; av_freep(&is->frame);