Revision 917d2bb3 ffplay.c

View differences:

ffplay.c
32 32
#include "libavcodec/opt.h"
33 33
#include "libavcodec/dsputil.h"
34 34

  
35
#if CONFIG_AVFILTER
36
# include "libavfilter/avfilter.h"
37
# include "libavfilter/avfiltergraph.h"
38
# include "libavfilter/graphparser.h"
39
#endif
40

  
35 41
#include "cmdutils.h"
36 42

  
37 43
#include <SDL.h>
......
72 78
/* NOTE: the size must be big enough to compensate the hardware audio buffersize size */
73 79
#define SAMPLE_ARRAY_SIZE (2*65536)
74 80

  
81
#if !CONFIG_AVFILTER
75 82
static int sws_flags = SWS_BICUBIC;
83
#endif
76 84

  
77 85
typedef struct PacketQueue {
78 86
    AVPacketList *first_pkt, *last_pkt;
......
93 101
    int width, height; /* source height & width */
94 102
    int allocated;
95 103
    SDL_TimerID timer_id;
104
    enum PixelFormat pix_fmt;
105

  
106
#if CONFIG_AVFILTER
107
    AVFilterPicRef *picref;
108
#endif
96 109
} VideoPicture;
97 110

  
98 111
typedef struct SubPicture {
......
180 193
    int pictq_size, pictq_rindex, pictq_windex;
181 194
    SDL_mutex *pictq_mutex;
182 195
    SDL_cond *pictq_cond;
196
#if !CONFIG_AVFILTER
183 197
    struct SwsContext *img_convert_ctx;
198
#endif
184 199

  
185 200
    //    QETimer *video_timer;
186 201
    char filename[1024];
......
191 206
    int64_t last_dts_for_fault_detection;
192 207
    int64_t last_pts_for_fault_detection;
193 208

  
209
#if CONFIG_AVFILTER
210
    AVFilterContext *out_video_filter;          ///<the last filter in the video chain
211
#endif
194 212
} VideoState;
195 213

  
196 214
static void show_help(void);
......
234 252
static int error_concealment = 3;
235 253
static int decoder_reorder_pts= -1;
236 254
static int autoexit;
255
#if CONFIG_AVFILTER
256
static char *vfilters = NULL;
257
#endif
237 258

  
238 259
/* current context */
239 260
static int is_full_screen;
......
668 689

  
669 690
    vp = &is->pictq[is->pictq_rindex];
670 691
    if (vp->bmp) {
692
#if CONFIG_AVFILTER
693
         if (vp->picref->pixel_aspect.num == 0)
694
             aspect_ratio = 0;
695
         else
696
             aspect_ratio = av_q2d(vp->picref->pixel_aspect);
697
#else
698

  
671 699
        /* XXX: use variable in the frame */
672 700
        if (is->video_st->sample_aspect_ratio.num)
673 701
            aspect_ratio = av_q2d(is->video_st->sample_aspect_ratio);
......
675 703
            aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio);
676 704
        else
677 705
            aspect_ratio = 0;
706
#endif
678 707
        if (aspect_ratio <= 0.0)
679 708
            aspect_ratio = 1.0;
680
        aspect_ratio *= (float)is->video_st->codec->width / is->video_st->codec->height;
709
        aspect_ratio *= (float)vp->width / (float)vp->height;
681 710
        /* if an active format is indicated, then it overrides the
682 711
           mpeg format */
