• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavcodec/dxva2_vc1.c

Go to the documentation of this file.
00001 /*
00002  * DXVA2 WMV3/VC-1 HW acceleration.
00003  *
00004  * copyright (c) 2010 Laurent Aimar
00005  *
00006  * This file is part of FFmpeg.
00007  *
00008  * FFmpeg is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public
00010  * License as published by the Free Software Foundation; either
00011  * version 2.1 of the License, or (at your option) any later version.
00012  *
00013  * FFmpeg is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with FFmpeg; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00021  */
00022 
00023 #include "dxva2_internal.h"
00024 #include "vc1.h"
00025 #include "vc1data.h"
00026 
00027 struct dxva2_picture_context {
00028     DXVA_PictureParameters pp;
00029     DXVA_SliceInfo         si;
00030 
00031     const uint8_t          *bitstream;
00032     unsigned               bitstream_size;
00033 };
00034 
00035 static void fill_picture_parameters(AVCodecContext *avctx,
00036                                     struct dxva_context *ctx, const VC1Context *v,
00037                                     DXVA_PictureParameters *pp)
00038 {
00039     const MpegEncContext *s = &v->s;
00040     const Picture *current_picture = s->current_picture_ptr;
00041 
00042     memset(pp, 0, sizeof(*pp));
00043     pp->wDecodedPictureIndex    =
00044     pp->wDeblockedPictureIndex  = ff_dxva2_get_surface_index(ctx, current_picture);
00045     if (s->pict_type != FF_I_TYPE)
00046         pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->last_picture);
00047     else
00048         pp->wForwardRefPictureIndex = 0xffff;
00049     if (s->pict_type == FF_B_TYPE)
00050         pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->next_picture);
00051     else
00052         pp->wBackwardRefPictureIndex = 0xffff;
00053     if (v->profile == PROFILE_ADVANCED) {
00054         /* It is the cropped width/height -1 of the frame */
00055         pp->wPicWidthInMBminus1 = avctx->width  - 1;
00056         pp->wPicHeightInMBminus1= avctx->height - 1;
00057     } else {
00058         /* It is the coded width/height in macroblock -1 of the frame */
00059         pp->wPicWidthInMBminus1 = s->mb_width  - 1;
00060         pp->wPicHeightInMBminus1= s->mb_height - 1;
00061     }
00062     pp->bMacroblockWidthMinus1  = 15;
00063     pp->bMacroblockHeightMinus1 = 15;
00064     pp->bBlockWidthMinus1       = 7;
00065     pp->bBlockHeightMinus1      = 7;
00066     pp->bBPPminus1              = 7;
00067     if (s->picture_structure & PICT_TOP_FIELD)
00068         pp->bPicStructure      |= 0x01;
00069     if (s->picture_structure & PICT_BOTTOM_FIELD)
00070         pp->bPicStructure      |= 0x02;
00071     pp->bSecondField            = v->interlace && v->fcm != 0x03 && !s->first_field;
00072     pp->bPicIntra               = s->pict_type == FF_I_TYPE;
00073     pp->bPicBackwardPrediction  = s->pict_type == FF_B_TYPE;
00074     pp->bBidirectionalAveragingMode = (1                                           << 7) |
00075                                       ((ctx->cfg->ConfigIntraResidUnsigned != 0)   << 6) |
00076                                       ((ctx->cfg->ConfigResidDiffAccelerator != 0) << 5) |
00077                                       ((v->lumscale != 32 || v->lumshift != 0)     << 4) |
00078                                       ((v->profile == PROFILE_ADVANCED)            << 3);
00079     pp->bMVprecisionAndChromaRelation = ((v->mv_mode == MV_PMODE_1MV_HPEL_BILIN) << 3) |
00080                                         (1                                       << 2) |
00081                                         (0                                       << 1) |
00082                                         (!s->quarter_sample                          );
00083     pp->bChromaFormat           = v->chromaformat;
00084     ctx->report_id++;
00085     if (ctx->report_id >= (1 << 16))
00086         ctx->report_id = 1;
00087     pp->bPicScanFixed           = ctx->report_id >> 8;
00088     pp->bPicScanMethod          = ctx->report_id & 0xff;
00089     pp->bPicReadbackRequests    = 0;
00090     pp->bRcontrol               = v->rnd;
00091     pp->bPicSpatialResid8       = (v->panscanflag  << 7) |
00092                                   (v->refdist_flag << 6) |
00093                                   (s->loop_filter  << 5) |
00094                                   (v->fastuvmc     << 4) |
00095                                   (v->extended_mv  << 3) |
00096                                   (v->dquant       << 1) |
00097                                   (v->vstransform      );
00098     pp->bPicOverflowBlocks      = (v->quantizer_mode << 6) |
00099                                   (v->multires       << 5) |
00100                                   (s->resync_marker  << 4) |
00101                                   (v->rangered       << 3) |
00102                                   (s->max_b_frames       );
00103     pp->bPicExtrapolation       = (!v->interlace || v->fcm == 0x00) ? 1 : 2;
00104     pp->bPicDeblocked           = ((v->profile != PROFILE_ADVANCED && v->rangeredfrm) << 5) |
00105                                   (s->loop_filter                                     << 1);
00106     pp->bPicDeblockConfined     = (v->postprocflag             << 7) |
00107                                   (v->broadcast                << 6) |
00108                                   (v->interlace                << 5) |
00109                                   (v->tfcntrflag               << 4) |
00110                                   (v->finterpflag              << 3) |
00111                                   ((s->pict_type != FF_B_TYPE) << 2) |
00112                                   (v->psf                      << 1) |
00113                                   (v->extended_dmv                 );
00114     if (s->pict_type != FF_I_TYPE)
00115         pp->bPic4MVallowed      = v->mv_mode == MV_PMODE_MIXED_MV ||
00116                                   (v->mv_mode == MV_PMODE_INTENSITY_COMP &&
00117                                    v->mv_mode2 == MV_PMODE_MIXED_MV);
00118     if (v->profile == PROFILE_ADVANCED)
00119         pp->bPicOBMC            = (v->range_mapy_flag  << 7) |
00120                                   (v->range_mapy       << 4) |
00121                                   (v->range_mapuv_flag << 3) |
00122                                   (v->range_mapuv          );
00123     pp->bPicBinPB               = 0;
00124     pp->bMV_RPS                 = 0;
00125     pp->bReservedBits           = 0;
00126     if (s->picture_structure == PICT_FRAME) {
00127         pp->wBitstreamFcodes        = v->lumscale;
00128         pp->wBitstreamPCEelements   = v->lumshift;
00129     } else {
00130         /* Syntax: (top_field_param << 8) | bottom_field_param */
00131         pp->wBitstreamFcodes        = (v->lumscale << 8) | v->lumscale;
00132         pp->wBitstreamPCEelements   = (v->lumshift << 8) | v->lumshift;
00133     }
00134     pp->bBitstreamConcealmentNeed   = 0;
00135     pp->bBitstreamConcealmentMethod = 0;
00136 }
00137 
00138 static void fill_slice(AVCodecContext *avctx, DXVA_SliceInfo *slice,
00139                        unsigned position, unsigned size)
00140 {
00141     const VC1Context *v = avctx->priv_data;
00142     const MpegEncContext *s = &v->s;
00143 
00144     memset(slice, 0, sizeof(*slice));
00145     slice->wHorizontalPosition = 0;
00146     slice->wVerticalPosition   = s->mb_y;
00147     slice->dwSliceBitsInBuffer = 8 * size;
00148     slice->dwSliceDataLocation = position;
00149     slice->bStartCodeBitOffset = 0;
00150     slice->bReservedBits       = 0;
00151     slice->wMBbitOffset        = get_bits_count(&s->gb);
00152     slice->wNumberMBsInSlice   = s->mb_width * s->mb_height; /* XXX We assume 1 slice */
00153     slice->wQuantizerScaleCode = v->pq;
00154     slice->wBadSliceChopping   = 0;
00155 }
00156 
00157 static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx,
00158                                              DXVA2_DecodeBufferDesc *bs,
00159                                              DXVA2_DecodeBufferDesc *sc)
00160 {
00161     const VC1Context *v = avctx->priv_data;
00162     struct dxva_context *ctx = avctx->hwaccel_context;
00163     const MpegEncContext *s = &v->s;
00164     struct dxva2_picture_context *ctx_pic = s->current_picture_ptr->hwaccel_picture_private;
00165 
00166     DXVA_SliceInfo *slice = &ctx_pic->si;
00167 
00168     static const uint8_t start_code[] = { 0, 0, 1, 0x0d };
00169     const unsigned start_code_size = avctx->codec_id == CODEC_ID_VC1 ? sizeof(start_code) : 0;
00170     const unsigned slice_size = slice->dwSliceBitsInBuffer / 8;
00171     const unsigned padding = 128 - ((start_code_size + slice_size) & 127);
00172     const unsigned data_size = start_code_size + slice_size + padding;
00173 
00174     uint8_t  *dxva_data;
00175     unsigned dxva_size;
00176     int result;
00177 
00178     if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder,
00179                                               DXVA2_BitStreamDateBufferType,
00180                                               &dxva_data, &dxva_size)))
00181         return -1;
00182 
00183     result = data_size <= dxva_size ? 0 : -1;
00184     if (!result) {
00185         if (start_code_size > 0)
00186             memcpy(dxva_data, start_code, start_code_size);
00187         memcpy(dxva_data + start_code_size,
00188                ctx_pic->bitstream + slice->dwSliceDataLocation, slice_size);
00189         if (padding > 0)
00190             memset(dxva_data + start_code_size + slice_size, 0, padding);
00191         slice->dwSliceBitsInBuffer = 8 * data_size;
00192     }
00193     if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder,
00194                                                   DXVA2_BitStreamDateBufferType)))
00195         return -1;
00196     if (result)
00197         return result;
00198 
00199     memset(bs, 0, sizeof(*bs));
00200     bs->CompressedBufferType = DXVA2_BitStreamDateBufferType;
00201     bs->DataSize             = data_size;
00202     bs->NumMBsInBuffer       = s->mb_width * s->mb_height;
00203     assert((bs->DataSize & 127) == 0);
00204 
00205     return ff_dxva2_commit_buffer(avctx, ctx, sc,
00206                                   DXVA2_SliceControlBufferType,
00207                                   slice, sizeof(*slice), bs->NumMBsInBuffer);
00208 }
00209 
00210 static int start_frame(AVCodecContext *avctx,
00211                        av_unused const uint8_t *buffer,
00212                        av_unused uint32_t size)
00213 {
00214     const VC1Context *v = avctx->priv_data;
00215     struct dxva_context *ctx = avctx->hwaccel_context;
00216     struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private;
00217 
00218     if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0)
00219         return -1;
00220     assert(ctx_pic);
00221 
00222     fill_picture_parameters(avctx, ctx, v, &ctx_pic->pp);
00223 
00224     ctx_pic->bitstream_size = 0;
00225     ctx_pic->bitstream      = NULL;
00226     return 0;
00227 }
00228 
00229 static int decode_slice(AVCodecContext *avctx,
00230                         const uint8_t *buffer, uint32_t size)
00231 {
00232     const VC1Context *v = avctx->priv_data;
00233     const Picture *current_picture = v->s.current_picture_ptr;
00234     struct dxva2_picture_context *ctx_pic = current_picture->hwaccel_picture_private;
00235 
00236     if (ctx_pic->bitstream_size > 0)
00237         return -1;
00238 
00239     if (avctx->codec_id == CODEC_ID_VC1 &&
00240         size >= 4 && IS_MARKER(AV_RB32(buffer))) {
00241         buffer += 4;
00242         size   -= 4;
00243     }
00244 
00245     ctx_pic->bitstream_size = size;
00246     ctx_pic->bitstream      = buffer;
00247 
00248     fill_slice(avctx, &ctx_pic->si, 0, size);
00249     return 0;
00250 }
00251 
00252 static int end_frame(AVCodecContext *avctx)
00253 {
00254     VC1Context *v = avctx->priv_data;
00255     struct dxva2_picture_context *ctx_pic = v->s.current_picture_ptr->hwaccel_picture_private;
00256 
00257     if (ctx_pic->bitstream_size <= 0)
00258         return -1;
00259 
00260     return ff_dxva2_common_end_frame(avctx, &v->s,
00261                                      &ctx_pic->pp, sizeof(ctx_pic->pp),
00262                                      NULL, 0,
00263                                      commit_bitstream_and_slice_buffer);
00264 }
00265 
00266 #if CONFIG_WMV3_DXVA2_HWACCEL
00267 AVHWAccel wmv3_dxva2_hwaccel = {
00268     .name           = "wmv3_dxva2",
00269     .type           = AVMEDIA_TYPE_VIDEO,
00270     .id             = CODEC_ID_WMV3,
00271     .pix_fmt        = PIX_FMT_DXVA2_VLD,
00272     .capabilities   = 0,
00273     .start_frame    = start_frame,
00274     .decode_slice   = decode_slice,
00275     .end_frame      = end_frame,
00276     .priv_data_size = sizeof(struct dxva2_picture_context),
00277 };
00278 #endif
00279 
00280 AVHWAccel vc1_dxva2_hwaccel = {
00281     .name           = "vc1_dxva2",
00282     .type           = AVMEDIA_TYPE_VIDEO,
00283     .id             = CODEC_ID_VC1,
00284     .pix_fmt        = PIX_FMT_DXVA2_VLD,
00285     .capabilities   = 0,
00286     .start_frame    = start_frame,
00287     .decode_slice   = decode_slice,
00288     .end_frame      = end_frame,
00289     .priv_data_size = sizeof(struct dxva2_picture_context),
00290 };
00291 

Generated on Fri Sep 16 2011 17:17:36 for FFmpeg by  doxygen 1.7.1