Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(429)

Side by Side Diff: ffmpeg/source/patched-ffmpeg/libavcodec/vp8.c

Issue 8341002: VP8: fix up handling of segmentation_maps in reference frames. (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party
Patch Set: merge Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ffmpeg/source/patched-ffmpeg/libavcodec/vp8.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /** 1 /**
2 * VP8 compatible video decoder 2 * VP8 compatible video decoder
3 * 3 *
4 * Copyright (C) 2010 David Conrad 4 * Copyright (C) 2010 David Conrad
5 * Copyright (C) 2010 Ronald S. Bultje 5 * Copyright (C) 2010 Ronald S. Bultje
6 * Copyright (C) 2010 Jason Garrett-Glaser 6 * Copyright (C) 2010 Jason Garrett-Glaser
7 * 7 *
8 * This file is part of FFmpeg. 8 * This file is part of FFmpeg.
9 * 9 *
10 * FFmpeg is free software; you can redistribute it and/or 10 * FFmpeg is free software; you can redistribute it and/or
(...skipping 23 matching lines...) Expand all
34 #endif 34 #endif
35 35
36 static void free_buffers(VP8Context *s) 36 static void free_buffers(VP8Context *s)
37 { 37 {
38 av_freep(&s->macroblocks_base); 38 av_freep(&s->macroblocks_base);
39 av_freep(&s->filter_strength); 39 av_freep(&s->filter_strength);
40 av_freep(&s->intra4x4_pred_mode_top); 40 av_freep(&s->intra4x4_pred_mode_top);
41 av_freep(&s->top_nnz); 41 av_freep(&s->top_nnz);
42 av_freep(&s->edge_emu_buffer); 42 av_freep(&s->edge_emu_buffer);
43 av_freep(&s->top_border); 43 av_freep(&s->top_border);
44 av_freep(&s->segmentation_map);
45 44
46 s->macroblocks = NULL; 45 s->macroblocks = NULL;
47 } 46 }
48 47
49 static void vp8_decode_flush(AVCodecContext *avctx) 48 static int vp8_alloc_frame(VP8Context *s, AVFrame *f)
49 {
50 int ret;
51 if ((ret = ff_thread_get_buffer(s->avctx, f)) < 0)
52 return ret;
53 if (!s->maps_are_invalid && s->num_maps_to_be_freed) {
54 f->ref_index[0] = s->segmentation_maps[--s->num_maps_to_be_freed];
55 } else if (!(f->ref_index[0] = av_mallocz(s->mb_width * s->mb_height))) {
56 ff_thread_release_buffer(s->avctx, f);
57 return AVERROR(ENOMEM);
58 }
59 return 0;
60 }
61
62 static void vp8_release_frame(VP8Context *s, AVFrame *f, int is_close)
63 {
64 if (!is_close) {
65 if (f->ref_index[0]) {
66 assert(s->num_maps_to_be_freed < FF_ARRAY_ELEMS(s->segmentation_maps ));
67 s->segmentation_maps[s->num_maps_to_be_freed++] = f->ref_index[0];
68 f->ref_index[0] = NULL;
69 }
70 } else {
71 av_freep(&f->ref_index[0]);
72 }
73 ff_thread_release_buffer(s->avctx, f);
74 }
75
76 static void vp8_decode_flush_impl(AVCodecContext *avctx, int force, int is_close )
50 { 77 {
51 VP8Context *s = avctx->priv_data; 78 VP8Context *s = avctx->priv_data;
52 int i; 79 int i;
53 80
54 if (!avctx->is_copy) { 81 if (!avctx->is_copy || force) {
55 for (i = 0; i < 5; i++) 82 for (i = 0; i < 5; i++)
56 if (s->frames[i].data[0]) 83 if (s->frames[i].data[0])
57 ff_thread_release_buffer(avctx, &s->frames[i]); 84 vp8_release_frame(s, &s->frames[i], is_close);
58 } 85 }
59 memset(s->framep, 0, sizeof(s->framep)); 86 memset(s->framep, 0, sizeof(s->framep));
60 87
61 free_buffers(s); 88 free_buffers(s);
89 s->maps_are_invalid = 1;
90 }
91
92 static void vp8_decode_flush(AVCodecContext *avctx)
93 {
94 vp8_decode_flush_impl(avctx, 0, 0);
62 } 95 }
63 96
64 static int update_dimensions(VP8Context *s, int width, int height) 97 static int update_dimensions(VP8Context *s, int width, int height)
65 { 98 {
66 if (width != s->avctx->width || 99 if (width != s->avctx->width ||
67 height != s->avctx->height) { 100 height != s->avctx->height) {
68 if (av_image_check_size(width, height, 0, s->avctx)) 101 if (av_image_check_size(width, height, 0, s->avctx))
69 return AVERROR_INVALIDDATA; 102 return AVERROR_INVALIDDATA;
70 103
71 vp8_decode_flush(s->avctx); 104 vp8_decode_flush_impl(s->avctx, 1, 0);
72 105
73 avcodec_set_dimensions(s->avctx, width, height); 106 avcodec_set_dimensions(s->avctx, width, height);
74 } 107 }
75 108
76 s->mb_width = (s->avctx->coded_width +15) / 16; 109 s->mb_width = (s->avctx->coded_width +15) / 16;
77 s->mb_height = (s->avctx->coded_height+15) / 16; 110 s->mb_height = (s->avctx->coded_height+15) / 16;
78 111
79 s->macroblocks_base = av_mallocz((s->mb_width+s->mb_height*2+1)*sizeo f(*s->macroblocks)); 112 s->macroblocks_base = av_mallocz((s->mb_width+s->mb_height*2+1)*sizeo f(*s->macroblocks));
80 s->filter_strength = av_mallocz(s->mb_width*sizeof(*s->filter_streng th)); 113 s->filter_strength = av_mallocz(s->mb_width*sizeof(*s->filter_streng th));
81 s->intra4x4_pred_mode_top = av_mallocz(s->mb_width*4); 114 s->intra4x4_pred_mode_top = av_mallocz(s->mb_width*4);
82 s->top_nnz = av_mallocz(s->mb_width*sizeof(*s->top_nnz)); 115 s->top_nnz = av_mallocz(s->mb_width*sizeof(*s->top_nnz));
83 s->top_border = av_mallocz((s->mb_width+1)*sizeof(*s->top_borde r)); 116 s->top_border = av_mallocz((s->mb_width+1)*sizeof(*s->top_borde r));
84 s->segmentation_map = av_mallocz(s->mb_width*s->mb_height);
85 117
86 if (!s->macroblocks_base || !s->filter_strength || !s->intra4x4_pred_mode_to p || 118 if (!s->macroblocks_base || !s->filter_strength || !s->intra4x4_pred_mode_to p ||
87 !s->top_nnz || !s->top_border || !s->segmentation_map) 119 !s->top_nnz || !s->top_border)
88 return AVERROR(ENOMEM); 120 return AVERROR(ENOMEM);
89 121
90 s->macroblocks = s->macroblocks_base + 1; 122 s->macroblocks = s->macroblocks_base + 1;
91 123
92 return 0; 124 return 0;
93 } 125 }
94 126
95 static void parse_segment_info(VP8Context *s) 127 static void parse_segment_info(VP8Context *s)
96 { 128 {
97 VP56RangeCoder *c = &s->c; 129 VP56RangeCoder *c = &s->c;
(...skipping 1402 matching lines...) Expand 10 before | Expand all | Expand 10 after
1500 uint8_t *dst = curframe->data[0] + 16*mb_y*s->linesize; 1532 uint8_t *dst = curframe->data[0] + 16*mb_y*s->linesize;
1501 int mb_x; 1533 int mb_x;
1502 1534
1503 for (mb_x = 0; mb_x < s->mb_width; mb_x++) { 1535 for (mb_x = 0; mb_x < s->mb_width; mb_x++) {
1504 backup_mb_border(s->top_border[mb_x+1], dst, NULL, NULL, s->linesize, 0, 1); 1536 backup_mb_border(s->top_border[mb_x+1], dst, NULL, NULL, s->linesize, 0, 1);
1505 filter_mb_simple(s, dst, f++, mb_x, mb_y); 1537 filter_mb_simple(s, dst, f++, mb_x, mb_y);
1506 dst += 16; 1538 dst += 16;
1507 } 1539 }
1508 } 1540 }
1509 1541
1542 static void release_queued_segmaps(VP8Context *s, int is_close)
1543 {
1544 int leave_behind = is_close ? 0 : !s->maps_are_invalid;
1545 while (s->num_maps_to_be_freed > leave_behind)
1546 av_freep(&s->segmentation_maps[--s->num_maps_to_be_freed]);
1547 s->maps_are_invalid = 0;
1548 }
1549
1510 static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size, 1550 static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
1511 AVPacket *avpkt) 1551 AVPacket *avpkt)
1512 { 1552 {
1513 VP8Context *s = avctx->priv_data; 1553 VP8Context *s = avctx->priv_data;
1514 int ret, mb_x, mb_y, i, y, referenced; 1554 int ret, mb_x, mb_y, i, y, referenced;
1515 enum AVDiscard skip_thresh; 1555 enum AVDiscard skip_thresh;
1516 AVFrame *av_uninit(curframe), *prev_frame = s->framep[VP56_FRAME_CURRENT]; 1556 AVFrame *av_uninit(curframe), *prev_frame = s->framep[VP56_FRAME_CURRENT];
1517 1557
1558 release_queued_segmaps(s, 0);
1559
1518 if ((ret = decode_frame_header(s, avpkt->data, avpkt->size)) < 0) 1560 if ((ret = decode_frame_header(s, avpkt->data, avpkt->size)) < 0)
1519 return ret; 1561 return ret;
1520 1562
1521 referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT 1563 referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT
1522 || s->update_altref == VP56_FRAME_CURRENT; 1564 || s->update_altref == VP56_FRAME_CURRENT;
1523 1565
1524 skip_thresh = !referenced ? AVDISCARD_NONREF : 1566 skip_thresh = !referenced ? AVDISCARD_NONREF :
1525 !s->keyframe ? AVDISCARD_NONKEY : AVDISCARD_ALL; 1567 !s->keyframe ? AVDISCARD_NONKEY : AVDISCARD_ALL;
1526 1568
1527 if (avctx->skip_frame >= skip_thresh) { 1569 if (avctx->skip_frame >= skip_thresh) {
1528 s->invisible = 1; 1570 s->invisible = 1;
1529 goto skip_decode; 1571 goto skip_decode;
1530 } 1572 }
1531 s->deblock_filter = s->filter.level && avctx->skip_loop_filter < skip_thresh ; 1573 s->deblock_filter = s->filter.level && avctx->skip_loop_filter < skip_thresh ;
1532 1574
1533 // release no longer referenced frames 1575 // release no longer referenced frames
1534 for (i = 0; i < 5; i++) 1576 for (i = 0; i < 5; i++)
1535 if (s->frames[i].data[0] && 1577 if (s->frames[i].data[0] &&
1536 &s->frames[i] != prev_frame && 1578 &s->frames[i] != prev_frame &&
1537 &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] && 1579 &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&
1538 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && 1580 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] &&
1539 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) 1581 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2])
1540 ff_thread_release_buffer(avctx, &s->frames[i]); 1582 vp8_release_frame(s, &s->frames[i], 0);
1541 1583
1542 // find a free buffer 1584 // find a free buffer
1543 for (i = 0; i < 5; i++) 1585 for (i = 0; i < 5; i++)
1544 if (&s->frames[i] != prev_frame && 1586 if (&s->frames[i] != prev_frame &&
1545 &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] && 1587 &s->frames[i] != s->framep[VP56_FRAME_PREVIOUS] &&
1546 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] && 1588 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN] &&
1547 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) { 1589 &s->frames[i] != s->framep[VP56_FRAME_GOLDEN2]) {
1548 curframe = s->framep[VP56_FRAME_CURRENT] = &s->frames[i]; 1590 curframe = s->framep[VP56_FRAME_CURRENT] = &s->frames[i];
1549 break; 1591 break;
1550 } 1592 }
1551 if (i == 5) { 1593 if (i == 5) {
1552 av_log(avctx, AV_LOG_FATAL, "Ran out of free frames!\n"); 1594 av_log(avctx, AV_LOG_FATAL, "Ran out of free frames!\n");
1553 abort(); 1595 abort();
1554 } 1596 }
1555 if (curframe->data[0]) 1597 if (curframe->data[0])
1556 ff_thread_release_buffer(avctx, curframe); 1598 ff_thread_release_buffer(avctx, curframe);
1557 1599
1558 curframe->key_frame = s->keyframe; 1600 curframe->key_frame = s->keyframe;
1559 curframe->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P; 1601 curframe->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
1560 curframe->reference = referenced ? 3 : 0; 1602 curframe->reference = referenced ? 3 : 0;
1561 curframe->ref_index[0] = s->segmentation_map; 1603 if ((ret = vp8_alloc_frame(s, curframe))) {
1562 if ((ret = ff_thread_get_buffer(avctx, curframe))) {
1563 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed!\n"); 1604 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed!\n");
1564 return ret; 1605 return ret;
1565 } 1606 }
1566 1607
1567 // check if golden and altref are swapped 1608 // check if golden and altref are swapped
1568 if (s->update_altref != VP56_FRAME_NONE) { 1609 if (s->update_altref != VP56_FRAME_NONE) {
1569 s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[s->update_altref]; 1610 s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[s->update_altref];
1570 } else { 1611 } else {
1571 s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[VP56_FRAME_GOLDEN2]; 1612 s->next_framep[VP56_FRAME_GOLDEN2] = s->framep[VP56_FRAME_GOLDEN2];
1572 } 1613 }
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1644 s->mv_min.x = -MARGIN; 1685 s->mv_min.x = -MARGIN;
1645 s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN; 1686 s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN;
1646 if (prev_frame && s->segmentation.enabled && !s->segmentation.update_map ) 1687 if (prev_frame && s->segmentation.enabled && !s->segmentation.update_map )
1647 ff_thread_await_progress(prev_frame, mb_y, 0); 1688 ff_thread_await_progress(prev_frame, mb_y, 0);
1648 1689
1649 for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) { 1690 for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) {
1650 /* Prefetch the current frame, 4 MBs ahead */ 1691 /* Prefetch the current frame, 4 MBs ahead */
1651 s->dsp.prefetch(dst[0] + (mb_x&3)*4*s->linesize + 64, s->linesize, 4 ); 1692 s->dsp.prefetch(dst[0] + (mb_x&3)*4*s->linesize + 64, s->linesize, 4 );
1652 s->dsp.prefetch(dst[1] + (mb_x&7)*s->uvlinesize + 64, dst[2] - dst[1 ], 2); 1693 s->dsp.prefetch(dst[1] + (mb_x&7)*s->uvlinesize + 64, dst[2] - dst[1 ], 2);
1653 1694
1654 decode_mb_mode(s, mb, mb_x, mb_y, s->segmentation_map + mb_xy, 1695 decode_mb_mode(s, mb, mb_x, mb_y, curframe->ref_index[0] + mb_xy,
1655 prev_frame ? prev_frame->ref_index[0] + mb_xy : NULL) ; 1696 prev_frame && prev_frame->ref_index[0] ? prev_frame-> ref_index[0] + mb_xy : NULL);
1656 1697
1657 prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_PREVIOUS); 1698 prefetch_motion(s, mb, mb_x, mb_y, mb_xy, VP56_FRAME_PREVIOUS);
1658 1699
1659 if (!mb->skip) 1700 if (!mb->skip)
1660 decode_mb_coeffs(s, c, mb, s->top_nnz[mb_x], s->left_nnz); 1701 decode_mb_coeffs(s, c, mb, s->top_nnz[mb_x], s->left_nnz);
1661 1702
1662 if (mb->mode <= MODE_I4x4) 1703 if (mb->mode <= MODE_I4x4)
1663 intra_predict(s, dst, mb, mb_x, mb_y); 1704 intra_predict(s, dst, mb, mb_x, mb_y);
1664 else 1705 else
1665 inter_predict(s, dst, mb, mb_x, mb_y); 1706 inter_predict(s, dst, mb, mb_x, mb_y);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1728 1769
1729 dsputil_init(&s->dsp, avctx); 1770 dsputil_init(&s->dsp, avctx);
1730 ff_h264_pred_init(&s->hpc, CODEC_ID_VP8, 8); 1771 ff_h264_pred_init(&s->hpc, CODEC_ID_VP8, 8);
1731 ff_vp8dsp_init(&s->vp8dsp); 1772 ff_vp8dsp_init(&s->vp8dsp);
1732 1773
1733 return 0; 1774 return 0;
1734 } 1775 }
1735 1776
1736 static av_cold int vp8_decode_free(AVCodecContext *avctx) 1777 static av_cold int vp8_decode_free(AVCodecContext *avctx)
1737 { 1778 {
1738 vp8_decode_flush(avctx); 1779 vp8_decode_flush_impl(avctx, 0, 1);
1780 release_queued_segmaps(avctx->priv_data, 1);
1739 return 0; 1781 return 0;
1740 } 1782 }
1741 1783
1742 static av_cold int vp8_decode_init_thread_copy(AVCodecContext *avctx) 1784 static av_cold int vp8_decode_init_thread_copy(AVCodecContext *avctx)
1743 { 1785 {
1744 VP8Context *s = avctx->priv_data; 1786 VP8Context *s = avctx->priv_data;
1745 1787
1746 s->avctx = avctx; 1788 s->avctx = avctx;
1747 1789
1748 return 0; 1790 return 0;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1782 vp8_decode_init, 1824 vp8_decode_init,
1783 NULL, 1825 NULL,
1784 vp8_decode_free, 1826 vp8_decode_free,
1785 vp8_decode_frame, 1827 vp8_decode_frame,
1786 CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS, 1828 CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
1787 .flush = vp8_decode_flush, 1829 .flush = vp8_decode_flush,
1788 .long_name = NULL_IF_CONFIG_SMALL("On2 VP8"), 1830 .long_name = NULL_IF_CONFIG_SMALL("On2 VP8"),
1789 .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy ), 1831 .init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy ),
1790 .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_co ntext), 1832 .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_co ntext),
1791 }; 1833 };
OLDNEW
« no previous file with comments | « ffmpeg/source/patched-ffmpeg/libavcodec/vp8.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698