]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/mpegvideo.c
Replace Subversion revisions in comments by Git hashes.
[ffmpeg] / libavcodec / mpegvideo.c
index b6cc459631de93a358eae6c775c2455506dcfb3f..d190606eff5c490e6f21efdccd153c744512ae99 100644 (file)
@@ -38,6 +38,7 @@
 #include "msmpeg4.h"
 #include "faandct.h"
 #include "xvmc_internal.h"
+#include "thread.h"
 #include <limits.h>
 
 //#undef NDEBUG
@@ -65,44 +66,61 @@ static void dct_unquantize_h263_inter_c(MpegEncContext *s,
 //#define DEBUG
 
 
-static const uint8_t ff_default_chroma_qscale_table[32]={
-//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-    0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
+static const uint8_t ff_default_chroma_qscale_table[32] = {
+//   0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
+    16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
 };
 
-const uint8_t ff_mpeg1_dc_scale_table[128]={
-//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
-    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+const uint8_t ff_mpeg1_dc_scale_table[128] = {
+//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+    8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
 };
 
-static const uint8_t mpeg2_dc_scale_table1[128]={
-//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+static const uint8_t mpeg2_dc_scale_table1[128] = {
+//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
 };
 
-static const uint8_t mpeg2_dc_scale_table2[128]={
-//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+static const uint8_t mpeg2_dc_scale_table2[128] = {
+//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
 };
 
-static const uint8_t mpeg2_dc_scale_table3[128]={
-//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+static const uint8_t mpeg2_dc_scale_table3[128] = {
+//  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
 };
 
-const uint8_t * const ff_mpeg2_dc_scale_table[4]={
+const uint8_t *const ff_mpeg2_dc_scale_table[4] = {
     ff_mpeg1_dc_scale_table,
     mpeg2_dc_scale_table1,
     mpeg2_dc_scale_table2,
@@ -117,53 +135,59 @@ const enum PixelFormat ff_pixfmt_list_420[] = {
 const enum PixelFormat ff_hwaccel_pixfmt_list_420[] = {
     PIX_FMT_DXVA2_VLD,
     PIX_FMT_VAAPI_VLD,
+    PIX_FMT_VDA_VLD,
     PIX_FMT_YUV420P,
     PIX_FMT_NONE
 };
 
-const uint8_t *ff_find_start_code(const uint8_t * restrict p, const uint8_t *end, uint32_t * restrict state){
+const uint8_t *avpriv_mpv_find_start_code(const uint8_t *restrict p,
+                                          const uint8_t *end,
+                                          uint32_t * restrict state)
+{
     int i;
 
-    assert(p<=end);
-    if(p>=end)
+    assert(p <= end);
+    if (p >= end)
         return end;
 
-    for(i=0; i<3; i++){
-        uint32_t tmp= *state << 8;
-        *state= tmp + *(p++);
-        if(tmp == 0x100 || p==end)
+    for (i = 0; i < 3; i++) {
+        uint32_t tmp = *state << 8;
+        *state = tmp + *(p++);
+        if (tmp == 0x100 || p == end)
             return p;
     }
 
-    while(p<end){
-        if     (p[-1] > 1      ) p+= 3;
-        else if(p[-2]          ) p+= 2;
-        else if(p[-3]|(p[-1]-1)) p++;
-        else{
+    while (p < end) {
+        if      (p[-1] > 1      ) p += 3;
+        else if (p[-2]          ) p += 2;
+        else if (p[-3]|(p[-1]-1)) p++;
+        else {
             p++;
             break;
         }
     }
 
-    p= FFMIN(p, end)-4;
-    *state= AV_RB32(p);
+    p = FFMIN(p, end) - 4;
+    *state = AV_RB32(p);
 
-    return p+4;
+    return p + 4;
 }
 
 /* init common dct for both encoder and decoder */
 av_cold int ff_dct_common_init(MpegEncContext *s)
 {
+    dsputil_init(&s->dsp, s->avctx);
+
     s->dct_unquantize_h263_intra = dct_unquantize_h263_intra_c;
     s->dct_unquantize_h263_inter = dct_unquantize_h263_inter_c;
     s->dct_unquantize_mpeg1_intra = dct_unquantize_mpeg1_intra_c;
     s->dct_unquantize_mpeg1_inter = dct_unquantize_mpeg1_inter_c;
     s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_c;
-    if(s->flags & CODEC_FLAG_BITEXACT)
+    if (s->flags & CODEC_FLAG_BITEXACT)
         s->dct_unquantize_mpeg2_intra = dct_unquantize_mpeg2_intra_bitexact;
     s->dct_unquantize_mpeg2_inter = dct_unquantize_mpeg2_inter_c;
 
-#if   HAVE_MMX
+#if HAVE_MMX
     MPV_common_init_mmx(s);
 #elif ARCH_ALPHA
     MPV_common_init_axp(s);
@@ -180,12 +204,12 @@ av_cold int ff_dct_common_init(MpegEncContext *s)
 #endif
 
     /* load & permutate scantables
-       note: only wmv uses different ones
-    */
-    if(s->alternate_scan){
+     * note: only wmv uses different ones
+     */
+    if (s->alternate_scan) {
         ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable  , ff_alternate_vertical_scan);
         ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable  , ff_alternate_vertical_scan);
-    }else{
+    } else {
         ff_init_scantable(s->dsp.idct_permutation, &s->inter_scantable  , ff_zigzag_direct);
         ff_init_scantable(s->dsp.idct_permutation, &s->intra_scantable  , ff_zigzag_direct);
     }
@@ -195,9 +219,10 @@ av_cold int ff_dct_common_init(MpegEncContext *s)
     return 0;
 }
 
-void ff_copy_picture(Picture *dst, Picture *src){
+void ff_copy_picture(Picture *dst, Picture *src)
+{
     *dst = *src;
-    dst->type= FF_BUFFER_TYPE_COPY;
+    dst->f.type = FF_BUFFER_TYPE_COPY;
 }
 
 /**
@@ -205,8 +230,14 @@ void ff_copy_picture(Picture *dst, Picture *src){
  */
 static void free_frame_buffer(MpegEncContext *s, Picture *pic)
 {
-    s->avctx->release_buffer(s->avctx, (AVFrame*)pic);
-    av_freep(&pic->hwaccel_picture_private);
+    /* Windows Media Image codecs allocate internal buffers with different
+     * dimensions; ignore user defined callbacks for these
+     */
+    if (s->codec_id != CODEC_ID_WMV3IMAGE && s->codec_id != CODEC_ID_VC1IMAGE)
+        ff_thread_release_buffer(s->avctx, (AVFrame *) pic);
+    else
+        avcodec_default_release_buffer(s->avctx, (AVFrame *) pic);
+    av_freep(&pic->f.hwaccel_picture_private);
 }
 
 /**
@@ -217,32 +248,39 @@ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic)
     int r;
 
     if (s->avctx->hwaccel) {
-        assert(!pic->hwaccel_picture_private);
+        assert(!pic->f.hwaccel_picture_private);
         if (s->avctx->hwaccel->priv_data_size) {
-            pic->hwaccel_picture_private = av_mallocz(s->avctx->hwaccel->priv_data_size);
-            if (!pic->hwaccel_picture_private) {
+            pic->f.hwaccel_picture_private = av_mallocz(s->avctx->hwaccel->priv_data_size);
+            if (!pic->f.hwaccel_picture_private) {
                 av_log(s->avctx, AV_LOG_ERROR, "alloc_frame_buffer() failed (hwaccel private data allocation)\n");
                 return -1;
             }
         }
     }
 
-    r = s->avctx->get_buffer(s->avctx, (AVFrame*)pic);
+    if (s->codec_id != CODEC_ID_WMV3IMAGE && s->codec_id != CODEC_ID_VC1IMAGE)
+        r = ff_thread_get_buffer(s->avctx, (AVFrame *) pic);
+    else
+        r = avcodec_default_get_buffer(s->avctx, (AVFrame *) pic);
 
-    if (r<0 || !pic->age || !pic->type || !pic->data[0]) {
-        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (%d %d %d %p)\n", r, pic->age, pic->type, pic->data[0]);
-        av_freep(&pic->hwaccel_picture_private);
+    if (r < 0 || !pic->f.type || !pic->f.data[0]) {
+        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (%d %d %p)\n",
+               r, pic->f.type, pic->f.data[0]);
+        av_freep(&pic->f.hwaccel_picture_private);
         return -1;
     }
 
-    if (s->linesize && (s->linesize != pic->linesize[0] || s->uvlinesize != pic->linesize[1])) {
-        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (stride changed)\n");
+    if (s->linesize && (s->linesize   != pic->f.linesize[0] ||
+                        s->uvlinesize != pic->f.linesize[1])) {
+        av_log(s->avctx, AV_LOG_ERROR,
+               "get_buffer() failed (stride changed)\n");
         free_frame_buffer(s, pic);
         return -1;
     }
 
-    if (pic->linesize[1] != pic->linesize[2]) {
-        av_log(s->avctx, AV_LOG_ERROR, "get_buffer() failed (uv stride mismatch)\n");
+    if (pic->f.linesize[1] != pic->f.linesize[2]) {
+        av_log(s->avctx, AV_LOG_ERROR,
+               "get_buffer() failed (uv stride mismatch)\n");
         free_frame_buffer(s, pic);
         return -1;
     }
@@ -251,144 +289,170 @@ static int alloc_frame_buffer(MpegEncContext *s, Picture *pic)
 }
 
 /**
- * allocates a Picture
- * The pixels are allocated/set by calling get_buffer() if shared=0
+ * Allocate a Picture.
+ * The pixels are allocated/set by calling get_buffer() if shared = 0
  */
-int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared){
-    const int big_mb_num= s->mb_stride*(s->mb_height+1) + 1; //the +1 is needed so memset(,,stride*height) does not sig11
-    const int mb_array_size= s->mb_stride*s->mb_height;
-    const int b8_array_size= s->b8_stride*s->mb_height*2;
-    const int b4_array_size= s->b4_stride*s->mb_height*4;
+int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared)
+{
+    const int big_mb_num = s->mb_stride * (s->mb_height + 1) + 1;
+
+    // the + 1 is needed so memset(,,stride*height) does not sig11
+
+    const int mb_array_size = s->mb_stride * s->mb_height;
+    const int b8_array_size = s->b8_stride * s->mb_height * 2;
+    const int b4_array_size = s->b4_stride * s->mb_height * 4;
     int i;
-    int r= -1;
+    int r = -1;
 
-    if(shared){
-        assert(pic->data[0]);
-        assert(pic->type == 0 || pic->type == FF_BUFFER_TYPE_SHARED);
-        pic->type= FF_BUFFER_TYPE_SHARED;
-    }else{
-        assert(!pic->data[0]);
+    if (shared) {
+        assert(pic->f.data[0]);
+        assert(pic->f.type == 0 || pic->f.type == FF_BUFFER_TYPE_SHARED);
+        pic->f.type = FF_BUFFER_TYPE_SHARED;
+    } else {
+        assert(!pic->f.data[0]);
 
         if (alloc_frame_buffer(s, pic) < 0)
             return -1;
 
-        s->linesize  = pic->linesize[0];
-        s->uvlinesize= pic->linesize[1];
+        s->linesize   = pic->f.linesize[0];
+        s->uvlinesize = pic->f.linesize[1];
     }
 
-    if(pic->qscale_table==NULL){
+    if (pic->f.qscale_table == NULL) {
         if (s->encoding) {
-            FF_ALLOCZ_OR_GOTO(s->avctx, pic->mb_var   , mb_array_size * sizeof(int16_t)  , fail)
-            FF_ALLOCZ_OR_GOTO(s->avctx, pic->mc_mb_var, mb_array_size * sizeof(int16_t)  , fail)
-            FF_ALLOCZ_OR_GOTO(s->avctx, pic->mb_mean  , mb_array_size * sizeof(int8_t )  , fail)
+            FF_ALLOCZ_OR_GOTO(s->avctx, pic->mb_var,
+                              mb_array_size * sizeof(int16_t), fail)
+            FF_ALLOCZ_OR_GOTO(s->avctx, pic->mc_mb_var,
+                              mb_array_size * sizeof(int16_t), fail)
+            FF_ALLOCZ_OR_GOTO(s->avctx, pic->mb_mean,
+                              mb_array_size * sizeof(int8_t ), fail)
         }
 
-        FF_ALLOCZ_OR_GOTO(s->avctx, pic->mbskip_table , mb_array_size * sizeof(uint8_t)+2, fail) //the +2 is for the slice end check
-        FF_ALLOCZ_OR_GOTO(s->avctx, pic->qscale_table , mb_array_size * sizeof(uint8_t)  , fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, pic->mb_type_base , (big_mb_num + s->mb_stride) * sizeof(uint32_t), fail)
-        pic->mb_type= pic->mb_type_base + 2*s->mb_stride+1;
-        if(s->out_format == FMT_H264){
-            for(i=0; i<2; i++){
-                FF_ALLOCZ_OR_GOTO(s->avctx, pic->motion_val_base[i], 2 * (b4_array_size+4)  * sizeof(int16_t), fail)
-                pic->motion_val[i]= pic->motion_val_base[i]+4;
-                FF_ALLOCZ_OR_GOTO(s->avctx, pic->ref_index[i], 4*mb_array_size * sizeof(uint8_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.mbskip_table,
+                          mb_array_size * sizeof(uint8_t) + 2, fail)// the + 2 is for the slice end check
+        FF_ALLOCZ_OR_GOTO(s->avctx, pic->qscale_table_base,
+                          (big_mb_num + s->mb_stride) * sizeof(uint8_t),
+                          fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, pic->mb_type_base,
+                          (big_mb_num + s->mb_stride) * sizeof(uint32_t),
+                          fail)
+        pic->f.mb_type = pic->mb_type_base + 2 * s->mb_stride + 1;
+        pic->f.qscale_table = pic->qscale_table_base + 2 * s->mb_stride + 1;
+        if (s->out_format == FMT_H264) {
+            for (i = 0; i < 2; i++) {
+                FF_ALLOCZ_OR_GOTO(s->avctx, pic->motion_val_base[i],
+                                  2 * (b4_array_size + 4) * sizeof(int16_t),
+                                  fail)
+                pic->f.motion_val[i] = pic->motion_val_base[i] + 4;
+                FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.ref_index[i],
+                                  4 * mb_array_size * sizeof(uint8_t), fail)
             }
-            pic->motion_subsample_log2= 2;
-        }else if(s->out_format == FMT_H263 || s->encoding || (s->avctx->debug&FF_DEBUG_MV) || (s->avctx->debug_mv)){
-            for(i=0; i<2; i++){
-                FF_ALLOCZ_OR_GOTO(s->avctx, pic->motion_val_base[i], 2 * (b8_array_size+4) * sizeof(int16_t), fail)
-                pic->motion_val[i]= pic->motion_val_base[i]+4;
-                FF_ALLOCZ_OR_GOTO(s->avctx, pic->ref_index[i], 4*mb_array_size * sizeof(uint8_t), fail)
+            pic->f.motion_subsample_log2 = 2;
+        } else if (s->out_format == FMT_H263 || s->encoding ||
+                   (s->avctx->debug & FF_DEBUG_MV) || s->avctx->debug_mv) {
+            for (i = 0; i < 2; i++) {
+                FF_ALLOCZ_OR_GOTO(s->avctx, pic->motion_val_base[i],
+                                  2 * (b8_array_size + 4) * sizeof(int16_t),
+                                  fail)
+                pic->f.motion_val[i] = pic->motion_val_base[i] + 4;
+                FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.ref_index[i],
+                                  4 * mb_array_size * sizeof(uint8_t), fail)
             }
-            pic->motion_subsample_log2= 3;
+            pic->f.motion_subsample_log2 = 3;
         }
-        if(s->avctx->debug&FF_DEBUG_DCT_COEFF) {
-            FF_ALLOCZ_OR_GOTO(s->avctx, pic->dct_coeff, 64 * mb_array_size * sizeof(DCTELEM)*6, fail)
+        if (s->avctx->debug&FF_DEBUG_DCT_COEFF) {
+            FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.dct_coeff,
+                              64 * mb_array_size * sizeof(DCTELEM) * 6, fail)
         }
-        pic->qstride= s->mb_stride;
-        FF_ALLOCZ_OR_GOTO(s->avctx, pic->pan_scan , 1 * sizeof(AVPanScan), fail)
+        pic->f.qstride = s->mb_stride;
+        FF_ALLOCZ_OR_GOTO(s->avctx, pic->f.pan_scan,
+                          1 * sizeof(AVPanScan), fail)
     }
 
-    /* It might be nicer if the application would keep track of these
-     * but it would require an API change. */
-    memmove(s->prev_pict_types+1, s->prev_pict_types, PREV_PICT_TYPES_BUFFER_SIZE-1);
-    s->prev_pict_types[0]= s->dropable ? FF_B_TYPE : s->pict_type;
-    if(pic->age < PREV_PICT_TYPES_BUFFER_SIZE && s->prev_pict_types[pic->age] == FF_B_TYPE)
-        pic->age= INT_MAX; // Skipped MBs in B-frames are quite rare in MPEG-1/2 and it is a bit tricky to skip them anyway.
+    pic->owner2 = s;
 
     return 0;
-fail: //for the FF_ALLOCZ_OR_GOTO macro
-    if(r>=0)
+fail: // for  the FF_ALLOCZ_OR_GOTO macro
+    if (r >= 0)
         free_frame_buffer(s, pic);
     return -1;
 }
 
 /**
- * deallocates a picture
+ * Deallocate a picture.
  */
-static void free_picture(MpegEncContext *s, Picture *pic){
+static void free_picture(MpegEncContext *s, Picture *pic)
+{
     int i;
 
-    if(pic->data[0] && pic->type!=FF_BUFFER_TYPE_SHARED){
+    if (pic->f.data[0] && pic->f.type != FF_BUFFER_TYPE_SHARED) {
         free_frame_buffer(s, pic);
     }
 
     av_freep(&pic->mb_var);
     av_freep(&pic->mc_mb_var);
     av_freep(&pic->mb_mean);
-    av_freep(&pic->mbskip_table);
-    av_freep(&pic->qscale_table);
+    av_freep(&pic->f.mbskip_table);
+    av_freep(&pic->qscale_table_base);
     av_freep(&pic->mb_type_base);
-    av_freep(&pic->dct_coeff);
-    av_freep(&pic->pan_scan);
-    pic->mb_type= NULL;
-    for(i=0; i<2; i++){
+    av_freep(&pic->f.dct_coeff);
+    av_freep(&pic->f.pan_scan);
+    pic->f.mb_type = NULL;
+    for (i = 0; i < 2; i++) {
         av_freep(&pic->motion_val_base[i]);
-        av_freep(&pic->ref_index[i]);
+        av_freep(&pic->f.ref_index[i]);
     }
 
-    if(pic->type == FF_BUFFER_TYPE_SHARED){
-        for(i=0; i<4; i++){
-            pic->base[i]=
-            pic->data[i]= NULL;
+    if (pic->f.type == FF_BUFFER_TYPE_SHARED) {
+        for (i = 0; i < 4; i++) {
+            pic->f.base[i] =
+            pic->f.data[i] = NULL;
         }
-        pic->type= 0;
+        pic->f.type = 0;
     }
 }
 
-static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base){
+static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base)
+{
     int y_size = s->b8_stride * (2 * s->mb_height + 1);
     int c_size = s->mb_stride * (s->mb_height + 1);
     int yc_size = y_size + 2 * c_size;
     int i;
 
-    // edge emu needs blocksize + filter length - 1 (=17x17 for halfpel / 21x21 for h264)
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->allocated_edge_emu_buffer, (s->width+64)*2*21*2, fail); //(width + edge + align)*interlaced*MBsize*tolerance
-    s->edge_emu_buffer= s->allocated_edge_emu_buffer + (s->width+64)*2*21;
-
-     //FIXME should be linesize instead of s->width*2 but that is not known before get_buffer()
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->me.scratchpad,  (s->width+64)*4*16*2*sizeof(uint8_t), fail)
-    s->me.temp=         s->me.scratchpad;
-    s->rd_scratchpad=   s->me.scratchpad;
-    s->b_scratchpad=    s->me.scratchpad;
-    s->obmc_scratchpad= s->me.scratchpad + 16;
+    // edge emu needs blocksize + filter length - 1
+    // (= 17x17 for  halfpel / 21x21 for  h264)
+    FF_ALLOCZ_OR_GOTO(s->avctx, s->edge_emu_buffer,
+                      (s->width + 64) * 2 * 21 * 2, fail);    // (width + edge + align)*interlaced*MBsize*tolerance
+
+    // FIXME should be linesize instead of s->width * 2
+    // but that is not known before get_buffer()
+    FF_ALLOCZ_OR_GOTO(s->avctx, s->me.scratchpad,
+                      (s->width + 64) * 4 * 16 * 2 * sizeof(uint8_t), fail)
+    s->me.temp         = s->me.scratchpad;
+    s->rd_scratchpad   = s->me.scratchpad;
+    s->b_scratchpad    = s->me.scratchpad;
+    s->obmc_scratchpad = s->me.scratchpad + 16;
     if (s->encoding) {
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->me.map      , ME_MAP_SIZE*sizeof(uint32_t), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->me.score_map, ME_MAP_SIZE*sizeof(uint32_t), fail)
-        if(s->avctx->noise_reduction){
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_error_sum, 2 * 64 * sizeof(int), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->me.map,
+                          ME_MAP_SIZE * sizeof(uint32_t), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->me.score_map,
+                          ME_MAP_SIZE * sizeof(uint32_t), fail)
+        if (s->avctx->noise_reduction) {
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_error_sum,
+                              2 * 64 * sizeof(int), fail)
         }
     }
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->blocks, 64*12*2 * sizeof(DCTELEM), fail)
-    s->block= s->blocks[0];
+    FF_ALLOCZ_OR_GOTO(s->avctx, s->blocks, 64 * 12 * 2 * sizeof(DCTELEM), fail)
+    s->block = s->blocks[0];
 
-    for(i=0;i<12;i++){
+    for (i = 0; i < 12; i++) {
         s->pblocks[i] = &s->block[i];
     }
 
     if (s->out_format == FMT_H263) {
         /* ac values */
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_val_base, yc_size * sizeof(int16_t) * 16, fail);
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_val_base,
+                          yc_size * sizeof(int16_t) * 16, fail);
         s->ac_val[0] = s->ac_val_base + s->b8_stride + 1;
         s->ac_val[1] = s->ac_val_base + y_size + s->mb_stride + 1;
         s->ac_val[2] = s->ac_val[1] + c_size;
@@ -396,30 +460,32 @@ static int init_duplicate_context(MpegEncContext *s, MpegEncContext *base){
 
     return 0;
 fail:
-    return -1; //free() through MPV_common_end()
+    return -1; // free() through MPV_common_end()
 }
 
-static void free_duplicate_context(MpegEncContext *s){
-    if(s==NULL) return;
+static void free_duplicate_context(MpegEncContext *s)
+{
+    if (s == NULL)
+        return;
 
-    av_freep(&s->allocated_edge_emu_buffer); s->edge_emu_buffer= NULL;
+    av_freep(&s->edge_emu_buffer);
     av_freep(&s->me.scratchpad);
-    s->me.temp=
-    s->rd_scratchpad=
-    s->b_scratchpad=
-    s->obmc_scratchpad= NULL;
+    s->me.temp =
+    s->rd_scratchpad =
+    s->b_scratchpad =
+    s->obmc_scratchpad = NULL;
 
     av_freep(&s->dct_error_sum);
     av_freep(&s->me.map);
     av_freep(&s->me.score_map);
     av_freep(&s->blocks);
     av_freep(&s->ac_val_base);
-    s->block= NULL;
+    s->block = NULL;
 }
 
-static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src){
-#define COPY(a) bak->a= src->a
-    COPY(allocated_edge_emu_buffer);
+static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src)
+{
+#define COPY(a) bak->a = src->a
     COPY(edge_emu_buffer);
     COPY(me.scratchpad);
     COPY(me.temp);
@@ -444,47 +510,142 @@ static void backup_duplicate_context(MpegEncContext *bak, MpegEncContext *src){
 #undef COPY
 }
 
-void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src){
+void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src)
+{
     MpegEncContext bak;
     int i;
-    //FIXME copy only needed parts
-//START_TIMER
+    // FIXME copy only needed parts
+    // START_TIMER
     backup_duplicate_context(&bak, dst);
     memcpy(dst, src, sizeof(MpegEncContext));
     backup_duplicate_context(dst, &bak);
-    for(i=0;i<12;i++){
+    for (i = 0; i < 12; i++) {
         dst->pblocks[i] = &dst->block[i];
     }
-//STOP_TIMER("update_duplicate_context") //about 10k cycles / 0.01 sec for 1000frames on 1ghz with 2 threads
+    // STOP_TIMER("update_duplicate_context")
+    // about 10k cycles / 0.01 sec for  1000frames on 1ghz with 2 threads
+}
+
+int ff_mpeg_update_thread_context(AVCodecContext *dst,
+                                  const AVCodecContext *src)
+{
+    MpegEncContext *s = dst->priv_data, *s1 = src->priv_data;
+
+    if (dst == src || !s1->context_initialized)
+        return 0;
+
+    // FIXME can parameters change on I-frames?
+    // in that case dst may need a reinit
+    if (!s->context_initialized) {
+        memcpy(s, s1, sizeof(MpegEncContext));
+
+        s->avctx                 = dst;
+        s->picture_range_start  += MAX_PICTURE_COUNT;
+        s->picture_range_end    += MAX_PICTURE_COUNT;
+        s->bitstream_buffer      = NULL;
+        s->bitstream_buffer_size = s->allocated_bitstream_buffer_size = 0;
+
+        MPV_common_init(s);
+    }
+
+    s->avctx->coded_height  = s1->avctx->coded_height;
+    s->avctx->coded_width   = s1->avctx->coded_width;
+    s->avctx->width         = s1->avctx->width;
+    s->avctx->height        = s1->avctx->height;
+
+    s->coded_picture_number = s1->coded_picture_number;
+    s->picture_number       = s1->picture_number;
+    s->input_picture_number = s1->input_picture_number;
+
+    memcpy(s->picture, s1->picture, s1->picture_count * sizeof(Picture));
+    memcpy(&s->last_picture, &s1->last_picture,
+           (char *) &s1->last_picture_ptr - (char *) &s1->last_picture);
+
+    s->last_picture_ptr    = REBASE_PICTURE(s1->last_picture_ptr,    s, s1);
+    s->current_picture_ptr = REBASE_PICTURE(s1->current_picture_ptr, s, s1);
+    s->next_picture_ptr    = REBASE_PICTURE(s1->next_picture_ptr,    s, s1);
+
+    // Error/bug resilience
+    s->next_p_frame_damaged = s1->next_p_frame_damaged;
+    s->workaround_bugs      = s1->workaround_bugs;
+
+    // MPEG4 timing info
+    memcpy(&s->time_increment_bits, &s1->time_increment_bits,
+           (char *) &s1->shape - (char *) &s1->time_increment_bits);
+
+    // B-frame info
+    s->max_b_frames = s1->max_b_frames;
+    s->low_delay    = s1->low_delay;
+    s->dropable     = s1->dropable;
+
+    // DivX handling (doesn't work)
+    s->divx_packed  = s1->divx_packed;
+
+    if (s1->bitstream_buffer) {
+        if (s1->bitstream_buffer_size +
+            FF_INPUT_BUFFER_PADDING_SIZE > s->allocated_bitstream_buffer_size)
+            av_fast_malloc(&s->bitstream_buffer,
+                           &s->allocated_bitstream_buffer_size,
+                           s1->allocated_bitstream_buffer_size);
+            s->bitstream_buffer_size = s1->bitstream_buffer_size;
+        memcpy(s->bitstream_buffer, s1->bitstream_buffer,
+               s1->bitstream_buffer_size);
+        memset(s->bitstream_buffer + s->bitstream_buffer_size, 0,
+               FF_INPUT_BUFFER_PADDING_SIZE);
+    }
+
+    // MPEG2/interlacing info
+    memcpy(&s->progressive_sequence, &s1->progressive_sequence,
+           (char *) &s1->rtp_mode - (char *) &s1->progressive_sequence);
+
+    if (!s1->first_field) {
+        s->last_pict_type = s1->pict_type;
+        if (s1->current_picture_ptr)
+            s->last_lambda_for[s1->pict_type] = s1->current_picture_ptr->f.quality;
+
+        if (s1->pict_type != AV_PICTURE_TYPE_B) {
+            s->last_non_b_pict_type = s1->pict_type;
+        }
+    }
+
+    return 0;
 }
 
 /**
- * sets the given MpegEncContext to common defaults (same for encoding and decoding).
- * the changed fields will not depend upon the prior state of the MpegEncContext.
+ * Set the given MpegEncContext to common defaults
+ * (same for encoding and decoding).
+ * The changed fields will not depend upon the
+ * prior state of the MpegEncContext.
  */
-void MPV_common_defaults(MpegEncContext *s){
-    s->y_dc_scale_table=
-    s->c_dc_scale_table= ff_mpeg1_dc_scale_table;
-    s->chroma_qscale_table= ff_default_chroma_qscale_table;
-    s->progressive_frame= 1;
-    s->progressive_sequence= 1;
-    s->picture_structure= PICT_FRAME;
-
-    s->coded_picture_number = 0;
-    s->picture_number = 0;
-    s->input_picture_number = 0;
+void MPV_common_defaults(MpegEncContext *s)
+{
+    s->y_dc_scale_table      =
+    s->c_dc_scale_table      = ff_mpeg1_dc_scale_table;
+    s->chroma_qscale_table   = ff_default_chroma_qscale_table;
+    s->progressive_frame     = 1;
+    s->progressive_sequence  = 1;
+    s->picture_structure     = PICT_FRAME;
+
+    s->coded_picture_number  = 0;
+    s->picture_number        = 0;
+    s->input_picture_number  = 0;
 
     s->picture_in_gop_number = 0;
 
-    s->f_code = 1;
-    s->b_code = 1;
+    s->f_code                = 1;
+    s->b_code                = 1;
+
+    s->picture_range_start   = 0;
+    s->picture_range_end     = MAX_PICTURE_COUNT;
 }
 
 /**
- * sets the given MpegEncContext to defaults for decoding.
- * the changed fields will not depend upon the prior state of the MpegEncContext.
+ * Set the given MpegEncContext to defaults for decoding.
+ * the changed fields will not depend upon
+ * the prior state of the MpegEncContext.
  */
-void MPV_decode_defaults(MpegEncContext *s){
+void MPV_decode_defaults(MpegEncContext *s)
+{
     MPV_common_defaults(s);
 }
 
@@ -494,186 +655,259 @@ void MPV_decode_defaults(MpegEncContext *s){
  */
 av_cold int MPV_common_init(MpegEncContext *s)
 {
-    int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y, threads;
+    int y_size, c_size, yc_size, i, mb_array_size, mv_table_size, x, y,
+        threads = (s->encoding ||
+                   (HAVE_THREADS &&
+                    s->avctx->active_thread_type & FF_THREAD_SLICE)) ?
+                  s->avctx->thread_count : 1;
 
-    if(s->codec_id == CODEC_ID_MPEG2VIDEO && !s->progressive_sequence)
+    if (s->codec_id == CODEC_ID_MPEG2VIDEO && !s->progressive_sequence)
         s->mb_height = (s->height + 31) / 32 * 2;
     else if (s->codec_id != CODEC_ID_H264)
         s->mb_height = (s->height + 15) / 16;
 
-    if(s->avctx->pix_fmt == PIX_FMT_NONE){
-        av_log(s->avctx, AV_LOG_ERROR, "decoding to PIX_FMT_NONE is not supported.\n");
+    if (s->avctx->pix_fmt == PIX_FMT_NONE) {
+        av_log(s->avctx, AV_LOG_ERROR,
+               "decoding to PIX_FMT_NONE is not supported.\n");
         return -1;
     }
 
-    if(s->avctx->thread_count > MAX_THREADS || (s->avctx->thread_count > s->mb_height && s->mb_height)){
-        av_log(s->avctx, AV_LOG_ERROR, "too many threads\n");
-        return -1;
+    if ((s->encoding || (s->avctx->active_thread_type & FF_THREAD_SLICE)) &&
+        (s->avctx->thread_count > MAX_THREADS ||
+         (s->avctx->thread_count > s->mb_height && s->mb_height))) {
+        int max_threads = FFMIN(MAX_THREADS, s->mb_height);
+        av_log(s->avctx, AV_LOG_WARNING,
+               "too many threads (%d), reducing to %d\n",
+               s->avctx->thread_count, max_threads);
+        threads = max_threads;
     }
 
-    if((s->width || s->height) && av_image_check_size(s->width, s->height, 0, s->avctx))
+    if ((s->width || s->height) &&
+        av_image_check_size(s->width, s->height, 0, s->avctx))
         return -1;
 
-    dsputil_init(&s->dsp, s->avctx);
     ff_dct_common_init(s);
 
-    s->flags= s->avctx->flags;
-    s->flags2= s->avctx->flags2;
-
-    s->mb_width  = (s->width  + 15) / 16;
-    s->mb_stride = s->mb_width + 1;
-    s->b8_stride = s->mb_width*2 + 1;
-    s->b4_stride = s->mb_width*4 + 1;
-    mb_array_size= s->mb_height * s->mb_stride;
-    mv_table_size= (s->mb_height+2) * s->mb_stride + 1;
-
-    /* set chroma shifts */
-    avcodec_get_chroma_sub_sample(s->avctx->pix_fmt,&(s->chroma_x_shift),
-                                                    &(s->chroma_y_shift) );
-
-    /* set default edge pos, will be overriden in decode_header if needed */
-    s->h_edge_pos= s->mb_width*16;
-    s->v_edge_pos= s->mb_height*16;
+    s->flags  = s->avctx->flags;
+    s->flags2 = s->avctx->flags2;
 
-    s->mb_num = s->mb_width * s->mb_height;
+    if (s->width && s->height) {
+        s->mb_width   = (s->width + 15) / 16;
+        s->mb_stride  = s->mb_width + 1;
+        s->b8_stride  = s->mb_width * 2 + 1;
+        s->b4_stride  = s->mb_width * 4 + 1;
+        mb_array_size = s->mb_height * s->mb_stride;
+        mv_table_size = (s->mb_height + 2) * s->mb_stride + 1;
 
-    s->block_wrap[0]=
-    s->block_wrap[1]=
-    s->block_wrap[2]=
-    s->block_wrap[3]= s->b8_stride;
-    s->block_wrap[4]=
-    s->block_wrap[5]= s->mb_stride;
+        /* set chroma shifts */
+        avcodec_get_chroma_sub_sample(s->avctx->pix_fmt,&(s->chroma_x_shift),
+                                      &(s->chroma_y_shift) );
 
-    y_size = s->b8_stride * (2 * s->mb_height + 1);
-    c_size = s->mb_stride * (s->mb_height + 1);
-    yc_size = y_size + 2 * c_size;
+        /* set default edge pos, will be overriden
+         * in decode_header if needed */
+        s->h_edge_pos = s->mb_width * 16;
+        s->v_edge_pos = s->mb_height * 16;
 
-    /* convert fourcc to upper case */
-    s->codec_tag = ff_toupper4(s->avctx->codec_tag);
+        s->mb_num     = s->mb_width * s->mb_height;
 
-    s->stream_codec_tag = ff_toupper4(s->avctx->stream_codec_tag);
+        s->block_wrap[0] =
+        s->block_wrap[1] =
+        s->block_wrap[2] =
+        s->block_wrap[3] = s->b8_stride;
+        s->block_wrap[4] =
+        s->block_wrap[5] = s->mb_stride;
 
-    s->avctx->coded_frame= (AVFrame*)&s->current_picture;
+        y_size  = s->b8_stride * (2 * s->mb_height + 1);
+        c_size  = s->mb_stride * (s->mb_height + 1);
+        yc_size = y_size + 2   * c_size;
 
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num+1)*sizeof(int), fail) //error ressilience code looks cleaner with this
-    for(y=0; y<s->mb_height; y++){
-        for(x=0; x<s->mb_width; x++){
-            s->mb_index2xy[ x + y*s->mb_width ] = x + y*s->mb_stride;
-        }
-    }
-    s->mb_index2xy[ s->mb_height*s->mb_width ] = (s->mb_height-1)*s->mb_stride + s->mb_width; //FIXME really needed?
+        /* convert fourcc to upper case */
+        s->codec_tag          = avpriv_toupper4(s->avctx->codec_tag);
 
-    if (s->encoding) {
-        /* Allocate MV tables */
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base            , mv_table_size * 2 * sizeof(int16_t), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base       , mv_table_size * 2 * sizeof(int16_t), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base       , mv_table_size * 2 * sizeof(int16_t), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base , mv_table_size * 2 * sizeof(int16_t), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base , mv_table_size * 2 * sizeof(int16_t), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base     , mv_table_size * 2 * sizeof(int16_t), fail)
-        s->p_mv_table           = s->p_mv_table_base            + s->mb_stride + 1;
-        s->b_forw_mv_table      = s->b_forw_mv_table_base       + s->mb_stride + 1;
-        s->b_back_mv_table      = s->b_back_mv_table_base       + s->mb_stride + 1;
-        s->b_bidir_forw_mv_table= s->b_bidir_forw_mv_table_base + s->mb_stride + 1;
-        s->b_bidir_back_mv_table= s->b_bidir_back_mv_table_base + s->mb_stride + 1;
-        s->b_direct_mv_table    = s->b_direct_mv_table_base     + s->mb_stride + 1;
-
-        if(s->msmpeg4_version){
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats, 2*2*(MAX_LEVEL+1)*(MAX_RUN+1)*2*sizeof(int), fail);
-        }
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->avctx->stats_out, 256, fail);
+        s->stream_codec_tag   = avpriv_toupper4(s->avctx->stream_codec_tag);
 
-        /* Allocate MB type table */
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type  , mb_array_size * sizeof(uint16_t), fail) //needed for encoding
+        s->avctx->coded_frame = (AVFrame *)&s->current_picture;
 
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size * sizeof(int), fail)
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_index2xy, (s->mb_num + 1) * sizeof(int),
+                          fail); // error ressilience code looks cleaner with this
+        for (y = 0; y < s->mb_height; y++)
+            for (x = 0; x < s->mb_width; x++)
+                s->mb_index2xy[x + y * s->mb_width] = x + y * s->mb_stride;
 
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix  , 64*32   * sizeof(int), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix  , 64*32   * sizeof(int), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix16, 64*32*2 * sizeof(uint16_t), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix16, 64*32*2 * sizeof(uint16_t), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->input_picture, MAX_PICTURE_COUNT * sizeof(Picture*), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->reordered_input_picture, MAX_PICTURE_COUNT * sizeof(Picture*), fail)
+        s->mb_index2xy[s->mb_height * s->mb_width] =
+                       (s->mb_height - 1) * s->mb_stride + s->mb_width; // FIXME really needed?
 
-        if(s->avctx->noise_reduction){
-            FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset, 2 * 64 * sizeof(uint16_t), fail)
+        if (s->encoding) {
+            /* Allocate MV tables */
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->p_mv_table_base,
+                              mv_table_size * 2 * sizeof(int16_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_forw_mv_table_base,
+                              mv_table_size * 2 * sizeof(int16_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_back_mv_table_base,
+                              mv_table_size * 2 * sizeof(int16_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_forw_mv_table_base,
+                              mv_table_size * 2 * sizeof(int16_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_bidir_back_mv_table_base,
+                              mv_table_size * 2 * sizeof(int16_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->b_direct_mv_table_base,
+                              mv_table_size * 2 * sizeof(int16_t), fail);
+            s->p_mv_table            = s->p_mv_table_base +
+                                       s->mb_stride + 1;
+            s->b_forw_mv_table       = s->b_forw_mv_table_base +
+                                       s->mb_stride + 1;
+            s->b_back_mv_table       = s->b_back_mv_table_base +
+                                       s->mb_stride + 1;
+            s->b_bidir_forw_mv_table = s->b_bidir_forw_mv_table_base +
+                                       s->mb_stride + 1;
+            s->b_bidir_back_mv_table = s->b_bidir_back_mv_table_base +
+                                       s->mb_stride + 1;
+            s->b_direct_mv_table     = s->b_direct_mv_table_base +
+                                       s->mb_stride + 1;
+
+            if (s->msmpeg4_version) {
+                FF_ALLOCZ_OR_GOTO(s->avctx, s->ac_stats,
+                                  2 * 2 * (MAX_LEVEL + 1) *
+                                  (MAX_RUN + 1) * 2 * sizeof(int), fail);
+            }
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->avctx->stats_out, 256, fail);
+
+            /* Allocate MB type table */
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->mb_type, mb_array_size *
+                              sizeof(uint16_t), fail); // needed for encoding
+
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->lambda_table, mb_array_size *
+                              sizeof(int), fail);
+
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix,
+                              64 * 32   * sizeof(int), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix,
+                              64 * 32   * sizeof(int), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->q_intra_matrix16,
+                              64 * 32 * 2 * sizeof(uint16_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->q_inter_matrix16,
+                              64 * 32 * 2 * sizeof(uint16_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->input_picture,
+                              MAX_PICTURE_COUNT * sizeof(Picture *), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->reordered_input_picture,
+                              MAX_PICTURE_COUNT * sizeof(Picture *), fail);
+
+            if (s->avctx->noise_reduction) {
+                FF_ALLOCZ_OR_GOTO(s->avctx, s->dct_offset,
+                                  2 * 64 * sizeof(uint16_t), fail);
+            }
         }
     }
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->picture, MAX_PICTURE_COUNT * sizeof(Picture), fail)
-    for(i = 0; i < MAX_PICTURE_COUNT; i++) {
-        avcodec_get_frame_defaults((AVFrame *)&s->picture[i]);
+
+    s->picture_count = MAX_PICTURE_COUNT * FFMAX(1, s->avctx->thread_count);
+    FF_ALLOCZ_OR_GOTO(s->avctx, s->picture,
+                      s->picture_count * sizeof(Picture), fail);
+    for (i = 0; i < s->picture_count; i++) {
+        avcodec_get_frame_defaults((AVFrame *) &s->picture[i]);
     }
 
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->error_status_table, mb_array_size*sizeof(uint8_t), fail)
+    if (s->width && s->height) {
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->error_status_table,
+                          mb_array_size * sizeof(uint8_t), fail);
 
-    if(s->codec_id==CODEC_ID_MPEG4 || (s->flags & CODEC_FLAG_INTERLACED_ME)){
-        /* interlaced direct mode decoding tables */
-            for(i=0; i<2; i++){
+        if (s->codec_id == CODEC_ID_MPEG4 ||
+            (s->flags & CODEC_FLAG_INTERLACED_ME)) {
+            /* interlaced direct mode decoding tables */
+            for (i = 0; i < 2; i++) {
                 int j, k;
-                for(j=0; j<2; j++){
-                    for(k=0; k<2; k++){
-                        FF_ALLOCZ_OR_GOTO(s->avctx,    s->b_field_mv_table_base[i][j][k], mv_table_size * 2 * sizeof(int16_t), fail)
-                        s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] + s->mb_stride + 1;
+                for (j = 0; j < 2; j++) {
+                    for (k = 0; k < 2; k++) {
+                        FF_ALLOCZ_OR_GOTO(s->avctx,
+                                          s->b_field_mv_table_base[i][j][k],
+                                          mv_table_size * 2 * sizeof(int16_t),
+                                          fail);
+                        s->b_field_mv_table[i][j][k] = s->b_field_mv_table_base[i][j][k] +
+                                                       s->mb_stride + 1;
                     }
-                    FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j], mb_array_size * 2 * sizeof(uint8_t), fail)
-                    FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j], mv_table_size * 2 * sizeof(int16_t), fail)
-                    s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j]+ s->mb_stride + 1;
+                    FF_ALLOCZ_OR_GOTO(s->avctx, s->b_field_select_table [i][j],
+                                      mb_array_size * 2 * sizeof(uint8_t),
+                                      fail);
+                    FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_mv_table_base[i][j],
+                                      mv_table_size * 2 * sizeof(int16_t),
+                                      fail);
+                    s->p_field_mv_table[i][j] = s->p_field_mv_table_base[i][j]
+                                                + s->mb_stride + 1;
                 }
-                FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i], mb_array_size * 2 * sizeof(uint8_t), fail)
+                FF_ALLOCZ_OR_GOTO(s->avctx, s->p_field_select_table[i],
+                                  mb_array_size * 2 * sizeof(uint8_t),
+                                  fail);
             }
-    }
-    if (s->out_format == FMT_H263) {
-        /* cbp values */
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->coded_block_base, y_size, fail);
-        s->coded_block= s->coded_block_base + s->b8_stride + 1;
-
-        /* cbp, ac_pred, pred_dir */
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table     , mb_array_size * sizeof(uint8_t), fail)
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table, mb_array_size * sizeof(uint8_t), fail)
-    }
-
-    if (s->h263_pred || s->h263_plus || !s->encoding) {
-        /* dc values */
-        //MN: we need these for error resilience of intra-frames
-        FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base, yc_size * sizeof(int16_t), fail);
-        s->dc_val[0] = s->dc_val_base + s->b8_stride + 1;
-        s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1;
-        s->dc_val[2] = s->dc_val[1] + c_size;
-        for(i=0;i<yc_size;i++)
-            s->dc_val_base[i] = 1024;
-    }
-
-    /* which mb is a intra block */
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->mbintra_table, mb_array_size, fail);
-    memset(s->mbintra_table, 1, mb_array_size);
+        }
+        if (s->out_format == FMT_H263) {
+            /* cbp values */
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->coded_block_base, y_size, fail);
+            s->coded_block = s->coded_block_base + s->b8_stride + 1;
+
+            /* cbp, ac_pred, pred_dir */
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->cbp_table,
+                              mb_array_size * sizeof(uint8_t), fail);
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->pred_dir_table,
+                              mb_array_size * sizeof(uint8_t), fail);
+        }
 
