home *** CD-ROM | disk | FTP | other *** search
/ Chip 2005 June / ccd0605.iso / LINUX / gopchop-1.1.7.tar.tar / gopchop-1.1.7.tar / gopchop-1.1.7 / src / display.cpp < prev    next >
C/C++ Source or Header  |  2005-05-02  |  23KB  |  695 lines

  1. /*
  2. #
  3. # Display subsystem.
  4. #
  5. # $Id: display.cpp,v 1.9 2005/05/02 04:45:57 keescook Exp $
  6. #
  7. # Copyright (C) 2001-2005 Kees Cook
  8. # kees@outflux.net, http://outflux.net/
  9. # This program is free software; you can redistribute it and/or
  10. # modify it under the terms of the GNU General Public License
  11. # as published by the Free Software Foundation; either version 2
  12. # of the License, or (at your option) any later version.
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. # GNU General Public License for more details.
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program; if not, write to the Free Software
  19. # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20. # http://www.gnu.org/copyleft/gpl.html
  21. #
  22. */
  23.  
  24. #include "display.h"
  25.  
  26. #ifdef __cplusplus
  27. extern "C" {
  28. #endif
  29.  
  30. /* libmpeg2 */
  31. #include "video_out.h"
  32. #include <mpeg2dec/mpeg2.h>
  33.  
  34. #ifdef __cplusplus
  35. }
  36. #endif
  37.  
  38. #include <stdio.h>
  39. #include <unistd.h>
  40. #include <stdlib.h>
  41. #include <string.h>
  42.  
  43. #include "GOPchop.h"
  44. #include "main.h"
  45. #include "List.h"
  46. #include "Pack.h"
  47. #include "ElementStream.h"
  48. #include "mpeg2consts.h"
  49.  
  50. static
  51. void frame_draw(struct display_engine_t * engine)
  52. {
  53.     if (!engine) return;
  54.  
  55.     if (engine && engine->output && engine->output->draw &&
  56.         engine->parser_info && engine->parser_info->display_fbuf) {
  57.  
  58.         engine->output->draw(engine->output,
  59.                      engine->parser_info->display_fbuf->buf,
  60.                      engine->parser_info->display_fbuf->id);
  61.     }
  62. }
  63.  
  64. // decode function
  65. static
  66. void decode(struct display_engine_t * engine, uint8_t * buffer, size_t len)
  67. {
  68.     Window xwindow;
  69.     vo_setup_result_t setup_result;
  70.     int state;
  71. #ifdef DEBUG_VES
  72.     FILE *ves_debug;
  73. #endif
  74.  
  75.     //printf("decoding %ld bytes of VES data\n",len);
  76.  
  77.     /* make sure output and decoder are available */
  78.     if (!engine) {
  79.         fprintf(stderr, "%s", _("Display engine missing!\n"));
  80.         return;
  81.     }
  82.     if (!engine->output) {
  83.         fprintf(stderr, "%s", _("Output window missing!\n"));
  84.         return;
  85.     }
  86.     if (!engine->mpeg2dec) {
  87.         fprintf(stderr, "%s", _("MPEG2 decoder missing!\n"));
  88.         return;
  89.     }
  90.  
  91.     if (!buffer) {
  92.         fprintf(stderr,"%s",_("decode called with a missing buffer!?\n"));
  93.         return;
  94.     }
  95.  
  96.     //if (len) {
  97.         mpeg2_buffer(engine->mpeg2dec, buffer, buffer + len);
  98.         if (!(engine->parser_info = mpeg2_info(engine->mpeg2dec)))
  99.         {
  100.             fprintf(stderr, "%s", _("MPEG2 decoder info not available!?\n"));
  101.             exit(1);
  102.         }
  103.     //}
  104.  
  105. #ifdef DEBUG_VES
  106.     /* dump the VES packets to a file */
  107.     ves_debug = fopen("video.es", "a");
  108.     fwrite(buffer, len, 1, ves_debug);
  109.     fclose(ves_debug);
  110. #endif
  111.  
  112.     while ((state = mpeg2_parse(engine->mpeg2dec)) != STATE_BUFFER)
  113.     {
  114.         switch (state)
  115.         {
  116.             case STATE_SEQUENCE:
  117.                 if (engine->opt_show_states) printf("STATE_SEQUENCE\n");
  118.                 if (!engine->parser_info->sequence) {
  119.                     fprintf(stderr,"%s",_("Got STATE_SEQUENCE without a sequence!?\n"));
  120.                     break;
  121.                 }
  122.                 if (engine->opt_show_states)
  123.                     printf("saw sequence (%ux%u, pix %u:%u, disp %ux%u)\n",
  124.                         engine->parser_info->sequence->width,
  125.                         engine->parser_info->sequence->height,
  126.                         engine->parser_info->sequence->pixel_width,
  127.                         engine->parser_info->sequence->pixel_height,
  128.                         engine->parser_info->sequence->display_width*engine->parser_info->sequence->pixel_width/engine->parser_info->sequence->pixel_height,
  129.                         engine->parser_info->sequence->picture_height
  130.                         );
  131.                 /* sequence started, so initialize output window */
  132.                 if (engine->output->setup(engine->output,
  133.                                   engine->parser_info->sequence->width,
  134.                                   engine->parser_info->sequence->height,
  135.                                   engine->parser_info->sequence->display_width*engine->parser_info->sequence->pixel_width/engine->parser_info->sequence->pixel_height,
  136.                                   engine->parser_info->sequence->height,
  137.                                   engine->parser_info->sequence->chroma_width,
  138.                                   engine->parser_info->sequence->chroma_height,
  139.                                   &setup_result))
  140.                 {
  141.                     fprintf(stderr, "%s", _("Failed to setup display\n"));
  142.                     return;
  143.                 }
  144.  
  145.                 if (engine->output->window_handle) {
  146.                     xwindow = (Window)engine->output->window_handle(engine->output);
  147.                     engine->frame_window = gdk_window_foreign_new((int)xwindow);
  148.                     if (engine->frame_window) {
  149.                         gdk_window_set_events(engine->frame_window,GDK_ALL_EVENTS_MASK);
  150.                         // this doesn't catch screen motion :(
  151.                         XSelectInput(GDK_DISPLAY(), xwindow,
  152.                                      VisibilityChangeMask
  153.                                      // ExposureMask
  154.                                      // | PointerMotionMask
  155.                                      );
  156.                     }
  157.                 }
  158.  
  159.                 /* does the output need to be converted? */
  160.                 if (setup_result.convert)
  161.                     mpeg2_convert(engine->mpeg2dec, setup_result.convert, NULL);
  162.                 /* can the output provide an fbuf area? */
  163.                 if (engine->output->set_fbuf)
  164.                 {
  165.                     uint8_t *buf[3];
  166.                     void *id;
  167.  
  168.                     mpeg2_custom_fbuf(engine->mpeg2dec, 1);
  169.  
  170.                     engine->output->set_fbuf(engine->output, buf, &id);
  171.                     mpeg2_set_buf(engine->mpeg2dec, buf, id);
  172.  
  173.                     engine->output->set_fbuf(engine->output, buf, &id);
  174.                     mpeg2_set_buf(engine->mpeg2dec, buf, id);
  175.                 }
  176.                 else if (engine->output->setup_fbuf)
  177.                 {
  178.                     uint8_t *buf[3];
  179.                     void *id;
  180.  
  181.                     engine->output->setup_fbuf(engine->output, buf, &id);
  182.                     mpeg2_set_buf(engine->mpeg2dec, buf, id);
  183.                     engine->output->setup_fbuf(engine->output, buf, &id);
  184.                     mpeg2_set_buf(engine->mpeg2dec, buf, id);
  185.                     engine->output->setup_fbuf(engine->output, buf, &id);
  186.                     mpeg2_set_buf(engine->mpeg2dec, buf, id);
  187.                 }
  188.                 break;
  189.             case STATE_PICTURE:
  190.                 if (engine->opt_show_states) {
  191.                     printf("STATE_PICTURE:   ");
  192.                     if (engine->parser_info &&
  193.                         engine->parser_info->current_picture) {
  194.                         switch (engine->parser_info->current_picture->flags &
  195.                                 PIC_MASK_CODING_TYPE) {
  196.                             case PIC_FLAG_CODING_TYPE_I:
  197.                                 printf("I");
  198.                                 break;
  199.                             case PIC_FLAG_CODING_TYPE_B:
  200.                                 printf("B");
  201.                                 break;
  202.                             case PIC_FLAG_CODING_TYPE_P:
  203.                                 printf("P");
  204.                                 break;
  205.                             case PIC_FLAG_CODING_TYPE_D:
  206.                                 printf("D");
  207.                                 break;
  208.                             default:
  209.                                 printf("unknown");
  210.                                 break;
  211.                         }
  212.                         printf("(%02d)",
  213.                                engine->parser_info->current_picture->temporal_reference);
  214.                     }
  215.                     printf("       parsed\n");
  216.                 }
  217.  
  218.                 /* picture is starting */
  219.                 if (engine->output->set_fbuf)
  220.                 {
  221.                     uint8_t *buf[3];
  222.                     void *id;
  223.  
  224.                     engine->output->set_fbuf(engine->output, buf, &id);
  225.                     mpeg2_set_buf(engine->mpeg2dec, buf, id);
  226.                 }
  227.                 if (engine->output->start_fbuf) {
  228.                     if (engine->parser_info->current_fbuf) {
  229.                         engine->output->start_fbuf(engine->output,
  230.                                            engine->parser_info->current_fbuf->buf,
  231.                                            engine->parser_info->current_fbuf->id);
  232.                     }
  233.                     else {
  234.                         fprintf(stderr,"%s",_("Got STATE_PICTURE without a current_fbuf!?\n"));
  235.                     }
  236.                 }
  237.                 break;
  238.             case STATE_SLICE:
  239.             case STATE_END:
  240. #ifdef HAVE_MPEG2_FLUSH_PICTURE
  241.             case STATE_FLUSHED:
  242. #endif
  243.                 if (engine->opt_show_states) {
  244.                     printf("STATE_%s       ",
  245.                             state == STATE_SLICE ?    "SLICE:    "
  246.                               : (state == STATE_END ? "END:      "
  247.                                  :                    "FLUSHED:  "));
  248.                     if (engine->parser_info &&
  249.                         engine->parser_info->display_picture)
  250.                     {
  251.                         switch (engine->parser_info->display_picture->flags & PIC_MASK_CODING_TYPE)
  252.                         {
  253.                             case PIC_FLAG_CODING_TYPE_I:
  254.                                 printf("I");
  255.                                 break;
  256.                             case PIC_FLAG_CODING_TYPE_P:
  257.                                 printf("P");
  258.                                 break;
  259.                             case PIC_FLAG_CODING_TYPE_B:
  260.                                 printf("B");
  261.                                 break;
  262.                             case PIC_FLAG_CODING_TYPE_D:
  263.                                 printf("D");
  264.                                 break;
  265.                             default:
  266.                                 printf("unknown");
  267.                                 break;
  268.                         }
  269.                         printf("(%02d)",
  270.                            engine->parser_info->display_picture->temporal_reference);
  271.                     }
  272.                     else
  273.                     {
  274.                         printf("      nothing loaded to be");
  275.                     }
  276.                     printf(" rendered\n");
  277.                 }
  278.  
  279.                 /* draw current picture */
  280.                 frame_draw(engine);
  281.                 if (engine->output->discard && engine->parser_info->discard_fbuf)
  282.                     engine->output->discard(engine->output,
  283.                                     engine->parser_info->discard_fbuf->buf,
  284.                                     engine->parser_info->discard_fbuf->id);
  285.                 break;
  286.             case STATE_INVALID:
  287.                 if (engine->opt_show_states) printf("STATE_INVALID\n");
  288.                 break;
  289.             case STATE_INVALID_END:
  290.                 if (engine->opt_show_states) printf("STATE_INVALID_END\n");
  291.                 break;
  292.             case STATE_SEQUENCE_REPEATED:
  293.                 if (engine->opt_show_states) printf("STATE_SEQUENCE_REPEATED\n");
  294.                 break;
  295.             case STATE_GOP:
  296.                 if (engine->opt_show_states) printf("STATE_GOP\n");
  297.                 break;
  298.             case STATE_SLICE_1ST:
  299.                 if (engine->opt_show_states) printf("STATE_SLICE_1ST\n");
  300.                 break;
  301.             case STATE_PICTURE_2ND:
  302.                 if (engine->opt_show_states) printf("STATE_PICTURE_2ND\n");
  303.                 break;
  304.             default:
  305.                 if (engine->opt_show_states) printf("STATE: %d\n",state);
  306.                 break;
  307.         }
  308.     }
  309.     if (engine->opt_show_states) printf("STATE_BUFFER\n");
  310. }
  311.  
  312. struct display_engine_t * display_open(
  313.         int    desired_output,
  314.         char * opt_output_arg,
  315.         char * opt_videoout,
  316.         int    opt_show_states)
  317. {
  318.     struct display_engine_t * engine;
  319.  
  320.     if (!(engine=(struct display_engine_t*)calloc(1,sizeof(*engine)))) {
  321.         perror("malloc");
  322.         return NULL;
  323.     }
  324.     engine->opt_show_states=opt_show_states;
  325.     engine->desired_output=desired_output;
  326.  
  327.     vo_open_t * output_open = NULL;
  328.  
  329.     if (engine->desired_output==GOPCHOP_OUTPUT_LIBVO)
  330.     {
  331.         // decoding
  332.         uint32_t accel = 0;
  333.  
  334.         if (!(output_open=find_libvo_driver(opt_videoout)))
  335.         {
  336.             fprintf(stderr, _("Can't find output driver '%s'\n"), opt_videoout);
  337.             exit(1);
  338.         }
  339.     
  340.         if (!(engine->output = output_open()))
  341.         {
  342.             fprintf(stderr, _("Can't open output driver '%s'\n"), opt_videoout);
  343.         }
  344.     
  345.         accel = mpeg2_accel(MPEG2_ACCEL_DETECT);
  346. #ifdef ARCH_X86
  347.         if (accel & MPEG2_ACCEL_X86_MMXEXT)
  348.             printf("%s", _("Using x86 MMXext acceleration\n"));
  349.         else if (accel & MPEG2_ACCEL_X86_3DNOW)
  350.             printf("%s", _("Using x86 3DNow acceleration\n"));
  351.         else if (accel & MPEG2_ACCEL_X86_MMX)
  352.             printf("%s", _("Using x86 MMX acceleration\n"));
  353. #endif
  354. #ifdef ARCH_PPC
  355.         if (accel & MPEG2_ACCEL_PPC_ALTIVEC)
  356.             printf("%s", _("Using PowerPC Altivec acceleration\n"));
  357. #endif
  358. #ifdef ARCH_ALPHA
  359.         if (accel & MPEG2_ACCEL_ALPHA_MVI)
  360.             printf("%s", _("Using Alpha MVI acceleration\n"));
  361.         else if (accel & MPEG2_ACCEL_ALPHA)
  362.             printf("%s", _("Using Alpha acceleration\n"));
  363. #endif
  364. #ifdef ARCH_SPARC
  365.         if (accel & MPEG2_ACCEL_SPARC_VIS)
  366.             printf("%s", _("Using Sparc VIS acceleration\n"));
  367.         else if (accel & MPEG2_ACCEL_SPARC_VIS2)
  368.             printf("%s", _("Using Sparc VIS2 acceleration\n"));
  369. #endif
  370.         else
  371.             printf("%s", _("Using no special acceleration\n"));
  372.     
  373.         if (!(engine->mpeg2dec = mpeg2_init()))
  374.         {
  375.             fprintf(stderr, "%s", _("Cannot initialize mpeg2 decoder!\n"));
  376.             exit(1);
  377.         }
  378.     }
  379.     else if (engine->desired_output == GOPCHOP_OUTPUT_PIPE)
  380.     {
  381.         // try a piped command instead
  382.  
  383.         if (!opt_output_arg)
  384.         {
  385.             fprintf(stderr, "%s", _("Pipe command required.  Try --pipe\n"));
  386.             exit(1);
  387.         }
  388.  
  389.         // fork off a command
  390.         if (pipe(engine->pipes) < 0)
  391.         {
  392.             perror("pipe");
  393.             exit(1);
  394.         }
  395.  
  396.         pid_t pid = fork();
  397.  
  398.         // failure
  399.         if (pid < 0)
  400.         {
  401.             perror("fork");
  402.             exit(1);
  403.         }
  404.  
  405.         // child
  406.         if (pid == 0)
  407.         {
  408.             char * shell;
  409.  
  410.             close(engine->pipes[1]);
  411.             if (dup2(engine->pipes[0], STDIN_FILENO) < 0)
  412.             {
  413.                 perror("dup2");
  414.                 exit(1);
  415.             }
  416.     
  417.             // get the shell to use
  418.             if (!(shell=getenv("SHELL")))
  419.             {
  420.                 fprintf(stderr,"%s",
  421.                         _("Cannot figure out from environment what shell to exec.\n"));
  422.                 exit(1);
  423.             }
  424.  
  425.             execl(shell,shell,"-c", opt_output_arg, NULL);
  426.             perror("execl");
  427.             exit(1);
  428.         }
  429.     
  430.         // parent
  431.         engine->client_pipe = &engine->pipes[1];
  432.         close(engine->pipes[0]);
  433.     }
  434.     else {
  435.         fprintf(stderr,_("Unknown output desired!?\n"));
  436.     }
  437.  
  438.  
  439.     return engine;
  440. }
  441.  
  442. void display_close(struct display_engine_t * engine)
  443. {
  444.     if (!engine) return;
  445.  
  446.     if (engine->output)
  447.     {
  448.         // invalidate these
  449.         engine->frame_window = NULL;
  450.         engine->parser_info  = NULL;
  451.  
  452.         mpeg2_close(engine->mpeg2dec);
  453.         engine->mpeg2dec = NULL;
  454.         if (engine->output->close)
  455.             engine->output->close(engine->output);
  456.         engine->output = NULL;
  457.     }
  458.  
  459.     if (engine->client_pipe)
  460.     {
  461.         close(*engine->client_pipe);
  462.         engine->client_pipe = NULL;
  463.     }
  464.  
  465.     engine->last_valid=0;
  466.     engine->GOP=NULL;
  467. }
  468.  
  469. vo_open_t * find_libvo_driver(char * desired_driver)
  470. {
  471.     int i;
  472.     vo_driver_t const *drivers;
  473.  
  474.     drivers = vo_drivers();
  475.     for (i = 0; drivers[i].name; i++)
  476.         if (!desired_driver || !strcmp(drivers[i].name, desired_driver))
  477.             return drivers[i].open;
  478.  
  479.     return NULL;
  480. }
  481.  
  482.  
  483. void show_GOP(struct display_engine_t * engine, uint32_t wantedGOP)
  484. {
  485.     static int initdone = 0;
  486.     List *packets;
  487.     Pack *packet;
  488.     List *GOPs;
  489.     GroupOfPictures *GOP;
  490.     Bounds *bounds;
  491.     ElementStream *ves;
  492.     int start, stop;
  493.  
  494.     uint8_t *loc;
  495.     size_t len;
  496.  
  497.     if (!engine) return;
  498.  
  499.     if (engine->opt_show_states) printf("show GOP: %u\n",wantedGOP);
  500.  
  501.     // get our GOP list
  502.     if (!(GOPs = mpeg2parser->getGOPs()))
  503.     {
  504.         printf("%s", _("\tNo GOPs\n"));
  505.         return;
  506.     }
  507.  
  508.     // get our packet list
  509.     if (!(packets = mpeg2parser->getPackets()))
  510.     {
  511.         printf("%s", _("\tNo packets\n"));
  512.         return;
  513.     }
  514.  
  515.     // get GOP we're after
  516.     if (!(GOP = (GroupOfPictures *) GOPs->vector(wantedGOP)))
  517.     {
  518.         printf(_("\tGOP %d missing\n"), wantedGOP);
  519.         return;
  520.     }
  521.  
  522.     // handle reset logic
  523.     if (engine->last_valid) {
  524.         if (wantedGOP == engine->last_group) return;
  525.         if (  (engine->last_group+1 != wantedGOP) ||
  526.               (engine->last_flushed)  ) {
  527.             if (engine->opt_show_states) printf("MPEG2 reset\n");
  528.             mpeg2_reset(engine->mpeg2dec,0);
  529.             if (wantedGOP>0 && !GOP->has_sequence_info()) {
  530.                 uint32_t num;
  531.                 GroupOfPictures *previous=NULL;
  532.  
  533.                 for (num=wantedGOP-1;
  534.                      ;
  535.                      num--)
  536.                 {
  537.                     if (!(previous=(GroupOfPictures *) GOPs->vector(num))) {
  538.                         printf(_("\tGOP %d missing\n"), num);
  539.                         return;
  540.                     }
  541.                     if (previous->has_sequence_info()) break;
  542.                     previous=NULL;
  543.  
  544.                     if (num==0) break;
  545.                 }
  546.  
  547.                 // found a prior sequence header
  548.                 if (previous) {
  549.                     sequence_header bytes;
  550.                     if (engine->opt_show_states)
  551.                         printf("Injecting sequence from GOP %d\n",num);
  552.                     previous->get_sequence_header(&bytes);
  553.                     decode(engine,(uint8_t*)&bytes,sizeof(bytes));
  554.                 }
  555.                 else {
  556.                     if (engine->opt_show_states)
  557.                         printf("could not find needed sequence\n");
  558.                 }
  559.             }
  560.         }
  561.     }
  562.     engine->last_group = wantedGOP;
  563.     engine->last_flushed = 0;
  564.     engine->last_valid = 1;
  565.  
  566.  
  567.     // get our GOP's range of packets
  568.     bounds = GOP->getPacketBounds();
  569.     // remember our start and finish points
  570.     start = bounds->getFirst();
  571.     stop = bounds->getMax();
  572.  
  573.     for (uint32_t j = start; j < stop; j++)
  574.     {
  575.         if (!(packet = (Pack *) packets->vector(j)))
  576.         {
  577.             printf("%s", _("NULL packet?!\n"));
  578.             exit(1);
  579.         }
  580.  
  581.         if (engine->desired_output==GOPCHOP_OUTPUT_LIBVO && engine->output)
  582.         {
  583.             uint32_t ves_start, ves_stop;
  584.  
  585.             ves_start = packet->getVideoFirst();
  586.             ves_stop = packet->getVideoMax();
  587.  
  588.             for (uint32_t k = ves_start; k < ves_stop; k++)
  589.             {
  590.                 if (!(ves =
  591.                       (ElementStream *)mpeg2parser->getVideo()->vector(k)))
  592.                 {
  593.                     printf("%s", _("NULL VES?!\n"));
  594.                     exit(1);
  595.                 }
  596.     
  597.                 len = ves->getLen();
  598.                 loc = (uint8_t *)mpeg2parser->bytesAvail(ves->getStart(), len);
  599.     
  600.                 /*
  601.                 fprintf(stderr,_("\t\tVES: %d @ %llu (%d): 0x%08x\n"),
  602.                         k,ves->getStart(),len,
  603.                         (unsigned int)loc);
  604.                 */
  605.     
  606.                 if (loc && len)
  607.                     decode(engine, loc, len);
  608.             }
  609.         }
  610.         else if (engine->desired_output==GOPCHOP_OUTPUT_PIPE && engine->client_pipe)
  611.         {
  612.             // send entire packet to pipe
  613.  
  614.             len = packet->getLen();
  615.             loc = (uint8_t*)mpeg2parser->bytesAvail(packet->getStart(), len);
  616.             if (loc && engine->client_pipe)
  617.             {
  618.                 int written;
  619.     
  620.                 // stuff things into the pipe
  621.                 while (len > 0)
  622.                 {
  623.                     if ((written = write(*(engine->client_pipe), loc, len)) < 0)
  624.                     {
  625.                         perror("write");
  626.                         exit(1);
  627.                     }
  628.                     loc += written;
  629.                     len -= written;
  630.                 }
  631.             }
  632.         }
  633.         else {
  634.             fprintf(stderr,_("Unknown output desired!?\n"));
  635.         }
  636.  
  637.     }
  638. }
  639.  
  640. void display_flush(struct display_engine_t * engine)
  641. {
  642.     if (engine && engine->last_valid && !engine->last_flushed) {
  643.         if (engine->opt_show_states) printf("-- trying to flush pictures\n");
  644.         /* throw in an end-of-stream to make sure libvo kicks out the last frame */
  645.         if (engine->desired_output==GOPCHOP_OUTPUT_LIBVO && engine->output) {
  646. #ifdef HAVE_MPEG2_FLUSH_PICTURE
  647.             mpeg2_flush_picture(mpeg2dec);
  648.             decode(engine, (uint8_t*)"",0);
  649. #else
  650.             decode(engine, (uint8_t*)seq_end_buf,sizeof(seq_end_buf));
  651. #endif
  652.             engine->last_flushed = 1;
  653.         }
  654.         if (engine->opt_show_states) printf("-- done\n");
  655.     }
  656. }
  657.  
  658. void display_hookup_gop(struct display_engine_t * engine,
  659.                         GroupOfPictures *GOP)
  660. {
  661.     if (!engine) return;
  662.  
  663.     engine->GOP=GOP;
  664.     engine->last_valid=0;
  665. }
  666.  
  667. bool display_is_window(struct display_engine_t * engine,
  668.                                GdkWindow * window)
  669. {
  670.     if (engine && engine->frame_window == window) return true;
  671.     return false;
  672. }
  673.  
  674. void display_redraw(struct display_engine_t * engine)
  675. {
  676.     if (!engine) return;
  677.  
  678.     /* how the hell do we keep the window visible?  I don't want to have
  679.      * to totally reprocess the GOP every time we get visibility noticiation
  680.      */
  681.     if (engine->last_valid) {
  682.         // "forget" we were already here, and force a redraw
  683.         uint32_t gop = engine->last_group;
  684.         engine->last_group= gop + 1;
  685.         show_GOP(engine,gop);
  686.         flush();
  687.         display_flush(engine);
  688.     }
  689. }
  690.  
  691. /* vi:set ai ts=4 sw=4 expandtab: */
  692.