[mythtv] [PATCH] Add AFD support for aspect 'magic'

Neale Swinnerton mythtv-dev.spam at isismanor.com
Sun Jun 5 22:47:45 UTC 2005


Here's an updated version of the patch. It's a little cleaner, and I
fixed some stupid errors I made, that led to SEGV with certain
aspect/afd combos.

I'm particularly interested to see how this works with a 4_3_sp_14_9 AFD
(13) in a 16:9 frame. The correct behaviour is to crop a little of the
top and bottom and still leave the image pillarboxed. I suspect this
will cause problems with hardware scaling, because the size will be odd.

Neale.

Neale Swinnerton wrote:
> The Active Format Descriptor (AFD) is set by some broadcasters like ITV1
> and CH4 in the UK in their DVB-T streams. This signals what the format
> of the video is, and along with the aspect ratio of the video stream and
> your display it can resize the video 'better'.
> 
> This patch adds support for this to myth. To enable it go to
> Utilities/Setup->Settings->TV Settings->Playback and set aspect override
> to AFD.
> 
> When playing back streams that have AFD set you should see the image
> scaled better. ie. it will apply letterboxing/pillarboxing as
> appropriate, Shoot & Protect areas should be honoured.
> 
> AFD has some caveats:
> 	+ Only works where the MPEG Stream is either 4:3 or 16:9
> 	+ Only works where your display is either 4:3 or 16:9
> 
> Note that if you don't have GuiSizeForTv set the aspect ratio comes from
> the DisplaySize option in your xorg.conf, if GuiSizeForTv is set myth
> calculates the aspect ratio of your screen with the following code
> 
> void VideoOutputXv::InitDisplayMeasurements(uint width, uint height)
> {
>  <SNIP/>
>         int w = DisplayWidth(XJ_disp, XJ_screen_num);
>         int h = DisplayHeight(XJ_disp, XJ_screen_num);
>         int gui_w = w, gui_h = h;
>         gContext->GetResolutionSetting("Gui", gui_w,  gui_h);
>         if (gui_w)
>             w_mm = w_mm * gui_w / w;
>         if (gui_h)
>             h_mm = h_mm * gui_h / h;
> 
>         display_aspect = (float)w_mm/h_mm;
> <SNIP/>
> }
> 
> w_mm/h_mm is the width/height of your screen in mm as reported by X (ie.
> the values passed via DisplaySize option), for me this means I need a
> gui size of 1024x576 to get my display aspect to 1.78.
> 
> I left debug output switched on in the patch, so you will see what value
> myth is calculating for your aspect ratio....
> 
> TODO: I'm not sure that the size calculations for the various
> combinations are correct, it seems to work for my limited testing on
> ITV1 / Ch 4. I'm trying to find a test stream to test this out.
> 
> http://www.rsd.de/www/dev_center.nsf/frameset?OpenAgent&website=com&content=/www/dev_center.nsf/html/DV-TCMuseafd
> 
> looks ideal, but I don't have access to that sort of kit and I haven't
> found an easy way to generate such a stream. Any ideas?
> 
> TODO: It seems reasonable to add a 'AFD or Fill' mode that falls back to
> Fill Mode if the AFD isn't set. This should be easy, but the code needs
> a rejig to allow the fill code to be common to both modes.
> 
> TODO: Implement WSS line 23 switching in the Unichrome driver, to make
> this really slick. I doubt this is easily possible, maybe some boards
> support it (
> http://www.commell.com.tw/Product/Peripheral/MiniAGP/MA-HDTV.htm )
> 
> enjoy...
> 
> Neale.
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> diff -bBuwr mythtv-20050530/libs/libmythtv/NuppelVideoPlayer.cpp mythtv-20050530.patched/libs/libmythtv/NuppelVideoPlayer.cpp
> --- mythtv-20050530/libs/libmythtv/NuppelVideoPlayer.cpp	2005-05-24 03:59:13.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/NuppelVideoPlayer.cpp	2005-06-02 22:37:21.000000000 +0100
> @@ -455,6 +455,7 @@
>  
>      videofiltersLock.lock();
>      videoOutput->InputChanged(video_width, video_height, video_aspect);
> +    videoOutput->SetAfdMode(video_afd_mode);
>      if (videoOutput->IsErrored())
>      {
>          VERBOSE(VB_IMPORTANT, "ReinitVideo(): videoOutput->IsErrored()");
> @@ -531,13 +532,13 @@
>  
>  void NuppelVideoPlayer::SetVideoParams(int width, int height, double fps,
>                                         int keyframedistance, float aspect,
> -                                       FrameScanType scan, bool reinit)
> +                                       int afd_mode, FrameScanType scan, bool reinit)
>  {
>      if (width == 0 || height == 0 || isnan(aspect) || isnan(fps))
>          return;
>  
>      if (video_width == width && video_height == height && 
> -        aspect == video_aspect && fps == video_frame_rate)
> +        aspect == video_aspect && afd_mode == video_afd_mode && fps == video_frame_rate)
>      {
>          return;
>      }
> @@ -564,6 +565,8 @@
>              commDetect->SetVideoParams(aspect);
>      }
>  
> +    video_afd_mode = afd_mode;
> +
>      if (reinit)
>          ReinitVideo();
>  
> diff -bBuwr mythtv-20050530/libs/libmythtv/NuppelVideoPlayer.h mythtv-20050530.patched/libs/libmythtv/NuppelVideoPlayer.h
> --- mythtv-20050530/libs/libmythtv/NuppelVideoPlayer.h	2005-05-05 03:51:15.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/NuppelVideoPlayer.h	2005-06-02 22:36:30.000000000 +0100
> @@ -156,7 +156,8 @@
>      void SetKeyframeDistance(int keyframedistance);
>      void SetVideoParams(int width, int height, double fps,
>                          int keyframedistance, float aspect = 1.33333,
> -                        FrameScanType scan = kScan_Ignore, bool reinit = false);
> +                        int afd_code = kAfd_Unset, FrameScanType scan = kScan_Ignore, 
> +                        bool reinit = false);
>      void SetAudioParams(int bps, int channels, int samplerate);
>      void SetEffDsp(int dsprate);
>      void SetFileLength(int total, int frames);
> @@ -295,6 +296,7 @@
>      int video_size;
>      double video_frame_rate;
>      float video_aspect;
> +    int video_afd_mode;
>      FrameScanType m_scan;
>      bool m_double_framerate;
>      bool m_can_double;
> diff -bBuwr mythtv-20050530/libs/libmythtv/avformatdecoder.cpp mythtv-20050530.patched/libs/libmythtv/avformatdecoder.cpp
> --- mythtv-20050530/libs/libmythtv/avformatdecoder.cpp	2005-05-23 21:39:12.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/avformatdecoder.cpp	2005-06-03 07:19:11.000000000 +0100
> @@ -553,6 +553,7 @@
>      current_width = enc->width;
>      current_height = enc->height;
>      current_aspect = aspect_ratio;
> +    current_afd_mode = enc->dtg_active_format;
>  
>      enc->opaque = NULL;
>      enc->get_buffer = NULL;
> @@ -603,7 +604,7 @@
>          avcodec_align_dimensions(enc, &align_width, &align_height);
>  
>      m_parent->SetVideoParams(align_width, align_height, fps,
> -                             keyframedist, aspect_ratio, kScan_Detect);
> +                             keyframedist, aspect_ratio, current_afd_mode, kScan_Detect);
>  }
>  
>  #ifdef USING_XVMC
> @@ -1158,10 +1159,12 @@
>  
>                      float aspect = GetMpegAspect(context, aspectratioinfo,
>                                                   width, height);
> +		    int afd_mode = context->dtg_active_format;
>  
>                      if (width < 2500 && height < 2000 &&
>                          (CheckVideoParams(width, height) ||
> -                         aspect != current_aspect))
> +                         aspect != current_aspect ||
> +			 afd_mode != current_afd_mode))
>                      {
>                          int align_width = width;
>                          int align_height = height;
> @@ -1174,11 +1177,12 @@
>  
>                          m_parent->SetVideoParams(align_width,
>                                                   align_height, fps,
> -                                                 keyframedist, aspect, 
> +                                                 keyframedist, aspect, afd_mode,
>                                                   kScan_Detect, true);
>                          current_width = width;
>                          current_height = height;
>                          current_aspect = aspect;
> +			current_afd_mode = afd_mode;
>  
>                          if (d->mpeg2dec)
>                              d->ResetMPEG2();
> diff -bBuwr mythtv-20050530/libs/libmythtv/decoderbase.h mythtv-20050530.patched/libs/libmythtv/decoderbase.h
> --- mythtv-20050530/libs/libmythtv/decoderbase.h	2005-04-27 20:32:49.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/decoderbase.h	2005-06-03 07:16:20.000000000 +0100
> @@ -87,6 +87,7 @@
>      int current_width;
>      int current_height;
>      float current_aspect;
> +    int current_afd_mode;
>  
>      long long framesPlayed;
>      long long framesRead;
> diff -bBuwr mythtv-20050530/libs/libmythtv/tv_play.cpp mythtv-20050530.patched/libs/libmythtv/tv_play.cpp
> --- mythtv-20050530/libs/libmythtv/tv_play.cpp	2005-05-27 01:59:21.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/tv_play.cpp	2005-06-02 22:09:40.000000000 +0100
> @@ -3476,6 +3476,7 @@
>          case kLetterbox_16_9_Zoom:    text = tr("16:9 Zoom"); break;
>          case kLetterbox_16_9_Stretch: text = tr("16:9 Stretch"); break;
>          case kLetterbox_Fill:         text = tr("Fill"); break;
> +        case kLetterbox_Afd:          text = tr("Active Format"); break;
>          default:                      text = tr("Off"); break;
>      }
>  
> diff -bBuwr mythtv-20050530/libs/libmythtv/videooutbase.cpp mythtv-20050530.patched/libs/libmythtv/videooutbase.cpp
> --- mythtv-20050530/libs/libmythtv/videooutbase.cpp	2005-05-26 03:17:04.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/videooutbase.cpp	2005-06-04 01:09:38.365803256 +0100
> @@ -136,6 +136,7 @@
>  VideoOutput::VideoOutput()
>  {
>      letterbox = kLetterbox_Off;
> +    afd_mode = kAfd_Unset;
>  
>      framesPlayed = 0;
>  
> @@ -359,7 +360,8 @@
>      {
>          default:
>          case kLetterbox_Off:
> -        case kLetterbox_Fill:           XJ_aspect = videoAspect;
> +        case kLetterbox_Fill:           
> +        case kLetterbox_Afd:            XJ_aspect = videoAspect;
>                                          break;
>  
>          case kLetterbox_4_3:
> @@ -487,6 +489,9 @@
>      yoff   = imgy;
>      width  = imgw;
>      height = imgh;
> +    float displayAspect = GetDisplayAspect();
> +    bool displayAspectIs_16_9 = (fabs(displayAspect - 1.777777) < 0.05);
> +    bool videoAspectIs_16_9 = (fabs(XJ_aspect - 1.777777) < 0.05);
>  
>      switch (letterbox)
>      {
> @@ -504,19 +509,68 @@
>          case kLetterbox_Fill:
>              if (GetDisplayAspect() > XJ_aspect)
>              {
> -                int pixDisplayed = int(((XJ_aspect / GetDisplayAspect()) * imgh) + 0.5);
> +                int pixDisplayed = int(((XJ_aspect /displayAspect) * imgh) + 0.5);
>  
>                  height = pixDisplayed;
>                  yoff = (imgh - pixDisplayed) / 2;
>              }
>              else
>              {
> -                int pixDisplayed = int(((GetDisplayAspect() / XJ_aspect) * imgw) + 0.5);
> +                int pixDisplayed = int(((displayAspect / XJ_aspect) * imgw) + 0.5);
>  
>                  width = pixDisplayed;
>                  xoff = (imgw - pixDisplayed) / 2;
>              }
>              break;
> +        case kLetterbox_Afd:
> +         if ( videoAspectIs_16_9 ) {
> +             switch (afd_mode)
> +             {
> +                 case kAfd_Unset:
> +                 case kAfd_Same:
> +                 case kAfd_16_9:
> +                 case kAfd_14_9:
> +                 case kAfd_16_9_Sp_14_9:
> +                 case kAfd_Sp_4_3:
> +                         break;
> +                 case kAfd_4_3:
> +                     if (displayAspectIs_16_9) {
> +                            width *= 3/4;
> +                            xoff = width/6;
> +                     }
> +                     break;
> +                 case kAfd_4_3_Sp_14_9:
> +                     if (displayAspectIs_16_9) {
> +			    height *= 4/3; 
> +                            yoff -= height/6;
> +                            width *= 3/4;
> +                            xoff += width/6;
> +                     }
> +                     break;
> +             }
> +         } else { // videoAspectIs_4_3
> +             switch (afd_mode)
> +             {
> +                 case kAfd_Unset:
> +                 case kAfd_16_9:
> +                 case kAfd_16_9_Sp_14_9:
> +                     break;
> +                 case kAfd_Same:
> +                 case kAfd_Sp_4_3:
> +                     if (displayAspectIs_16_9) {
> +                            width *=  3/4;
> +                            xoff  += width/6;
> +		     }
> +		     break;
> +                 case kAfd_4_3_Sp_14_9:
> +                     if (displayAspectIs_16_9) {
> +                            width = width*4/3;
> +                            yoff -= height/6;
> +                     }
> +                     break;
> +             }
> +         }
> +            break;
>          default:
>              break;
>      }
> @@ -532,6 +586,7 @@
>  {
>      int yoff, xoff;
>      float displayAspect;
> +    int displayAspectIs_16_9, videoAspectIs_16_9;
>  
>      // Preset all image placement and sizing variables.
>      imgx = 0; imgy = 0;
> @@ -544,6 +599,8 @@
>  
>      // Get display aspect and correct for rounding errors
>      displayAspect = GetDisplayAspect();
> +    displayAspectIs_16_9 = (fabs(displayAspect - 1.777777) > 0.05)?0:1;
> +    videoAspectIs_16_9 = (fabs(XJ_aspect - 1.333333) > 0.05)?0:1;
>  
>      // Check if close to 4:3
>      if(fabs(displayAspect - 1.333333) < 0.05)
> @@ -659,11 +716,61 @@
>      // account the aspect ratios of both the video as well as the actual
>      // screen to allow proper letterboxing to take place.
>      
> -    //cout << "XJ aspect " << XJ_aspect << endl;
> -    //cout << "Display aspect " << GetDisplayAspect() << endl;
> -    //printf("Before: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff, 
> -    //    dispyoff);
> -    
> +    cout << "XJ aspect " << XJ_aspect << endl;
> +    cout << "Display aspect " << GetDisplayAspect() << endl;
> +    cout << "AFD " << afd_mode << endl;
> +    printf("Before: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff, 
> +        dispyoff);
> +    
> +    if ( letterbox == kLetterbox_Afd ){
> +         if ( videoAspectIs_16_9 ) {
> +             switch (afd_mode)
> +             {
> +                 case kAfd_Unset:
> +                 case kAfd_Same:
> +                 case kAfd_16_9:
> +                 case kAfd_14_9:
> +                 case kAfd_16_9_Sp_14_9:
> +                 case kAfd_Sp_4_3:
> +                         break;
> +                 case kAfd_4_3:
> +                     if (displayAspectIs_16_9) {
> +                            dispwoff =  dispwoff*3/4;
> +                            dispxoff += (dispwoff/6);
> +                     }
> +                     break;
> +                 case kAfd_4_3_Sp_14_9:
> +                     if (displayAspectIs_16_9) {
> +                            disphoff = disphoff*4/3;
> +                            dispyoff -= (disphoff/6);
> +                            dispwoff = (dispwoff*3/4);
> +                            dispxoff += (dispwoff/6);
> +                     }
> +                     break;
> +             }
> +         } else { // videoAspectIs_4_3
> +             switch (afd_mode)
> +             {
> +                 case kAfd_Unset:
> +                 case kAfd_16_9:
> +                 case kAfd_16_9_Sp_14_9:
> +                     break;
> +                 case kAfd_Same:
> +                 case kAfd_Sp_4_3:
> +                     if (displayAspectIs_16_9) {
> +                            dispwoff =  dispwoff*3/4;
> +                            dispxoff += (dispwoff/6);
> +		     }
> +		     break;
> +                 case kAfd_4_3_Sp_14_9:
> +                     if (displayAspectIs_16_9) {
> +                            dispyoff -= (disphoff/6);
> +                            disphoff = disphoff*4/3;
> +                     }
> +                     break;
> +             }
> +         }
> +    }
>      if ((fabs(displayAspect - XJ_aspect) / displayAspect) > 0.1){
>          if(letterbox == kLetterbox_Fill){
>              if (displayAspect > XJ_aspect)
> @@ -772,7 +880,6 @@
>      //printf("After: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff, 
>      //dispyoff);
>  
> -#if 0
>      printf("VideoOutput::MoveResize:\n");
>      printf("Img(%d,%d %d,%d)\n", imgx, imgy, imgw, imgh);
>      printf("Disp(%d,%d %d,%d)\n", dispxoff, dispyoff, dispwoff, disphoff);
> @@ -783,7 +890,6 @@
>      printf("XJ_aspect(%f)\n", XJ_aspect);
>      printf("CDisplayAspect: %f\n", displayAspect);
>      printf("Letterbox: %d\n", letterbox);
> -#endif
>   
>      VERBOSE(VB_PLAYBACK,
>              QString("Image size. dispxoff %1, dispyoff: %2, dispwoff: %3, "
> diff -bBuwr mythtv-20050530/libs/libmythtv/videooutbase.h mythtv-20050530.patched/libs/libmythtv/videooutbase.h
> --- mythtv-20050530/libs/libmythtv/videooutbase.h	2005-05-26 03:17:04.000000000 +0100
> +++ mythtv-20050530.patched/libs/libmythtv/videooutbase.h	2005-06-04 00:36:13.000000000 +0100
> @@ -105,9 +105,29 @@
>      kLetterbox_16_9_Zoom,
>      kLetterbox_16_9_Stretch,
>      kLetterbox_Fill,
> +    kLetterbox_Afd,
>      kLetterbox_END
>  };
>  
> +/* Active Format Description(AFD) is set in DVB Streams.
> + * By considering both the aspect ratio and the AFD it 
> + * is posible to determine how to present the image in the
> + * correct manner. 
> + * See http://www.dtg.org.uk/publications/books/afd.pdf
> + * for the gory details
> + */
> +enum AfdMode {
> +    kAfd_Unset        = 0,
> +    kAfd_Same         = 8,
> +    kAfd_4_3          = 9,
> +    kAfd_16_9         = 10,
> +    kAfd_14_9         = 11,
> +    kAfd_4_3_Sp_14_9  = 13,
> +    kAfd_16_9_Sp_14_9 = 14,
> +    kAfd_Sp_4_3       = 15,
> +    kAfd_END
> +};
> +
>  enum FrameScanType {
>      kScan_Ignore      = -1,
>      kScan_Progressive =  0,
> @@ -162,6 +182,8 @@
>      int GetLetterbox(void) { return letterbox; }
>      void ToggleLetterbox(int letterboxMode = kLetterbox_Toggle);
>  
> +    void SetAfdMode(int afd_mode) { this->afd_mode = afd_mode; };
> +    
>      // pass in null to use the pause frame, if it exists.
>      virtual void ProcessFrame(VideoFrame *frame, OSD *osd,
>                                FilterChain *filterList,
> @@ -298,6 +321,7 @@
>      int brightness, contrast, colour, hue;
>  
>      int letterbox;
> +    int afd_mode;
>  
>      int PIPLocation;
>  
> diff -bBuwr mythtv-20050530/programs/mythfrontend/globalsettings.cpp mythtv-20050530.patched/programs/mythfrontend/globalsettings.cpp
> --- mythtv-20050530/programs/mythfrontend/globalsettings.cpp	2005-05-28 01:48:30.000000000 +0100
> +++ mythtv-20050530.patched/programs/mythfrontend/globalsettings.cpp	2005-06-04 01:14:06.980231084 +0100
> @@ -1160,11 +1160,15 @@
>      gc->addSelection(QObject::tr("16/9 Zoom"), "4");
>      gc->addSelection(QObject::tr("16/9 Stretch"), "5");
>      gc->addSelection(QObject::tr("Fill"), "6");
> +    gc->addSelection(QObject::tr("AFD"), "7");
>      gc->setHelpText(QObject::tr("This will override any aspect ratio in the "
>                      "recorded stream, the same as pressing the W Key "
>                      "during playback. "
>  		    "Fill will \"fill\" the screen with the image clipping as required. "
>  		    "Fill is useful when using 4:3 interlaced TV's for display."
> +                    "AFD will use the active format descriptor from the stream "
> +		    "to determine the appropriate display. "
> +		    "(UK ITV & Ch4 only?)"
>  		    ));
>      return gc;
>  }
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> mythtv-dev mailing list
> mythtv-dev at mythtv.org
> http://mythtv.org/cgi-bin/mailman/listinfo/mythtv-dev
-------------- next part --------------
Index: libs/libmythtv/NuppelVideoPlayer.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoPlayer.cpp,v
retrieving revision 1.474
diff -a -u -b -B -r1.474 NuppelVideoPlayer.cpp
--- libs/libmythtv/NuppelVideoPlayer.cpp	3 Jun 2005 04:05:22 -0000	1.474
+++ libs/libmythtv/NuppelVideoPlayer.cpp	5 Jun 2005 15:08:50 -0000
@@ -456,6 +456,7 @@
 
     videofiltersLock.lock();
     videoOutput->InputChanged(video_width, video_height, video_aspect);
+    videoOutput->SetAfdMode(video_afd_mode);
     if (videoOutput->IsErrored())
     {
         VERBOSE(VB_IMPORTANT, "ReinitVideo(): videoOutput->IsErrored()");
@@ -532,13 +533,13 @@
 
 void NuppelVideoPlayer::SetVideoParams(int width, int height, double fps,
                                        int keyframedistance, float aspect,
-                                       FrameScanType scan, bool reinit)
+                                       int afd_mode, FrameScanType scan, bool reinit)
 {
     if (width == 0 || height == 0 || isnan(aspect) || isnan(fps))
         return;
 
     if (video_width == width && video_height == height && 
-        aspect == video_aspect && fps == video_frame_rate)
+        aspect == video_aspect && afd_mode == video_afd_mode && fps == video_frame_rate)
     {
         return;
     }
@@ -565,6 +566,8 @@
             commDetect->SetVideoParams(aspect);
     }
 
+    video_afd_mode = afd_mode;
+
     if (reinit)
         ReinitVideo();
 
Index: libs/libmythtv/NuppelVideoPlayer.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/NuppelVideoPlayer.h,v
retrieving revision 1.180
diff -a -u -b -B -r1.180 NuppelVideoPlayer.h
--- libs/libmythtv/NuppelVideoPlayer.h	2 Jun 2005 22:41:10 -0000	1.180
+++ libs/libmythtv/NuppelVideoPlayer.h	5 Jun 2005 15:08:50 -0000
@@ -156,7 +156,8 @@
     void SetKeyframeDistance(int keyframedistance);
     void SetVideoParams(int width, int height, double fps,
                         int keyframedistance, float aspect = 1.33333,
-                        FrameScanType scan = kScan_Ignore, bool reinit = false);
+                        int afd_code = kAfd_Unset, FrameScanType scan = kScan_Ignore, 
+                        bool reinit = false);
     void SetAudioParams(int bps, int channels, int samplerate);
     void SetEffDsp(int dsprate);
     void SetFileLength(int total, int frames);
@@ -301,6 +302,7 @@
     int video_size;
     double video_frame_rate;
     float video_aspect;
+    int video_afd_mode;
     FrameScanType m_scan;
     bool m_double_framerate;
     bool m_can_double;
Index: libs/libmythtv/avformatdecoder.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/avformatdecoder.cpp,v
retrieving revision 1.151
diff -a -u -b -B -r1.151 avformatdecoder.cpp
--- libs/libmythtv/avformatdecoder.cpp	3 Jun 2005 18:21:36 -0000	1.151
+++ libs/libmythtv/avformatdecoder.cpp	5 Jun 2005 15:08:51 -0000
@@ -553,6 +553,7 @@
     current_width = enc->width;
     current_height = enc->height;
     current_aspect = aspect_ratio;
+    current_afd_mode = enc->dtg_active_format;
 
     enc->opaque = NULL;
     enc->get_buffer = NULL;
@@ -603,7 +604,7 @@
         avcodec_align_dimensions(enc, &align_width, &align_height);
 
     m_parent->SetVideoParams(align_width, align_height, fps,
-                             keyframedist, aspect_ratio, kScan_Detect);
+                             keyframedist, aspect_ratio, current_afd_mode, kScan_Detect);
 }
 
 #ifdef USING_XVMC
@@ -1158,10 +1159,12 @@
 
                     float aspect = GetMpegAspect(context, aspectratioinfo,
                                                  width, height);
+                    int afd_mode = context->dtg_active_format;
 
                     if (width < 2500 && height < 2000 &&
                         (CheckVideoParams(width, height) ||
-                         aspect != current_aspect))
+                         aspect != current_aspect ||
+                         afd_mode != current_afd_mode))
                     {
                         int align_width = width;
                         int align_height = height;
@@ -1174,11 +1177,12 @@
 
                         m_parent->SetVideoParams(align_width,
                                                  align_height, fps,
-                                                 keyframedist, aspect, 
+                                                 keyframedist, aspect, afd_mode,
                                                  kScan_Detect, true);
                         current_width = width;
                         current_height = height;
                         current_aspect = aspect;
+                        current_afd_mode = afd_mode;
 
                         if (d->mpeg2dec)
                             d->ResetMPEG2();
Index: libs/libmythtv/decoderbase.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/decoderbase.h,v
retrieving revision 1.28
diff -a -u -b -B -r1.28 decoderbase.h
--- libs/libmythtv/decoderbase.h	27 Apr 2005 19:32:49 -0000	1.28
+++ libs/libmythtv/decoderbase.h	5 Jun 2005 15:08:51 -0000
@@ -87,6 +87,7 @@
     int current_width;
     int current_height;
     float current_aspect;
+    int current_afd_mode;
 
     long long framesPlayed;
     long long framesRead;
Index: libs/libmythtv/tv_play.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/tv_play.cpp,v
retrieving revision 1.271
diff -a -u -b -B -r1.271 tv_play.cpp
--- libs/libmythtv/tv_play.cpp	2 Jun 2005 22:41:11 -0000	1.271
+++ libs/libmythtv/tv_play.cpp	5 Jun 2005 15:08:52 -0000
@@ -3568,6 +3568,7 @@
         case kLetterbox_16_9_Zoom:    text = tr("16:9 Zoom"); break;
         case kLetterbox_16_9_Stretch: text = tr("16:9 Stretch"); break;
         case kLetterbox_Fill:         text = tr("Fill"); break;
+        case kLetterbox_Afd:          text = tr("AFD"); break;
         default:                      text = tr("Off"); break;
     }
 
Index: libs/libmythtv/videooutbase.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/videooutbase.cpp,v
retrieving revision 1.74
diff -a -u -b -B -r1.74 videooutbase.cpp
--- libs/libmythtv/videooutbase.cpp	26 May 2005 02:17:04 -0000	1.74
+++ libs/libmythtv/videooutbase.cpp	5 Jun 2005 15:08:52 -0000
@@ -136,6 +136,7 @@
 VideoOutput::VideoOutput()
 {
     letterbox = kLetterbox_Off;
+    afd_mode = kAfd_Unset;
 
     framesPlayed = 0;
 
@@ -359,7 +360,8 @@
     {
         default:
         case kLetterbox_Off:
-        case kLetterbox_Fill:           XJ_aspect = videoAspect;
+        case kLetterbox_Fill:           
+        case kLetterbox_Afd:            XJ_aspect = videoAspect;
                                         break;
 
         case kLetterbox_4_3:
@@ -487,6 +489,7 @@
     yoff   = imgy;
     width  = imgw;
     height = imgh;
+    float displayAspect = GetDisplayAspect();
 
     switch (letterbox)
     {
@@ -502,21 +505,75 @@
             xoff = imgw/8;
             break;
         case kLetterbox_Fill:
-            if (GetDisplayAspect() > XJ_aspect)
+            if (displayAspect > XJ_aspect)
             {
-                int pixDisplayed = int(((XJ_aspect / GetDisplayAspect()) * imgh) + 0.5);
+                int pixDisplayed = int(((XJ_aspect /displayAspect) * imgh) + 0.5);
 
                 height = pixDisplayed;
                 yoff = (imgh - pixDisplayed) / 2;
             }
             else
             {
-                int pixDisplayed = int(((GetDisplayAspect() / XJ_aspect) * imgw) + 0.5);
+                int pixDisplayed = int(((displayAspect / XJ_aspect) * imgw) + 0.5);
 
                 width = pixDisplayed;
                 xoff = (imgw - pixDisplayed) / 2;
             }
             break;
+        case kLetterbox_Afd:
+            if ( AspectIs16_9(videoAspect) ) {
+                switch (afd_mode)
+                {
+                     case kAfd_Unset:
+                     case kAfd_Same:
+                     case kAfd_16_9:
+                     case kAfd_14_9:
+                     case kAfd_16_9_Sp_14_9:
+                     case kAfd_Sp_4_3:
+                         break;
+                     case kAfd_4_3:
+                         if (AspectIs16_9(displayAspect)) {
+                             width  = (width*3)/4;
+                             xoff  += (width/6);
+                         }
+                         break;
+                     case kAfd_4_3_Sp_14_9:
+                         if (AspectIs16_9(displayAspect)) {
+                            height  = (height*4)/3; 
+                            yoff   -= (height/6);
+                            width   = (width*3)/4;
+                            xoff   += (width/6);
+                         }
+                         break;
+                     default:
+                         break;
+                }
+            } else { // videoAspectIs4_3
+                switch (afd_mode)
+                {
+                     case kAfd_Unset:
+                     case kAfd_Same:
+                     case kAfd_16_9:
+                     case kAfd_14_9:
+                     case kAfd_16_9_Sp_14_9:
+                         break;
+                     case kAfd_Sp_4_3:
+                         if (AspectIs16_9(displayAspect)) {
+                             width  = (width*3)/4;
+                             xoff  += (width/6);
+                         }
+                         break;
+                     case kAfd_4_3_Sp_14_9:
+                         if (AspectIs16_9(displayAspect)) {
+                             width  = (width*9)/14;
+                             xoff  += (width*7)/8;
+                         }
+                         break;
+                     default:
+                         break;
+                 }
+            } 
+            break;
         default:
             break;
     }
@@ -546,11 +604,11 @@
     displayAspect = GetDisplayAspect();
 
     // Check if close to 4:3
-    if(fabs(displayAspect - 1.333333) < 0.05)
+    if(AspectIs4_3(displayAspect))
         displayAspect = 1.333333;
 
     // Check if close to 16:9
-    if(fabs(displayAspect - 1.777777) < 0.05)
+    if(AspectIs16_9(displayAspect))
         displayAspect = 1.777777;
 
 /*
@@ -658,12 +716,70 @@
     // Manage aspect ratio and letterbox settings.  Code should take into
     // account the aspect ratios of both the video as well as the actual
     // screen to allow proper letterboxing to take place.
+#if 0
+    cout << "XJ aspect " << XJ_aspect << endl;
+    cout << "Display aspect " << GetDisplayAspect() << endl;
+    cout << "AFD " << afd_mode << endl;
+    printf("Before: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff, 
+        dispyoff);
+#endif
     
-    //cout << "XJ aspect " << XJ_aspect << endl;
-    //cout << "Display aspect " << GetDisplayAspect() << endl;
-    //printf("Before: %dx%d%+d%+d\n", dispwoff, disphoff, dispxoff, 
-    //    dispyoff);
+    if ( letterbox == kLetterbox_Afd ){
+
+         VERBOSE(VB_PLAYBACK, 
+								QString("Applying AFD of %1, video aspect is %2, display aspect is %3").arg(afd_mode).arg(videoAspect).arg(displayAspect));
     
+         if ( AspectIs16_9(videoAspect) ) {
+             switch (afd_mode)
+             {
+                 case kAfd_Unset:
+                 case kAfd_Same:
+                 case kAfd_16_9:
+                 case kAfd_14_9:
+                 case kAfd_16_9_Sp_14_9:
+                 case kAfd_Sp_4_3:
+                         break;
+                 case kAfd_4_3:
+                     if (AspectIs16_9(displayAspect)) {
+                            dispwoff =  (dispwoff*3)/4;
+                            dispxoff += (dispwoff/6);
+                     }
+                     break;
+                 case kAfd_4_3_Sp_14_9:
+                     if (AspectIs16_9(displayAspect)) {
+                            disphoff  = (disphoff*4)/3;
+                            dispyoff -= (disphoff/6);
+                            dispwoff  = (dispwoff*3/4);
+                            dispxoff += (dispwoff/6);
+                     }
+                     break;
+             }
+         } else { // videoAspectIs4_3
+             switch (afd_mode)
+             {
+                 case kAfd_Unset:
+                 case kAfd_16_9:
+                 case kAfd_16_9_Sp_14_9:
+                     break;
+                 case kAfd_Same:
+                 case kAfd_Sp_4_3:
+                     if (AspectIs16_9(displayAspect)) {
+                            dispwoff  = (dispwoff*3)/4;
+                            dispxoff += (dispwoff/6);
+                     }
+                     break;
+                 case kAfd_4_3_Sp_14_9:
+                     // this will crop the top and bottom of the 
+                     // image, and still leave it pillarboxed.
+                     if (AspectIs16_9(displayAspect)) {
+                            // 7/8 is (9/16) * (14/9)
+                            dispyoff -= (disphoff*7)/8;
+                            disphoff  = (disphoff*9)/14;
+                     }
+                     break;
+             }
+         }
+    }
     if ((fabs(displayAspect - XJ_aspect) / displayAspect) > 0.1){
         if(letterbox == kLetterbox_Fill){
             if (displayAspect > XJ_aspect)
@@ -1181,3 +1296,10 @@
 */
 }
 
+bool VideoOutput::AspectIs16_9(float aspect) {
+				return (fabs(aspect - 1.777777) < 0.05);
+}
+
+bool VideoOutput::AspectIs4_3(float aspect) {
+				return (fabs(aspect - 1.333333) < 0.05);
+}
Index: libs/libmythtv/videooutbase.h
===================================================================
RCS file: /var/lib/mythcvs/mythtv/libs/libmythtv/videooutbase.h,v
retrieving revision 1.51
diff -a -u -b -B -r1.51 videooutbase.h
--- libs/libmythtv/videooutbase.h	26 May 2005 02:17:04 -0000	1.51
+++ libs/libmythtv/videooutbase.h	5 Jun 2005 15:08:52 -0000
@@ -105,9 +105,29 @@
     kLetterbox_16_9_Zoom,
     kLetterbox_16_9_Stretch,
     kLetterbox_Fill,
+    kLetterbox_Afd,
     kLetterbox_END
 };
 
+/* Active Format Description(AFD) is set in DVB Streams.
+ * By considering both the aspect ratio and the AFD it 
+ * is posible to determine how to present the image in the
+ * correct manner. 
+ * See http://www.dtg.org.uk/publications/books/afd.pdf
+ * for the gory details
+ */
+enum AfdMode {
+    kAfd_Unset        = 0,
+    kAfd_Same         = 8,
+    kAfd_4_3          = 9,
+    kAfd_16_9         = 10,
+    kAfd_14_9         = 11,
+    kAfd_4_3_Sp_14_9  = 13,
+    kAfd_16_9_Sp_14_9 = 14,
+    kAfd_Sp_4_3       = 15,
+    kAfd_END
+};
+
 enum FrameScanType {
     kScan_Ignore      = -1,
     kScan_Progressive =  0,
@@ -162,6 +182,8 @@
     int GetLetterbox(void) { return letterbox; }
     void ToggleLetterbox(int letterboxMode = kLetterbox_Toggle);
 
+    void SetAfdMode(int afd_mode) { this->afd_mode = afd_mode; };
+    
     // pass in null to use the pause frame, if it exists.
     virtual void ProcessFrame(VideoFrame *frame, OSD *osd,
                               FilterChain *filterList,
@@ -275,6 +297,9 @@
 
     void AspectSet(float aspect);
 
+    bool AspectIs16_9(float aspect);
+    bool AspectIs4_3(float aspect);
+
     int XJ_width, XJ_height;
     float XJ_aspect;
     float videoAspect;
@@ -298,6 +323,7 @@
     int brightness, contrast, colour, hue;
 
     int letterbox;
+    int afd_mode;
 
     int PIPLocation;
 
Index: programs/mythfrontend/globalsettings.cpp
===================================================================
RCS file: /var/lib/mythcvs/mythtv/programs/mythfrontend/globalsettings.cpp,v
retrieving revision 1.254
diff -a -u -b -B -r1.254 globalsettings.cpp
--- programs/mythfrontend/globalsettings.cpp	28 May 2005 00:48:30 -0000	1.254
+++ programs/mythfrontend/globalsettings.cpp	5 Jun 2005 15:08:53 -0000
@@ -1160,12 +1160,14 @@
     gc->addSelection(QObject::tr("16/9 Zoom"), "4");
     gc->addSelection(QObject::tr("16/9 Stretch"), "5");
     gc->addSelection(QObject::tr("Fill"), "6");
+    gc->addSelection(QObject::tr("AFD"), "7");
     gc->setHelpText(QObject::tr("This will override any aspect ratio in the "
                     "recorded stream, the same as pressing the W Key "
                     "during playback. "
 		    "Fill will \"fill\" the screen with the image clipping as required. "
 		    "Fill is useful when using 4:3 interlaced TV's for display."
-		    ));
+                    "AFD will use the active format descriptor from the stream "
+                    "to determine the appropriate display. "));
     return gc;
 }
 


More information about the mythtv-dev mailing list