From 055a141e440b90d1406d9e75699c09b8cc1e823b Mon Sep 17 00:00:00 2001 From: Andrey Utkin Date: Tue, 8 Nov 2011 17:24:04 +0200 Subject: [PATCH 01/16] lavf: don't leak corrupted packets Signed-off-by: Anton Khirnov --- libavformat/utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/utils.c b/libavformat/utils.c index 309fb97a0d..c2beeaee7a 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -732,6 +732,7 @@ int av_read_packet(AVFormatContext *s, AVPacket *pkt) av_log(s, AV_LOG_WARNING, "Dropped corrupted packet (stream = %d)\n", pkt->stream_index); + av_free_packet(pkt); continue; } From 6475a6e1ca47ebf33fd5e89eafa6baabe9f0d792 Mon Sep 17 00:00:00 2001 From: shahriman AMS Date: Tue, 8 Nov 2011 08:47:30 +0000 Subject: [PATCH 02/16] vc1dec: take ME precision into account while scaling MV predictors. Signed-off-by: Anton Khirnov --- libavcodec/vc1dec.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 60cca333fe..5220104b94 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1422,29 +1422,36 @@ static av_always_inline int scaleforsame(VC1Context *v, int i, int n /* MV */, int dim, int dir) { int brfd, scalesame; + int hpel = 1 - v->s.quarter_sample; + n >>= hpel; if (v->s.pict_type != AV_PICTURE_TYPE_B || v->second_field || !dir) { if (dim) - return scaleforsame_y(v, i, n, dir); + n = scaleforsame_y(v, i, n, dir) << hpel; else - return scaleforsame_x(v, n, dir); + n = scaleforsame_x(v, n, dir) << hpel; + return n; } brfd = FFMIN(v->brfd, 3); scalesame = vc1_b_field_mvpred_scales[0][brfd]; - return n * scalesame >> 8; + n = (n * scalesame >> 8) << hpel; + return n; } static av_always_inline int scaleforopp(VC1Context *v, int n /* MV */, int dim, int dir) { int refdist, scaleopp; + int hpel = 1 - v->s.quarter_sample; + n >>= hpel; if (v->s.pict_type == AV_PICTURE_TYPE_B && !v->second_field && dir == 1) { if (dim) - return scaleforopp_y(v, n, dir); + n = scaleforopp_y(v, n, dir) << hpel; else - return scaleforopp_x(v, n); + n = scaleforopp_x(v, n) << hpel; + return n; } if (v->s.pict_type != AV_PICTURE_TYPE_B) refdist = FFMIN(v->refdist, 3); @@ -1452,7 +1459,8 @@ static av_always_inline int scaleforopp(VC1Context *v, int n /* MV */, refdist = dir ? v->brfd : v->frfd; scaleopp = vc1_field_mvpred_scales[dir ^ v->second_field][0][refdist]; - return n * scaleopp >> 8; + n = (n * scaleopp >> 8) << hpel; + return n; } /** Predict and set motion vector From 4344ce08f1d0b3ca90e60362ae4726e524dc85ba Mon Sep 17 00:00:00 2001 From: shahriman AMS Date: Tue, 8 Nov 2011 08:47:31 +0000 Subject: [PATCH 03/16] vc1dec: Partial rewrite of vc1_pred_mv() The current code is a generalization of the earlier progressive MV prediction code. This was supposed to predict MVs for both interlaced and progressive pictures. But the interlaced MV prediction is buggy and works mostly by luck. This partially fixes interlaced MV prediction. Signed-off-by: Anton Khirnov --- libavcodec/vc1dec.c | 189 +++++++++++++++++++------------------------- 1 file changed, 80 insertions(+), 109 deletions(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 5220104b94..f473b5d016 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1475,12 +1475,10 @@ static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, int px, py; int sum; int mixedmv_pic, num_samefield = 0, num_oppfield = 0; - int opposit, f; - int16_t samefield_pred[2], oppfield_pred[2]; - int16_t samefield_predA[2], oppfield_predA[2]; - int16_t samefield_predB[2], oppfield_predB[2]; - int16_t samefield_predC[2], oppfield_predC[2]; - int16_t *predA, *predC; + int opposit, a_f, b_f, c_f; + int16_t field_predA[2]; + int16_t field_predB[2]; + int16_t field_predC[2]; int a_valid, b_valid, c_valid; int hybridmv_thresh, y_bias = 0; @@ -1554,96 +1552,34 @@ static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, } if (a_valid) { - f = v->mv_f[dir][xy - wrap + v->blocks_off]; - num_oppfield += f; - num_samefield += 1 - f; - if (f) { - oppfield_predA[0] = A[0]; - oppfield_predA[1] = A[1]; - samefield_predA[0] = scaleforsame(v, 0, A[0], 0, dir); - samefield_predA[1] = scaleforsame(v, n, A[1], 1, dir); - } else { - samefield_predA[0] = A[0]; - samefield_predA[1] = A[1]; - if (v->numref) - oppfield_predA[0] = scaleforopp(v, A[0], 0, dir); - if (v->numref) - oppfield_predA[1] = scaleforopp(v, A[1], 1, dir); - } + a_f = v->mv_f[dir][xy - wrap + v->blocks_off]; + num_oppfield += a_f; + num_samefield += 1 - a_f; + field_predA[0] = A[0]; + field_predA[1] = A[1]; } else { - samefield_predA[0] = samefield_predA[1] = 0; - oppfield_predA[0] = oppfield_predA[1] = 0; + field_predA[0] = field_predA[1] = 0; + a_f = 0; } if (c_valid) { - f = v->mv_f[dir][xy - 1 + v->blocks_off]; - num_oppfield += f; - num_samefield += 1 - f; - if (f) { - oppfield_predC[0] = C[0]; - oppfield_predC[1] = C[1]; - samefield_predC[0] = scaleforsame(v, 0, C[0], 0, dir); - samefield_predC[1] = scaleforsame(v, n, C[1], 1, dir); - } else { - samefield_predC[0] = C[0]; - samefield_predC[1] = C[1]; - if (v->numref) - oppfield_predC[0] = scaleforopp(v, C[0], 0, dir); - if (v->numref) - oppfield_predC[1] = scaleforopp(v, C[1], 1, dir); - } + c_f = v->mv_f[dir][xy - 1 + v->blocks_off]; + num_oppfield += c_f; + num_samefield += 1 - c_f; + field_predC[0] = C[0]; + field_predC[1] = C[1]; } else { - samefield_predC[0] = samefield_predC[1] = 0; - oppfield_predC[0] = oppfield_predC[1] = 0; + field_predC[0] = field_predC[1] = 0; + c_f = 0; } if (b_valid) { - f = v->mv_f[dir][xy - wrap + off + v->blocks_off]; - num_oppfield += f; - num_samefield += 1 - f; - if (f) { - oppfield_predB[0] = B[0]; - oppfield_predB[1] = B[1]; - samefield_predB[0] = scaleforsame(v, 0, B[0], 0, dir); - samefield_predB[1] = scaleforsame(v, n, B[1], 1, dir); - } else { - samefield_predB[0] = B[0]; - samefield_predB[1] = B[1]; - if (v->numref) - oppfield_predB[0] = scaleforopp(v, B[0], 0, dir); - if (v->numref) - oppfield_predB[1] = scaleforopp(v, B[1], 1, dir); - } + b_f = v->mv_f[dir][xy - wrap + off + v->blocks_off]; + num_oppfield += b_f; + num_samefield += 1 - b_f; + field_predB[0] = B[0]; + field_predB[1] = B[1]; } else { - samefield_predB[0] = samefield_predB[1] = 0; - oppfield_predB[0] = oppfield_predB[1] = 0; - } - - if (a_valid) { - samefield_pred[0] = samefield_predA[0]; - samefield_pred[1] = samefield_predA[1]; - oppfield_pred[0] = oppfield_predA[0]; - oppfield_pred[1] = oppfield_predA[1]; - } else if (c_valid) { - samefield_pred[0] = samefield_predC[0]; - samefield_pred[1] = samefield_predC[1]; - oppfield_pred[0] = oppfield_predC[0]; - oppfield_pred[1] = oppfield_predC[1]; - } else if (b_valid) { - samefield_pred[0] = samefield_predB[0]; - samefield_pred[1] = samefield_predB[1]; - oppfield_pred[0] = oppfield_predB[0]; - oppfield_pred[1] = oppfield_predB[1]; - } else { - samefield_pred[0] = samefield_pred[1] = 0; - oppfield_pred[0] = oppfield_pred[1] = 0; - } - - if (num_samefield + num_oppfield > 1) { - samefield_pred[0] = mid_pred(samefield_predA[0], samefield_predB[0], samefield_predC[0]); - samefield_pred[1] = mid_pred(samefield_predA[1], samefield_predB[1], samefield_predC[1]); - if (v->numref) - oppfield_pred[0] = mid_pred(oppfield_predA[0], oppfield_predB[0], oppfield_predC[0]); - if (v->numref) - oppfield_pred[1] = mid_pred(oppfield_predA[1], oppfield_predB[1], oppfield_predC[1]); + field_predB[0] = field_predB[1] = 0; + b_f = 0; } if (v->field_mode) { @@ -1654,21 +1590,56 @@ static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, } else opposit = 0; if (opposit) { - px = oppfield_pred[0]; - py = oppfield_pred[1]; - predA = oppfield_predA; - predC = oppfield_predC; - v->mv_f[dir][xy + v->blocks_off] = f = 1; + if (a_valid && !a_f) { + field_predA[0] = scaleforopp(v, field_predA[0], 0, dir); + field_predA[1] = scaleforopp(v, field_predA[1], 1, dir); + } + if (b_valid && !b_f) { + field_predB[0] = scaleforopp(v, field_predB[0], 0, dir); + field_predB[1] = scaleforopp(v, field_predB[1], 1, dir); + } + if (c_valid && !c_f) { + field_predC[0] = scaleforopp(v, field_predC[0], 0, dir); + field_predC[1] = scaleforopp(v, field_predC[1], 1, dir); + } + v->mv_f[dir][xy + v->blocks_off] = 1; v->ref_field_type[dir] = !v->cur_field_type; } else { - px = samefield_pred[0]; - py = samefield_pred[1]; - predA = samefield_predA; - predC = samefield_predC; - v->mv_f[dir][xy + v->blocks_off] = f = 0; + if (a_valid && a_f) { + field_predA[0] = scaleforsame(v, n, field_predA[0], 0, dir); + field_predA[1] = scaleforsame(v, n, field_predA[1], 1, dir); + } + if (b_valid && b_f) { + field_predB[0] = scaleforsame(v, n, field_predB[0], 0, dir); + field_predB[1] = scaleforsame(v, n, field_predB[1], 1, dir); + } + if (c_valid && c_f) { + field_predC[0] = scaleforsame(v, n, field_predC[0], 0, dir); + field_predC[1] = scaleforsame(v, n, field_predC[1], 1, dir); + } + v->mv_f[dir][xy + v->blocks_off] = 0; v->ref_field_type[dir] = v->cur_field_type; } + if (a_valid) { + px = field_predA[0]; + py = field_predA[1]; + } else if (c_valid) { + px = field_predC[0]; + py = field_predC[1]; + } else if (b_valid) { + px = field_predB[0]; + py = field_predB[1]; + } else { + px = 0; + py = 0; + } + + if (num_samefield + num_oppfield > 1) { + px = mid_pred(field_predA[0], field_predB[0], field_predC[0]); + py = mid_pred(field_predA[1], field_predB[1], field_predC[1]); + } + /* Pullback MV as specified in 8.3.5.3.4 */ if (!v->field_mode) { int qx, qy, X, Y; @@ -1697,27 +1668,27 @@ static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, if (is_intra[xy - wrap]) sum = FFABS(px) + FFABS(py); else - sum = FFABS(px - predA[0]) + FFABS(py - predA[1]); + sum = FFABS(px - field_predA[0]) + FFABS(py - field_predA[1]); if (sum > hybridmv_thresh) { if (get_bits1(&s->gb)) { // read HYBRIDPRED bit - px = predA[0]; - py = predA[1]; + px = field_predA[0]; + py = field_predA[1]; } else { - px = predC[0]; - py = predC[1]; + px = field_predC[0]; + py = field_predC[1]; } } else { if (is_intra[xy - 1]) sum = FFABS(px) + FFABS(py); else - sum = FFABS(px - predC[0]) + FFABS(py - predC[1]); + sum = FFABS(px - field_predC[0]) + FFABS(py - field_predC[1]); if (sum > hybridmv_thresh) { if (get_bits1(&s->gb)) { - px = predA[0]; - py = predA[1]; + px = field_predA[0]; + py = field_predA[1]; } else { - px = predC[0]; - py = predC[1]; + px = field_predC[0]; + py = field_predC[1]; } } } From 4bceeaf0c1a2411f9fffd05f44e26c54abd26835 Mon Sep 17 00:00:00 2001 From: shahriman AMS Date: Tue, 8 Nov 2011 08:47:32 +0000 Subject: [PATCH 04/16] vc1dec: use correct hybrid prediction threshold. Signed-off-by: Anton Khirnov --- libavcodec/vc1dec.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index f473b5d016..8cd6980779 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1660,10 +1660,7 @@ static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, if (!v->field_mode || s->pict_type != AV_PICTURE_TYPE_B) { /* Calculate hybrid prediction as specified in 8.3.5.3.5 (also 10.3.5.4.3.5) */ - if (v->field_mode && !s->quarter_sample) - hybridmv_thresh = 16; - else - hybridmv_thresh = 32; + hybridmv_thresh = 32; if (a_valid && c_valid) { if (is_intra[xy - wrap]) sum = FFABS(px) + FFABS(py); From 62622d04eb515c792e871e1cc9f5de66531b775c Mon Sep 17 00:00:00 2001 From: shahriman AMS Date: Tue, 8 Nov 2011 08:47:33 +0000 Subject: [PATCH 05/16] vc1dec: move an if() block. There are no reason for "if (c_valid) { ... }" to appear before "if (b_valid) { ... }". Signed-off-by: Anton Khirnov --- libavcodec/vc1dec.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 8cd6980779..4f366b8aa8 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -1561,16 +1561,6 @@ static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, field_predA[0] = field_predA[1] = 0; a_f = 0; } - if (c_valid) { - c_f = v->mv_f[dir][xy - 1 + v->blocks_off]; - num_oppfield += c_f; - num_samefield += 1 - c_f; - field_predC[0] = C[0]; - field_predC[1] = C[1]; - } else { - field_predC[0] = field_predC[1] = 0; - c_f = 0; - } if (b_valid) { b_f = v->mv_f[dir][xy - wrap + off + v->blocks_off]; num_oppfield += b_f; @@ -1581,6 +1571,16 @@ static inline void vc1_pred_mv(VC1Context *v, int n, int dmv_x, int dmv_y, field_predB[0] = field_predB[1] = 0; b_f = 0; } + if (c_valid) { + c_f = v->mv_f[dir][xy - 1 + v->blocks_off]; + num_oppfield += c_f; + num_samefield += 1 - c_f; + field_predC[0] = C[0]; + field_predC[1] = C[1]; + } else { + field_predC[0] = field_predC[1] = 0; + c_f = 0; + } if (v->field_mode) { if (num_samefield <= num_oppfield) From c33d4916fba4e81a520b0a579cfb5c3b7c7cf9c7 Mon Sep 17 00:00:00 2001 From: shahriman AMS Date: Tue, 8 Nov 2011 08:51:45 +0000 Subject: [PATCH 06/16] VC1: Add bottom field offset to block_index[] to avoid rewriting (+10L) Signed-off-by: Anton Khirnov --- libavcodec/vc1dec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/vc1dec.c b/libavcodec/vc1dec.c index 4f366b8aa8..7a65f31826 100644 --- a/libavcodec/vc1dec.c +++ b/libavcodec/vc1dec.c @@ -930,8 +930,8 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) if (!v->field_mode || (v->field_mode && !v->numref)) { valid_count = get_chroma_mv(mvx, mvy, intra, 0, &tx, &ty); if (!valid_count) { - s->current_picture.f.motion_val[1][s->block_index[0]][0] = 0; - s->current_picture.f.motion_val[1][s->block_index[0]][1] = 0; + s->current_picture.f.motion_val[1][s->block_index[0] + v->blocks_off][0] = 0; + s->current_picture.f.motion_val[1][s->block_index[0] + v->blocks_off][1] = 0; v->luma_mv[s->mb_x][0] = v->luma_mv[s->mb_x][1] = 0; return; //no need to do MC for intra blocks } @@ -943,8 +943,8 @@ static void vc1_mc_4mv_chroma(VC1Context *v, int dir) if (dominant) chroma_ref_type = !v->cur_field_type; } - s->current_picture.f.motion_val[1][s->block_index[0]][0] = tx; - s->current_picture.f.motion_val[1][s->block_index[0]][1] = ty; + s->current_picture.f.motion_val[1][s->block_index[0] + v->blocks_off][0] = tx; + s->current_picture.f.motion_val[1][s->block_index[0] + v->blocks_off][1] = ty; uvmx = (tx + ((tx & 3) == 3)) >> 1; uvmy = (ty + ((ty & 3) == 3)) >> 1; From 65ac51373b7e6a2e2bf4e8131acfda32c0708034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Wed, 9 Nov 2011 11:45:01 +0200 Subject: [PATCH 07/16] udp: Allow specifying the local IP address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is useful if sending multicast data on a host with multiple interfaces. Signed-off-by: Martin Storsjö --- doc/protocols.texi | 5 +++++ libavformat/udp.c | 15 ++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/doc/protocols.texi b/doc/protocols.texi index 8aee5f639c..f06546c6c1 100644 --- a/doc/protocols.texi +++ b/doc/protocols.texi @@ -446,6 +446,11 @@ set the UDP buffer size in bytes @item localport=@var{port} override the local UDP port to bind with +@item localaddr=@var{addr} +Choose the local IP address. This is useful e.g. if sending multicast +and the host has multiple interfaces, where the user can choose +which interface to send on by specifying the IP address of that interface. + @item pkt_size=@var{size} set the size in bytes of UDP packets diff --git a/libavformat/udp.c b/libavformat/udp.c index bd95a811de..178cef477a 100644 --- a/libavformat/udp.c +++ b/libavformat/udp.c @@ -29,6 +29,7 @@ #include "avformat.h" #include "avio_internal.h" #include "libavutil/parseutils.h" +#include "libavutil/avstring.h" #include #include "internal.h" #include "network.h" @@ -178,8 +179,8 @@ static int udp_set_url(struct sockaddr_storage *addr, return addr_len; } -static int udp_socket_create(UDPContext *s, - struct sockaddr_storage *addr, int *addr_len) +static int udp_socket_create(UDPContext *s, struct sockaddr_storage *addr, + int *addr_len, const char *localaddr) { int udp_fd = -1; struct addrinfo *res0 = NULL, *res = NULL; @@ -187,7 +188,8 @@ static int udp_socket_create(UDPContext *s, if (((struct sockaddr *) &s->dest_addr)->sa_family) family = ((struct sockaddr *) &s->dest_addr)->sa_family; - res0 = udp_resolve_host(0, s->local_port, SOCK_DGRAM, family, AI_PASSIVE); + res0 = udp_resolve_host(localaddr[0] ? localaddr : NULL, s->local_port, + SOCK_DGRAM, family, AI_PASSIVE); if (res0 == 0) goto fail; for (res = res0; res; res=res->ai_next) { @@ -302,7 +304,7 @@ static int udp_get_file_handle(URLContext *h) /* return non zero if error */ static int udp_open(URLContext *h, const char *uri, int flags) { - char hostname[1024]; + char hostname[1024], localaddr[1024] = ""; int port, udp_fd = -1, tmp, bind_ret = -1; UDPContext *s = NULL; int is_output; @@ -350,6 +352,9 @@ static int udp_open(URLContext *h, const char *uri, int flags) if (av_find_info_tag(buf, sizeof(buf), "connect", p)) { s->is_connected = strtol(buf, NULL, 10); } + if (av_find_info_tag(buf, sizeof(buf), "localaddr", p)) { + av_strlcpy(localaddr, buf, sizeof(localaddr)); + } } /* fill the dest addr */ @@ -367,7 +372,7 @@ static int udp_open(URLContext *h, const char *uri, int flags) if ((s->is_multicast || !s->local_port) && (h->flags & AVIO_FLAG_READ)) s->local_port = port; - udp_fd = udp_socket_create(s, &my_addr, &len); + udp_fd = udp_socket_create(s, &my_addr, &len, localaddr); if (udp_fd < 0) goto fail; From 9cb70ce34bf12621f6dffc08830aff763d00aa11 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 9 Nov 2011 13:45:50 -0500 Subject: [PATCH 08/16] ra288: fix formatting of LOCAL_ALIGNED_16 --- libavcodec/ra288.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/ra288.c b/libavcodec/ra288.c index ddbda1de4c..eac2e2e3cd 100644 --- a/libavcodec/ra288.c +++ b/libavcodec/ra288.c @@ -128,9 +128,9 @@ static void do_hybrid_window(RA288Context *ractx, int i; float buffer1[MAX_BACKWARD_FILTER_ORDER + 1]; float buffer2[MAX_BACKWARD_FILTER_ORDER + 1]; - LOCAL_ALIGNED_16(float, work)[FFALIGN(MAX_BACKWARD_FILTER_ORDER + - MAX_BACKWARD_FILTER_LEN + - MAX_BACKWARD_FILTER_NONREC, 8)]; + LOCAL_ALIGNED_16(float, work, [FFALIGN(MAX_BACKWARD_FILTER_ORDER + + MAX_BACKWARD_FILTER_LEN + + MAX_BACKWARD_FILTER_NONREC, 8)]); ractx->dsp.vector_fmul(work, window, hist, FFALIGN(order + n + non_rec, 8)); From 0005f9a35bc4b755f79a5cd96c27c4dd312c18b2 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sat, 29 Oct 2011 00:49:38 -0400 Subject: [PATCH 09/16] sipr: do not needlessly set *data_size to 0 when returning an error --- libavcodec/sipr.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libavcodec/sipr.c b/libavcodec/sipr.c index 08dd63aa5c..70227c33a3 100644 --- a/libavcodec/sipr.c +++ b/libavcodec/sipr.c @@ -518,8 +518,6 @@ static int sipr_decode_frame(AVCodecContext *avctx, void *datap, av_log(avctx, AV_LOG_ERROR, "Error processing packet: packet size (%d) too small\n", avpkt->size); - - *data_size = 0; return -1; } @@ -530,8 +528,6 @@ static int sipr_decode_frame(AVCodecContext *avctx, void *datap, av_log(avctx, AV_LOG_ERROR, "Error processing packet: output buffer (%d) too small\n", *data_size); - - *data_size = 0; return -1; } From 3468ff106008da160b8cbb2d69d396a751fe8a08 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sat, 29 Oct 2011 01:20:39 -0400 Subject: [PATCH 10/16] sipr: set mode based on block_align instead of bit_rate the user is not required to set bit_rate --- libavcodec/sipr.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/libavcodec/sipr.c b/libavcodec/sipr.c index 70227c33a3..4257496e0e 100644 --- a/libavcodec/sipr.c +++ b/libavcodec/sipr.c @@ -480,10 +480,15 @@ static av_cold int sipr_decoder_init(AVCodecContext * avctx) SiprContext *ctx = avctx->priv_data; int i; - if (avctx->bit_rate > 12200) ctx->mode = MODE_16k; - else if (avctx->bit_rate > 7500 ) ctx->mode = MODE_8k5; - else if (avctx->bit_rate > 5750 ) ctx->mode = MODE_6k5; - else ctx->mode = MODE_5k0; + switch (avctx->block_align) { + case 20: ctx->mode = MODE_16k; break; + case 19: ctx->mode = MODE_8k5; break; + case 29: ctx->mode = MODE_6k5; break; + case 37: ctx->mode = MODE_5k0; break; + default: + av_log(avctx, AV_LOG_ERROR, "Invalid block_align: %d\n", avctx->block_align); + return AVERROR(EINVAL); + } av_log(avctx, AV_LOG_DEBUG, "Mode: %s\n", modes[ctx->mode].mode_name); From 979c8de549b7a627e6ce26026e39a01672dbd0b1 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 3 Nov 2011 22:10:15 -0400 Subject: [PATCH 11/16] sipr: use a function pointer to select the decode_frame function --- libavcodec/sipr.c | 11 ++++++----- libavcodec/sipr.h | 24 ++++++++++++++---------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/libavcodec/sipr.c b/libavcodec/sipr.c index 4257496e0e..10a12c52a5 100644 --- a/libavcodec/sipr.c +++ b/libavcodec/sipr.c @@ -492,8 +492,12 @@ static av_cold int sipr_decoder_init(AVCodecContext * avctx) av_log(avctx, AV_LOG_DEBUG, "Mode: %s\n", modes[ctx->mode].mode_name); - if (ctx->mode == MODE_16k) + if (ctx->mode == MODE_16k) { ff_sipr_init_16k(ctx); + ctx->decode_frame = ff_sipr_decode_frame_16k; + } else { + ctx->decode_frame = decode_frame; + } for (i = 0; i < LP_FILTER_ORDER; i++) ctx->lsp_history[i] = cos((i+1) * M_PI / (LP_FILTER_ORDER + 1)); @@ -541,10 +545,7 @@ static int sipr_decode_frame(AVCodecContext *avctx, void *datap, for (i = 0; i < mode_par->frames_per_packet; i++) { decode_parameters(&parm, &gb, mode_par); - if (ctx->mode == MODE_16k) - ff_sipr_decode_frame_16k(ctx, &parm, data); - else - decode_frame(ctx, &parm, data); + ctx->decode_frame(ctx, &parm, data); data += subframe_size * mode_par->subframe_count; } diff --git a/libavcodec/sipr.h b/libavcodec/sipr.h index 5b2198ea87..951532167f 100644 --- a/libavcodec/sipr.h +++ b/libavcodec/sipr.h @@ -53,8 +53,18 @@ typedef enum { MODE_COUNT } SiprMode; -typedef struct { +typedef struct SiprParameters { + int ma_pred_switch; ///< switched moving average predictor + int vq_indexes[5]; + int pitch_delay[5]; ///< pitch delay + int gp_index[5]; ///< adaptive-codebook gain indexes + int16_t fc_indexes[5][10]; ///< fixed-codebook indexes + int gc_index[5]; ///< fixed-codebook gain indexes +} SiprParameters; + +typedef struct SiprContext { AVCodecContext *avctx; + AVFrame frame; SiprMode mode; @@ -85,16 +95,10 @@ typedef struct { float mem_preemph[LP_FILTER_ORDER_16k]; float synth[LP_FILTER_ORDER_16k]; double lsp_history_16k[16]; -} SiprContext; -typedef struct { - int ma_pred_switch; ///< switched moving average predictor - int vq_indexes[5]; - int pitch_delay[5]; ///< pitch delay - int gp_index[5]; ///< adaptive-codebook gain indexes - int16_t fc_indexes[5][10]; ///< fixed-codebook indexes - int gc_index[5]; ///< fixed-codebook gain indexes -} SiprParameters; + void (*decode_frame)(struct SiprContext *ctx, SiprParameters *params, + float *out_data); +} SiprContext; extern const float ff_pow_0_5[16]; From c86c3c8017da512591e6a490d447f64dc3d9253f Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 9 Nov 2011 16:19:52 -0500 Subject: [PATCH 12/16] smackaud: use sign_extend() for difference value instead of casting --- libavcodec/smacker.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index d8a3d7733b..7013aa1f05 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -33,6 +33,7 @@ #include "avcodec.h" #include "libavutil/audioconvert.h" +#include "mathops.h" #define ALT_BITSTREAM_READER_LE #include "get_bits.h" @@ -655,7 +656,7 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, else res = 0; val |= h[3].values[res] << 8; - pred[1] += (int16_t)val; + pred[1] += sign_extend(val, 16); *samples++ = pred[1]; } else { if(vlc[0].table) @@ -668,7 +669,7 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, else res = 0; val |= h[1].values[res] << 8; - pred[0] += val; + pred[0] += sign_extend(val, 16); *samples++ = pred[0]; } } @@ -683,14 +684,14 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3); else res = 0; - pred[1] += (int8_t)h[1].values[res]; + pred[1] += sign_extend(h[1].values[res], 8); *samples8++ = pred[1]; } else { if(vlc[0].table) res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); else res = 0; - pred[0] += (int8_t)h[0].values[res]; + pred[0] += sign_extend(h[0].values[res], 8); *samples8++ = pred[0]; } } From 375ca0aca81be2951d9ba4731196e70e490d3cdf Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 9 Nov 2011 16:20:45 -0500 Subject: [PATCH 13/16] smackaud: clip output samples --- libavcodec/smacker.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index 7013aa1f05..83ed8018a5 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -657,7 +657,7 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, res = 0; val |= h[3].values[res] << 8; pred[1] += sign_extend(val, 16); - *samples++ = pred[1]; + *samples++ = av_clip_int16(pred[1]); } else { if(vlc[0].table) res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); @@ -670,7 +670,7 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, res = 0; val |= h[1].values[res] << 8; pred[0] += sign_extend(val, 16); - *samples++ = pred[0]; + *samples++ = av_clip_int16(pred[0]); } } } else { //8-bit data @@ -685,14 +685,14 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, else res = 0; pred[1] += sign_extend(h[1].values[res], 8); - *samples8++ = pred[1]; + *samples8++ = av_clip_uint8(pred[1]); } else { if(vlc[0].table) res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3); else res = 0; pred[0] += sign_extend(h[0].values[res], 8); - *samples8++ = pred[0]; + *samples8++ = av_clip_uint8(pred[0]); } } } From 818a3bdedffedcc131a00f57d12597e5b7e054e6 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 9 Nov 2011 16:21:08 -0500 Subject: [PATCH 14/16] smackaud: use uint8_t* for 8-bit output buffer type This matches the output sample format and the range of the output values. --- libavcodec/smacker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/smacker.c b/libavcodec/smacker.c index 83ed8018a5..00ba4b8c5d 100644 --- a/libavcodec/smacker.c +++ b/libavcodec/smacker.c @@ -580,7 +580,7 @@ static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, HuffContext h[4]; VLC vlc[4]; int16_t *samples = data; - int8_t *samples8 = data; + uint8_t *samples8 = data; int val; int i, res; int unp_size; From fed5ca255feacb03500a22f3fcd920cc98e9dcee Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Tue, 8 Nov 2011 17:47:09 -0500 Subject: [PATCH 15/16] ra144enc: add sample_fmts list to ff_ra_144_encoder This enables the user (i.e. avconv) to automatically convert to the supported sample format if needed. --- libavcodec/ra144enc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/ra144enc.c b/libavcodec/ra144enc.c index c475cbc933..1d260b7a22 100644 --- a/libavcodec/ra144enc.c +++ b/libavcodec/ra144enc.c @@ -516,5 +516,7 @@ AVCodec ff_ra_144_encoder = { .init = ra144_encode_init, .encode = ra144_encode_frame, .close = ra144_encode_close, + .sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_S16, + AV_SAMPLE_FMT_NONE }, .long_name = NULL_IF_CONFIG_SMALL("RealAudio 1.0 (14.4K) encoder"), }; From f1f6d3615f3f9a81f41905ea0c8116b4985870e4 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Mon, 31 Oct 2011 13:41:47 -0400 Subject: [PATCH 16/16] avcodec: add support for planar signed 8-bit PCM. It is found in some 8svx files (e.g. ones created by SoX). Currently the decoder reuses the 8svx functions because we already have handling of a single large planar packet for the compressed 8svx codecs. --- libavcodec/8svx.c | 45 +++++++++++++++++++++++++++++++++++++----- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/version.h | 2 +- libavformat/iff.c | 2 +- 6 files changed, 45 insertions(+), 7 deletions(-) diff --git a/libavcodec/8svx.c b/libavcodec/8svx.c index a7b9c86065..3e3eae6c87 100644 --- a/libavcodec/8svx.c +++ b/libavcodec/8svx.c @@ -73,6 +73,15 @@ static void delta_decode(uint8_t *dst, const uint8_t *src, int src_size, *state = val; } +static void raw_decode(uint8_t *dst, const int8_t *src, int src_size, + int channels) +{ + while (src_size--) { + *dst = *src++ + 128; + dst += channels; + } +} + /** decode a frame */ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) @@ -81,12 +90,14 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si int buf_size; uint8_t *out_data = data; int out_data_size; + int is_compr = (avctx->codec_id != CODEC_ID_PCM_S8_PLANAR); /* for the first packet, copy data to buffer */ if (avpkt->data) { - int chan_size = (avpkt->size / avctx->channels) - 2; + int hdr_size = is_compr ? 2 : 0; + int chan_size = (avpkt->size - hdr_size * avctx->channels) / avctx->channels; - if (avpkt->size < 2) { + if (avpkt->size < hdr_size * avctx->channels) { av_log(avctx, AV_LOG_ERROR, "packet size is too small\n"); return AVERROR(EINVAL); } @@ -95,9 +106,11 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si return AVERROR(EINVAL); } + if (is_compr) { esc->fib_acc[0] = avpkt->data[1] + 128; if (avctx->channels == 2) esc->fib_acc[1] = avpkt->data[2+chan_size+1] + 128; + } esc->data_idx = 0; esc->data_size = chan_size; @@ -109,9 +122,9 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si return AVERROR(ENOMEM); } } - memcpy(esc->data[0], &avpkt->data[2], chan_size); + memcpy(esc->data[0], &avpkt->data[hdr_size], chan_size); if (avctx->channels == 2) - memcpy(esc->data[1], &avpkt->data[2+chan_size+2], chan_size); + memcpy(esc->data[1], &avpkt->data[2*hdr_size+chan_size], chan_size); } if (!esc->data[0]) { av_log(avctx, AV_LOG_ERROR, "unexpected empty packet\n"); @@ -124,18 +137,26 @@ static int eightsvx_decode_frame(AVCodecContext *avctx, void *data, int *data_si *data_size = 0; return avpkt->size; } - out_data_size = buf_size * 2 * avctx->channels; + out_data_size = buf_size * (is_compr + 1) * avctx->channels; if (*data_size < out_data_size) { av_log(avctx, AV_LOG_ERROR, "Provided buffer with size %d is too small.\n", *data_size); return AVERROR(EINVAL); } + if (is_compr) { delta_decode(out_data, &esc->data[0][esc->data_idx], buf_size, &esc->fib_acc[0], esc->table, avctx->channels); if (avctx->channels == 2) { delta_decode(&out_data[1], &esc->data[1][esc->data_idx], buf_size, &esc->fib_acc[1], esc->table, avctx->channels); } + } else { + int ch; + for (ch = 0; ch < avctx->channels; ch++) { + raw_decode((int8_t *)&out_data[ch], &esc->data[ch][esc->data_idx], + buf_size, avctx->channels); + } + } esc->data_idx += buf_size; *data_size = out_data_size; @@ -159,6 +180,8 @@ static av_cold int eightsvx_decode_init(AVCodecContext *avctx) case CODEC_ID_8SVX_EXP: esc->table = exponential; break; + case CODEC_ID_PCM_S8_PLANAR: + break; default: return -1; } @@ -199,3 +222,15 @@ AVCodec ff_eightsvx_exp_decoder = { .capabilities = CODEC_CAP_DELAY, .long_name = NULL_IF_CONFIG_SMALL("8SVX exponential"), }; + +AVCodec ff_pcm_s8_planar_decoder = { + .name = "pcm_s8_planar", + .type = AVMEDIA_TYPE_AUDIO, + .id = CODEC_ID_PCM_S8_PLANAR, + .priv_data_size = sizeof(EightSvxContext), + .init = eightsvx_decode_init, + .close = eightsvx_decode_close, + .decode = eightsvx_decode_frame, + .capabilities = CODEC_CAP_DELAY, + .long_name = NULL_IF_CONFIG_SMALL("PCM signed 8-bit planar"), +}; diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 413b04d142..5fabd8b7fc 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -453,6 +453,7 @@ OBJS-$(CONFIG_PCM_MULAW_DECODER) += pcm.o OBJS-$(CONFIG_PCM_MULAW_ENCODER) += pcm.o OBJS-$(CONFIG_PCM_S8_DECODER) += pcm.o OBJS-$(CONFIG_PCM_S8_ENCODER) += pcm.o +OBJS-$(CONFIG_PCM_S8_PLANAR_DECODER) += 8svx.o OBJS-$(CONFIG_PCM_S16BE_DECODER) += pcm.o OBJS-$(CONFIG_PCM_S16BE_ENCODER) += pcm.o OBJS-$(CONFIG_PCM_S16LE_DECODER) += pcm.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index 2beb81c0b8..e9be06398d 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -299,6 +299,7 @@ void avcodec_register_all(void) REGISTER_DECODER (PCM_LXF, pcm_lxf); REGISTER_ENCDEC (PCM_MULAW, pcm_mulaw); REGISTER_ENCDEC (PCM_S8, pcm_s8); + REGISTER_DECODER (PCM_S8_PLANAR, pcm_s8_planar); REGISTER_ENCDEC (PCM_S16BE, pcm_s16be); REGISTER_ENCDEC (PCM_S16LE, pcm_s16le); REGISTER_DECODER (PCM_S16LE_PLANAR, pcm_s16le_planar); diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index f169bec37e..76562834ed 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -250,6 +250,7 @@ enum CodecID { CODEC_ID_PCM_BLURAY, CODEC_ID_PCM_LXF, CODEC_ID_S302M, + CODEC_ID_PCM_S8_PLANAR, /* various ADPCM codecs */ CODEC_ID_ADPCM_IMA_QT = 0x11000, diff --git a/libavcodec/version.h b/libavcodec/version.h index 5e07ec28e3..c11f09c9d4 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -21,7 +21,7 @@ #define AVCODEC_VERSION_H #define LIBAVCODEC_VERSION_MAJOR 53 -#define LIBAVCODEC_VERSION_MINOR 17 +#define LIBAVCODEC_VERSION_MINOR 18 #define LIBAVCODEC_VERSION_MICRO 0 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ diff --git a/libavformat/iff.c b/libavformat/iff.c index 5e8f1689c4..e621373862 100644 --- a/libavformat/iff.c +++ b/libavformat/iff.c @@ -220,7 +220,7 @@ static int iff_read_header(AVFormatContext *s, switch(compression) { case COMP_NONE: - st->codec->codec_id = CODEC_ID_PCM_S8; + st->codec->codec_id = CODEC_ID_PCM_S8_PLANAR; break; case COMP_FIB: st->codec->codec_id = CODEC_ID_8SVX_FIB;