Home | History | Annotate | Download | only in nouveau
      1 /*
      2  * Copyright 2011-2013 Maarten Lankhorst
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     20  * OTHER DEALINGS IN THE SOFTWARE.
     21  */
     22 
     23 #include "nouveau_vp3_video.h"
     24 
     25 struct strparm_bsp {
     26    uint32_t w0[4]; // bits 0-23 length, bits 24-31 addr_hi
     27    uint32_t w1[4]; // bit 8-24 addr_lo
     28    uint32_t unk20; // should be idx * 0x8000000, bitstream offset
     29    uint32_t do_crypto_crap; // set to 0
     30 };
     31 
     32 struct mpeg12_picparm_bsp {
     33    uint16_t width;
     34    uint16_t height;
     35    uint8_t picture_structure;
     36    uint8_t picture_coding_type;
     37    uint8_t intra_dc_precision;
     38    uint8_t frame_pred_frame_dct;
     39    uint8_t concealment_motion_vectors;
     40    uint8_t intra_vlc_format;
     41    uint16_t pad;
     42    uint8_t f_code[2][2];
     43 };
     44 
     45 struct mpeg4_picparm_bsp {
     46    uint16_t width;
     47    uint16_t height;
     48    uint8_t vop_time_increment_size;
     49    uint8_t interlaced;
     50    uint8_t resync_marker_disable;
     51 };
     52 
     53 struct vc1_picparm_bsp {
     54    uint16_t width;
     55    uint16_t height;
     56    uint8_t profile; // 04 0 simple, 1 main, 2 advanced
     57    uint8_t postprocflag; // 05
     58    uint8_t pulldown; // 06
     59    uint8_t interlaced; // 07
     60    uint8_t tfcntrflag; // 08
     61    uint8_t finterpflag; // 09
     62    uint8_t psf; // 0a
     63    uint8_t pad; // 0b
     64    uint8_t multires; // 0c
     65    uint8_t syncmarker; // 0d
     66    uint8_t rangered; // 0e
     67    uint8_t maxbframes; // 0f
     68    uint8_t dquant; // 10
     69    uint8_t panscan_flag; // 11
     70    uint8_t refdist_flag; // 12
     71    uint8_t quantizer; // 13
     72    uint8_t extended_mv; // 14
     73    uint8_t extended_dmv; // 15
     74    uint8_t overlap; // 16
     75    uint8_t vstransform; // 17
     76 };
     77 
     78 struct h264_picparm_bsp {
     79    // 00
     80    uint32_t unk00;
     81    // 04
     82    uint32_t log2_max_frame_num_minus4; // 04 checked
     83    uint32_t pic_order_cnt_type; // 08 checked
     84    uint32_t log2_max_pic_order_cnt_lsb_minus4; // 0c checked
     85    uint32_t delta_pic_order_always_zero_flag; // 10, or unknown
     86 
     87    uint32_t frame_mbs_only_flag; // 14, always 1?
     88    uint32_t direct_8x8_inference_flag; // 18, always 1?
     89    uint32_t width_mb; // 1c checked
     90    uint32_t height_mb; // 20 checked
     91    // 24
     92    //struct picparm2
     93    uint32_t entropy_coding_mode_flag; // 00, checked
     94    uint32_t pic_order_present_flag; // 04 checked
     95    uint32_t unk; // 08 seems to be 0?
     96    uint32_t pad1; // 0c seems to be 0?
     97    uint32_t pad2; // 10 always 0 ?
     98    uint32_t num_ref_idx_l0_active_minus1; // 14 always 0?
     99    uint32_t num_ref_idx_l1_active_minus1; // 18 always 0?
    100    uint32_t weighted_pred_flag; // 1c checked
    101    uint32_t weighted_bipred_idc; // 20 checked
    102    uint32_t pic_init_qp_minus26; // 24 checked
    103    uint32_t deblocking_filter_control_present_flag; // 28 always 1?
    104    uint32_t redundant_pic_cnt_present_flag; // 2c always 0?
    105    uint32_t transform_8x8_mode_flag; // 30 checked
    106    uint32_t mb_adaptive_frame_field_flag; // 34 checked-ish
    107    uint8_t field_pic_flag; // 38 checked
    108    uint8_t bottom_field_flag; // 39 checked
    109    uint8_t real_pad[0x1b]; // XX why?
    110 };
    111 
    112 static uint32_t
    113 nouveau_vp3_fill_picparm_mpeg12_bsp(struct nouveau_vp3_decoder *dec,
    114                                     struct pipe_mpeg12_picture_desc *desc,
    115                                     char *map)
    116 {
    117    struct mpeg12_picparm_bsp *pic_bsp = (struct mpeg12_picparm_bsp *)map;
    118    int i;
    119    pic_bsp->width = dec->base.width;
    120    pic_bsp->height = dec->base.height;
    121    pic_bsp->picture_structure = desc->picture_structure;
    122    pic_bsp->picture_coding_type = desc->picture_coding_type;
    123    pic_bsp->intra_dc_precision = desc->intra_dc_precision;
    124    pic_bsp->frame_pred_frame_dct = desc->frame_pred_frame_dct;
    125    pic_bsp->concealment_motion_vectors = desc->concealment_motion_vectors;
    126    pic_bsp->intra_vlc_format = desc->intra_vlc_format;
    127    pic_bsp->pad = 0;
    128    for (i = 0; i < 4; ++i)
    129       pic_bsp->f_code[i/2][i%2] = desc->f_code[i/2][i%2] + 1; // FU
    130 
    131    return (desc->num_slices << 4) | (dec->base.profile != PIPE_VIDEO_PROFILE_MPEG1);
    132 }
    133 
    134 static uint32_t
    135 nouveau_vp3_fill_picparm_mpeg4_bsp(struct nouveau_vp3_decoder *dec,
    136                                    struct pipe_mpeg4_picture_desc *desc,
    137                                    char *map)
    138 {
    139    struct mpeg4_picparm_bsp *pic_bsp = (struct mpeg4_picparm_bsp *)map;
    140    uint32_t t, bits = 0;
    141    pic_bsp->width = dec->base.width;
    142    pic_bsp->height = dec->base.height;
    143    assert(desc->vop_time_increment_resolution > 0);
    144 
    145    t = desc->vop_time_increment_resolution - 1;
    146    while (t) {
    147       bits++;
    148       t /= 2;
    149    }
    150    if (!bits)
    151       bits = 1;
    152    t = desc->vop_time_increment_resolution - 1;
    153    pic_bsp->vop_time_increment_size = bits;
    154    pic_bsp->interlaced = desc->interlaced;
    155    pic_bsp->resync_marker_disable = desc->resync_marker_disable;
    156    return 4;
    157 }
    158 
    159 static uint32_t
    160 nouveau_vp3_fill_picparm_vc1_bsp(struct nouveau_vp3_decoder *dec,
    161                                  struct pipe_vc1_picture_desc *d,
    162                                  char *map)
    163 {
    164    struct vc1_picparm_bsp *vc = (struct vc1_picparm_bsp *)map;
    165    uint32_t caps = (d->slice_count << 4)&0xfff0;
    166    vc->width = dec->base.width;
    167    vc->height = dec->base.height;
    168    vc->profile = dec->base.profile - PIPE_VIDEO_PROFILE_VC1_SIMPLE; // 04
    169    vc->postprocflag = d->postprocflag;
    170    vc->pulldown = d->pulldown;
    171    vc->interlaced = d->interlace;
    172    vc->tfcntrflag = d->tfcntrflag; // 08
    173    vc->finterpflag = d->finterpflag;
    174    vc->psf = d->psf;
    175    vc->pad = 0;
    176    vc->multires = d->multires; // 0c
    177    vc->syncmarker = d->syncmarker;
    178    vc->rangered = d->rangered;
    179    vc->maxbframes = d->maxbframes;
    180    vc->dquant = d->dquant; // 10
    181    vc->panscan_flag = d->panscan_flag;
    182    vc->refdist_flag = d->refdist_flag;
    183    vc->quantizer = d->quantizer;
    184    vc->extended_mv = d->extended_mv; // 14
    185    vc->extended_dmv = d->extended_dmv;
    186    vc->overlap = d->overlap;
    187    vc->vstransform = d->vstransform;
    188    return caps | 2;
    189 }
    190 
    191 static uint32_t
    192 nouveau_vp3_fill_picparm_h264_bsp(struct nouveau_vp3_decoder *dec,
    193                                   struct pipe_h264_picture_desc *d,
    194                                   char *map)
    195 {
    196    struct h264_picparm_bsp stub_h = {}, *h = &stub_h;
    197    uint32_t caps = (d->slice_count << 4)&0xfff0;
    198 
    199    assert(!(d->slice_count & ~0xfff));
    200    if (d->slice_count & 0x1000)
    201       caps |= 1 << 20;
    202 
    203    assert(offsetof(struct h264_picparm_bsp, bottom_field_flag) == (0x39 + 0x24));
    204    h->unk00 = 1;
    205    h->pad1 = h->pad2 = 0;
    206    h->unk = 0;
    207    h->log2_max_frame_num_minus4 = d->pps->sps->log2_max_frame_num_minus4;
    208    h->frame_mbs_only_flag = d->pps->sps->frame_mbs_only_flag;
    209    h->direct_8x8_inference_flag = d->pps->sps->direct_8x8_inference_flag;
    210    h->width_mb = mb(dec->base.width);
    211    h->height_mb = mb(dec->base.height);
    212    h->entropy_coding_mode_flag = d->pps->entropy_coding_mode_flag;
    213    h->pic_order_present_flag = d->pps->bottom_field_pic_order_in_frame_present_flag;
    214    h->pic_order_cnt_type = d->pps->sps->pic_order_cnt_type;
    215    h->log2_max_pic_order_cnt_lsb_minus4 = d->pps->sps->log2_max_pic_order_cnt_lsb_minus4;
    216    h->delta_pic_order_always_zero_flag = d->pps->sps->delta_pic_order_always_zero_flag;
    217    h->num_ref_idx_l0_active_minus1 = d->num_ref_idx_l0_active_minus1;
    218    h->num_ref_idx_l1_active_minus1 = d->num_ref_idx_l1_active_minus1;
    219    h->weighted_pred_flag = d->pps->weighted_pred_flag;
    220    h->weighted_bipred_idc = d->pps->weighted_bipred_idc;
    221    h->pic_init_qp_minus26 = d->pps->pic_init_qp_minus26;
    222    h->deblocking_filter_control_present_flag = d->pps->deblocking_filter_control_present_flag;
    223    h->redundant_pic_cnt_present_flag = d->pps->redundant_pic_cnt_present_flag;
    224    h->transform_8x8_mode_flag = d->pps->transform_8x8_mode_flag;
    225    h->mb_adaptive_frame_field_flag = d->pps->sps->mb_adaptive_frame_field_flag;
    226    h->field_pic_flag = d->field_pic_flag;
    227    h->bottom_field_flag = d->bottom_field_flag;
    228    memset(h->real_pad, 0, sizeof(h->real_pad));
    229    *(struct h264_picparm_bsp *)map = *h;
    230    return caps | 3;
    231 }
    232 
    233 static inline struct strparm_bsp *strparm_bsp(struct nouveau_vp3_decoder *dec)
    234 {
    235    unsigned comm_seq = dec->fence_seq;
    236    struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH];
    237    return (struct strparm_bsp *)(bsp_bo->map + 0x100);
    238 }
    239 
    240 void
    241 nouveau_vp3_bsp_begin(struct nouveau_vp3_decoder *dec)
    242 {
    243    struct strparm_bsp *str_bsp = strparm_bsp(dec);
    244 
    245    dec->bsp_ptr = (void *)str_bsp;
    246    memset(str_bsp, 0, 0x80);
    247    dec->bsp_ptr += 0x100;
    248    /* Reserved for picparm_vp */
    249    dec->bsp_ptr += 0x300;
    250    /* Reserved for comm */
    251 #if !NOUVEAU_VP3_DEBUG_FENCE
    252    memset(dec->bsp_ptr, 0, 0x200);
    253 #endif
    254    dec->bsp_ptr += 0x200;
    255 }
    256 
    257 void
    258 nouveau_vp3_bsp_next(struct nouveau_vp3_decoder *dec, unsigned num_buffers,
    259                      const void *const *data, const unsigned *num_bytes)
    260 {
    261 #ifndef NDEBUG
    262    unsigned comm_seq = dec->fence_seq;
    263    struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH];
    264 #endif
    265    struct strparm_bsp *str_bsp = strparm_bsp(dec);
    266    int i;
    267 
    268    for (i = 0; i < num_buffers; ++i) {
    269 #ifndef NDEBUG
    270       assert(bsp_bo->size >= str_bsp->w0[0] + num_bytes[i]);
    271 #endif
    272       memcpy(dec->bsp_ptr, data[i], num_bytes[i]);
    273       dec->bsp_ptr += num_bytes[i];
    274       str_bsp->w0[0] += num_bytes[i];
    275    }
    276 }
    277 
    278 uint32_t
    279 nouveau_vp3_bsp_end(struct nouveau_vp3_decoder *dec, union pipe_desc desc)
    280 {
    281    enum pipe_video_format codec = u_reduce_video_profile(dec->base.profile);
    282    unsigned comm_seq = dec->fence_seq;
    283    struct nouveau_bo *bsp_bo = dec->bsp_bo[comm_seq % NOUVEAU_VP3_VIDEO_QDEPTH];
    284    uint32_t endmarker, caps;
    285    struct strparm_bsp *str_bsp = strparm_bsp(dec);
    286    char *bsp = bsp_bo->map;
    287    /*
    288     * 0x000..0x100: picparm_bsp
    289     * 0x200..0x500: picparm_vp
    290     * 0x500..0x700: comm
    291     * 0x700..onward: raw bitstream
    292     */
    293 
    294    switch (codec){
    295    case PIPE_VIDEO_FORMAT_MPEG12:
    296       endmarker = 0xb7010000;
    297       caps = nouveau_vp3_fill_picparm_mpeg12_bsp(dec, desc.mpeg12, bsp);
    298       break;
    299    case PIPE_VIDEO_FORMAT_MPEG4:
    300       endmarker = 0xb1010000;
    301       caps = nouveau_vp3_fill_picparm_mpeg4_bsp(dec, desc.mpeg4, bsp);
    302       break;
    303    case PIPE_VIDEO_FORMAT_VC1: {
    304       endmarker = 0x0a010000;
    305       caps = nouveau_vp3_fill_picparm_vc1_bsp(dec, desc.vc1, bsp);
    306       break;
    307    }
    308    case PIPE_VIDEO_FORMAT_MPEG4_AVC: {
    309       endmarker = 0x0b010000;
    310       caps = nouveau_vp3_fill_picparm_h264_bsp(dec, desc.h264, bsp);
    311       break;
    312    }
    313    default: assert(0); return -1;
    314    }
    315 
    316    caps |= 0 << 16; // reset struct comm if flag is set
    317    caps |= 1 << 17; // enable watchdog
    318    caps |= 0 << 18; // do not report error to VP, so it can continue decoding what we have
    319    caps |= 0 << 19; // if enabled, use crypto crap?
    320 
    321    str_bsp = strparm_bsp(dec);
    322    str_bsp->w1[0] = 0x1;
    323 
    324    /* Append end sequence */
    325    *(uint32_t *)dec->bsp_ptr = endmarker;
    326    dec->bsp_ptr += 4;
    327    *(uint32_t *)dec->bsp_ptr = 0x00000000;
    328    dec->bsp_ptr += 4;
    329    *(uint32_t *)dec->bsp_ptr = endmarker;
    330    dec->bsp_ptr += 4;
    331    *(uint32_t *)dec->bsp_ptr = 0x00000000;
    332    str_bsp->w0[0] += 16;
    333 
    334    dec->bsp_ptr = NULL;
    335 
    336    return caps;
    337 }
    338