683 712
#if 0
......
927 956
    } else if(!is_full_screen && screen_width){
928 957
        w = screen_width;
929 958
        h = screen_height;
959
#if CONFIG_AVFILTER
960
    }else if (is->out_video_filter && is->out_video_filter->inputs[0]){
961
        w = is->out_video_filter->inputs[0]->w;
962
        h = is->out_video_filter->inputs[0]->h;
963
#else
930 964
    }else if (is->video_st && is->video_st->codec->width){
931 965
        w = is->video_st->codec->width;
932 966
        h = is->video_st->codec->height;
967
#endif
933 968
    } else {
934 969
        w = 640;
935 970
        h = 480;
......
1241 1276
    if (vp->bmp)
1242 1277
        SDL_FreeYUVOverlay(vp->bmp);
1243 1278

  
1244
    vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,
1245
                                   is->video_st->codec->height,
1279
#if CONFIG_AVFILTER
1280
    if (vp->picref)
1281
        avfilter_unref_pic(vp->picref);
1282
    vp->picref = NULL;
1283

  
1284
    vp->width   = is->out_video_filter->inputs[0]->w;
1285
    vp->height  = is->out_video_filter->inputs[0]->h;
1286
    vp->pix_fmt = is->out_video_filter->inputs[0]->format;
1287
#else
1288
    vp->width   = is->video_st->codec->width;
1289
    vp->height  = is->video_st->codec->height;
1290
    vp->pix_fmt = is->video_st->codec->pix_fmt;
1291
#endif
1292

  
1293
    vp->bmp = SDL_CreateYUVOverlay(vp->width, vp->height,
1246 1294
                                   SDL_YV12_OVERLAY,
1247 1295
                                   screen);
1248
    vp->width = is->video_st->codec->width;
1249
    vp->height = is->video_st->codec->height;
1250 1296

  
1251 1297
    SDL_LockMutex(is->pictq_mutex);
1252 1298
    vp->allocated = 1;
......
1262 1308
{
1263 1309
    VideoPicture *vp;
1264 1310
    int dst_pix_fmt;
1265

  
1311
#if CONFIG_AVFILTER
1312
    AVPicture pict_src;
1313
#endif
1266 1314
    /* wait until we have space to put a new picture */
1267 1315
    SDL_LockMutex(is->pictq_mutex);
1268 1316
    while (is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&
......
1278 1326

  
1279 1327
    /* alloc or resize hardware picture buffer */
1280 1328
    if (!vp->bmp ||
1329
#if CONFIG_AVFILTER
1330
        vp->width  != is->out_video_filter->inputs[0]->w ||
1331
        vp->height != is->out_video_filter->inputs[0]->h) {
1332
#else
1281 1333
        vp->width != is->video_st->codec->width ||
1282 1334
        vp->height != is->video_st->codec->height) {
1335
#endif
1283 1336
        SDL_Event event;
1284 1337

  
1285 1338
        vp->allocated = 0;
......
1304 1357
    /* if the frame is not skipped, then display it */
1305 1358
    if (vp->bmp) {
1306 1359
        AVPicture pict;
1360
#if CONFIG_AVFILTER
1361
        if(vp->picref)
1362
            avfilter_unref_pic(vp->picref);
1363
        vp->picref = src_frame->opaque;
1364
#endif
1307 1365

  
1308 1366
        /* get a pointer on the bitmap */
1309 1367
        SDL_LockYUVOverlay (vp->bmp);
......
1317 1375
        pict.linesize[0] = vp->bmp->pitches[0];
1318 1376
        pict.linesize[1] = vp->bmp->pitches[2];
1319 1377
        pict.linesize[2] = vp->bmp->pitches[1];
1378

  
1379
#if CONFIG_AVFILTER
1380
        pict_src.data[0] = src_frame->data[0];
1381
        pict_src.data[1] = src_frame->data[1];
1382
        pict_src.data[2] = src_frame->data[2];
1383

  
1384
        pict_src.linesize[0] = src_frame->linesize[0];
1385
        pict_src.linesize[1] = src_frame->linesize[1];
1386
        pict_src.linesize[2] = src_frame->linesize[2];
1387

  
1388
        //FIXME use direct rendering
1389
        av_picture_copy(&pict, &pict_src,
1390
                        vp->pix_fmt, vp->width, vp->height);
1391
#else
1320 1392
        sws_flags = av_get_int(sws_opts, "sws_flags", NULL);
1321 1393
        is->img_convert_ctx = sws_getCachedContext(is->img_convert_ctx,
1322
            is->video_st->codec->width, is->video_st->codec->height,
1323
            is->video_st->codec->pix_fmt,
1324
            is->video_st->codec->width, is->video_st->codec->height,
1394
            vp->width, vp->height, vp->pix_fmt, vp->width, vp->height,
1325 1395
            dst_pix_fmt, sws_flags, NULL, NULL, NULL);
1326 1396
        if (is->img_convert_ctx == NULL) {
1327 1397
            fprintf(stderr, "Cannot initialize the conversion context\n");
1328 1398
            exit(1);
1329 1399
        }
1330 1400
        sws_scale(is->img_convert_ctx, src_frame->data, src_frame->linesize,
1331
                  0, is->video_st->codec->height, pict.data, pict.linesize);
1401
                  0, vp->height, pict.data, pict.linesize);
1402
#endif
1332 1403
        /* update the bitmap content */
1333 1404
        SDL_UnlockYUVOverlay(vp->bmp);
1334 1405

  
......
1386 1457
    return queue_picture(is, src_frame, pts, pos);
1387 1458
}
1388 1459

  
1389
static int video_thread(void *arg)
1460
static int get_video_frame(VideoState *is, AVFrame *frame, uint64_t *pts, AVPacket *pkt)
1390 1461
{
1391
    VideoState *is = arg;
1392
    AVPacket pkt1, *pkt = &pkt1;
1393 1462
    int len1, got_picture, i;
1394
    AVFrame *frame= avcodec_alloc_frame();
1395
    double pts;
1396 1463

  
1397
    for(;;) {
1398
        while (is->paused && !is->videoq.abort_request) {
1399
            SDL_Delay(10);
1400
        }
1401 1464
        if (packet_queue_get(&is->videoq, pkt, 1) < 0)
1402
            break;
1465
            return -1;
1403 1466

  
1404 1467
        if(pkt->data == flush_pkt.data){
1405 1468
            avcodec_flush_buffers(is->video_st->codec);
......
1425 1488
            is->frame_last_delay = 0;
1426 1489
            is->frame_timer = (double)av_gettime() / 1000000.0;
1427 1490

  
1428
            continue;
1491
            return 0;
1429 1492
        }
1430 1493

  
1431 1494
        /* NOTE: ipts is the PTS of the _first_ picture beginning in
......
1450 1513
               || (decoder_reorder_pts && is->faulty_pts<is->faulty_dts)
1451 1514
               || pkt->dts == AV_NOPTS_VALUE)
1452 1515
           && frame->reordered_opaque != AV_NOPTS_VALUE)
1453
            pts= frame->reordered_opaque;
1516
            *pts= frame->reordered_opaque;
1454 1517
        else if(pkt->dts != AV_NOPTS_VALUE)
1455
            pts= pkt->dts;
1518
            *pts= pkt->dts;
1456 1519
        else
1457
            pts= 0;
1458
        pts *= av_q2d(is->video_st->time_base);
1520
            *pts= 0;
1521

  
1522
        /* put pts into units of 1/AV_TIME_BASE */
1523
        *pts = av_rescale_q(pts,is->video_st->time_base, AV_TIME_BASE_Q);
1459 1524

  
1460 1525
//            if (len1 < 0)
1461 1526
//                break;
1462
        if (got_picture) {
1463
            if (output_picture2(is, frame, pts, pkt->pos) < 0)
1464
                goto the_end;
1465
        }
1466
        av_free_packet(pkt);
1527
    if (got_picture)
1528
        return 1;
1529
    return 0;
1530
}
1531

  
1532
#if CONFIG_AVFILTER
1533
typedef struct {
1534
    VideoState *is;
1535
    AVFrame *frame;
1536
} FilterPriv;
1537

  
1538
static int input_init(AVFilterContext *ctx, const char *args, void *opaque)
1539
{
1540
    FilterPriv *priv = ctx->priv;
1541
    if(!opaque) return -1;
1542

  
1543
    priv->is = opaque;
1544
    priv->frame = avcodec_alloc_frame();
1545

  
1546
    return 0;
1547
}
1548

  
1549
static void input_uninit(AVFilterContext *ctx)
1550
{
1551
    FilterPriv *priv = ctx->priv;
1552
    av_free(priv->frame);
1553
}
1554

  
1555
static int input_request_frame(AVFilterLink *link)
1556
{
1557
    FilterPriv *priv = link->src->priv;
1558
    AVFilterPicRef *picref;
1559
    uint64_t pts = 0;
1560
    AVPacket pkt;
1561
    int ret;
1562

  
1563
    while (!(ret = get_video_frame(priv->is, priv->frame, &pts, &pkt)))
1564
        av_free_packet(&pkt);
1565
    if (ret < 0)
1566
        return -1;
1567

  
1568
    /* FIXME: until I figure out how to hook everything up to the codec
1569
     * right, we're just copying the entire frame. */
1570
    picref = avfilter_get_video_buffer(link, AV_PERM_WRITE, link->w, link->h);
1571
    av_picture_copy((AVPicture *)&picref->data, (AVPicture *)priv->frame,
1572
                    picref->pic->format, link->w, link->h);
1573
    av_free_packet(&pkt);
1574

  
1575
    picref->pts = pts;
1576
    picref->pixel_aspect = priv->is->video_st->codec->sample_aspect_ratio;
1577
    avfilter_start_frame(link, avfilter_ref_pic(picref, ~0));
1578
    avfilter_draw_slice(link, 0, link->h, 1);
1579
    avfilter_end_frame(link);
1580
    avfilter_unref_pic(picref);
1581

  
1582
    return 0;
1583
}
1584

  
1585
static int input_query_formats(AVFilterContext *ctx)
1586
{
1587
    FilterPriv *priv = ctx->priv;
1588
    enum PixelFormat pix_fmts[] = {
1589
        priv->is->video_st->codec->pix_fmt, PIX_FMT_NONE
1590
    };
1591

  
1592
    avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
1593
    return 0;
1594
}
1595

  
1596
static int input_config_props(AVFilterLink *link)
1597
{
1598
    FilterPriv *priv  = link->src->priv;
1599
    AVCodecContext *c = priv->is->video_st->codec;
1600

  
1601
    link->w = c->width;
1602
    link->h = c->height;
1603

  
1604
    return 0;
1605
}
1606

  
1607
static AVFilter input_filter =
1608
{
1609
    .name      = "ffplay_input",
1610

  
1611
    .priv_size = sizeof(FilterPriv),
1612

  
1613
    .init      = input_init,
1614
    .uninit    = input_uninit,
1615

  
1616
    .query_formats = input_query_formats,
1617

  
1618
    .inputs    = (AVFilterPad[]) {{ .name = NULL }},
1619
    .outputs   = (AVFilterPad[]) {{ .name = "default",
1620
                                    .type = CODEC_TYPE_VIDEO,
1621
                                    .request_frame = input_request_frame,
1622
                                    .config_props  = input_config_props, },
1623
                                  { .name = NULL }},
1624
};
1625

  
1626
static void output_end_frame(AVFilterLink *link)
1627
{
1628
}
1629

  
1630
static int output_query_formats(AVFilterContext *ctx)
1631
{
1632
    enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
1633

  
1634
    avfilter_set_common_formats(ctx, avfilter_make_format_list(pix_fmts));
1635
    return 0;
1636
}
1637

  
1638
static int get_filtered_video_frame(AVFilterContext *ctx, AVFrame *frame,
1639
                                    uint64_t *pts)
1640
{
1641
    AVFilterPicRef *pic;
1642

  
1643
    if(avfilter_request_frame(ctx->inputs[0]))
1644
        return -1;
1645
    if(!(pic = ctx->inputs[0]->cur_pic))
1646
        return -1;
1647
    ctx->inputs[0]->cur_pic = NULL;
1648

  
1649
    frame->opaque = pic;
1650
    *pts          = pic->pts;
1651

  
1652
    memcpy(frame->data,     pic->data,     sizeof(frame->data));
1653
    memcpy(frame->linesize, pic->linesize, sizeof(frame->linesize));
1654

  
1655
    return 1;
1656
}
1657

  
1658
static AVFilter output_filter =
1659
{
1660
    .name      = "ffplay_output",
1661

  
1662
    .query_formats = output_query_formats,
1663

  
1664
    .inputs    = (AVFilterPad[]) {{ .name          = "default",
1665
                                    .type          = CODEC_TYPE_VIDEO,
1666
                                    .end_frame     = output_end_frame,
1667
                                    .min_perms     = AV_PERM_READ, },
1668
                                  { .name = NULL }},
1669
    .outputs   = (AVFilterPad[]) {{ .name = NULL }},
1670
};
1671
#endif  /* CONFIG_AVFILTER */
1672

  
1673
static int video_thread(void *arg)
1674
{
1675
    VideoState *is = arg;
1676
    AVFrame *frame= avcodec_alloc_frame();
1677
    uint64_t pts_int;
1678
    double pts;
1679
    int ret;
1680

  
1681
#if CONFIG_AVFILTER
1682
    AVFilterContext *filt_src = NULL, *filt_out = NULL;
1683
    AVFilterGraph *graph = av_mallocz(sizeof(AVFilterGraph));
1684
    graph->scale_sws_opts = av_strdup("sws_flags=bilinear");
1685

  
1686
    if(!(filt_src = avfilter_open(&input_filter,  "src")))   goto the_end;
1687
    if(!(filt_out = avfilter_open(&output_filter, "out")))   goto the_end;
1688

  
1689
    if(avfilter_init_filter(filt_src, NULL, is))             goto the_end;
1690
    if(avfilter_init_filter(filt_out, NULL, frame))          goto the_end;
1691

  
1692

  
1693
    if(vfilters) {
1694
        AVFilterInOut *outputs = av_malloc(sizeof(AVFilterInOut));
1695
        AVFilterInOut *inputs  = av_malloc(sizeof(AVFilterInOut));
1696

  
1697
        outputs->name    = av_strdup("in");
1698
        outputs->filter  = filt_src;
1699
        outputs->pad_idx = 0;
1700
        outputs->next    = NULL;
1701

  
1702
        inputs->name    = av_strdup("out");
1703
        inputs->filter  = filt_out;
1704
        inputs->pad_idx = 0;
1705
        inputs->next    = NULL;
1706

  
1707
        if (avfilter_graph_parse(graph, vfilters, inputs, outputs, NULL) < 0)
1708
            goto the_end;
1709
        av_freep(&vfilters);
1710
    } else {
1711
        if(avfilter_link(filt_src, 0, filt_out, 0) < 0)          goto the_end;
1712
    }
1713
    avfilter_graph_add_filter(graph, filt_src);
1714
    avfilter_graph_add_filter(graph, filt_out);
1715

  
1716
    if(avfilter_graph_check_validity(graph, NULL))           goto the_end;
1717
    if(avfilter_graph_config_formats(graph, NULL))           goto the_end;
1718
    if(avfilter_graph_config_links(graph, NULL))             goto the_end;
1719

  
1720
    is->out_video_filter = filt_out;
1721
#endif
1722

  
1723
    for(;;) {
1724
#if !CONFIG_AVFILTER
1725
        AVPacket pkt;
1726
#endif
1727
        while (is->paused && !is->videoq.abort_request)
1728
            SDL_Delay(10);
1729
#if CONFIG_AVFILTER
1730
        ret = get_filtered_video_frame(filt_out, frame, &pts_int);
1731
#else
1732
        ret = get_video_frame(is, frame, &pts_int, &pkt);
1733
#endif
1734

  
1735
        if (ret < 0) goto the_end;
1736

  
1737
        if (!ret)
1738
            continue;
1739

  
1740
        pts  = pts_int;
1741
        pts /= AV_TIME_BASE;
1742

  
1743
#if CONFIG_AVFILTER
1744
        ret = output_picture2(is, frame, pts,  -1); /* fixme: unknown pos */
1745
#else
1746
        ret = output_picture2(is, frame, pts,  pkt->pos);
1747
        av_free_packet(&pkt);
1748
#endif
1749
        if (ret < 0)
1750
            goto the_end;
1751

  
1467 1752
        if (step)
1468 1753
            if (cur_stream)
1469 1754
                stream_pause(cur_stream);
1470 1755
    }
1471 1756
 the_end:
1757
#if CONFIG_AVFILTER
1758
    avfilter_graph_destroy(graph);
1759
    av_freep(&graph);
1760
#endif
1472 1761
    av_free(frame);
1473 1762
    return 0;
1474 1763
}
......
2265 2554
    /* free all pictures */
2266 2555
    for(i=0;i<VIDEO_PICTURE_QUEUE_SIZE; i++) {
2267 2556
        vp = &is->pictq[i];
2557
#if CONFIG_AVFILTER
2558
        if (vp->picref) {
2559
            avfilter_unref_pic(vp->picref);
2560
            vp->picref = NULL;
2561
        }
2562
#endif
2268 2563
        if (vp->bmp) {
2269 2564
            SDL_FreeYUVOverlay(vp->bmp);
2270 2565
            vp->bmp = NULL;
......
2274 2569
    SDL_DestroyCond(is->pictq_cond);
2275 2570
    SDL_DestroyMutex(is->subpq_mutex);
2276 2571
    SDL_DestroyCond(is->subpq_cond);
2572
#if !CONFIG_AVFILTER
2277 2573
    if (is->img_convert_ctx)
2278 2574
        sws_freeContext(is->img_convert_ctx);
2575
#endif
2279 2576
    av_free(is);
2280 2577
}
2281 2578

  
......
2367 2664
        av_free(avcodec_opts[i]);
2368 2665
    av_free(avformat_opts);
2369 2666
    av_free(sws_opts);
2667
#if CONFIG_AVFILTER
2668
    avfilter_uninit();
2669
#endif
2370 2670
    if (show_status)
2371 2671
        printf("\n");
2372 2672
    SDL_Quit();
......
2637 2937
    { "sync", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_sync}, "set audio-video sync. type (type=audio/video/ext)", "type" },
2638 2938
    { "threads", HAS_ARG | OPT_FUNC2 | OPT_EXPERT, {(void*)opt_thread_count}, "thread count", "count" },
2639 2939
    { "autoexit", OPT_BOOL | OPT_EXPERT, {(void*)&autoexit}, "exit at the end", "" },
2940
#if CONFIG_AVFILTER
2941
    { "vfilters", OPT_STRING | HAS_ARG, {(void*)&vfilters}, "video filters", "filter list" },
2942
#endif
2640 2943
    { "default", OPT_FUNC2 | HAS_ARG | OPT_AUDIO | OPT_VIDEO | OPT_EXPERT, {(void*)opt_default}, "generic catch all option", "" },
2641 2944
    { NULL, },
2642 2945
};
......
2689 2992
    /* register all codecs, demux and protocols */
2690 2993
    avcodec_register_all();
2691 2994
    avdevice_register_all();
2995
#if CONFIG_AVFILTER
2996
    avfilter_register_all();
2997
#endif
2692 2998
    av_register_all();
2693 2999

  
2694 3000
    for(i=0; i<CODEC_TYPE_NB; i++){
2695 3001
        avcodec_opts[i]= avcodec_alloc_context2(i);
2696 3002
    }
2697 3003
    avformat_opts = avformat_alloc_context();
3004
#if !CONFIG_AVFILTER
2698 3005
    sws_opts = sws_getContext(16,16,0, 16,16,0, sws_flags, NULL,NULL,NULL);
3006
#endif
2699 3007

  
2700 3008
    show_banner();
2701 3009

  

Also available in: Unified diff