Ticket #963: frapsMTv2.patch

File frapsMTv2.patch, 15.3 KB (added by STaRGaZeR, 5 years ago)
  • libavcodec/fraps.c

    From a4065ca4146fb0dfe555ffa7ed553f687af200a6 Mon Sep 17 00:00:00 2001
    From: Javier Cabezas <jcabgz@gmail.com>
    Date: Mon, 30 Jan 2012 20:16:55 +0100
    Subject: [PATCH] Fraps: restore old behavior regarding P frames.
    
    P frames are repeated frames in Fraps, not skip frames. Restore the old behavior where those P frames are outputted as normal frames with their own timestamp. This matches the Fraps reference decoder. In order to make frame multithreading work, a 2 frame buffer is used.
    ---
     libavcodec/fraps.c |  228 +++++++++++++++++++++++++++++++++++-----------------
     1 files changed, 154 insertions(+), 74 deletions(-)
    
    diff --git a/libavcodec/fraps.c b/libavcodec/fraps.c
    index a7d5a73..8e3b816 100644
    a b  
    3232 */ 
    3333 
    3434#include "avcodec.h" 
     35#include "internal.h" 
    3536#include "get_bits.h" 
    3637#include "huffman.h" 
    3738#include "bytestream.h" 
    3839#include "dsputil.h" 
    3940#include "thread.h" 
     41#include "libavutil/imgutils.h" 
    4042 
    4143#define FPS_TAG MKTAG('F', 'P', 'S', 'x') 
    4244 
     
    4547 */ 
    4648typedef struct FrapsContext{ 
    4749    AVCodecContext *avctx; 
    48     AVFrame frame; 
     50    int cur_index, prev_index; 
     51    int next_cur_index, next_prev_index; 
     52    AVFrame buf_ptrs[2]; 
    4953    uint8_t *tmpbuf; 
    5054    int tmpbuf_size; 
    5155    DSPContext dsp; 
    static av_cold int decode_init(AVCodecContext *avctx) 
    6165{ 
    6266    FrapsContext * const s = avctx->priv_data; 
    6367 
    64     avcodec_get_frame_defaults(&s->frame); 
    65     avctx->coded_frame = (AVFrame*)&s->frame; 
     68    s->prev_index = 0; 
     69    s->cur_index = 1; 
    6670 
    6771    s->avctx = avctx; 
    6872    s->tmpbuf = NULL; 
    static av_cold int decode_init(AVCodecContext *avctx) 
    7276    return 0; 
    7377} 
    7478 
     79static int fraps_decode_update_thread_context(AVCodecContext *avctx, const AVCodecContext *avctx_from) 
     80{ 
     81    FrapsContext *dst = avctx->priv_data, *src = avctx_from->priv_data; 
     82 
     83    if (avctx == avctx_from) return 0; 
     84 
     85    dst->cur_index  = src->next_cur_index; 
     86    dst->prev_index = src->next_prev_index; 
     87 
     88    memcpy(dst->buf_ptrs, src->buf_ptrs, sizeof(src->buf_ptrs)); 
     89 
     90    memset(&dst->buf_ptrs[dst->cur_index], 0, sizeof(AVFrame)); 
     91 
     92    return 0; 
     93} 
     94 
    7595/** 
    7696 * Comparator - our nodes should ascend by count 
    7797 * but with preserved symbol order 
    static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, 
    93113    VLC vlc; 
    94114    Node nodes[512]; 
    95115 
    96     for(i = 0; i < 256; i++) 
     116    for (i = 0; i < 256; i++) 
    97117        nodes[i].count = bytestream_get_le32(&src); 
    98118    size -= 1024; 
    99119    if (ff_huff_build_tree(s->avctx, &vlc, 256, nodes, huff_cmp, 
    static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, 
    105125    s->dsp.bswap_buf((uint32_t *)s->tmpbuf, (const uint32_t *)src, size >> 2); 
    106126 
    107127    init_get_bits(&gb, s->tmpbuf, size * 8); 
    108     for(j = 0; j < h; j++){ 
    109         for(i = 0; i < w*step; i += step){ 
     128    for (j = 0; j < h; j++){ 
     129        for (i = 0; i < w*step; i += step){ 
    110130            dst[i] = get_vlc2(&gb, vlc.table, 9, 3); 
    111131            /* lines are stored as deltas between previous lines 
    112132             * and we need to add 0x80 to the first lines of chroma planes 
    113133             */ 
    114             if(j) dst[i] += dst[i - stride]; 
    115             else if(Uoff) dst[i] += 0x80; 
     134            if (j) 
     135                dst[i] += dst[i - stride]; 
     136            else if (Uoff) 
     137                dst[i] += 0x80; 
    116138            if (get_bits_left(&gb) < 0) { 
    117139                free_vlc(&vlc); 
    118140                return AVERROR_INVALIDDATA; 
    static int fraps2_decode_plane(FrapsContext *s, uint8_t *dst, int stride, int w, 
    124146    return 0; 
    125147} 
    126148 
     149static void fraps_frame_copy(FrapsContext *s, uint8_t *dst_data[3], int dst_linesizes[3], 
     150                             uint8_t *src_data[3], const int src_linesizes[3], 
     151                             enum PixelFormat pix_fmt, int width, int height) 
     152{ 
     153    const AVPixFmtDescriptor *desc = &av_pix_fmt_descriptors[pix_fmt]; 
     154    int i; 
     155 
     156    for (i = 0; i < 3; i++) { 
     157        int h = height; 
     158        int bwidth = av_image_get_linesize(pix_fmt, width, i); 
     159        if (i) { 
     160            h = -((-height)>>desc->log2_chroma_h); 
     161        } 
     162        ff_thread_await_progress(&s->buf_ptrs[s->prev_index], i, 0); 
     163        av_image_copy_plane(dst_data[i], dst_linesizes[i], 
     164                            src_data[i], src_linesizes[i], 
     165                            bwidth, h); 
     166        ff_thread_report_progress(&s->buf_ptrs[s->cur_index], i, 0); 
     167    } 
     168} 
     169 
    127170static int decode_frame(AVCodecContext *avctx, 
    128171                        void *data, int *data_size, 
    129172                        AVPacket *avpkt) 
    static int decode_frame(AVCodecContext *avctx, 
    131174    const uint8_t *buf = avpkt->data; 
    132175    int buf_size = avpkt->size; 
    133176    FrapsContext * const s = avctx->priv_data; 
    134     AVFrame *frame = data; 
    135     AVFrame * const f = (AVFrame*)&s->frame; 
    136177    uint32_t header; 
    137     unsigned int version,header_size; 
     178    unsigned int version, header_size; 
    138179    unsigned int x, y; 
    139180    const uint32_t *buf32; 
    140     uint32_t *luma1,*luma2,*cb,*cr; 
     181    uint32_t *luma1, *luma2, *cb, *cr; 
    141182    uint32_t offs[4]; 
    142     int i, j, is_chroma; 
     183    int i, j, is_chroma, is_Pframe, ret; 
    143184    const int planes = 3; 
    144185    uint8_t *out; 
    145186 
    static int decode_frame(AVCodecContext *avctx, 
    148189    version = header & 0xff; 
    149190    header_size = (header & (1<<30))? 8 : 4; /* bit 30 means pad to 8 bytes */ 
    150191 
     192    buf += header_size; 
     193 
    151194    if (version > 5) { 
    152195        av_log(avctx, AV_LOG_ERROR, 
    153196               "This file is encoded with Fraps version %d. " \ 
    static int decode_frame(AVCodecContext *avctx, 
    155198        return -1; 
    156199    } 
    157200 
    158     buf += header_size; 
    159  
    160201    avctx->pix_fmt = version & 1 ? PIX_FMT_BGR24 : PIX_FMT_YUVJ420P; 
    161202 
    162203    if (version < 2) { 
    163204        unsigned needed_size = avctx->width*avctx->height*3; 
    164         if (version == 0) needed_size /= 2; 
     205        if (version == 0) { 
     206            if ( (avctx->width % 8) != 0 || (avctx->height % 2) != 0 ) { 
     207                av_log(avctx, AV_LOG_ERROR, "Invalid frame size %dx%d\n", 
     208                       avctx->width, avctx->height); 
     209                return -1; 
     210            } 
     211            needed_size /= 2; 
     212        } 
    165213        needed_size += header_size; 
    166214        if (buf_size != needed_size && buf_size != header_size) { 
    167215            av_log(avctx, AV_LOG_ERROR, 
    static int decode_frame(AVCodecContext *avctx, 
    169217                   buf_size, needed_size); 
    170218            return -1; 
    171219        } 
    172         /* bit 31 means same as previous pic */ 
    173         if (header & (1U<<31)) { 
    174             *data_size = 0; 
    175             return buf_size; 
    176         } 
     220        is_Pframe = (header & (1U<<31)) ? 1 : 0; 
    177221    } else { 
    178         /* skip frame */ 
    179         if (buf_size == 8) { 
    180             *data_size = 0; 
    181             return buf_size; 
    182         } 
    183         if (AV_RL32(buf) != FPS_TAG || buf_size < planes*1024 + 24) { 
    184             av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n"); 
    185             return -1; 
    186         } 
    187         for(i = 0; i < planes; i++) { 
    188             offs[i] = AV_RL32(buf + 4 + i * 4); 
    189             if(offs[i] >= buf_size - header_size || (i && offs[i] <= offs[i - 1] + 1024)) { 
    190                 av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i); 
     222        is_Pframe = buf_size == 8 ? 1 : 0; 
     223        if (!is_Pframe) { 
     224            if (AV_RL32(buf) != FPS_TAG || buf_size < (planes*1024 + 24)) { 
     225                av_log(avctx, AV_LOG_ERROR, "Fraps: error in data stream\n"); 
    191226                return -1; 
    192227            } 
    193         } 
    194         offs[planes] = buf_size - header_size; 
    195         for(i = 0; i < planes; i++) { 
    196             av_fast_padded_malloc(&s->tmpbuf, &s->tmpbuf_size, offs[i + 1] - offs[i] - 1024); 
    197             if (!s->tmpbuf) 
    198                 return AVERROR(ENOMEM); 
     228            for(i = 0; i < planes; i++) { 
     229                offs[i] = AV_RL32(buf + 4 + i * 4); 
     230                if(offs[i] >= buf_size - header_size || (i && offs[i] <= offs[i - 1] + 1024)) { 
     231                    av_log(avctx, AV_LOG_ERROR, "Fraps: plane %i offset is out of bounds\n", i); 
     232                    return -1; 
     233                } 
     234            } 
     235            offs[planes] = buf_size - header_size; 
     236            for(i = 0; i < planes; i++) { 
     237                av_fast_padded_malloc(&s->tmpbuf, &s->tmpbuf_size, offs[i + 1] - offs[i] - 1024); 
     238                if (!s->tmpbuf) 
     239                    return AVERROR(ENOMEM); 
     240            } 
    199241        } 
    200242    } 
    201243 
    202     if (f->data[0]) 
    203         ff_thread_release_buffer(avctx, f); 
    204     f->pict_type = AV_PICTURE_TYPE_I; 
    205     f->key_frame = 1; 
    206     f->reference = 0; 
    207     f->buffer_hints = FF_BUFFER_HINTS_VALID; 
    208     if (ff_thread_get_buffer(avctx, f)) { 
    209         av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 
     244    if (is_Pframe && !s->buf_ptrs[s->prev_index].data[0]) { 
     245        av_log(avctx, AV_LOG_ERROR, "decoding must start with keyframe\n"); 
    210246        return -1; 
    211247    } 
    212248 
    213     switch(version) { 
     249    s->buf_ptrs[s->cur_index].reference = 3; 
     250 
     251    if (is_Pframe) { 
     252        s->buf_ptrs[s->cur_index].pict_type = AV_PICTURE_TYPE_P; 
     253        s->buf_ptrs[s->cur_index].key_frame = 0; 
     254    } else { 
     255        s->buf_ptrs[s->cur_index].pict_type = AV_PICTURE_TYPE_I; 
     256        s->buf_ptrs[s->cur_index].key_frame = 1; 
     257    } 
     258 
     259    if ((ret = ff_thread_get_buffer(avctx, &s->buf_ptrs[s->cur_index])) < 0) { 
     260        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 
     261        return ret; 
     262    } 
     263 
     264    s->next_prev_index = s->cur_index; 
     265    s->next_cur_index  = (s->cur_index - 1) & 1; 
     266 
     267    ff_thread_finish_setup(avctx); 
     268 
     269    /* Copy previous frame */ 
     270    if (is_Pframe) { 
     271        fraps_frame_copy(s, s->buf_ptrs[s->cur_index].data, s->buf_ptrs[s->cur_index].linesize, 
     272                         s->buf_ptrs[s->prev_index].data, s->buf_ptrs[s->prev_index].linesize, 
     273                         avctx->pix_fmt, avctx->width, avctx->height); 
     274        goto end; 
     275    } 
     276 
     277    /* Decode I-frame */ 
     278    switch (version) { 
    214279    case 0: 
    215280    default: 
    216281        /* Fraps v0 is a reordered YUV420 */ 
    217         if ( (avctx->width % 8) != 0 || (avctx->height % 2) != 0 ) { 
    218             av_log(avctx, AV_LOG_ERROR, "Invalid frame size %dx%d\n", 
    219                    avctx->width, avctx->height); 
    220             return -1; 
    221         } 
    222  
    223         buf32=(const uint32_t*)buf; 
    224         for(y=0; y<avctx->height/2; y++){ 
    225             luma1=(uint32_t*)&f->data[0][ y*2*f->linesize[0] ]; 
    226             luma2=(uint32_t*)&f->data[0][ (y*2+1)*f->linesize[0] ]; 
    227             cr=(uint32_t*)&f->data[1][ y*f->linesize[1] ]; 
    228             cb=(uint32_t*)&f->data[2][ y*f->linesize[2] ]; 
    229             for(x=0; x<avctx->width; x+=8){ 
     282        buf32 = (const uint32_t*)buf; 
     283        for(y = 0; y < avctx->height/2; y++){ 
     284            luma1 = (uint32_t*)&s->buf_ptrs[s->cur_index].data[0][y*2*s->buf_ptrs[s->cur_index].linesize[0]]; 
     285            luma2 = (uint32_t*)&s->buf_ptrs[s->cur_index].data[0][(y*2+1)*s->buf_ptrs[s->cur_index].linesize[0]]; 
     286            cr    = (uint32_t*)&s->buf_ptrs[s->cur_index].data[1][y*s->buf_ptrs[s->cur_index].linesize[1]]; 
     287            cb    = (uint32_t*)&s->buf_ptrs[s->cur_index].data[2][y*s->buf_ptrs[s->cur_index].linesize[2]]; 
     288            for(x = 0; x < avctx->width; x += 8){ 
    230289                *luma1++ = *buf32++; 
    231290                *luma1++ = *buf32++; 
    232291                *luma2++ = *buf32++; 
    static int decode_frame(AVCodecContext *avctx, 
    235294                *cb++    = *buf32++; 
    236295            } 
    237296        } 
     297        ff_thread_report_progress(&s->buf_ptrs[s->cur_index], INT_MAX, 0); 
    238298        break; 
    239299 
    240300    case 1: 
    241301        /* Fraps v1 is an upside-down BGR24 */ 
    242         for(y=0; y<avctx->height; y++) 
    243             memcpy(&f->data[0][ (avctx->height-y)*f->linesize[0] ], 
     302        for(y = 0; y < avctx->height; y++) 
     303            memcpy(&s->buf_ptrs[s->cur_index].data[0][(avctx->height-y)*s->buf_ptrs[s->cur_index].linesize[0]], 
    244304                   &buf[y*avctx->width*3], 
    245305                   3*avctx->width); 
     306        ff_thread_report_progress(&s->buf_ptrs[s->cur_index], INT_MAX, 0); 
    246307        break; 
    247308 
    248309    case 2: 
    static int decode_frame(AVCodecContext *avctx, 
    253314         */ 
    254315        for(i = 0; i < planes; i++){ 
    255316            is_chroma = !!i; 
    256             if(fraps2_decode_plane(s, f->data[i], f->linesize[i], avctx->width >> is_chroma, 
    257                     avctx->height >> is_chroma, buf + offs[i], offs[i + 1] - offs[i], is_chroma, 1) < 0) { 
     317            if(fraps2_decode_plane(s, s->buf_ptrs[s->cur_index].data[i], s->buf_ptrs[s->cur_index].linesize[i], avctx->width >> is_chroma, 
     318                                   avctx->height >> is_chroma, buf + offs[i], offs[i + 1] - offs[i], is_chroma, 1) < 0) { 
    258319                av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i); 
    259320                return -1; 
    260321            } 
     322            else 
     323                ff_thread_report_progress(&s->buf_ptrs[s->cur_index], i, 0); 
    261324        } 
    262325        break; 
     326 
    263327    case 3: 
    264328    case 5: 
    265329        /* Virtually the same as version 4, but is for RGB24 */ 
    266330        for(i = 0; i < planes; i++){ 
    267             if(fraps2_decode_plane(s, f->data[0] + i + (f->linesize[0] * (avctx->height - 1)), -f->linesize[0], 
    268                     avctx->width, avctx->height, buf + offs[i], offs[i + 1] - offs[i], 0, 3) < 0) { 
     331            if(fraps2_decode_plane(s, s->buf_ptrs[s->cur_index].data[0] + i + (s->buf_ptrs[s->cur_index].linesize[0] * (avctx->height - 1)), -s->buf_ptrs[s->cur_index].linesize[0], 
     332                                   avctx->width, avctx->height, buf + offs[i], offs[i + 1] - offs[i], 0, 3) < 0) { 
    269333                av_log(avctx, AV_LOG_ERROR, "Error decoding plane %i\n", i); 
    270334                return -1; 
    271335            } 
    272336        } 
    273         out = f->data[0]; 
    274337        // convert pseudo-YUV into real RGB 
     338        out = s->buf_ptrs[s->cur_index].data[0]; 
    275339        for(j = 0; j < avctx->height; j++){ 
    276340            uint8_t *line_end = out + 3*avctx->width; 
    277341            while (out < line_end) { 
    static int decode_frame(AVCodecContext *avctx, 
    279343                out[2]  += out[1]; 
    280344                out += 3; 
    281345            } 
    282             out += f->linesize[0] - 3*avctx->width; 
     346            out += s->buf_ptrs[s->cur_index].linesize[0] - 3*avctx->width; 
    283347        } 
     348        ff_thread_report_progress(&s->buf_ptrs[s->cur_index], INT_MAX, 0); 
    284349        break; 
    285350    } 
    286351 
    287     *frame = *f; 
     352end: 
     353    *(AVFrame*)data = s->buf_ptrs[s->cur_index]; 
    288354    *data_size = sizeof(AVFrame); 
    289355 
     356    s->prev_index = s->next_prev_index; 
     357    s->cur_index  = s->next_cur_index; 
     358 
     359    /* Only release frames that aren't used anymore */ 
     360    if(s->buf_ptrs[s->cur_index].data[0]) 
     361        ff_thread_release_buffer(avctx, &s->buf_ptrs[s->cur_index]); 
     362 
    290363    return buf_size; 
    291364} 
    292365 
    static int decode_frame(AVCodecContext *avctx, 
    299372static av_cold int decode_end(AVCodecContext *avctx) 
    300373{ 
    301374    FrapsContext *s = (FrapsContext*)avctx->priv_data; 
    302  
    303     if (s->frame.data[0]) 
    304         avctx->release_buffer(avctx, &s->frame); 
     375    int i; 
    305376 
    306377    av_freep(&s->tmpbuf); 
     378 
     379    if (avctx->internal->is_copy) 
     380        return 0; 
     381 
     382    for(i = 0; i < 2; i++) 
     383        if(s->buf_ptrs[i].data[0]) 
     384            ff_thread_release_buffer(avctx, &s->buf_ptrs[i]); 
     385 
    307386    return 0; 
    308387} 
    309388 
    AVCodec ff_fraps_decoder = { 
    318397    .decode         = decode_frame, 
    319398    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, 
    320399    .long_name = NULL_IF_CONFIG_SMALL("Fraps"), 
     400    .update_thread_context = ONLY_IF_THREADS_ENABLED(fraps_decode_update_thread_context) 
    321401};