* This can be used to prevent truncation of the last audio samples.
*/
#define AV_CODEC_CAP_SMALL_LAST_FRAME (1 << 6)
- #if FF_API_CAP_VDPAU
- /**
- * Codec can export data for HW decoding (VDPAU).
- */
- #define AV_CODEC_CAP_HWACCEL_VDPAU (1 << 7)
- #endif
-
+
/**
* Codec can output multiple frames per AVPacket
* Normally demuxers return one frame at a time, demuxers which do not do
* Codec can be fed a final frame with a smaller size.
* This can be used to prevent truncation of the last audio samples.
*/
-#define CODEC_CAP_SMALL_LAST_FRAME 0x0040
+#define CODEC_CAP_SMALL_LAST_FRAME AV_CODEC_CAP_SMALL_LAST_FRAME
- #if FF_API_CAP_VDPAU
- /**
- * Codec can export data for HW decoding (VDPAU).
- */
- #define CODEC_CAP_HWACCEL_VDPAU AV_CODEC_CAP_HWACCEL_VDPAU
- #endif
++
/**
* Codec can output multiple frames per AVPacket
* Normally demuxers return one frame at a time, demuxers which do not do
s->error_occurred = 0;
}
- #if FF_API_CAP_VDPAU
- s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU ||
- #endif
+static int er_supported(ERContext *s)
+{
+ if(s->avctx->hwaccel && s->avctx->hwaccel->decode_slice ||
+ !s->cur_pic.f ||
+ s->cur_pic.field_picture
+ )
+ return 0;
+ return 1;
+}
+
/**
* Add a slice.
* @param endx x component of the last macroblock, can be -1
int err = 0;
h->mb_y = 0;
- #if FF_API_CAP_VDPAU
- if (CONFIG_H264_VDPAU_DECODER &&
- h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU)
- ff_vdpau_h264_set_reference_frames(h);
- #endif
- if (!in_setup && !h->droppable)
- ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
- h->picture_structure == PICT_BOTTOM_FIELD);
--
if (in_setup || !(avctx->active_thread_type & FF_THREAD_FRAME)) {
if (!h->droppable) {
err = ff_h264_execute_ref_pic_marking(h);
"hardware accelerator failed to decode picture\n");
}
- #if FF_API_CAP_VDPAU
- if (CONFIG_H264_VDPAU_DECODER &&
- h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU)
- ff_vdpau_h264_picture_complete(h);
- #endif
-#if CONFIG_ERROR_RESILIENCE
- /*
- * FIXME: Error handling code does not seem to support interlaced
- * when slices span multiple rows
- * The ff_er_add_slice calls don't work right for bottom
- * fields; they cause massive erroneous error concealing
- * Error marking covers both fields (top and bottom).
- * This causes a mismatched s->error_count
- * and a bad error table. Further, the error count goes to
- * INT_MAX when called for bottom field, because mb_y is
- * past end by one (callers fault) and resync_mb_y != 0
- * causes problems for the first MB line, too.
- */
- if (!FIELD_PICTURE(h) && h->enable_er) {
- h264_set_erpic(&sl->er.cur_pic, h->cur_pic_ptr);
- h264_set_erpic(&sl->er.last_pic,
- sl->ref_count[0] ? sl->ref_list[0][0].parent : NULL);
- h264_set_erpic(&sl->er.next_pic,
- sl->ref_count[1] ? sl->ref_list[1][0].parent : NULL);
- ff_er_frame_end(&sl->er);
- }
-#endif /* CONFIG_ERROR_RESILIENCE */
--
+ if (!in_setup && !h->droppable)
+ ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
+ h->picture_structure == PICT_BOTTOM_FIELD);
emms_c();
h->current_slice = 0;
pic->f->crop_top = h->crop_top;
pic->f->crop_bottom = h->crop_bottom;
- if (CONFIG_ERROR_RESILIENCE && h->enable_er)
+ if ((ret = alloc_picture(h, pic)) < 0)
+ return ret;
- if(!h->frame_recovered && !h->avctx->hwaccel
- #if FF_API_CAP_VDPAU
- && !(h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU)
- #endif
- )
++ if(!h->frame_recovered && !h->avctx->hwaccel)
+ ff_color_frame(pic->f, c);
+
+ h->cur_pic_ptr = pic;
+ ff_h264_unref_picture(h, &h->cur_pic);
+ if (CONFIG_ERROR_RESILIENCE) {
+ ff_h264_set_erpic(&h->slice_ctx[0].er.cur_pic, NULL);
+ }
+
+ if ((ret = ff_h264_ref_picture(h, &h->cur_pic, h->cur_pic_ptr)) < 0)
+ return ret;
+
+ for (i = 0; i < h->nb_slice_ctx; i++) {
+ h->slice_ctx[i].linesize = h->cur_pic_ptr->f->linesize[0];
+ h->slice_ctx[i].uvlinesize = h->cur_pic_ptr->f->linesize[1];
+ }
+
+ if (CONFIG_ERROR_RESILIENCE && h->enable_er) {
ff_er_frame_start(&h->slice_ctx[0].er);
+ ff_h264_set_erpic(&h->slice_ctx[0].er.last_pic, NULL);
+ ff_h264_set_erpic(&h->slice_ctx[0].er.next_pic, NULL);
+ }
for (i = 0; i < 16; i++) {
h->block_offset[i] = (4 * ((scan8[i] - scan8[0]) & 7) << pixel_shift) + 4 * pic->f->linesize[0] * ((scan8[i] - scan8[0]) >> 3);
ret = ff_h264_alloc_tables(h);
if (ret < 0) {
av_log(h->avctx, AV_LOG_ERROR, "Could not allocate memory\n");
- return ret;
+ goto fail;
}
- #if FF_API_CAP_VDPAU
- if (h->avctx->codec &&
- h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU &&
- (sps->bit_depth_luma != 8 || sps->chroma_format_idc > 1)) {
- av_log(h->avctx, AV_LOG_ERROR,
- "VDPAU decoding does not support video colorspace.\n");
- ret = AVERROR_INVALIDDATA;
- goto fail;
- }
- #endif
-
- if (sps->bit_depth_luma < 8 || sps->bit_depth_luma > 10) {
+ if (sps->bit_depth_luma < 8 || sps->bit_depth_luma > 14 ||
+ sps->bit_depth_luma == 11 || sps->bit_depth_luma == 13
+ ) {
av_log(h->avctx, AV_LOG_ERROR, "Unsupported bit depth %d\n",
sps->bit_depth_luma);
- return AVERROR_INVALIDDATA;
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
}
+ h->cur_bit_depth_luma =
h->avctx->bits_per_raw_sample = sps->bit_depth_luma;
+ h->cur_chroma_format_idc = sps->chroma_format_idc;
h->pixel_shift = sps->bit_depth_luma > 8;
h->chroma_format_idc = sps->chroma_format_idc;
h->bit_depth_luma = sps->bit_depth_luma;
int ret = 0;
int i, j;
- if (h->avctx->hwaccel || context_count < 1
- #if FF_API_CAP_VDPAU
- || h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU
- #endif
- )
+ h->slice_ctx[0].next_slice_idx = INT_MAX;
+
+ if (h->avctx->hwaccel || context_count < 1)
return 0;
+
+ av_assert0(context_count && h->slice_ctx[context_count - 1].mb_y < h->mb_height);
+
if (context_count == 1) {
h->slice_ctx[0].next_slice_idx = h->mb_width * h->mb_height;
err = 0;
switch (nal->type) {
case H264_NAL_IDR_SLICE:
- idr(h); // FIXME ensure we don't lose some frames if there is reordering
+ if ((nal->data[1] & 0xFC) == 0x98) {
+ av_log(h->avctx, AV_LOG_ERROR, "Invalid inter IDR frame\n");
+ h->next_outputed_poc = INT_MIN;
+ ret = -1;
+ goto end;
+ }
+ if(!idr_cleared) {
+ if (h->current_slice && (avctx->active_thread_type & FF_THREAD_SLICE)) {
+ av_log(h, AV_LOG_ERROR, "invalid mixed IDR / non IDR frames cannot be decoded in slice multithreading mode\n");
+ ret = AVERROR_INVALIDDATA;
+ goto end;
+ }
+ idr(h); // FIXME ensure we don't lose some frames if there is reordering
+ }
+ idr_cleared = 1;
+ h->has_recovery_point = 1;
case H264_NAL_SLICE:
- if ((err = ff_h264_queue_decode_slice(h, nal)))
+ h->has_slice = 1;
+
+ if ((err = ff_h264_queue_decode_slice(h, nal))) {
+ H264SliceContext *sl = h->slice_ctx + h->nb_slice_ctx_queued;
+ sl->ref_count[0] = sl->ref_count[1] = 0;
break;
+ }
+
+ if (h->current_slice == 1) {
+ if (avctx->active_thread_type & FF_THREAD_FRAME &&
+ i >= nals_needed && !h->setup_finished && h->cur_pic_ptr) {
+ ff_thread_finish_setup(avctx);
+ h->setup_finished = 1;
+ }
- if (avctx->active_thread_type & FF_THREAD_FRAME &&
- i >= nals_needed && !h->setup_finished && h->cur_pic_ptr) {
- ff_thread_finish_setup(avctx);
- h->setup_finished = 1;
+ if (h->avctx->hwaccel &&
+ (ret = h->avctx->hwaccel->start_frame(h->avctx, buf, buf_size)) < 0)
+ goto end;
- #if FF_API_CAP_VDPAU
- if (CONFIG_H264_VDPAU_DECODER &&
- h->avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU)
- ff_vdpau_h264_picture_start(h);
- #endif
}
max_slice_ctx = avctx->hwaccel ? 1 : h->nb_slice_ctx;
int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me,
ScratchpadContext *sc, int linesize)
{
- int alloc_size = FFALIGN(FFABS(linesize) + 32, 32);
+ int alloc_size = FFALIGN(FFABS(linesize) + 64, 32);
+
- if (avctx->hwaccel
- #if FF_API_CAP_VDPAU
- || avctx->codec->capabilities & AV_CODEC_CAP_HWACCEL_VDPAU
- #endif
- )
++ if (avctx->hwaccel)
+ return 0;
+
+ if (linesize < 24) {
+ av_log(avctx, AV_LOG_ERROR, "Image too small, temporary buffers cannot function\n");
+ return AVERROR_PATCHWELCOME;
+ }
// edge emu needs blocksize + filter length - 1
// (= 17x17 for halfpel / 21x21 for H.264)
return -1;
}
- if (!avctx->hwaccel
- #if FF_API_CAP_VDPAU
- && !(avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU)
- #endif
- ) {
- memset(s->last_picture_ptr->f->data[0], 0,
- avctx->height * s->last_picture_ptr->f->linesize[0]);
- memset(s->last_picture_ptr->f->data[1], 0x80,
- (avctx->height >> v_chroma_shift) *
- s->last_picture_ptr->f->linesize[1]);
- memset(s->last_picture_ptr->f->data[2], 0x80,
- (avctx->height >> v_chroma_shift) *
- s->last_picture_ptr->f->linesize[2]);
++ if (!avctx->hwaccel) {
+ for(i=0; i<avctx->height; i++)
+ memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i,
+ 0x80, avctx->width);
+ if (s->last_picture_ptr->f->data[2]) {
+ for(i=0; i<AV_CEIL_RSHIFT(avctx->height, v_chroma_shift); i++) {
+ memset(s->last_picture_ptr->f->data[1] + s->last_picture_ptr->f->linesize[1]*i,
+ 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift));
+ memset(s->last_picture_ptr->f->data[2] + s->last_picture_ptr->f->linesize[2]*i,
+ 0x80, AV_CEIL_RSHIFT(avctx->width, h_chroma_shift));
+ }
+ }
+
+ if(s->codec_id == AV_CODEC_ID_FLV1 || s->codec_id == AV_CODEC_ID_H263){
+ for(i=0; i<avctx->height; i++)
+ memset(s->last_picture_ptr->f->data[0] + s->last_picture_ptr->f->linesize[0]*i, 16, avctx->width);
+ }
+ }
ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 0);
ff_thread_report_progress(&s->last_picture_ptr->tf, INT_MAX, 1);
/**
* Print debugging info for the given picture.
*/
-void ff_print_debug_info(MpegEncContext *s, Picture *p)
+void ff_print_debug_info2(AVCodecContext *avctx, AVFrame *pict, uint8_t *mbskip_table,
+ uint32_t *mbtype_table, int8_t *qscale_table, int16_t (*motion_val[2])[2],
+ int *low_delay,
+ int mb_width, int mb_height, int mb_stride, int quarter_sample)
{
- AVFrame *pict;
- if (s->avctx->hwaccel || !p || !p->mb_type)
+ if ((avctx->flags2 & AV_CODEC_FLAG2_EXPORT_MVS) && mbtype_table && motion_val[0]) {
+ const int shift = 1 + quarter_sample;
+ const int scale = 1 << shift;
+ const int mv_sample_log2 = avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_SVQ3 ? 2 : 1;
+ const int mv_stride = (mb_width << mv_sample_log2) +
+ (avctx->codec->id == AV_CODEC_ID_H264 ? 0 : 1);
+ int mb_x, mb_y, mbcount = 0;
+
+ /* size is width * height * 2 * 4 where 2 is for directions and 4 is
+ * for the maximum number of MB (4 MB in case of IS_8x8) */
+ AVMotionVector *mvs = av_malloc_array(mb_width * mb_height, 2 * 4 * sizeof(AVMotionVector));
+ if (!mvs)
+ return;
+
+ for (mb_y = 0; mb_y < mb_height; mb_y++) {
+ for (mb_x = 0; mb_x < mb_width; mb_x++) {
+ int i, direction, mb_type = mbtype_table[mb_x + mb_y * mb_stride];
+ for (direction = 0; direction < 2; direction++) {
+ if (!USES_LIST(mb_type, direction))
+ continue;
+ if (IS_8X8(mb_type)) {
+ for (i = 0; i < 4; i++) {
+ int sx = mb_x * 16 + 4 + 8 * (i & 1);
+ int sy = mb_y * 16 + 4 + 8 * (i >> 1);
+ int xy = (mb_x * 2 + (i & 1) +
+ (mb_y * 2 + (i >> 1)) * mv_stride) << (mv_sample_log2 - 1);
+ int mx = motion_val[direction][xy][0];
+ int my = motion_val[direction][xy][1];
+ mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction);
+ }
+ } else if (IS_16X8(mb_type)) {
+ for (i = 0; i < 2; i++) {
+ int sx = mb_x * 16 + 8;
+ int sy = mb_y * 16 + 4 + 8 * i;
+ int xy = (mb_x * 2 + (mb_y * 2 + i) * mv_stride) << (mv_sample_log2 - 1);
+ int mx = motion_val[direction][xy][0];
+ int my = motion_val[direction][xy][1];
+
+ if (IS_INTERLACED(mb_type))
+ my *= 2;
+
+ mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction);
+ }
+ } else if (IS_8X16(mb_type)) {
+ for (i = 0; i < 2; i++) {
+ int sx = mb_x * 16 + 4 + 8 * i;
+ int sy = mb_y * 16 + 8;
+ int xy = (mb_x * 2 + i + mb_y * 2 * mv_stride) << (mv_sample_log2 - 1);
+ int mx = motion_val[direction][xy][0];
+ int my = motion_val[direction][xy][1];
+
+ if (IS_INTERLACED(mb_type))
+ my *= 2;
+
+ mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction);
+ }
+ } else {
+ int sx = mb_x * 16 + 8;
+ int sy = mb_y * 16 + 8;
+ int xy = (mb_x + mb_y * mv_stride) << mv_sample_log2;
+ int mx = motion_val[direction][xy][0];
+ int my = motion_val[direction][xy][1];
+ mbcount += add_mb(mvs + mbcount, mb_type, sx, sy, mx, my, scale, direction);
+ }
+ }
+ }
+ }
+
+ if (mbcount) {
+ AVFrameSideData *sd;
+
+ av_log(avctx, AV_LOG_DEBUG, "Adding %d MVs info to frame %d\n", mbcount, avctx->frame_number);
+ sd = av_frame_new_side_data(pict, AV_FRAME_DATA_MOTION_VECTORS, mbcount * sizeof(AVMotionVector));
+ if (!sd) {
+ av_freep(&mvs);
+ return;
+ }
+ memcpy(sd->data, mvs, mbcount * sizeof(AVMotionVector));
+ }
+
+ av_freep(&mvs);
+ }
+
+ /* TODO: export all the following to make them accessible for users (and filters) */
- if (avctx->hwaccel || !mbtype_table
- #if FF_API_CAP_VDPAU
- || (avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU)
- #endif
- )
++ if (avctx->hwaccel || !mbtype_table)
return;
- pict = p->f;
- if (s->avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) {
+
+ if (avctx->debug & (FF_DEBUG_SKIP | FF_DEBUG_QP | FF_DEBUG_MB_TYPE)) {
int x,y;
- av_log(s->avctx,AV_LOG_DEBUG,"New frame, type: ");
- switch (pict->pict_type) {
- 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++) {
- if (s->avctx->debug & FF_DEBUG_SKIP) {
- int count = s->mbskip_table[x + y * s->mb_stride];
+ av_log(avctx, AV_LOG_DEBUG, "New frame, type: %c\n",
+ av_get_picture_type_char(pict->pict_type));
+ for (y = 0; y < mb_height; y++) {
+ for (x = 0; x < mb_width; x++) {
+ if (avctx->debug & FF_DEBUG_SKIP) {
+ int count = mbskip_table ? mbskip_table[x + y * mb_stride] : 0;
if (count > 9)
count = 9;
- av_log(s->avctx, AV_LOG_DEBUG, "%1d", count);
+ av_log(avctx, AV_LOG_DEBUG, "%1d", count);
}
- if (s->avctx->debug & FF_DEBUG_QP) {
- av_log(s->avctx, AV_LOG_DEBUG, "%2d",
- p->qscale_table[x + y * s->mb_stride]);
+ if (avctx->debug & FF_DEBUG_QP) {
+ av_log(avctx, AV_LOG_DEBUG, "%2d",
+ qscale_table[x + y * mb_stride]);
}
- if (s->avctx->debug & FF_DEBUG_MB_TYPE) {
- int mb_type = p->mb_type[x + y * s->mb_stride];
+ if (avctx->debug & FF_DEBUG_MB_TYPE) {
+ int mb_type = mbtype_table[x + y * mb_stride];
// Type & MV direction
if (IS_PCM(mb_type))
- av_log(s->avctx, AV_LOG_DEBUG, "P");
+ av_log(avctx, AV_LOG_DEBUG, "P");
else if (IS_INTRA(mb_type) && IS_ACPRED(mb_type))
- av_log(s->avctx, AV_LOG_DEBUG, "A");
+ av_log(avctx, AV_LOG_DEBUG, "A");
else if (IS_INTRA4x4(mb_type))
- av_log(s->avctx, AV_LOG_DEBUG, "i");
+ av_log(avctx, AV_LOG_DEBUG, "i");
else if (IS_INTRA16x16(mb_type))
- av_log(s->avctx, AV_LOG_DEBUG, "I");
+ av_log(avctx, AV_LOG_DEBUG, "I");
else if (IS_DIRECT(mb_type) && IS_SKIP(mb_type))
- av_log(s->avctx, AV_LOG_DEBUG, "d");
+ av_log(avctx, AV_LOG_DEBUG, "d");
else if (IS_DIRECT(mb_type))
- av_log(s->avctx, AV_LOG_DEBUG, "D");
+ av_log(avctx, AV_LOG_DEBUG, "D");
else if (IS_GMC(mb_type) && IS_SKIP(mb_type))
- av_log(s->avctx, AV_LOG_DEBUG, "g");
+ av_log(avctx, AV_LOG_DEBUG, "g");
else if (IS_GMC(mb_type))
- av_log(s->avctx, AV_LOG_DEBUG, "G");
+ av_log(avctx, AV_LOG_DEBUG, "G");
else if (IS_SKIP(mb_type))
- av_log(s->avctx, AV_LOG_DEBUG, "S");
+ av_log(avctx, AV_LOG_DEBUG, "S");
else if (!USES_LIST(mb_type, 1))
- av_log(s->avctx, AV_LOG_DEBUG, ">");
+ av_log(avctx, AV_LOG_DEBUG, ">");
else if (!USES_LIST(mb_type, 0))
- av_log(s->avctx, AV_LOG_DEBUG, "<");
+ av_log(avctx, AV_LOG_DEBUG, "<");
else {
- assert(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1));
- av_log(s->avctx, AV_LOG_DEBUG, "X");
+ av_assert2(USES_LIST(mb_type, 0) && USES_LIST(mb_type, 1));
+ av_log(avctx, AV_LOG_DEBUG, "X");
}
// segmentation
*got_frame = 1;
}
- return 0;
+ return buf_size;
}
- #if FF_API_CAP_VDPAU
- if (s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU) {
- if (v->profile < PROFILE_ADVANCED)
- avctx->pix_fmt = AV_PIX_FMT_VDPAU_WMV3;
- else
- avctx->pix_fmt = AV_PIX_FMT_VDPAU_VC1;
- }
- #endif
-
//for advanced profile we may need to parse and unescape data
if (avctx->codec_id == AV_CODEC_ID_VC1 || avctx->codec_id == AV_CODEC_ID_VC1IMAGE) {
int buf_size2 = 0;
break;
case VC1_CODE_FIELD: {
int buf_size3;
- if (avctx->hwaccel
- #if FF_API_CAP_VDPAU
- || s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU
- #endif
- )
- tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1));
- if (!tmp)
++ if (avctx->hwaccel)
+ buf_start_second_field = start;
+ tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1));
+ if (!tmp) {
+ ret = AVERROR(ENOMEM);
goto err;
+ }
slices = tmp;
slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!slices[n_slices].buf)
+ if (!slices[n_slices].buf) {
+ ret = AVERROR(ENOMEM);
goto err;
+ }
buf_size3 = vc1_unescape_buffer(start + 4, size,
slices[n_slices].buf);
init_get_bits(&slices[n_slices].gb, slices[n_slices].buf,
divider = find_next_marker(buf, buf + buf_size);
if ((divider == (buf + buf_size)) || AV_RB32(divider) != VC1_CODE_FIELD) {
av_log(avctx, AV_LOG_ERROR, "Error in WVC1 interlaced frame\n");
+ ret = AVERROR_INVALIDDATA;
goto err;
} else { // found field marker, unescape second field
- if (avctx->hwaccel
- #if FF_API_CAP_VDPAU
- || s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU
- #endif
- )
- tmp = av_realloc(slices, sizeof(*slices) * (n_slices+1));
- if (!tmp)
++ if (avctx->hwaccel)
+ buf_start_second_field = divider;
+ tmp = av_realloc_array(slices, sizeof(*slices), (n_slices+1));
+ if (!tmp) {
+ ret = AVERROR(ENOMEM);
goto err;
+ }
slices = tmp;
slices[n_slices].buf = av_mallocz(buf_size + AV_INPUT_BUFFER_PADDING_SIZE);
- if (!slices[n_slices].buf)
+ if (!slices[n_slices].buf) {
+ ret = AVERROR(ENOMEM);
goto err;
+ }
buf_size3 = vc1_unescape_buffer(divider + 4, buf + buf_size - divider - 4, slices[n_slices].buf);
init_get_bits(&slices[n_slices].gb, slices[n_slices].buf,
buf_size3 << 3);
s->me.qpel_put = s->qdsp.put_qpel_pixels_tab;
s->me.qpel_avg = s->qdsp.avg_qpel_pixels_tab;
- #if FF_API_CAP_VDPAU
- if ((CONFIG_VC1_VDPAU_DECODER)
- &&s->avctx->codec->capabilities&AV_CODEC_CAP_HWACCEL_VDPAU) {
- if (v->field_mode && buf_start_second_field) {
- ff_vdpau_vc1_decode_picture(s, buf_start, buf_start_second_field - buf_start);
- ff_vdpau_vc1_decode_picture(s, buf_start_second_field, (buf + buf_size) - buf_start_second_field);
- } else {
- ff_vdpau_vc1_decode_picture(s, buf_start, (buf + buf_size) - buf_start);
- }
- } else
- #endif
if (avctx->hwaccel) {
- if (avctx->hwaccel->start_frame(avctx, buf, buf_size) < 0)
- goto err;
- if (avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start) < 0)
- goto err;
- if (avctx->hwaccel->end_frame(avctx) < 0)
- goto err;
+ s->mb_y = 0;
+ if (v->field_mode && buf_start_second_field) {
+ // decode first field
+ s->picture_structure = PICT_BOTTOM_FIELD - v->tff;
+ if ((ret = avctx->hwaccel->start_frame(avctx, buf_start, buf_start_second_field - buf_start)) < 0)
+ goto err;
+ if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start, buf_start_second_field - buf_start)) < 0)
+ goto err;
+ if ((ret = avctx->hwaccel->end_frame(avctx)) < 0)
+ goto err;
+
+ // decode second field
+ s->gb = slices[n_slices1 + 1].gb;
+ s->picture_structure = PICT_TOP_FIELD + v->tff;
+ v->second_field = 1;
+ v->pic_header_flag = 0;
+ if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
+ av_log(avctx, AV_LOG_ERROR, "parsing header for second field failed");
+ ret = AVERROR_INVALIDDATA;
+ goto err;
+ }
+ v->s.current_picture_ptr->f->pict_type = v->s.pict_type;
+
+ if ((ret = avctx->hwaccel->start_frame(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field)) < 0)
+ goto err;
+ if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start_second_field, (buf + buf_size) - buf_start_second_field)) < 0)
+ goto err;
+ if ((ret = avctx->hwaccel->end_frame(avctx)) < 0)
+ goto err;
+ } else {
+ s->picture_structure = PICT_FRAME;
+ if ((ret = avctx->hwaccel->start_frame(avctx, buf_start, (buf + buf_size) - buf_start)) < 0)
+ goto err;
+
+ if (n_slices == 0) {
+ // no slices, decode the frame as-is
+ if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start, (buf + buf_size) - buf_start)) < 0)
+ goto err;
+ } else {
+ // decode the frame part as the first slice
+ if ((ret = avctx->hwaccel->decode_slice(avctx, buf_start, slices[0].rawbuf - buf_start)) < 0)
+ goto err;
+
+ // and process the slices as additional slices afterwards
+ for (i = 0 ; i < n_slices; i++) {
+ s->gb = slices[i].gb;
+ s->mb_y = slices[i].mby_start;
+
+ v->pic_header_flag = get_bits1(&s->gb);
+ if (v->pic_header_flag) {
+ if (ff_vc1_parse_frame_header_adv(v, &s->gb) < 0) {
+ av_log(v->s.avctx, AV_LOG_ERROR, "Slice header damaged\n");
+ ret = AVERROR_INVALIDDATA;
+ if (avctx->err_recognition & AV_EF_EXPLODE)
+ goto err;
+ continue;
+ }
+ }
+
+ if ((ret = avctx->hwaccel->decode_slice(avctx, slices[i].rawbuf, slices[i].raw_size)) < 0)
+ goto err;
+ }
+ }
+ if ((ret = avctx->hwaccel->end_frame(avctx)) < 0)
+ goto err;
+ }
} else {
int header_ret = 0;
* FF_API_* defines may be placed below to indicate public API that will be
* dropped at a future version bump. The defines themselves are not part of
* the public API and may change, break or disappear at any time.
+ *
+ * @note, when bumping the major version it is recommended to manually
+ * disable each FF_API_* in its own commit instead of disabling them all
+ * at once through the bump. This improves the git bisect-ability of the change.
*/
- #ifndef FF_API_CAP_VDPAU
- #define FF_API_CAP_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58)
- #endif
+#ifndef FF_API_VIMA_DECODER
+#define FF_API_VIMA_DECODER (LIBAVCODEC_VERSION_MAJOR < 58)
+#endif
+#ifndef FF_API_LOWRES
+#define FF_API_LOWRES (LIBAVCODEC_VERSION_MAJOR < 59)
+#endif
#ifndef FF_API_BUFS_VDPAU
#define FF_API_BUFS_VDPAU (LIBAVCODEC_VERSION_MAJOR < 58)
#endif