Libav 0.7.1
|
00001 /* 00002 * MPEG-2 HW acceleration. 00003 * 00004 * copyright (c) 2010 Laurent Aimar 00005 * 00006 * This file is part of Libav. 00007 * 00008 * Libav 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 * Libav 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 Libav; 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 00025 #define MAX_SLICES (SLICE_MAX_START_CODE - SLICE_MIN_START_CODE + 1) 00026 struct dxva2_picture_context { 00027 DXVA_PictureParameters pp; 00028 DXVA_QmatrixData qm; 00029 unsigned slice_count; 00030 DXVA_SliceInfo slice[MAX_SLICES]; 00031 00032 const uint8_t *bitstream; 00033 unsigned bitstream_size; 00034 }; 00035 00036 static void fill_picture_parameters(AVCodecContext *avctx, 00037 struct dxva_context *ctx, 00038 const struct MpegEncContext *s, 00039 DXVA_PictureParameters *pp) 00040 { 00041 const Picture *current_picture = s->current_picture_ptr; 00042 int is_field = s->picture_structure != PICT_FRAME; 00043 00044 memset(pp, 0, sizeof(*pp)); 00045 pp->wDecodedPictureIndex = ff_dxva2_get_surface_index(ctx, current_picture); 00046 pp->wDeblockedPictureIndex = 0; 00047 if (s->pict_type != AV_PICTURE_TYPE_I) 00048 pp->wForwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->last_picture); 00049 else 00050 pp->wForwardRefPictureIndex = 0xffff; 00051 if (s->pict_type == AV_PICTURE_TYPE_B) 00052 pp->wBackwardRefPictureIndex = ff_dxva2_get_surface_index(ctx, &s->next_picture); 00053 else 00054 pp->wBackwardRefPictureIndex = 0xffff; 00055 pp->wPicWidthInMBminus1 = s->mb_width - 1; 00056 pp->wPicHeightInMBminus1 = (s->mb_height >> is_field) - 1; 00057 pp->bMacroblockWidthMinus1 = 15; 00058 pp->bMacroblockHeightMinus1 = 15; 00059 pp->bBlockWidthMinus1 = 7; 00060 pp->bBlockHeightMinus1 = 7; 00061 pp->bBPPminus1 = 7; 00062 pp->bPicStructure = s->picture_structure; 00063 pp->bSecondField = is_field && !s->first_field; 00064 pp->bPicIntra = s->pict_type == AV_PICTURE_TYPE_I; 00065 pp->bPicBackwardPrediction = s->pict_type == AV_PICTURE_TYPE_B; 00066 pp->bBidirectionalAveragingMode = 0; 00067 pp->bMVprecisionAndChromaRelation= 0; /* FIXME */ 00068 pp->bChromaFormat = s->chroma_format; 00069 pp->bPicScanFixed = 1; 00070 pp->bPicScanMethod = s->alternate_scan ? 1 : 0; 00071 pp->bPicReadbackRequests = 0; 00072 pp->bRcontrol = 0; 00073 pp->bPicSpatialResid8 = 0; 00074 pp->bPicOverflowBlocks = 0; 00075 pp->bPicExtrapolation = 0; 00076 pp->bPicDeblocked = 0; 00077 pp->bPicDeblockConfined = 0; 00078 pp->bPic4MVallowed = 0; 00079 pp->bPicOBMC = 0; 00080 pp->bPicBinPB = 0; 00081 pp->bMV_RPS = 0; 00082 pp->bReservedBits = 0; 00083 pp->wBitstreamFcodes = (s->mpeg_f_code[0][0] << 12) | 00084 (s->mpeg_f_code[0][1] << 8) | 00085 (s->mpeg_f_code[1][0] << 4) | 00086 (s->mpeg_f_code[1][1] ); 00087 pp->wBitstreamPCEelements = (s->intra_dc_precision << 14) | 00088 (s->picture_structure << 12) | 00089 (s->top_field_first << 11) | 00090 (s->frame_pred_frame_dct << 10) | 00091 (s->concealment_motion_vectors << 9) | 00092 (s->q_scale_type << 8) | 00093 (s->intra_vlc_format << 7) | 00094 (s->alternate_scan << 6) | 00095 (s->repeat_first_field << 5) | 00096 (s->chroma_420_type << 4) | 00097 (s->progressive_frame << 3); 00098 pp->bBitstreamConcealmentNeed = 0; 00099 pp->bBitstreamConcealmentMethod = 0; 00100 } 00101 00102 static void fill_quantization_matrices(AVCodecContext *avctx, 00103 struct dxva_context *ctx, 00104 const struct MpegEncContext *s, 00105 DXVA_QmatrixData *qm) 00106 { 00107 int i; 00108 for (i = 0; i < 4; i++) 00109 qm->bNewQmatrix[i] = 1; 00110 for (i = 0; i < 64; i++) { 00111 int n = s->dsp.idct_permutation[ff_zigzag_direct[i]]; 00112 qm->Qmatrix[0][i] = s->intra_matrix[n];; 00113 qm->Qmatrix[1][i] = s->inter_matrix[n];; 00114 qm->Qmatrix[2][i] = s->chroma_intra_matrix[n];; 00115 qm->Qmatrix[3][i] = s->chroma_inter_matrix[n];; 00116 } 00117 } 00118 00119 static void fill_slice(AVCodecContext *avctx, 00120 const struct MpegEncContext *s, 00121 DXVA_SliceInfo *slice, 00122 unsigned position, 00123 const uint8_t *buffer, unsigned size) 00124 { 00125 int is_field = s->picture_structure != PICT_FRAME; 00126 GetBitContext gb; 00127 00128 memset(slice, 0, sizeof(*slice)); 00129 slice->wHorizontalPosition = s->mb_x; 00130 slice->wVerticalPosition = s->mb_y >> is_field; 00131 slice->dwSliceBitsInBuffer = 8 * size; 00132 slice->dwSliceDataLocation = position; 00133 slice->bStartCodeBitOffset = 0; 00134 slice->bReservedBits = 0; 00135 /* XXX We store the index of the first MB and it will be fixed later */ 00136 slice->wNumberMBsInSlice = (s->mb_y >> is_field) * s->mb_width + s->mb_x; 00137 slice->wBadSliceChopping = 0; 00138 00139 init_get_bits(&gb, &buffer[4], 8 * (size - 4)); 00140 00141 slice->wQuantizerScaleCode = get_bits(&gb, 5); 00142 while (get_bits1(&gb)) 00143 skip_bits(&gb, 8); 00144 00145 slice->wMBbitOffset = 4 * 8 + get_bits_count(&gb); 00146 } 00147 static int commit_bitstream_and_slice_buffer(AVCodecContext *avctx, 00148 DXVA2_DecodeBufferDesc *bs, 00149 DXVA2_DecodeBufferDesc *sc) 00150 { 00151 const struct MpegEncContext *s = avctx->priv_data; 00152 struct dxva_context *ctx = avctx->hwaccel_context; 00153 struct dxva2_picture_context *ctx_pic = 00154 s->current_picture_ptr->hwaccel_picture_private; 00155 const int is_field = s->picture_structure != PICT_FRAME; 00156 const unsigned mb_count = s->mb_width * (s->mb_height >> is_field); 00157 uint8_t *dxva_data, *current, *end; 00158 unsigned dxva_size; 00159 unsigned i; 00160 00161 if (FAILED(IDirectXVideoDecoder_GetBuffer(ctx->decoder, 00162 DXVA2_BitStreamDateBufferType, 00163 &dxva_data, &dxva_size))) 00164 return -1; 00165 current = dxva_data; 00166 end = dxva_data + dxva_size; 00167 00168 for (i = 0; i < ctx_pic->slice_count; i++) { 00169 DXVA_SliceInfo *slice = &ctx_pic->slice[i]; 00170 unsigned position = slice->dwSliceDataLocation; 00171 unsigned size = slice->dwSliceBitsInBuffer / 8; 00172 if (size > end - current) { 00173 av_log(avctx, AV_LOG_ERROR, "Failed to build bitstream"); 00174 break; 00175 } 00176 slice->dwSliceDataLocation = current - dxva_data; 00177 00178 if (i < ctx_pic->slice_count - 1) 00179 slice->wNumberMBsInSlice = 00180 slice[1].wNumberMBsInSlice - slice[0].wNumberMBsInSlice; 00181 else 00182 slice->wNumberMBsInSlice = 00183 mb_count - slice[0].wNumberMBsInSlice; 00184 00185 memcpy(current, &ctx_pic->bitstream[position], size); 00186 current += size; 00187 } 00188 if (FAILED(IDirectXVideoDecoder_ReleaseBuffer(ctx->decoder, 00189 DXVA2_BitStreamDateBufferType))) 00190 return -1; 00191 if (i < ctx_pic->slice_count) 00192 return -1; 00193 00194 memset(bs, 0, sizeof(*bs)); 00195 bs->CompressedBufferType = DXVA2_BitStreamDateBufferType; 00196 bs->DataSize = current - dxva_data; 00197 bs->NumMBsInBuffer = mb_count; 00198 00199 return ff_dxva2_commit_buffer(avctx, ctx, sc, 00200 DXVA2_SliceControlBufferType, 00201 ctx_pic->slice, 00202 ctx_pic->slice_count * sizeof(*ctx_pic->slice), 00203 mb_count); 00204 } 00205 00206 static int start_frame(AVCodecContext *avctx, 00207 av_unused const uint8_t *buffer, 00208 av_unused uint32_t size) 00209 { 00210 const struct MpegEncContext *s = avctx->priv_data; 00211 struct dxva_context *ctx = avctx->hwaccel_context; 00212 struct dxva2_picture_context *ctx_pic = 00213 s->current_picture_ptr->hwaccel_picture_private; 00214 00215 if (!ctx->decoder || !ctx->cfg || ctx->surface_count <= 0) 00216 return -1; 00217 assert(ctx_pic); 00218 00219 fill_picture_parameters(avctx, ctx, s, &ctx_pic->pp); 00220 fill_quantization_matrices(avctx, ctx, s, &ctx_pic->qm); 00221 00222 ctx_pic->slice_count = 0; 00223 ctx_pic->bitstream_size = 0; 00224 ctx_pic->bitstream = NULL; 00225 return 0; 00226 } 00227 00228 static int decode_slice(AVCodecContext *avctx, 00229 const uint8_t *buffer, uint32_t size) 00230 { 00231 const struct MpegEncContext *s = avctx->priv_data; 00232 struct dxva2_picture_context *ctx_pic = 00233 s->current_picture_ptr->hwaccel_picture_private; 00234 unsigned position; 00235 00236 if (ctx_pic->slice_count >= MAX_SLICES) 00237 return -1; 00238 00239 if (!ctx_pic->bitstream) 00240 ctx_pic->bitstream = buffer; 00241 ctx_pic->bitstream_size += size; 00242 00243 position = buffer - ctx_pic->bitstream; 00244 fill_slice(avctx, s, &ctx_pic->slice[ctx_pic->slice_count++], position, 00245 buffer, size); 00246 return 0; 00247 } 00248 00249 static int end_frame(AVCodecContext *avctx) 00250 { 00251 struct MpegEncContext *s = avctx->priv_data; 00252 struct dxva2_picture_context *ctx_pic = 00253 s->current_picture_ptr->hwaccel_picture_private; 00254 00255 if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0) 00256 return -1; 00257 return ff_dxva2_common_end_frame(avctx, s, 00258 &ctx_pic->pp, sizeof(ctx_pic->pp), 00259 &ctx_pic->qm, sizeof(ctx_pic->qm), 00260 commit_bitstream_and_slice_buffer); 00261 } 00262 00263 AVHWAccel ff_mpeg2_dxva2_hwaccel = { 00264 .name = "mpeg2_dxva2", 00265 .type = AVMEDIA_TYPE_VIDEO, 00266 .id = CODEC_ID_MPEG2VIDEO, 00267 .pix_fmt = PIX_FMT_DXVA2_VLD, 00268 .capabilities = 0, 00269 .start_frame = start_frame, 00270 .decode_slice = decode_slice, 00271 .end_frame = end_frame, 00272 .priv_data_size = sizeof(struct dxva2_picture_context), 00273 }; 00274