5a6
>  * Video-playing capability added Copyright © 2015 Jim Turner <turnerjw784@yahoo.com>
20a22,25
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> 
33a39,54
> #include <stdint.h>
> #include "libavutil/common.h"
> #include "libavutil/dict.h"
> #include "libavutil/log.h"
> #include "libavformat/version.h"
> #include "libavformat/avio.h"
> extern "C" {
> #include <libswscale/swscale.h>
> }
> #include <SDL.h>
> #include <SDL_thread.h>
> 
> #define SDL_AUDIO_BUFFER_SIZE 4096
> #define MAX_AUDIO_FRAME_SIZE 192000
> 
> 
64a86,89
> static bool play_video;          /* JWT: TRUE IF USER IS CURRENTLY PLAYING VIDEO (KILLINV VID. WINDOW TURNS OFF! */
> static bool play_video_wason;    /* JWT: TRUE IF USER WANTS VIDEO PART OF VIDEO FILES DISPLAYED */
> static bool fromstdin;           /* JWT: TRUE IF INPUT IS STREAMED IN VIA STDIN, FALSE OTHERWISE */
> 
72a98,203
> static CodecInfo cinfo;          /* JWT: SAVE THE AUDIO & VIDEO CODEC STRUCTURES SINCE NOW REFERENCED IN 2 FUNCTIONS: */
> static CodecInfo vcinfo;
> 
> /* 
>     JWT: ADDED ALL THIS QUEUE STUFF TO SMOOTH VIDEO PERFORMANCE SO THAT VIDEO FRAMES WOULD 
>     BE OUTPUT MORE INTERLACED WITH THE AUDIO FRAMES BY QUEUEING VIDEO FRAMES UNTIL AN 
>     AUDIO FRAME IS PROCESSED, THEN DEQUEUEING AND PROCESSING 'EM WITH EACH AUDIO FRAME.  
>     THE SIZE OF THIS QUEUE IS SET BY video_qsize CONFIG PARAMETER AND DEFAULTS TO 20.
>     HAVING TOO MANY CAN RESULT IN DELAYED VIDEO, SO EXPERIMENT.  IDEALLY, PACKETS SHOULD 
>     BE PROCESSED:  V A V A V A..., BUT THIS HANDLES:  
>     V1 V2 V3 V4 V5 A1 A2 A3 A4 A5 A6 A7 V7 A8... AS: 
>     (Q:V1 V2 V3 V4 V5 V6) A1 A2 V1 A3 A4 V2 A5 A6 V3 A7 A8...
>     WE DON'T WANT TO INTERRUPT AUDIO PERFORMANCE AND I DON'T KNOW HOW TO THREAD IT UP,
>     BUT THIS SIMPLE APPROACH SEEMS TO WORK PRETTY SMOOTH FOR ME!  OTHERWISE TRY 
>     INCREASING video_qsize IN config file OTHERWISE.
>     BORROWED THESE FUNCTIONS FROM:
>     http://www.thelearningpoint.net/computer-science/data-structures-queues--with-c-program-source-code
> */
> 
> typedef struct 
> {
>     int capacity;
>     int size;
>     int front;
>     int rear;
>     AVPacket *elements;
> }
> pktQueue;
> 
> pktQueue * createQueue (int maxElements)
> {
>     /* Create a Queue */
>     pktQueue *Q;
>     Q = (pktQueue *)malloc(sizeof(pktQueue));
>     /* Initialise its properties */
>     Q->elements = (AVPacket *)malloc(sizeof(AVPacket)*maxElements);
>     Q->size = 0;
>     Q->capacity = maxElements;
>     Q->front = 0;
>     Q->rear = -1;
>     /* Return the pointer */
>     return Q;
> }
> 
> bool Dequeue (pktQueue *Q)
> {
>     /* If Queue size is zero then it is empty. So we cannot pop */
>     if(Q->size==0)
>         return false;
>     /* Removing an element is equivalent to incrementing index of front by one */
>     else
>     {
>         Q->size--;
>         if (Q->elements[Q->front].data)
>             av_free_packet(&Q->elements[Q->front]);
> 
>         Q->front++;
>         /* As we fill elements in circular fashion */
>         if(Q->front==Q->capacity)
>         {
>                 Q->front=0;
>         }
>     }
>     return true;
> }
> 
> AVPacket * QFront (pktQueue *Q)
> {
>     if(Q->size==0)
>     {
>             AUDDBG("Queue is Empty\n");
>             return nullptr;
>     }
>     /* Return the element which is at the front*/
>     return &Q->elements[Q->front];
> }
> 
> bool isQueueFull (pktQueue *Q)
> {
>     return (Q->size == Q->capacity) ? true : false;
> }
> 
> bool Enqueue (pktQueue *Q, AVPacket element)
> {
>     /* If the Queue is full, we cannot push an element into it as there is no space for it.*/
>     if(Q->size == Q->capacity)
>     {
>             printf("Queue is Full\n");
>             return false;
>     }
>     else
>     {
>             Q->size++;
>             Q->rear = Q->rear + 1;
>             /* As we fill the queue in circular fashion */
>             if(Q->rear == Q->capacity)
>             {
>                     Q->rear = 0;
>             }
>             /* Insert the element in its rear side */ 
>             Q->elements[Q->rear] = element;
>     }
>     return true;
> }
> 
> /* JWT:END OF ADDED VIDEO PACKET QUEUEING FUNCTIONS */
140a272,275
>     /* JWT:SAVE config OPTION VALUE FOR CLOSING THINGS, IN CASE USER KILLS VIDEO WINDOW 
>         THUS TURNING "play_video" OFF DURING PLAY.
>     */
>     play_video_wason = aud_get_bool ("ffaudio", "play_video");
241c376
< static AVFormatContext * open_input_file (const char * name, VFSFile & file)
---
> bool isFromStdin ()  /* JWT: TRUE IF INPUT IS STREAMED IN VIA STDIN, FALSE OTHERWISE */
243,253c378,379
<     AVInputFormat * f = get_format (name, file);
< 
<     if (! f)
<     {
<         AUDERR ("Unknown format for %s.\n", name);
<         return nullptr;
<     }
< 
<     AVFormatContext * c = avformat_alloc_context ();
<     AVIOContext * io = io_context_new (file);
<     c->pb = io;
---
>     return fromstdin;
> }
255c381,383
<     int ret = avformat_open_input (& c, name, f, nullptr);
---
> static AVFormatContext * open_input_file (const char * name, VFSFile & file)
> {
>     AVFormatContext * c = NULL;
257c385,390
<     if (ret < 0)
---
>     play_video = aud_get_bool ("ffaudio", "play_video");   //JWT:RESET PLAY-VIDEO, CASE TURNED OFF ON PREV. PLAY
>     const char * xname = name;
>     if (fromstdin)
>         xname = "pipe:";
>     int ret = avformat_open_input (&c, xname, NULL, NULL);
>     if (ret)
259,260c392
<         AUDERR ("avformat_open_input failed for %s: %s.\n", name, ffaudio_strerror (ret));
<         io_context_free (io);
---
>         AUDERR ("avformat_open_input failed for %s: %s.\n", xname, ffaudio_strerror (ret));
267c399
< static void close_input_file (AVFormatContext * c)
---
> static void close_input_file (AVFormatContext * c, CodecInfo * cinfo, CodecInfo * vcinfo)
269,270c401,404
<     AVIOContext * io = c->pb;
< 
---
>     if (play_video_wason)
>         avcodec_close(vcinfo->context);
>     play_video_wason = play_video;
>     avcodec_close(cinfo->context);
277d410
<     io_context_free (io);
280c413
< static bool find_codec (AVFormatContext * c, CodecInfo * cinfo)
---
> static bool find_codec (AVFormatContext * c, CodecInfo * cinfo, CodecInfo * vcinfo)
282c415
<     avformat_find_stream_info (c, nullptr);
---
>     avformat_find_stream_info (c, NULL);
283a417,418
>     int videoStream=-1;
>     int audioStream=-1;
286c421,435
<         AVStream * stream = c->streams[i];
---
>         if (c->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO)
>             videoStream=i;
>         else if (c->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO && audioStream < 0)
>             audioStream=i;
>     }
>     if (audioStream==-1)   /* PUNT IF NO AUDIO SINCE AUDACIOUS IS AN *AUDIO* PLAYER! */
>         return false;
> 
>     AVCodec * codec = avcodec_find_decoder (c->streams[audioStream]->codec->codec_id);
>     if (codec)
>     {
>         cinfo->stream_idx = audioStream;
>         cinfo->stream = c->streams[audioStream];
>         cinfo->context = c->streams[audioStream]->codec;
>         cinfo->codec = codec;
288c437,438
<         if (stream && stream->codec && stream->codec->codec_type == AVMEDIA_TYPE_AUDIO)
---
>         /* JWT: NOW IF USER WANTS VIDEO, SEE IF WE GOT A VIDEO STREAM TOO: */
>         if (play_video && videoStream >= 0)
290,292c440,441
<             AVCodec * codec = avcodec_find_decoder (stream->codec->codec_id);
< 
<             if (codec)
---
>             AVCodec * vcodec = avcodec_find_decoder (c->streams[videoStream]->codec->codec_id);
>             if (vcodec)
294,299c443,446
<                 cinfo->stream_idx = i;
<                 cinfo->stream = stream;
<                 cinfo->context = stream->codec;
<                 cinfo->codec = codec;
< 
<                 return true;
---
>                 vcinfo->stream_idx = videoStream;
>                 vcinfo->stream = c->streams[videoStream];
>                 vcinfo->context = c->streams[videoStream]->codec;
>                 vcinfo->codec = vcodec;
301a449,452
>         else
>             play_video = false;  /* turn off video playback, since we could not find stream! */
> 
>         return true;
351,353c502,508
<     AVFormatContext * ic = open_input_file (filename, file);
< 
<     if (ic)
---
>     fromstdin = (!strcmp(filename, "-") || strstr(filename, "://-.")) ? true : false;
>     AUDDBG("Filename =%s=\n", filename);
>     if (fromstdin)
>     {
>         tuple.set_filename (filename);
>     }
>     else   /* JWT:THIS STUFF DEFERRED UNTIL PLAY FOR STDIN, BUT SEEMS TO HAVE TO BE HERE FOR DIRECT */
355c510
<         CodecInfo cinfo;
---
>         AVFormatContext * ic = open_input_file (filename, file);
357c512
<         if (find_codec (ic, & cinfo))
---
>         if (ic)
359,362c514,516
<             tuple.set_filename (filename);
< 
<             tuple.set_int (Tuple::Length, ic->duration / 1000);
<             tuple.set_int (Tuple::Bitrate, ic->bit_rate / 1000);
---
>             if (find_codec (ic, & cinfo, & vcinfo))
>             {
>                 tuple.set_filename (filename);
364,365c518,528
<             if (cinfo.codec->long_name)
<                 tuple.set_str (Tuple::Codec, cinfo.codec->long_name);
---
>                 tuple.set_int (Tuple::Length, ic->duration / 1000);
>                 tuple.set_int (Tuple::Bitrate, ic->bit_rate / 1000);
>                 if (cinfo.codec->long_name)
>                     tuple.set_str (Tuple::Codec, cinfo.codec->long_name);
>                 if (ic->metadata)
>                     read_metadata_dict (tuple, ic->metadata);
>                 if (cinfo.stream->metadata)
>                     read_metadata_dict (tuple, cinfo.stream->metadata);
>                 if (play_video && vcinfo.stream->metadata)
>                     read_metadata_dict (tuple, vcinfo.stream->metadata);
>             }
367,370c530
<             if (ic->metadata)
<                 read_metadata_dict (tuple, ic->metadata);
<             if (cinfo.stream->metadata)
<                 read_metadata_dict (tuple, cinfo.stream->metadata);
---
>             close_input_file (ic, & cinfo, & vcinfo);
373c533,537
<         close_input_file (ic);
---
>         if (tuple && ! file.fseek (0, VFS_SEEK_SET))
>             audtag::tuple_read (tuple, file);
>             /* JWT:BUILD NOTE:  IF USING LATEST AUDACIOUS VERSIONS YOU MAY NEED TO REPLACE ABOVE LINE WITH:
>                 audtag::read_tag (file, & tuple, nullptr);
>             */
376,378d539
<     if (tuple && ! file.fseek (0, VFS_SEEK_SET))
<         audtag::read_tag (file, & tuple, nullptr);
< 
397a559,596
> /* JWT: NEW FUNCTION TO WRITE VIDEO FRAMES TO THE POPUP WINDOW: */
> bool write_videoframe (SwsContext * sws_ctx, AVFrame * vframe, SDL_Overlay * bmp, 
>     AVPacket *pkt, int * frameFinished, int video_width, int video_height)
> {
>     SDL_Rect rect;
>     int len = avcodec_decode_video2 (vcinfo.context, vframe, frameFinished, pkt);
>     // Did we get a video frame?
>     if (len < 0)
>     {
>         AUDERR ("decode_video() failed, code %d\n", len);
>         return false;
>     }
>     if (*frameFinished)
>     {
>         SDL_LockYUVOverlay(bmp);
>         AVPicture pict;
>         pict.data[0] = bmp->pixels[0];
>         pict.data[1] = bmp->pixels[2];
>         pict.data[2] = bmp->pixels[1];
>         pict.linesize[0] = bmp->pitches[0];
>         pict.linesize[1] = bmp->pitches[2];
>         pict.linesize[2] = bmp->pitches[1];
>         // Convert the image into YUV format that SDL uses
>         sws_scale(sws_ctx, (uint8_t const * const *)vframe->data,
>             vframe->linesize, 0, vcinfo.context->height,
>             pict.data, pict.linesize);
>         SDL_UnlockYUVOverlay(bmp);
> 
>         rect.x = 0;
>         rect.y = 0;
>         rect.w = video_width;
>         rect.h = video_height;
>         SDL_DisplayYUVOverlay(bmp, &rect);
>         return false;
>     }
>     return true;
> }
> 
404c603
<     bool codec_opened = false;
---
>     /* bool codec_opened = false;  //JWT:DON'T THINK WE NEED ANYMORE. */
407a607,614
>     SDL_Overlay     *bmp = nullptr;    /* JWT: ALL SDL_* STUFF IS FOR PLAYING VIDEOS */
>     SDL_Surface     *screen = nullptr;
>     SDL_Event       event;
>     int video_width = 0;
>     int video_height = 0;
>     play_video_wason = play_video;
>     float video_aspect_ratio = 0;
>     struct SwsContext *sws_ctx = NULL;
412,413c619,624
<     if (! ic)
<         return false;
---
>     const char * fileext = strrchr (filename, '.');
>     if (ic)
>     {
>         if (fromstdin)  /* JWT: FOR STDIN: TRY TO GET "read_tuple()" STUFF NOW, SINCE FILE COULD NOT BE OPENED EARLIER IN read_tuple()! */
>         {
>             Tuple tuple;
415c626,629
<     CodecInfo cinfo;
---
>             AUDDBG ("---- playing from STDIN: get TUPLE stuff now: IC is defined\n");
>             if (find_codec (ic, & cinfo, & vcinfo))
>             {
>                 tuple.set_filename (filename);
417,420c631,656
<     if (! find_codec (ic, & cinfo))
<     {
<         AUDERR ("No codec found for %s.\n", filename);
<         goto error_exit;
---
>                 tuple.set_int (Tuple::Length, ic->duration / 1000);
>                 tuple.set_int (Tuple::Bitrate, ic->bit_rate / 1000);
>                 if (cinfo.codec->long_name)
>                     tuple.set_str (Tuple::Codec, cinfo.codec->long_name);
>                 if (ic->metadata)
>                     read_metadata_dict (tuple, ic->metadata);
>                 if (cinfo.stream->metadata)
>                     read_metadata_dict (tuple, cinfo.stream->metadata);
>                 if (play_video && vcinfo.stream->metadata)
>                     read_metadata_dict (tuple, vcinfo.stream->metadata);
>                 set_playback_tuple (tuple.ref ());
>             }
>             else
>             {
>                 AUDERR ("No codec found for %s.\n", filename);
>                 goto error_exit;
>             }
>         }
>         else
>         {
>             if (! find_codec (ic, & cinfo, & vcinfo))
>             {
>                 AUDERR ("No codec found for %s.\n", filename);
>                 goto error_exit;
>             }
>         }
421a658,659
>     else
>         return false;
425c663
<     if (avcodec_open2 (cinfo.context, cinfo.codec, nullptr) < 0)
---
>     if (avcodec_open2 (cinfo.context, cinfo.codec, NULL) < 0)
428c666,765
<     codec_opened = true;
---
>     /* JWT: IF abUSER ALSO WANTS TO PLAY VIDEO THEN WE SET UP POP-UP VIDEO SCREEN: */
>     if (play_video)
>     {
>         String video_windowtitle;
>         int video_sws_scale = 0;
>         if (avcodec_open2 (vcinfo.context, vcinfo.codec, NULL) < 0)
>             goto error_exit;
> 
>         // Allocate a place to put our YUV image on that screen (initialize to video's size,
>         // then (later) resize to user's size prefs if specified (must do this way to get video to scale:
> #ifndef __DARWIN__
>         screen = SDL_SetVideoMode(vcinfo.context->width, vcinfo.context->height, 0, SDL_RESIZABLE);
> #else
>         screen = SDL_SetVideoMode(vcinfo.context->width, vcinfo.context->height, 24, SDL_RESIZABLE);
> #endif
> 
>         video_windowtitle = aud_get_str ("ffaudio", "video_windowtitle");
>         if (video_windowtitle)
>             SDL_WM_SetCaption(video_windowtitle, NULL);
>         if (aud_get_int ("ffaudio", "video_sws_scale"))   //USER CAN CHOOSE SWS_SCALE VALUE.
>             video_sws_scale = aud_get_int ("ffaudio", "video_sws_scale");
>         else
>             video_sws_scale = SWS_BICUBIC;  //default=4
> 
>         bmp = SDL_CreateYUVOverlay(
>             vcinfo.context->width,
>             vcinfo.context->height,
>             SDL_YV12_OVERLAY,
>             screen
>         );
>         sws_ctx = sws_getContext (
>           	 vcinfo.context->width,
>           	 vcinfo.context->height,
>           	 vcinfo.context->pix_fmt,
>           	 vcinfo.context->width,
>         	   vcinfo.context->height,
>           	 PIX_FMT_YUV420P,
>           	 video_sws_scale,
>           	 NULL,
>           	 NULL,
>         	   NULL
>         );
> 
>         /* NOW CALCULATE THE WIDTH, HEIGHT, & ASPECT BASED ON VIDEO'S SIZE & AND ANY USER PARAMATERS GIVEN: */
>         video_aspect_ratio = vcinfo.context->height
>             ? (float)vcinfo.context->width / (float)vcinfo.context->height : 1.0;
>         int vx = aud_get_int ("ffaudio", "video_xsize");
>         int vy = aud_get_int ("ffaudio", "video_ysize");
>         /* JWT:FIXME:FLV AND SWF STREAMS ERROR OUT ON ATTEMPT TO CHANGE SIZE AT STARTUP?!
>             THOUGH USER CAN STILL RESIZE WINDOW LATER!  ERROR MSG:
>             "Assertion ref->size >= offset + s->mb_stride * ((f->height+15)/16) failed 
>             at libavcodec/mpegvideo.c:1963 
>         */
>         if (! strcmp_nocase (fileext, ".flv") || ! strcmp_nocase (fileext, ".swf"))
>             vx = vy = 0;
>         if (vx && !vy)   //user specified width only, calc. height based on aspect:
>         {
>             vcinfo.context->width = video_width = vx;
>             vcinfo.context->height = video_height = (int)((float)vx / video_aspect_ratio);
>         }
>         else if (!vx && vy)   //user specified height only, calc. height based on aspect:
>         {
>             vcinfo.context->height = video_height = vy;
>             vcinfo.context->width = video_width = (int)((float)vy * video_aspect_ratio);
>             
>         }
>         else if (vx && vy)   //user specified fixed width and height:
>         {
>             vcinfo.context->width = video_width = vx;
>             vcinfo.context->height = video_height = vy;
>         }
>         else   //user specified nothing, use video's desired wXh:
>         {
>             video_width = vcinfo.context->width;
>             video_height = vcinfo.context->height;
>         }
>         video_aspect_ratio = video_height
>             ? (float)video_width / (float)video_height : 1.0;   //fall thru to square to avoid possibliity of "/0"!
> 
>         //NOW "RESIZE" screen to user's wXh, if user set something:
>         if (vx || vy)
>         {
> #ifndef __DARWIN__
>             screen = SDL_SetVideoMode(video_width, video_height, 0, SDL_RESIZABLE);
> #else
>             screen = SDL_SetVideoMode(video_width, video_height, 24, SDL_RESIZABLE);
> #endif
> 
>             if(!screen) {
>                 AUDERR("SDL: could not re-set video mode - exiting\n");
>                 goto error_exit;
>             }
>         }
>         if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) {
>             AUDERR("Could not initialize SDL - %s\n", SDL_GetError());
>             goto error_exit;
>         }
>     }
> 
>     /* codec_opened = true;  //JWT:DON'T THINK WE NEED ANYMORE. */
448c785
<     AUDDBG("opening audio output\n");
---
>     AUDDBG("opening audio output - bitrate=%d=\n", ic->bit_rate);
450a788
> 
454a793,824
>     int seek_value, ret, frameFinished, decoded, len, size, video_qsize, acount, vcount;
>     bool knit1perl2;
>     acount = 0; vcount = 0;  /* JWT:LET'S COUNT PACKETS OF EACH SIZE FOR DEBUGGING. */
>     AVFrame * frame;
>     AVFrame * vframe;
>     /* JWT:video_qsize:  MAX # VIDEO PACKETS TO QUEUE UP FOR INTERLACING TO SMOOTH VIDEO 
>         PLAYBACK - GOOD RANGE IS 8-56, NOT ENOUGH=JITTERY VIDEO, 
>         TOO MANY=AUDIO/VIDEO BECOME NOTICABLY OUT OF SYNC!
>     */
>     video_qsize = (aud_get_int ("ffaudio", "video_qsize"))
>         ? aud_get_int ("ffaudio", "video_qsize") : 16;
>     if (video_qsize < 1)
>         video_qsize = 1;
> 
>     pktQueue *pktQ;
>     pktQ = createQueue(video_qsize);
>     /* 
>         JWT: THIS FLAG FORCES THE VIDEO QUEUE TO BE POPPED ONCE FOR EVERY *TWO* AUDIO 
>         PACKETS - MOST VIDEOS SEEM TO HAVE A/B 2-1 RATIO OF AUDIO TO VIDEO PACKETS & 
>         THIS PRETTY MUCH *ELIMINATED* THE VIDEO JITTER!!!
>     */
>     knit1perl2 = true;  /* ALTERNATES BETWEEN ON AND OFF EVERY OTHER AUDIO PACKET */
> 
>     AUDDBG("video queue size %d\n", video_qsize);
> #if CHECK_LIBAVCODEC_VERSION (55, 45, 101, 55, 28, 1)
>     frame = av_frame_alloc ();
>     vframe = av_frame_alloc ();
> #else
>     frame = avcodec_alloc_frame ();
>     vframe = avcodec_alloc_frame ();
> #endif
> 
457c827
<         int seek_value = check_seek ();
---
>         seek_value = check_seek ();
460a831,836
>             /* JWT:FIRST, PROCESS VIDEO PACKETS SITTING IN THE QUEUE TO CLEAR THE QUEUE! */
>             while (Dequeue (pktQ))
>                 continue;
> 
>             /* JWT: HAD TO CHANGE THIS FROM "AVSEEK_FLAG_ANY" TO AVSEEK_FLAG_BACKWARD 
>                 TO GET SEEK TO NOT RANDOMLY BRICK?! */
462c838
<              1000, AVSEEK_FLAG_ANY) < 0)
---
>                 1000, AVSEEK_FLAG_BACKWARD) < 0)
472d847
<         int ret;
497,498c872,876
<             av_free_packet(&pkt);
<             continue;
---
>             if (!play_video || pkt.stream_index != vcinfo.stream_idx)
>             {
>                 av_free_packet(&pkt);
>                 continue;
>             }
502a881
>         frameFinished = 0;
512,520c891,892
< #if CHECK_LIBAVCODEC_VERSION (55, 45, 101, 55, 28, 1)
<             AVFrame * frame = av_frame_alloc ();
< #else
<             AVFrame * frame = avcodec_alloc_frame ();
< #endif
<             int decoded = 0;
<             int len = avcodec_decode_audio4 (cinfo.context, frame, & decoded, & tmp);
< 
<             if (len < 0)
---
>             decoded = 0;
>             if (pkt.stream_index == cinfo.stream_idx)  /* PROCESS AUDIO PACKET: */
522,524c894,930
<                 AUDERR ("decode_audio() failed, code %d\n", len);
<                 break;
<             }
---
>                 ++acount;
>                 /* JWT:IF PLAYING VIDEO, CHECK VIDEO QUEUE. */
>                 if (play_video)
>                 {
>                     int i,pkts2pop;
>                     /* FIRST PROCESS THE NEXT # VIDEO PACKETS, IF ANY IN THE QUEUE:
>                         FOR EVERY *OTHER* AUDIO PACKET, GRAB 1 VIDEO PKT. OFF QUEUE,
>                         UNLESS QUEUE IS FULL, THEN GRAB 2 SO WE HAVE ROOM FOR THE NEXT ONE!
>                     */
>                     pkts2pop = knit1perl2 ? ((pktQ->size == pktQ->capacity) ? 2 : 1) : 0;
>                     if (pkts2pop > video_qsize)
>                         pkts2pop = video_qsize;
>                     knit1perl2 = ! knit1perl2;  //WE'RE ASSUMING LIKELY NEAR 2x AUDIO TO VIDEO FRAMES:
>                     AVPacket * pktRef;
>                     for (i=1; i<=pkts2pop; i++)
>                     {
>                         pktRef = QFront (pktQ);
>                         if (pktRef)
>                         {
> 
>                             while (1)
>                             {
>                                 if (!write_videoframe (sws_ctx, vframe, bmp, pktRef, &frameFinished, 
>                                         video_width, video_height))
>                                     break;
>                             }
>                             if (!Dequeue (pktQ))
>                                 AUDERR("Queue is Empty\n");
>                         }
>                     }
>                 }
>                 len = avcodec_decode_audio4 (cinfo.context, frame, & decoded, & tmp);
>                 if (len < 0)
>                 {
>                     AUDERR ("decode_audio() failed, code %d\n", len);
>                     break;
>                 }
526,527c932,933
<             tmp.size -= len;
<             tmp.data += len;
---
>                 tmp.size -= len;
>                 tmp.data += len;
529,530c935,944
<             if (! decoded)
<                 continue;
---
>                 if (! decoded)
>                     /* continue;  // JWT:NOT SURE WHY THIS WAS A CONTINUE INSTEAD OF A BREAK?! */
>                     break;
> 
>                 size = FMT_SIZEOF (out_fmt) * cinfo.context->channels * frame->nb_samples;
> 
>                 if (planar)
>                 {
>                     if (size > buf.len ())
>                         buf.resize (size);
532c946,951
<             int size = FMT_SIZEOF (out_fmt) * cinfo.context->channels * frame->nb_samples;
---
>                     audio_interlace ((const void * *) frame->data, out_fmt,
>                      cinfo.context->channels, buf.begin (), frame->nb_samples);
>                     write_audio (buf.begin (), size);
>                 }
>                 else
>                     write_audio (frame->data[0], size);
534c953,954
<             if (planar)
---
>             }
>             else    /* JWT:PROCESS VIDEO PACKET HERE: */
536,537c956,961
<                 if (size > buf.len ())
<                     buf.resize (size);
---
>                 ++vcount;
>                 /* JWT: IF QUEUE IS FULL, PROCESS NEXT 2 VIDEO PACKETS FROM QUEUE. */
>                 if (isQueueFull (pktQ))
>                 {
>                     int i, pkts2pop;
>                     AVPacket * pktRef;
539,541c963,987
<                 audio_interlace ((const void * *) frame->data, out_fmt,
<                  cinfo.context->channels, buf.begin (), frame->nb_samples);
<                 write_audio (buf.begin (), size);
---
>                     pkts2pop = (video_qsize > 1) ? 2 : 1;
>                     for (i=1; i<=pkts2pop; i++)
>                     {
>                         pktRef = QFront (pktQ);
>                         if (pktRef)
>                         {
>                             while (1)
>                             {
>                                 if (!write_videoframe (sws_ctx, vframe, bmp, pktRef, &frameFinished, 
>                                         video_width, video_height))
>                                     break;
>                             }
>                             if (!Dequeue (pktQ))
>                                 AUDERR("Queue is Empty\n");
>                         }
>                     }
>                     AUDDBG("Queue filled.\n");
>                 }
>                 if (Enqueue(pktQ, pkt)) {  /* VIDEO PACKETS TAKE A NUMBER & GET IN LINE! */
>                     break;
>                 }
>                 AUDERR("Could not enqueue packet, refuses to wait in line, so process NOW!\n");
>                 if (!write_videoframe (sws_ctx, vframe, bmp, &pkt, &frameFinished, 
>                         video_width, video_height))
>                     break;
543,544d988
<             else
<                 write_audio (frame->data[0], size);
546,549c990,1020
< #if CHECK_LIBAVCODEC_VERSION (55, 45, 101, 55, 28, 1)
<             av_frame_free (& frame);
< #elif CHECK_LIBAVCODEC_VERSION (54, 59, 100, 54, 28, 0)
<             avcodec_free_frame (& frame);
---
>             /* JWT: NOW HANDLE VIDEO UI EVENTS SUCH AS RESIZE OR KILL SCREEN: */
>             if (play_video)
>             {
>                 SDL_Rect rect;
> 
>                 SDL_PollEvent(&event);
>                 switch(event.type) {
>                 case SDL_QUIT:
>                     SDL_Quit();
>                     play_video = false;
>                     //goto error_exit;
>                     break;
> 
>                 case SDL_VIDEORESIZE:
>                     //Resize the screen
>                     float new_aspect_ratio;  //FOR SOME REASON C++ REQUIRES 2 LINES HERE?!
>                     new_aspect_ratio = event.resize.h
>                         ? (float)event.resize.w / (float)event.resize.h : 1.0;
>                     if (new_aspect_ratio > video_aspect_ratio)
>                     {
>                         video_height = event.resize.h;
>                         video_width = (int)(video_aspect_ratio * (float)video_height);
>                     }
>                     else
>                     {
>                         video_width = event.resize.w;
>                         video_height = (int)((float)video_width / video_aspect_ratio);
>                     }
> 
> #ifndef __DARWIN__
>                     screen = SDL_SetVideoMode( video_width, video_height, 0, SDL_RESIZABLE );
551c1022
<             av_free (frame);
---
>                     screen = SDL_SetVideoMode( video_width, video_height, 24, SDL_RESIZABLE );
553d1023
<         }
555,556c1025,1041
<         if (pkt.data)
<             av_free_packet(&pkt);
---
>                     //If there's an error
>                     if( screen == NULL )
>                         break;
> 
>                 case SDL_VIDEOEXPOSE:
>                     rect.x = 0;
>                     rect.y = 0;
>                     rect.w = video_width;
>                     rect.h = video_height;
>                     SDL_DisplayYUVOverlay(bmp, &rect);
>                     break;
> 
>                 default:
>                     break;
>                 }
>             }
>         }
559a1045,1059
>     AUDDBG("end of playback - % audio frames, % video frames processed.", acount, vcount);
>     if (play_video)
>         SDL_Quit();
> 
> #if CHECK_LIBAVCODEC_VERSION (55, 45, 101, 55, 28, 1)
>     av_frame_free (& vframe);
>     av_frame_free (& frame);
> #elif CHECK_LIBAVCODEC_VERSION (54, 59, 100, 54, 28, 0)
>     avcodec_free_frame (& vframe);
>     avcodec_free_frame (& frame);
> #else
>     av_free (vframe);
>     av_free (frame);
> #endif
> 
562,563d1061
<     if (codec_opened)
<         avcodec_close(cinfo.context);
565c1063
<         close_input_file(ic);
---
>         close_input_file(ic, & cinfo, & vcinfo);
619a1118,1123
> 
>     /* AVI  // JWT:ADDED */
>     "avi",
> 
>     /* FLV  // JWT:ADDED */
>     "flv",