-    /* init macroblock skip table */
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size+2, fail);
-    //Note the +1 is for a quicker mpeg4 slice_end detection
-    FF_ALLOCZ_OR_GOTO(s->avctx, s->prev_pict_types, PREV_PICT_TYPES_BUFFER_SIZE, fail);
+        if (s->h263_pred || s->h263_plus || !s->encoding) {
+            /* dc values */
+            // MN: we need these for  error resilience of intra-frames
+            FF_ALLOCZ_OR_GOTO(s->avctx, s->dc_val_base,
+                              yc_size * sizeof(int16_t), fail);
+            s->dc_val[0] = s->dc_val_base + s->b8_stride + 1;
+            s->dc_val[1] = s->dc_val_base + y_size + s->mb_stride + 1;
+            s->dc_val[2] = s->dc_val[1] + c_size;
+            for (i = 0; i < yc_size; i++)
+                s->dc_val_base[i] = 1024;
+        }
 
-    s->parse_context.state= -1;
-    if((s->avctx->debug&(FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) || (s->avctx->debug_mv)){
-       s->visualization_buffer[0] = av_malloc((s->mb_width*16 + 2*EDGE_WIDTH) * s->mb_height*16 + 2*EDGE_WIDTH);
-       s->visualization_buffer[1] = av_malloc((s->mb_width*16 + 2*EDGE_WIDTH) * s->mb_height*16 + 2*EDGE_WIDTH);
-       s->visualization_buffer[2] = av_malloc((s->mb_width*16 + 2*EDGE_WIDTH) * s->mb_height*16 + 2*EDGE_WIDTH);
+        /* which mb is a intra block */
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->mbintra_table, mb_array_size, fail);
+        memset(s->mbintra_table, 1, mb_array_size);
+
+        /* init macroblock skip table */
+        FF_ALLOCZ_OR_GOTO(s->avctx, s->mbskip_table, mb_array_size + 2, fail);
+        // Note the + 1 is for  a quicker mpeg4 slice_end detection
+
+        s->parse_context.state = -1;
+        if ((s->avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) ||
+            s->avctx->debug_mv) {
+            s->visualization_buffer[0] = av_malloc((s->mb_width * 16 +
+                        2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH);
+            s->visualization_buffer[1] = av_malloc((s->mb_width * 16 +
+                        2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH);
+            s->visualization_buffer[2] = av_malloc((s->mb_width * 16 +
+                        2 * EDGE_WIDTH) * s->mb_height * 16 + 2 * EDGE_WIDTH);
+        }
     }
 
     s->context_initialized = 1;
+    s->thread_context[0]   = s;
+
+    if (s->width && s->height) {
+        if (s->encoding || (HAVE_THREADS &&
+                            s->avctx->active_thread_type&FF_THREAD_SLICE)) {
+            for (i = 1; i < threads; i++) {
+                s->thread_context[i] = av_malloc(sizeof(MpegEncContext));
+                memcpy(s->thread_context[i], s, sizeof(MpegEncContext));
+            }
 
-    s->thread_context[0]= s;
-    threads = s->avctx->thread_count;
-
-    for(i=1; i<threads; i++){
-        s->thread_context[i]= av_malloc(sizeof(MpegEncContext));
-        memcpy(s->thread_context[i], s, sizeof(MpegEncContext));
-    }
-
-    for(i=0; i<threads; i++){
-        if(init_duplicate_context(s->thread_context[i], s) < 0)
-           goto fail;
-        s->thread_context[i]->start_mb_y= (s->mb_height*(i  ) + s->avctx->thread_count/2) / s->avctx->thread_count;
-        s->thread_context[i]->end_mb_y  = (s->mb_height*(i+1) + s->avctx->thread_count/2) / s->avctx->thread_count;
+            for (i = 0; i < threads; i++) {
+                if (init_duplicate_context(s->thread_context[i], s) < 0)
+                    goto fail;
+                    s->thread_context[i]->start_mb_y =
+                        (s->mb_height * (i) + s->avctx->thread_count / 2) /
+                        s->avctx->thread_count;
+                    s->thread_context[i]->end_mb_y   =
+                        (s->mb_height * (i + 1) + s->avctx->thread_count / 2) /
+                        s->avctx->thread_count;
+            }
+        } else {
+            if (init_duplicate_context(s, s) < 0)
+                goto fail;
+            s->start_mb_y = 0;
+            s->end_mb_y   = s->mb_height;
+        }
     }
 
     return 0;
@@ -687,15 +921,18 @@ void MPV_common_end(MpegEncContext *s)
 {
     int i, j, k;
 
-    for(i=0; i<s->avctx->thread_count; i++){
-        free_duplicate_context(s->thread_context[i]);
-    }
-    for(i=1; i<s->avctx->thread_count; i++){
-        av_freep(&s->thread_context[i]);
-    }
+    if (s->encoding || (HAVE_THREADS &&
+        s->avctx->active_thread_type & FF_THREAD_SLICE)) {
+        for (i = 0; i < s->avctx->thread_count; i++) {
+            free_duplicate_context(s->thread_context[i]);
+        }
+        for (i = 1; i < s->avctx->thread_count; i++) {
+            av_freep(&s->thread_context[i]);
+        }
+    } else free_duplicate_context(s);
 
     av_freep(&s->parse_context.buffer);
-    s->parse_context.buffer_size=0;
+    s->parse_context.buffer_size = 0;
 
     av_freep(&s->mb_type);
     av_freep(&s->p_mv_table_base);
@@ -704,21 +941,21 @@ void MPV_common_end(MpegEncContext *s)
     av_freep(&s->b_bidir_forw_mv_table_base);
     av_freep(&s->b_bidir_back_mv_table_base);
     av_freep(&s->b_direct_mv_table_base);
-    s->p_mv_table= NULL;
-    s->b_forw_mv_table= NULL;
-    s->b_back_mv_table= NULL;
-    s->b_bidir_forw_mv_table= NULL;
-    s->b_bidir_back_mv_table= NULL;
-    s->b_direct_mv_table= NULL;
-    for(i=0; i<2; i++){
-        for(j=0; j<2; j++){
-            for(k=0; k<2; k++){
+    s->p_mv_table            = NULL;
+    s->b_forw_mv_table       = NULL;
+    s->b_back_mv_table       = NULL;
+    s->b_bidir_forw_mv_table = NULL;
+    s->b_bidir_back_mv_table = NULL;
+    s->b_direct_mv_table     = NULL;
+    for (i = 0; i < 2; i++) {
+        for (j = 0; j < 2; j++) {
+            for (k = 0; k < 2; k++) {
                 av_freep(&s->b_field_mv_table_base[i][j][k]);
-                s->b_field_mv_table[i][j][k]=NULL;
+                s->b_field_mv_table[i][j][k] = NULL;
             }
             av_freep(&s->b_field_select_table[i][j]);
             av_freep(&s->p_field_mv_table_base[i][j]);
-            s->p_field_mv_table[i][j]=NULL;
+            s->p_field_mv_table[i][j] = NULL;
         }
         av_freep(&s->p_field_select_table[i]);
     }
@@ -730,9 +967,8 @@ void MPV_common_end(MpegEncContext *s)
     av_freep(&s->pred_dir_table);
 
     av_freep(&s->mbskip_table);
-    av_freep(&s->prev_pict_types);
     av_freep(&s->bitstream_buffer);
-    s->allocated_bitstream_buffer_size=0;
+    s->allocated_bitstream_buffer_size = 0;
 
     av_freep(&s->avctx->stats_out);
     av_freep(&s->ac_stats);
@@ -747,36 +983,38 @@ void MPV_common_end(MpegEncContext *s)
     av_freep(&s->reordered_input_picture);
     av_freep(&s->dct_offset);
 
-    if(s->picture){
-        for(i=0; i<MAX_PICTURE_COUNT; i++){
+    if (s->picture && !s->avctx->internal->is_copy) {
+        for (i = 0; i < s->picture_count; i++) {
             free_picture(s, &s->picture[i]);
         }
     }
     av_freep(&s->picture);
-    s->context_initialized = 0;
-    s->last_picture_ptr=
-    s->next_picture_ptr=
-    s->current_picture_ptr= NULL;
-    s->linesize= s->uvlinesize= 0;
+    s->context_initialized      = 0;
+    s->last_picture_ptr         =
+    s->next_picture_ptr         =
+    s->current_picture_ptr      = NULL;
+    s->linesize = s->uvlinesize = 0;
 
-    for(i=0; i<3; i++)
+    for (i = 0; i < 3; i++)
         av_freep(&s->visualization_buffer[i]);
 
-    avcodec_default_free_buffers(s->avctx);
+    if (!(s->avctx->active_thread_type & FF_THREAD_FRAME))
+        avcodec_default_free_buffers(s->avctx);
 }
 
-void init_rl(RLTable *rl, uint8_t static_store[2][2*MAX_RUN + MAX_LEVEL + 3])
+void init_rl(RLTable *rl,
+             uint8_t static_store[2][2 * MAX_RUN + MAX_LEVEL + 3])
 {
-    int8_t max_level[MAX_RUN+1], max_run[MAX_LEVEL+1];
-    uint8_t index_run[MAX_RUN+1];
+    int8_t  max_level[MAX_RUN + 1], max_run[MAX_LEVEL + 1];
+    uint8_t index_run[MAX_RUN + 1];
     int last, run, level, start, end, i;
 
-    /* If table is static, we can quit if rl->max_level[0] is not NULL */
-    if(static_store && rl->max_level[0])
+    /* If  table is static, we can quit if rl->max_level[0] is not NULL */
+    if (static_store && rl->max_level[0])
         return;
 
     /* compute max_level[], max_run[] and index_run[] */
-    for(last=0;last<2;last++) {
+    for (last = 0; last < 2; last++) {
         if (last == 0) {
             start = 0;
             end = rl->last;
@@ -788,8 +1026,8 @@ void init_rl(RLTable *rl, uint8_t static_store[2][2*MAX_RUN + MAX_LEVEL + 3])
         memset(max_level, 0, MAX_RUN + 1);
         memset(max_run, 0, MAX_LEVEL + 1);
         memset(index_run, rl->n, MAX_RUN + 1);
-        for(i=start;i<end;i++) {
-            run = rl->table_run[i];
+        for (i = start; i < end; i++) {
+            run   = rl->table_run[i];
             level = rl->table_level[i];
             if (index_run[run] == rl->n)
                 index_run[run] = i;
@@ -798,17 +1036,17 @@ void init_rl(RLTable *rl, uint8_t static_store[2][2*MAX_RUN + MAX_LEVEL + 3])
             if (run > max_run[level])
                 max_run[level] = run;
         }
-        if(static_store)
+        if (static_store)
             rl->max_level[last] = static_store[last];
         else
             rl->max_level[last] = av_malloc(MAX_RUN + 1);
         memcpy(rl->max_level[last], max_level, MAX_RUN + 1);
-        if(static_store)
-            rl->max_run[last] = static_store[last] + MAX_RUN + 1;
+        if (static_store)
+            rl->max_run[last]   = static_store[last] + MAX_RUN + 1;
         else
-            rl->max_run[last] = av_malloc(MAX_LEVEL + 1);
+            rl->max_run[last]   = av_malloc(MAX_LEVEL + 1);
         memcpy(rl->max_run[last], max_run, MAX_LEVEL + 1);
-        if(static_store)
+        if (static_store)
             rl->index_run[last] = static_store[last] + MAX_RUN + MAX_LEVEL + 2;
         else
             rl->index_run[last] = av_malloc(MAX_RUN + 1);
@@ -820,72 +1058,78 @@ void init_vlc_rl(RLTable *rl)
 {
     int i, q;
 
-    for(q=0; q<32; q++){
-        int qmul= q*2;
-        int qadd= (q-1)|1;
+    for (q = 0; q < 32; q++) {
+        int qmul = q * 2;
+        int qadd = (q - 1) | 1;
 
-        if(q==0){
-            qmul=1;
-            qadd=0;
+        if (q == 0) {
+            qmul = 1;
+            qadd = 0;
         }
-        for(i=0; i<rl->vlc.table_size; i++){
-            int code= rl->vlc.table[i][0];
-            int len = rl->vlc.table[i][1];
+        for (i = 0; i < rl->vlc.table_size; i++) {
+            int code = rl->vlc.table[i][0];
+            int len  = rl->vlc.table[i][1];
             int level, run;
 
-            if(len==0){ // illegal code
-                run= 66;
-                level= MAX_LEVEL;
-            }else if(len<0){ //more bits needed
-                run= 0;
-                level= code;
-            }else{
-                if(code==rl->n){ //esc
-                    run= 66;
-                    level= 0;
-                }else{
-                    run=   rl->table_run  [code] + 1;
-                    level= rl->table_level[code] * qmul + qadd;
-                    if(code >= rl->last) run+=192;
+            if (len == 0) { // illegal code
+                run   = 66;
+                level = MAX_LEVEL;
+            } else if (len < 0) { // more bits needed
+                run   = 0;
+                level = code;
+            } else {
+                if (code == rl->n) { // esc
+                    run   = 66;
+                    level =  0;
+                } else {
+                    run   = rl->table_run[code] + 1;
+                    level = rl->table_level[code] * qmul + qadd;
+                    if (code >= rl->last) run += 192;
                 }
             }
-            rl->rl_vlc[q][i].len= len;
-            rl->rl_vlc[q][i].level= level;
-            rl->rl_vlc[q][i].run= run;
+            rl->rl_vlc[q][i].len   = len;
+            rl->rl_vlc[q][i].level = level;
+            rl->rl_vlc[q][i].run   = run;
         }
     }
 }
 
-int ff_find_unused_picture(MpegEncContext *s, int shared){
+void ff_release_unused_pictures(MpegEncContext*s, int remove_current)
+{
     int i;
 
-    if(shared){
-        for(i=0; i<MAX_PICTURE_COUNT; i++){
-            if(s->picture[i].data[0]==NULL && s->picture[i].type==0) return i;
+    /* release non reference frames */
+    for (i = 0; i < s->picture_count; i++) {
+        if (s->picture[i].f.data[0] && !s->picture[i].f.reference &&
+            (!s->picture[i].owner2 || s->picture[i].owner2 == s) &&
+            (remove_current || &s->picture[i] !=  s->current_picture_ptr)
+            /* && s->picture[i].type!= FF_BUFFER_TYPE_SHARED */) {
+            free_frame_buffer(s, &s->picture[i]);
         }
-    }else{
-        for(i=0; i<MAX_PICTURE_COUNT; i++){
-            if(s->picture[i].data[0]==NULL && s->picture[i].type!=0) return i; //FIXME
+    }
+}
+
+int ff_find_unused_picture(MpegEncContext *s, int shared)
+{
+    int i;
+
+    if (shared) {
+        for (i = s->picture_range_start; i < s->picture_range_end; i++) {
+            if (s->picture[i].f.data[0] == NULL && s->picture[i].f.type == 0)
+                return i;
         }
-        for(i=0; i<MAX_PICTURE_COUNT; i++){
-            if(s->picture[i].data[0]==NULL) return i;
+    } else {
+        for (i = s->picture_range_start; i < s->picture_range_end; i++) {
+            if (s->picture[i].f.data[0] == NULL && s->picture[i].f.type != 0)
+                return i; // FIXME
+        }
+        for (i = s->picture_range_start; i < s->picture_range_end; i++) {
+            if (s->picture[i].f.data[0] == NULL)
+                return i;
         }
     }
 
-    av_log(s->avctx, AV_LOG_FATAL, "Internal error, picture buffer overflow\n");
-    /* We could return -1, but the codec would crash trying to draw into a
-     * non-existing frame anyway. This is safer than waiting for a random crash.
-     * Also the return of this is never useful, an encoder must only allocate
-     * as much as allowed in the specification. This has no relationship to how
-     * much libavcodec could allocate (and MAX_PICTURE_COUNT is always large
-     * enough for such valid streams).
-     * Plus, a decoder has to check stream validity and remove frames if too
-     * many reference frames are around. Waiting for "OOM" is not correct at
-     * all. Similarly, missing reference frames have to be replaced by
-     * interpolated/MC frames, anything else is a bug in the codec ...
-     */
-    abort();
-    return -1;
+    return AVERROR_INVALIDDATA;
 }
 
 static void update_noise_reduction(MpegEncContext *s){
@@ -917,16 +1161,18 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     assert(s->last_picture_ptr==NULL || s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3);
 
     /* mark&release old frames */
-    if (s->pict_type != FF_B_TYPE && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && s->last_picture_ptr->data[0]) {
+    if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && s->last_picture_ptr->f.data[0]) {
       if(s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3){
-          free_frame_buffer(s, s->last_picture_ptr);
+          if (s->last_picture_ptr->owner2 == s)
+              free_frame_buffer(s, s->last_picture_ptr);
 
         /* release forgotten pictures */
         /* if(mpeg124/h263) */
         if(!s->encoding){
-            for(i=0; i<MAX_PICTURE_COUNT; i++){
-                if(s->picture[i].data[0] && &s->picture[i] != s->next_picture_ptr && s->picture[i].reference){
-                    av_log(avctx, AV_LOG_ERROR, "releasing zombie picture\n");
+            for(i=0; i<s->picture_count; i++){
+                if (s->picture[i].owner2 == s && s->picture[i].f.data[0] && &s->picture[i] != s->next_picture_ptr && s->picture[i].f.reference) {
+                    if (!(avctx->active_thread_type & FF_THREAD_FRAME))
+                        av_log(avctx, AV_LOG_ERROR, "releasing zombie picture\n");
                     free_frame_buffer(s, &s->picture[i]);
                 }
             }
@@ -935,100 +1181,108 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     }
 
     if(!s->encoding){
-        /* release non reference frames */
-        for(i=0; i<MAX_PICTURE_COUNT; i++){
-            if(s->picture[i].data[0] && !s->picture[i].reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/){
-                free_frame_buffer(s, &s->picture[i]);
-            }
-        }
+        ff_release_unused_pictures(s, 1);
 
-        if(s->current_picture_ptr && s->current_picture_ptr->data[0]==NULL)
+        if (s->current_picture_ptr && s->current_picture_ptr->f.data[0] == NULL)
             pic= s->current_picture_ptr; //we already have a unused image (maybe it was set before reading the header)
         else{
             i= ff_find_unused_picture(s, 0);
+            if (i < 0)
+                return i;
             pic= &s->picture[i];
         }
 
-        pic->reference= 0;
+        pic->f.reference = 0;
         if (!s->dropable){
             if (s->codec_id == CODEC_ID_H264)
-                pic->reference = s->picture_structure;
-            else if (s->pict_type != FF_B_TYPE)
-                pic->reference = 3;
+                pic->f.reference = s->picture_structure;
+            else if (s->pict_type != AV_PICTURE_TYPE_B)
+                pic->f.reference = 3;
         }
 
-        pic->coded_picture_number= s->coded_picture_number++;
+        pic->f.coded_picture_number = s->coded_picture_number++;
 
         if(ff_alloc_picture(s, pic, 0) < 0)
             return -1;
 
         s->current_picture_ptr= pic;
         //FIXME use only the vars from current_pic
-        s->current_picture_ptr->top_field_first= s->top_field_first;
+        s->current_picture_ptr->f.top_field_first = s->top_field_first;
         if(s->codec_id == CODEC_ID_MPEG1VIDEO || s->codec_id == CODEC_ID_MPEG2VIDEO) {
             if(s->picture_structure != PICT_FRAME)
-                s->current_picture_ptr->top_field_first= (s->picture_structure == PICT_TOP_FIELD) == s->first_field;
+                s->current_picture_ptr->f.top_field_first = (s->picture_structure == PICT_TOP_FIELD) == s->first_field;
         }
-        s->current_picture_ptr->interlaced_frame= !s->progressive_frame && !s->progressive_sequence;
+        s->current_picture_ptr->f.interlaced_frame = !s->progressive_frame && !s->progressive_sequence;
+        s->current_picture_ptr->field_picture = s->picture_structure != PICT_FRAME;
     }
 
-    s->current_picture_ptr->pict_type= s->pict_type;
+    s->current_picture_ptr->f.pict_type = s->pict_type;
 //    if(s->flags && CODEC_FLAG_QSCALE)
   //      s->current_picture_ptr->quality= s->new_picture_ptr->quality;
-    s->current_picture_ptr->key_frame= s->pict_type == FF_I_TYPE;
+    s->current_picture_ptr->f.key_frame = s->pict_type == AV_PICTURE_TYPE_I;
 
     ff_copy_picture(&s->current_picture, s->current_picture_ptr);
 
-    if (s->pict_type != FF_B_TYPE) {
+    if (s->pict_type != AV_PICTURE_TYPE_B) {
         s->last_picture_ptr= s->next_picture_ptr;
         if(!s->dropable)
             s->next_picture_ptr= s->current_picture_ptr;
     }
 /*    av_log(s->avctx, AV_LOG_DEBUG, "L%p N%p C%p L%p N%p C%p type:%d drop:%d\n", s->last_picture_ptr, s->next_picture_ptr,s->current_picture_ptr,
-        s->last_picture_ptr    ? s->last_picture_ptr->data[0] : NULL,
-        s->next_picture_ptr    ? s->next_picture_ptr->data[0] : NULL,
-        s->current_picture_ptr ? s->current_picture_ptr->data[0] : NULL,
+        s->last_picture_ptr    ? s->last_picture_ptr->f.data[0]    : NULL,
+        s->next_picture_ptr    ? s->next_picture_ptr->f.data[0]    : NULL,
+        s->current_picture_ptr ? s->current_picture_ptr->f.data[0] : NULL,
         s->pict_type, s->dropable);*/
 
     if(s->codec_id != CODEC_ID_H264){
-        if((s->last_picture_ptr==NULL || s->last_picture_ptr->data[0]==NULL) && s->pict_type!=FF_I_TYPE){
-            av_log(avctx, AV_LOG_ERROR, "warning: first frame is no keyframe\n");
+        if ((s->last_picture_ptr == NULL || s->last_picture_ptr->f.data[0] == NULL) &&
+           (s->pict_type!=AV_PICTURE_TYPE_I || s->picture_structure != PICT_FRAME)){
+            if (s->pict_type != AV_PICTURE_TYPE_I)
+                av_log(avctx, AV_LOG_ERROR, "warning: first frame is no keyframe\n");
+            else if (s->picture_structure != PICT_FRAME)
+                av_log(avctx, AV_LOG_INFO, "allocate dummy last picture for field based first keyframe\n");
+
             /* Allocate a dummy frame */
             i= ff_find_unused_picture(s, 0);
+            if (i < 0)
+                return i;
             s->last_picture_ptr= &s->picture[i];
             if(ff_alloc_picture(s, s->last_picture_ptr, 0) < 0)
                 return -1;
+            ff_thread_report_progress((AVFrame*)s->last_picture_ptr, INT_MAX, 0);
+            ff_thread_report_progress((AVFrame*)s->last_picture_ptr, INT_MAX, 1);
         }
-        if((s->next_picture_ptr==NULL || s->next_picture_ptr->data[0]==NULL) && s->pict_type==FF_B_TYPE){
+        if ((s->next_picture_ptr == NULL || s->next_picture_ptr->f.data[0] == NULL) && s->pict_type == AV_PICTURE_TYPE_B) {
             /* Allocate a dummy frame */
             i= ff_find_unused_picture(s, 0);
+            if (i < 0)
+                return i;
             s->next_picture_ptr= &s->picture[i];
             if(ff_alloc_picture(s, s->next_picture_ptr, 0) < 0)
                 return -1;
+            ff_thread_report_progress((AVFrame*)s->next_picture_ptr, INT_MAX, 0);
+            ff_thread_report_progress((AVFrame*)s->next_picture_ptr, INT_MAX, 1);
         }
     }
 
     if(s->last_picture_ptr) ff_copy_picture(&s->last_picture, s->last_picture_ptr);
     if(s->next_picture_ptr) ff_copy_picture(&s->next_picture, s->next_picture_ptr);
 
-    assert(s->pict_type == FF_I_TYPE || (s->last_picture_ptr && s->last_picture_ptr->data[0]));
+    assert(s->pict_type == AV_PICTURE_TYPE_I || (s->last_picture_ptr && s->last_picture_ptr->f.data[0]));
 
     if(s->picture_structure!=PICT_FRAME && s->out_format != FMT_H264){
         int i;
         for(i=0; i<4; i++){
             if(s->picture_structure == PICT_BOTTOM_FIELD){
-                 s->current_picture.data[i] += s->current_picture.linesize[i];
+                 s->current_picture.f.data[i] += s->current_picture.f.linesize[i];
             }
-            s->current_picture.linesize[i] *= 2;
-            s->last_picture.linesize[i] *=2;
-            s->next_picture.linesize[i] *=2;
+            s->current_picture.f.linesize[i] *= 2;
+            s->last_picture.f.linesize[i]    *= 2;
+            s->next_picture.f.linesize[i]    *= 2;
         }
     }
 
-#if FF_API_HURRY_UP
-    s->hurry_up= s->avctx->hurry_up;
-#endif
-    s->error_recognition= avctx->error_recognition;
+    s->err_recognition = avctx->err_recognition;
 
     /* set dequantizer, we can't do it during init as it might change for mpeg4
        and we can't do it in the header decode as init is not called for mpeg4 there yet */
@@ -1059,37 +1313,41 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
 void MPV_frame_end(MpegEncContext *s)
 {
     int i;
-    /* draw edge for correct motion prediction if outside */
+    /* redraw edges for the frame if decoding didn't complete */
     //just to make sure that all data is rendered.
     if(CONFIG_MPEG_XVMC_DECODER && s->avctx->xvmc_acceleration){
         ff_xvmc_field_end(s);
-    }else if(!s->avctx->hwaccel
+   }else if((s->error_count || s->encoding)
+       && !s->avctx->hwaccel
        && !(s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
        && s->unrestricted_mv
-       && s->current_picture.reference
+       && s->current_picture.f.reference
        && !s->intra_only
        && !(s->flags&CODEC_FLAG_EMU_EDGE)) {
-            s->dsp.draw_edges(s->current_picture.data[0], s->linesize  ,
-                              s->h_edge_pos   , s->v_edge_pos   ,
-                              EDGE_WIDTH  , EDGE_TOP | EDGE_BOTTOM);
-            s->dsp.draw_edges(s->current_picture.data[1], s->uvlinesize,
-                              s->h_edge_pos>>1, s->v_edge_pos>>1,
-                              EDGE_WIDTH/2, EDGE_TOP | EDGE_BOTTOM);
-            s->dsp.draw_edges(s->current_picture.data[2], s->uvlinesize,
-                              s->h_edge_pos>>1, s->v_edge_pos>>1,
-                              EDGE_WIDTH/2, EDGE_TOP | EDGE_BOTTOM);
+            int hshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_w;
+            int vshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_h;
+            s->dsp.draw_edges(s->current_picture.f.data[0], s->linesize,
+                              s->h_edge_pos             , s->v_edge_pos,
+                              EDGE_WIDTH        , EDGE_WIDTH        , EDGE_TOP | EDGE_BOTTOM);
+            s->dsp.draw_edges(s->current_picture.f.data[1], s->uvlinesize,
+                              s->h_edge_pos>>hshift, s->v_edge_pos>>vshift,
+                              EDGE_WIDTH>>hshift, EDGE_WIDTH>>vshift, EDGE_TOP | EDGE_BOTTOM);
+            s->dsp.draw_edges(s->current_picture.f.data[2], s->uvlinesize,
+                              s->h_edge_pos>>hshift, s->v_edge_pos>>vshift,
+                              EDGE_WIDTH>>hshift, EDGE_WIDTH>>vshift, EDGE_TOP | EDGE_BOTTOM);
     }
+
     emms_c();
 
     s->last_pict_type    = s->pict_type;
-    s->last_lambda_for[s->pict_type]= s->current_picture_ptr->quality;
-    if(s->pict_type!=FF_B_TYPE){
+    s->last_lambda_for[s->pict_type] = s->current_picture_ptr->f.quality;
+    if(s->pict_type!=AV_PICTURE_TYPE_B){
         s->last_non_b_pict_type= s->pict_type;
     }
 #if 0
         /* copy back current_picture variables */
     for(i=0; i<MAX_PICTURE_COUNT; i++){
-        if(s->picture[i].data[0] == s->current_picture.data[0]){
+        if(s->picture[i].f.data[0] == s->current_picture.f.data[0]){
             s->picture[i]= s->current_picture;
             break;
         }
@@ -1099,8 +1357,8 @@ void MPV_frame_end(MpegEncContext *s)
 
     if(s->encoding){
         /* release non-reference frames */
-        for(i=0; i<MAX_PICTURE_COUNT; i++){
-            if(s->picture[i].data[0] && !s->picture[i].reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/){
+        for(i=0; i<s->picture_count; i++){
+            if (s->picture[i].f.data[0] && !s->picture[i].f.reference /*&& s->picture[i].type != FF_BUFFER_TYPE_SHARED*/) {
                 free_frame_buffer(s, &s->picture[i]);
             }
         }
@@ -1112,10 +1370,14 @@ void MPV_frame_end(MpegEncContext *s)
     memset(&s->current_picture, 0, sizeof(Picture));
 #endif
     s->avctx->coded_frame= (AVFrame*)s->current_picture_ptr;
+
+    if (s->codec_id != CODEC_ID_H264 && s->current_picture.f.reference) {
+        ff_thread_report_progress((AVFrame*)s->current_picture_ptr, s->mb_height-1, 0);
+    }
 }
 
 /**
- * draws an line from (ex, ey) -> (sx, sy).
+ * Draw a line from (ex, ey) -> (sx, sy).
  * @param w width of the image
  * @param h height of the image
  * @param stride stride/linesize of the image
@@ -1164,7 +1426,7 @@ static void draw_line(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int h
 }
 
 /**
- * draws an arrow from (ex, ey) -> (sx, sy).
+ * Draw an arrow from (ex, ey) -> (sx, sy).
  * @param w width of the image
  * @param h height of the image
  * @param stride stride/linesize of the image
@@ -1197,7 +1459,7 @@ static void draw_arrow(uint8_t *buf, int sx, int sy, int ex, int ey, int w, int
 }
 
 /**
- * prints debuging info for the given picture.
+ * Print debuging info for the given picture.
  */
 void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
 
@@ -1208,12 +1470,12 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
 
         av_log(s->avctx,AV_LOG_DEBUG,"New frame, type: ");
         switch (pict->pict_type) {
-            case FF_I_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"I\n"); break;
-            case FF_P_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"P\n"); break;
-            case FF_B_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"B\n"); break;
-            case FF_S_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"S\n"); break;
-            case FF_SI_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"SI\n"); break;
-            case FF_SP_TYPE: av_log(s->avctx,AV_LOG_DEBUG,"SP\n"); break;
+            case AV_PICTURE_TYPE_I: av_log(s->avctx,AV_LOG_DEBUG,"I\n"); break;
+            case AV_PICTURE_TYPE_P: av_log(s->avctx,AV_LOG_DEBUG,"P\n"); break;
+            case AV_PICTURE_TYPE_B: av_log(s->avctx,AV_LOG_DEBUG,"B\n"); break;
+            case AV_PICTURE_TYPE_S: av_log(s->avctx,AV_LOG_DEBUG,"S\n"); break;
+            case AV_PICTURE_TYPE_SI: av_log(s->avctx,AV_LOG_DEBUG,"SI\n"); break;
+            case AV_PICTURE_TYPE_SP: av_log(s->avctx,AV_LOG_DEBUG,"SP\n"); break;
         }
         for(y=0; y<s->mb_height; y++){
             for(x=0; x<s->mb_width; x++){
@@ -1279,7 +1541,8 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
         }
     }
 
-    if((s->avctx->debug&(FF_DEBUG_VIS_QP|FF_DEBUG_VIS_MB_TYPE)) || (s->avctx->debug_mv)){
+    if ((s->avctx->debug & (FF_DEBUG_VIS_QP | FF_DEBUG_VIS_MB_TYPE)) ||
+        s->avctx->debug_mv) {
         const int shift= 1 + s->quarter_sample;
         int mb_y;
         uint8_t *ptr;
@@ -1304,20 +1567,20 @@ void ff_print_debug_info(MpegEncContext *s, AVFrame *pict){
             int mb_x;
             for(mb_x=0; mb_x<s->mb_width; mb_x++){
                 const int mb_index= mb_x + mb_y*s->mb_stride;
-                if((s->avctx->debug_mv) && pict->motion_val){
+                if (s->avctx->debug_mv && pict->motion_val) {
                   int type;
                   for(type=0; type<3; type++){
                     int direction = 0;
                     switch (type) {
-                      case 0: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_P_FOR)) || (pict->pict_type!=FF_P_TYPE))
+                      case 0: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_P_FOR)) || (pict->pict_type!=AV_PICTURE_TYPE_P))
                                 continue;
                               direction = 0;
                               break;
-                      case 1: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_FOR)) || (pict->pict_type!=FF_B_TYPE))
+                      case 1: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_FOR)) || (pict->pict_type!=AV_PICTURE_TYPE_B))
                                 continue;
                               direction = 0;
                               break;
-                      case 2: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_BACK)) || (pict->pict_type!=FF_B_TYPE))
+                      case 2: if ((!(s->avctx->debug_mv&FF_DEBUG_VIS_MV_B_BACK)) || (pict->pict_type!=AV_PICTURE_TYPE_B))
                                 continue;
                               direction = 1;
                               break;
@@ -1516,8 +1779,8 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
     const int s_mask= (2<<lowres)-1;
     const int h_edge_pos = s->h_edge_pos >> lowres;
     const int v_edge_pos = s->v_edge_pos >> lowres;
-    linesize   = s->current_picture.linesize[0] << field_based;
-    uvlinesize = s->current_picture.linesize[1] << field_based;
+    linesize   = s->current_picture.f.linesize[0] << field_based;
+    uvlinesize = s->current_picture.f.linesize[1] << field_based;
 
     if(s->quarter_sample){ //FIXME obviously not perfect but qpel will not work in lowres anyway
         motion_x/=2;
@@ -1574,7 +1837,7 @@ static av_always_inline void mpeg_motion_lowres(MpegEncContext *s,
             }
     }
 
-    if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.data
+    if(bottom_field){ //FIXME use this for field pix too instead of the obnoxious hack which changes picture.f.data
         dest_y += s->linesize;
         dest_cb+= s->uvlinesize;
         dest_cr+= s->uvlinesize;
@@ -1713,8 +1976,8 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
                         ref_picture, pix_op,
                         s->mv[dir][1][0], s->mv[dir][1][1], block_s, mb_y);
         } else {
-            if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != FF_B_TYPE && !s->first_field){
-                ref_picture= s->current_picture_ptr->data;
+            if(s->picture_structure != s->field_select[dir][0] + 1 && s->pict_type != AV_PICTURE_TYPE_B && !s->first_field){
+                ref_picture = s->current_picture_ptr->f.data;
             }
 
             mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
@@ -1727,10 +1990,10 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
         for(i=0; i<2; i++){
             uint8_t ** ref2picture;
 
-            if(s->picture_structure == s->field_select[dir][i] + 1 || s->pict_type == FF_B_TYPE || s->first_field){
+            if(s->picture_structure == s->field_select[dir][i] + 1 || s->pict_type == AV_PICTURE_TYPE_B || s->first_field){
                 ref2picture= ref_picture;
             }else{
-                ref2picture= s->current_picture_ptr->data;
+                ref2picture = s->current_picture_ptr->f.data;
             }
 
             mpeg_motion_lowres(s, dest_y, dest_cb, dest_cr,
@@ -1767,7 +2030,7 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
 
                 //opposite parity is always in the same frame if this is second field
                 if(!s->first_field){
-                    ref_picture = s->current_picture_ptr->data;
+                    ref_picture = s->current_picture_ptr->f.data;
                 }
             }
         }
@@ -1776,6 +2039,43 @@ static inline void MPV_motion_lowres(MpegEncContext *s,
     }
 }
 
+/**
+ * find the lowest MB row referenced in the MVs
+ */
+int MPV_lowest_referenced_row(MpegEncContext *s, int dir)
+{
+    int my_max = INT_MIN, my_min = INT_MAX, qpel_shift = !s->quarter_sample;
+    int my, off, i, mvs;
+
+    if (s->picture_structure != PICT_FRAME) goto unhandled;
+
+    switch (s->mv_type) {
+        case MV_TYPE_16X16:
+            mvs = 1;
+            break;
+        case MV_TYPE_16X8:
+            mvs = 2;
+            break;
+        case MV_TYPE_8X8:
+            mvs = 4;
+            break;
+        default:
+            goto unhandled;
+    }
+
+    for (i = 0; i < mvs; i++) {
+        my = s->mv[dir][i][1]<<qpel_shift;
+        my_max = FFMAX(my_max, my);
+        my_min = FFMIN(my_min, my);
+    }
+
+    off = (FFMAX(-my_min, my_max) + 63) >> 6;
+
+    return FFMIN(FFMAX(s->mb_y + off, 0), s->mb_height-1);
+unhandled:
+    return s->mb_height-1;
+}
+
 /* put block[] to dest[] */
 static inline void put_dct(MpegEncContext *s,
                            DCTELEM *block, int i, uint8_t *dest, int line_size, int qscale)
@@ -1804,7 +2104,7 @@ static inline void add_dequant_dct(MpegEncContext *s,
 }
 
 /**
- * cleans dc, ac, coded_block for the current non intra MB
+ * Clean dc, ac, coded_block for the current non-intra MB.
  */
 void ff_clean_intra_table_entries(MpegEncContext *s)
 {
@@ -1859,13 +2159,18 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64],
     if(s->avctx->debug&FF_DEBUG_DCT_COEFF) {
        /* save DCT coefficients */
        int i,j;
-       DCTELEM *dct = &s->current_picture.dct_coeff[mb_xy*64*6];
-       for(i=0; i<6; i++)
-           for(j=0; j<64; j++)
+       DCTELEM *dct = &s->current_picture.f.dct_coeff[mb_xy * 64 * 6];
+       av_log(s->avctx, AV_LOG_DEBUG, "DCT coeffs of MB at %dx%d:\n", s->mb_x, s->mb_y);
+       for(i=0; i<6; i++){
+           for(j=0; j<64; j++){
                *dct++ = block[i][s->dsp.idct_permutation[j]];
+               av_log(s->avctx, AV_LOG_DEBUG, "%5d", dct[-1]);
+           }
+           av_log(s->avctx, AV_LOG_DEBUG, "\n");
+       }
     }
 
-    s->current_picture.qscale_table[mb_xy]= s->qscale;
+    s->current_picture.f.qscale_table[mb_xy] = s->qscale;
 
     /* update DC predictors for P macroblocks */
     if (!s->mb_intra) {
@@ -1881,38 +2186,27 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64],
     else if (!is_mpeg12 && (s->h263_pred || s->h263_aic))
         s->mbintra_table[mb_xy]=1;
 
-    if ((s->flags&CODEC_FLAG_PSNR) || !(s->encoding && (s->intra_only || s->pict_type==FF_B_TYPE) && s->avctx->mb_decision != FF_MB_DECISION_RD)) { //FIXME precalc
+    if ((s->flags&CODEC_FLAG_PSNR) || !(s->encoding && (s->intra_only || s->pict_type==AV_PICTURE_TYPE_B) && s->avctx->mb_decision != FF_MB_DECISION_RD)) { //FIXME precalc
         uint8_t *dest_y, *dest_cb, *dest_cr;
         int dct_linesize, dct_offset;
         op_pixels_func (*op_pix)[4];
         qpel_mc_func (*op_qpix)[16];
-        const int linesize= s->current_picture.linesize[0]; //not s->linesize as this would be wrong for field pics
-        const int uvlinesize= s->current_picture.linesize[1];
-        const int readable= s->pict_type != FF_B_TYPE || s->encoding || s->avctx->draw_horiz_band || lowres_flag;
+        const int linesize   = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics
+        const int uvlinesize = s->current_picture.f.linesize[1];
+        const int readable= s->pict_type != AV_PICTURE_TYPE_B || s->encoding || s->avctx->draw_horiz_band || lowres_flag;
         const int block_size= lowres_flag ? 8>>s->avctx->lowres : 8;
 
         /* avoid copy if macroblock skipped in last frame too */
         /* skip only during decoding as we might trash the buffers during encoding a bit */
         if(!s->encoding){
             uint8_t *mbskip_ptr = &s->mbskip_table[mb_xy];
-            const int age= s->current_picture.age;
-
-            assert(age);
 
             if (s->mb_skipped) {
                 s->mb_skipped= 0;
-                assert(s->pict_type!=FF_I_TYPE);
-
-                (*mbskip_ptr) ++; /* indicate that this time we skipped it */
-                if(*mbskip_ptr >99) *mbskip_ptr= 99;
-
-                /* if previous was skipped too, then nothing to do !  */
-                if (*mbskip_ptr >= age && s->current_picture.reference){
-                    return;
-                }
-            } else if(!s->current_picture.reference){
-                (*mbskip_ptr) ++; /* increase counter so the age can be compared cleanly */
-                if(*mbskip_ptr >99) *mbskip_ptr= 99;
+                assert(s->pict_type!=AV_PICTURE_TYPE_I);
+                *mbskip_ptr = 1;
+            } else if(!s->current_picture.f.reference) {
+                *mbskip_ptr = 1;
             } else{
                 *mbskip_ptr = 0; /* not skipped */
             }
@@ -1935,47 +2229,54 @@ void MPV_decode_mb_internal(MpegEncContext *s, DCTELEM block[12][64],
             /* motion handling */
             /* decoding or more than one mb_type (MC was already done otherwise) */
             if(!s->encoding){
+
+                if(HAVE_THREADS && s->avctx->active_thread_type&FF_THREAD_FRAME) {
+                    if (s->mv_dir & MV_DIR_FORWARD) {
+                        ff_thread_await_progress((AVFrame*)s->last_picture_ptr, MPV_lowest_referenced_row(s, 0), 0);
+                    }
+                    if (s->mv_dir & MV_DIR_BACKWARD) {
+                        ff_thread_await_progress((AVFrame*)s->next_picture_ptr, MPV_lowest_referenced_row(s, 1), 0);
+                    }
+                }
+
                 if(lowres_flag){
                     h264_chroma_mc_func *op_pix = s->dsp.put_h264_chroma_pixels_tab;
 
                     if (s->mv_dir & MV_DIR_FORWARD) {
-                        MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.data, op_pix);
+                        MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix);
                         op_pix = s->dsp.avg_h264_chroma_pixels_tab;
                     }
                     if (s->mv_dir & MV_DIR_BACKWARD) {
-                        MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.data, op_pix);
+                        MPV_motion_lowres(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix);
                     }
                 }else{
                     op_qpix= s->me.qpel_put;
-                    if ((!s->no_rounding) || s->pict_type==FF_B_TYPE){
+                    if ((!s->no_rounding) || s->pict_type==AV_PICTURE_TYPE_B){
                         op_pix = s->dsp.put_pixels_tab;
                     }else{
                         op_pix = s->dsp.put_no_rnd_pixels_tab;
                     }
                     if (s->mv_dir & MV_DIR_FORWARD) {
-                        MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.data, op_pix, op_qpix);
+                        MPV_motion(s, dest_y, dest_cb, dest_cr, 0, s->last_picture.f.data, op_pix, op_qpix);
                         op_pix = s->dsp.avg_pixels_tab;
                         op_qpix= s->me.qpel_avg;
                     }
                     if (s->mv_dir & MV_DIR_BACKWARD) {
-                        MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.data, op_pix, op_qpix);
+                        MPV_motion(s, dest_y, dest_cb, dest_cr, 1, s->next_picture.f.data, op_pix, op_qpix);
                     }
                 }
             }
 
             /* skip dequant / idct if we are really late ;) */
-#if FF_API_HURRY_UP
-            if(s->hurry_up>1) goto skip_idct;
-#endif
             if(s->avctx->skip_idct){
-                if(  (s->avctx->skip_idct >= AVDISCARD_NONREF && s->pict_type == FF_B_TYPE)
-                   ||(s->avctx->skip_idct >= AVDISCARD_NONKEY && s->pict_type != FF_I_TYPE)
+                if(  (s->avctx->skip_idct >= AVDISCARD_NONREF && s->pict_type == AV_PICTURE_TYPE_B)
+                   ||(s->avctx->skip_idct >= AVDISCARD_NONKEY && s->pict_type != AV_PICTURE_TYPE_I)
                    || s->avctx->skip_idct >= AVDISCARD_ALL)
                     goto skip_idct;
             }
 
             /* add dct residue */
-            if(s->encoding || !(   s->h263_msmpeg4 || s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO
+            if(s->encoding || !(   s->msmpeg4_version || s->codec_id==CODEC_ID_MPEG1VIDEO || s->codec_id==CODEC_ID_MPEG2VIDEO
                                 || (s->codec_id==CODEC_ID_MPEG4 && !s->mpeg_quant))){
                 add_dequant_dct(s, block[0], 0, dest_y                          , dct_linesize, s->qscale);
                 add_dequant_dct(s, block[1], 1, dest_y              + block_size, dct_linesize, s->qscale);
@@ -2097,40 +2398,65 @@ void MPV_decode_mb(MpegEncContext *s, DCTELEM block[12][64]){
 }
 
 /**
- *
  * @param h is the normal height, this will be reduced automatically if needed for the last row
  */
 void ff_draw_horiz_band(MpegEncContext *s, int y, int h){
-    if (s->avctx->draw_horiz_band) {
-        AVFrame *src;
-        const int field_pic= s->picture_structure != PICT_FRAME;
-        int offset[4];
+    const int field_pic= s->picture_structure != PICT_FRAME;
+    if(field_pic){
+        h <<= 1;
+        y <<= 1;
+    }
 
-        h= FFMIN(h, (s->avctx->height>>field_pic) - y);
+    if (!s->avctx->hwaccel
+       && !(s->avctx->codec->capabilities&CODEC_CAP_HWACCEL_VDPAU)
+       && s->unrestricted_mv
+       && s->current_picture.f.reference
+       && !s->intra_only
+       && !(s->flags&CODEC_FLAG_EMU_EDGE)) {
+        int sides = 0, edge_h;
+        int hshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_w;
+        int vshift = av_pix_fmt_descriptors[s->avctx->pix_fmt].log2_chroma_h;
+        if (y==0) sides |= EDGE_TOP;
+        if (y + h >= s->v_edge_pos) sides |= EDGE_BOTTOM;
 
-        if(field_pic && !(s->avctx->slice_flags&SLICE_FLAG_ALLOW_FIELD)){
-            h <<= 1;
-            y <<= 1;
-            if(s->first_field) return;
-        }
+        edge_h= FFMIN(h, s->v_edge_pos - y);
+
+        s->dsp.draw_edges(s->current_picture_ptr->f.data[0] +  y         *s->linesize,
+                          s->linesize,           s->h_edge_pos,         edge_h,
+                          EDGE_WIDTH,            EDGE_WIDTH,            sides);
+        s->dsp.draw_edges(s->current_picture_ptr->f.data[1] + (y>>vshift)*s->uvlinesize,
+                          s->uvlinesize,         s->h_edge_pos>>hshift, edge_h>>vshift,
+                          EDGE_WIDTH>>hshift,    EDGE_WIDTH>>vshift,    sides);
+        s->dsp.draw_edges(s->current_picture_ptr->f.data[2] + (y>>vshift)*s->uvlinesize,
+                          s->uvlinesize,         s->h_edge_pos>>hshift, edge_h>>vshift,
+                          EDGE_WIDTH>>hshift,    EDGE_WIDTH>>vshift,    sides);
+    }
+
+    h= FFMIN(h, s->avctx->height - y);
+
+    if(field_pic && s->first_field && !(s->avctx->slice_flags&SLICE_FLAG_ALLOW_FIELD)) return;
 
-        if(s->pict_type==FF_B_TYPE || s->low_delay || (s->avctx->slice_flags&SLICE_FLAG_CODED_ORDER))
+    if (s->avctx->draw_horiz_band) {
+        AVFrame *src;
+        int offset[AV_NUM_DATA_POINTERS];
+        int i;
+
+        if(s->pict_type==AV_PICTURE_TYPE_B || s->low_delay || (s->avctx->slice_flags&SLICE_FLAG_CODED_ORDER))
             src= (AVFrame*)s->current_picture_ptr;
         else if(s->last_picture_ptr)
             src= (AVFrame*)s->last_picture_ptr;
         else
             return;
 
-        if(s->pict_type==FF_B_TYPE && s->picture_structure == PICT_FRAME && s->out_format != FMT_H264){
-            offset[0]=
-            offset[1]=
-            offset[2]=
-            offset[3]= 0;
+        if(s->pict_type==AV_PICTURE_TYPE_B && s->picture_structure == PICT_FRAME && s->out_format != FMT_H264){
+            for (i = 0; i < AV_NUM_DATA_POINTERS; i++)
+                offset[i] = 0;
         }else{
             offset[0]= y * s->linesize;
             offset[1]=
             offset[2]= (y >> s->chroma_y_shift) * s->uvlinesize;
-            offset[3]= 0;
+            for (i = 3; i < AV_NUM_DATA_POINTERS; i++)
+                offset[i] = 0;
         }
 
         emms_c();
@@ -2141,8 +2467,8 @@ void ff_draw_horiz_band(MpegEncContext *s, int y, int h){
 }
 
 void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename
-    const int linesize= s->current_picture.linesize[0]; //not s->linesize as this would be wrong for field pics
-    const int uvlinesize= s->current_picture.linesize[1];
+    const int linesize   = s->current_picture.f.linesize[0]; //not s->linesize as this would be wrong for field pics
+    const int uvlinesize = s->current_picture.f.linesize[1];
     const int mb_size= 4 - s->avctx->lowres;
 
     s->block_index[0]= s->b8_stride*(s->mb_y*2    ) - 2 + s->mb_x*2;
@@ -2153,11 +2479,11 @@ void ff_init_block_index(MpegEncContext *s){ //FIXME maybe rename
     s->block_index[5]= s->mb_stride*(s->mb_y + s->mb_height + 2) + s->b8_stride*s->mb_height*2 + s->mb_x - 1;
     //block_index is not used by mpeg2, so it is not affected by chroma_format
 
-    s->dest[0] = s->current_picture.data[0] + ((s->mb_x - 1) << mb_size);
-    s->dest[1] = s->current_picture.data[1] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift));
-    s->dest[2] = s->current_picture.data[2] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift));
+    s->dest[0] = s->current_picture.f.data[0] + ((s->mb_x - 1) <<  mb_size);
+    s->dest[1] = s->current_picture.f.data[1] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift));
+    s->dest[2] = s->current_picture.f.data[2] + ((s->mb_x - 1) << (mb_size - s->chroma_x_shift));
 
-    if(!(s->pict_type==FF_B_TYPE && s->avctx->draw_horiz_band && s->picture_structure==PICT_FRAME))
+    if(!(s->pict_type==AV_PICTURE_TYPE_B && s->avctx->draw_horiz_band && s->picture_structure==PICT_FRAME))
     {
         if(s->picture_structure==PICT_FRAME){
         s->dest[0] += s->mb_y *   linesize << mb_size;
@@ -2179,15 +2505,15 @@ void ff_mpeg_flush(AVCodecContext *avctx){
     if(s==NULL || s->picture==NULL)
         return;
 
-    for(i=0; i<MAX_PICTURE_COUNT; i++){
-       if(s->picture[i].data[0] && (   s->picture[i].type == FF_BUFFER_TYPE_INTERNAL
-                                    || s->picture[i].type == FF_BUFFER_TYPE_USER))
+    for(i=0; i<s->picture_count; i++){
+       if (s->picture[i].f.data[0] &&
+           (s->picture[i].f.type == FF_BUFFER_TYPE_INTERNAL ||
+            s->picture[i].f.type == FF_BUFFER_TYPE_USER))
         free_frame_buffer(s, &s->picture[i]);
     }
     s->current_picture_ptr = s->last_picture_ptr = s->next_picture_ptr = NULL;
 
     s->mb_x= s->mb_y= 0;
-    s->closed_gop= 0;
 
     s->parse_context.state= -1;
     s->parse_context.frame_start_found= 0;
@@ -2433,3 +2759,9 @@ void ff_set_qscale(MpegEncContext * s, int qscale)
     s->y_dc_scale= s->y_dc_scale_table[ qscale ];
     s->c_dc_scale= s->c_dc_scale_table[ s->chroma_qscale ];
 }
+
+void MPV_report_decode_progress(MpegEncContext *s)
+{
+    if (s->pict_type != AV_PICTURE_TYPE_B && !s->partitioned_frame && !s->error_occurred)
+        ff_thread_report_progress((AVFrame*)s->current_picture_ptr, s->mb_y, 0);
+}