Ticket #224: 0002-Improve-libdc1394-mode-and-rate-selection.patch

File 0002-Improve-libdc1394-mode-and-rate-selection.patch, 14.3 KB (added by marlam, 2 years ago)
  • libavdevice/libdc1394.c

    From 9ee92a2af87ce36199cf1d58004b57cb0b2fdb27 Mon Sep 17 00:00:00 2001
    From: Martin Lambers <marlam@marlam.de>
    Date: Tue, 10 May 2011 16:36:54 +0200
    Subject: [PATCH 2/2] Improve libdc1394 mode and rate selection.
    
    The supported video modes and frame rates are queried from the camera. This
    information is used for a best-effort approach to find a suitable mode/rate
    combination.
    ---
     libavdevice/libdc1394.c |  295 ++++++++++++++++++++++++++++++++++++-----------
     1 files changed, 225 insertions(+), 70 deletions(-)
    
    diff --git a/libavdevice/libdc1394.c b/libavdevice/libdc1394.c
    index 158db09..8b2eeba 100644
    a b  
    2424#include "config.h" 
    2525#include "libavformat/avformat.h" 
    2626 
     27#include <stdlib.h> 
     28#include <string.h> 
     29 
    2730#include <dc1394/dc1394.h> 
    2831 
    2932#undef free 
    typedef struct dc1394_data { 
    3841    AVPacket packet; 
    3942} dc1394_data; 
    4043 
    41 struct dc1394_frame_format { 
    42     int width; 
    43     int height; 
    44     enum PixelFormat pix_fmt; 
    45     int frame_size_id; 
    46 } dc1394_frame_formats[] = { 
    47     { 320, 240, PIX_FMT_UYVY422, DC1394_VIDEO_MODE_320x240_YUV422 }, 
    48     { 640, 480, PIX_FMT_UYYVYY411, DC1394_VIDEO_MODE_640x480_YUV411 }, 
    49     { 640, 480, PIX_FMT_UYVY422, DC1394_VIDEO_MODE_640x480_YUV422 }, 
    50     { 0, 0, 0, 0 } /* gotta be the last one */ 
     44/* The list of color codings that we support, sorted in descending preference. 
     45 * We assume big endian for the dc1394 16bit modes: libdc1394 never sets the 
     46 * flag little_endian in dc1394video_frame_t. */ 
     47struct dc1394_color_coding { 
     48    int pix_fmt; 
     49    uint32_t coding; 
     50} dc1394_color_codings[] = { 
     51    { PIX_FMT_UYVY422,   DC1394_COLOR_CODING_YUV422 }, 
     52    { PIX_FMT_UYYVYY411, DC1394_COLOR_CODING_YUV411 }, 
     53    { PIX_FMT_RGB24,     DC1394_COLOR_CODING_RGB8   }, 
     54    { PIX_FMT_GRAY8,     DC1394_COLOR_CODING_MONO8  }, 
     55    { PIX_FMT_RGB48BE,   DC1394_COLOR_CODING_RGB16  }, 
     56    { PIX_FMT_GRAY16BE,  DC1394_COLOR_CODING_MONO16 }, 
     57    { PIX_FMT_NONE, 0 } /* gotta be the last one */ 
    5158}; 
    5259 
    5360struct dc1394_frame_rate { 
    struct dc1394_frame_rate { 
    6572    { 0, 0 } /* gotta be the last one */ 
    6673}; 
    6774 
    68 static inline int dc1394_read_common(AVFormatContext *c, AVFormatParameters *ap, 
    69                                      struct dc1394_frame_format **select_fmt, struct dc1394_frame_rate **select_fps) 
     75/* Sort video modes according to descending preference. */ 
     76static int  dc1394_video_mode_cmp(const void *va, const void *vb) 
    7077{ 
    71     dc1394_data* dc1394 = c->priv_data; 
    72     AVStream* vst; 
    73     struct dc1394_frame_format *fmt; 
    74     struct dc1394_frame_rate *fps; 
    75     enum PixelFormat pix_fmt = ap->pix_fmt == PIX_FMT_NONE ? PIX_FMT_UYVY422 : ap->pix_fmt; /* defaults */ 
    76     int width                = !ap->width ? 320 : ap->width; 
    77     int height               = !ap->height ? 240 : ap->height; 
    78     int frame_rate           = !ap->time_base.num ? 30000 : av_rescale(1000, ap->time_base.den, ap->time_base.num); 
    79  
    80     for (fmt = dc1394_frame_formats; fmt->width; fmt++) 
    81          if (fmt->pix_fmt == pix_fmt && fmt->width == width && fmt->height == height) 
    82              break; 
    83  
    84     for (fps = dc1394_frame_rates; fps->frame_rate; fps++) 
    85          if (fps->frame_rate == frame_rate) 
    86              break; 
    87  
    88     if (!fps->frame_rate || !fmt->width) { 
    89         av_log(c, AV_LOG_ERROR, "Can't find matching camera format for %s, %dx%d@%d:1000fps\n", avcodec_get_pix_fmt_name(pix_fmt), 
    90                                                                                                 width, height, frame_rate); 
    91         goto out; 
     78    const dc1394video_mode_t *a = va; 
     79    const dc1394video_mode_t *b = vb; 
     80    const struct dc1394_color_coding *c; 
     81    uint32_t a_w, a_h, a_c; 
     82    uint32_t b_w, b_h, b_c; 
     83 
     84    dc1394_get_image_size_from_video_mode (NULL, *a, &a_w, &a_h); 
     85    dc1394_get_image_size_from_video_mode (NULL, *b, &b_w, &b_h); 
     86    if (a_w == b_w && a_h == b_h) { 
     87        dc1394_get_color_coding_from_video_mode (NULL, *a, &a_c); 
     88        dc1394_get_color_coding_from_video_mode (NULL, *b, &b_c); 
     89        for (c = dc1394_color_codings; c->pix_fmt != PIX_FMT_NONE; c++) { 
     90            if (a_c == c->coding && b_c != c->coding) 
     91                return -1; 
     92            else if (b_c == c->coding && a_c != c->coding) 
     93                return +1; 
     94        } 
     95        return 0; 
     96    } else { 
     97        return (a_w > b_w || (a_w == b_w && a_h > b_h)) ? -1 : +1; 
    9298    } 
    93  
    94     /* create a video stream */ 
    95     vst = av_new_stream(c, 0); 
    96     if (!vst) 
    97         goto out; 
    98     av_set_pts_info(vst, 64, 1, 1000); 
    99     vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; 
    100     vst->codec->codec_id = CODEC_ID_RAWVIDEO; 
    101     vst->codec->time_base.den = fps->frame_rate; 
    102     vst->codec->time_base.num = 1000; 
    103     vst->codec->width = fmt->width; 
    104     vst->codec->height = fmt->height; 
    105     vst->codec->pix_fmt = fmt->pix_fmt; 
    106  
    107     /* packet init */ 
    108     av_init_packet(&dc1394->packet); 
    109     dc1394->packet.size = avpicture_get_size(fmt->pix_fmt, fmt->width, fmt->height); 
    110     dc1394->packet.stream_index = vst->index; 
    111     dc1394->packet.flags |= AV_PKT_FLAG_KEY; 
    112  
    113     dc1394->current_frame = 0; 
    114     dc1394->fps = fps->frame_rate; 
    115  
    116     vst->codec->bit_rate = av_rescale(dc1394->packet.size * 8, fps->frame_rate, 1000); 
    117     *select_fps = fps; 
    118     *select_fmt = fmt; 
    119     return 0; 
    120 out: 
    121     return -1; 
    12299} 
    123100 
    124101static int dc1394_read_header(AVFormatContext *c, AVFormatParameters * ap) 
    125102{ 
    126103    dc1394_data* dc1394 = c->priv_data; 
     104    AVStream *vst; 
     105    const struct dc1394_color_coding *cc; 
     106    const struct dc1394_frame_rate *fr; 
     107    int final_width, final_height, final_pix_fmt, final_frame_rate; 
    127108    dc1394camera_list_t *list; 
     109    dc1394video_modes_t video_modes; 
     110    dc1394video_mode_t video_mode; 
     111    dc1394framerates_t frame_rates; 
     112    dc1394framerate_t frame_rate; 
     113    uint32_t req_width, req_height, req_color_coding, req_frame_rate; 
     114    uint32_t width, height, color_coding; 
    128115    int res, i; 
    129     struct dc1394_frame_format *fmt = NULL; 
    130     struct dc1394_frame_rate *fps = NULL; 
    131  
    132     if (dc1394_read_common(c,ap,&fmt,&fps) != 0) 
    133        return -1; 
    134116 
    135117    /* Now let us prep the hardware. */ 
    136118    dc1394->d = dc1394_new(); 
    static int dc1394_read_header(AVFormatContext *c, AVFormatParameters * ap) 
    149131    /* Freeing list of cameras */ 
    150132    dc1394_camera_free_list (list); 
    151133 
     134    /* Get the list of video modes supported by the camera. */ 
     135    res = dc1394_video_get_supported_modes (dc1394->camera, &video_modes); 
     136    if (res != DC1394_SUCCESS) { 
     137        av_log(c, AV_LOG_ERROR, "Could not get video formats.\n"); 
     138        goto out_camera; 
     139    } 
     140    /* Remove formats that we currently do not support as they would require 
     141     * much more work. For the remaining modes, the functions 
     142     * dc1394_get_image_size_from_video_mode and 
     143     * dc1394_get_color_coding_from_video_mode do not need to query the camera, 
     144     * and thus cannot fail. */ 
     145    for (i = 0; i < video_modes.num;) { 
     146        if (video_modes.modes[i] == DC1394_VIDEO_MODE_EXIF 
     147                || (video_modes.modes[i] >= DC1394_VIDEO_MODE_FORMAT7_MIN 
     148                    && video_modes.modes[i] <= DC1394_VIDEO_MODE_FORMAT7_MAX)) { 
     149            memmove(video_modes.modes + i, video_modes.modes + i + 1, 
     150                    (video_modes.num - i - 1) * sizeof(video_modes.modes[0])); 
     151            video_modes.num--; 
     152        } else { 
     153            i++; 
     154        } 
     155    } 
     156    /* Remove formats with color codings that we cannot handle. */ 
     157    for (i = 0; i < video_modes.num;) { 
     158        dc1394_get_color_coding_from_video_mode (NULL, 
     159                video_modes.modes[i], &color_coding); 
     160        for (cc = dc1394_color_codings; cc->pix_fmt != PIX_FMT_NONE; cc++) 
     161            if (cc->coding == color_coding) 
     162                break; 
     163        if (cc->pix_fmt == PIX_FMT_NONE) { 
     164            memmove(video_modes.modes + i, video_modes.modes + i + 1, 
     165                    (video_modes.num - i - 1) * sizeof(video_modes.modes[0])); 
     166            video_modes.num--; 
     167        } else { 
     168            i++; 
     169        } 
     170    } 
     171    if (video_modes.num == 0) { 
     172        av_log(c, AV_LOG_ERROR, "No supported video modes available.\n"); 
     173        goto out_camera; 
     174    } 
     175    /* Sort the video modes according to preference. */ 
     176    qsort(video_modes.modes, video_modes.num, sizeof(video_modes.modes[0]), 
     177            dc1394_video_mode_cmp); 
     178 
     179    /* Frame size: if not specified, use the largest that is available */ 
     180    if (ap->width && ap->height) { 
     181        req_width = ap->width; 
     182        req_height = ap->height; 
     183    } else { 
     184        dc1394_get_image_size_from_video_mode (NULL, 
     185                video_modes.modes[0], &req_width, &req_height); 
     186    } 
     187    /* Pixel format: as a fallback, use pixel format of the preferred mode */ 
     188    if (ap->pix_fmt == PIX_FMT_NONE) { 
     189        dc1394_get_color_coding_from_video_mode (NULL, 
     190                video_modes.modes[0], &req_color_coding); 
     191    } else { 
     192        for (cc = dc1394_color_codings; cc->pix_fmt != PIX_FMT_NONE; cc++) { 
     193            if (cc->pix_fmt == ap->pix_fmt) { 
     194                req_color_coding = cc->coding; 
     195                break; 
     196            } 
     197        } 
     198        if (cc->pix_fmt == PIX_FMT_NONE) { 
     199            av_log(c, AV_LOG_WARNING, 
     200                    "Requested pixel format is not supported, using fallback.\n"); 
     201            dc1394_get_color_coding_from_video_mode (NULL, 
     202                    video_modes.modes[0], &req_color_coding); 
     203        } 
     204    } 
     205 
     206    /* Now look for a matching video mode. */ 
     207    for (i = 0; i < video_modes.num; i++) { 
     208        dc1394_get_image_size_from_video_mode (NULL, 
     209                video_modes.modes[i], &width, &height); 
     210        dc1394_get_color_coding_from_video_mode (NULL, 
     211                video_modes.modes[i], &color_coding); 
     212        if (width == req_width && height == req_height 
     213                && color_coding == req_color_coding) { 
     214            break; 
     215        } 
     216    } 
     217    /* Fall back to the preferred mode. */ 
     218    if (i == video_modes.num) { 
     219        i = 0; 
     220        av_log(c, AV_LOG_WARNING, 
     221                "Requested frame size / pixel format is not available, using fallback.\n"); 
     222    } 
     223    video_mode = video_modes.modes[i]; 
     224    /* Get the final size and pixel format. */ 
     225    dc1394_get_image_size_from_video_mode (NULL, video_mode, &width, &height); 
     226    final_width = width; 
     227    final_height = height; 
     228    dc1394_get_color_coding_from_video_mode (NULL, video_mode, &color_coding); 
     229    for (cc = dc1394_color_codings; cc->pix_fmt != PIX_FMT_NONE; cc++) { 
     230        if (cc->coding == color_coding) { 
     231            final_pix_fmt = cc->pix_fmt; 
     232            break; 
     233        } 
     234    } 
     235 
     236    /* Get the list of frame rates supported by the camera for the selected 
     237     * video mode. This list is sorted in ascending order according to libdc1394 
     238     * example programs. */ 
     239    res = dc1394_video_get_supported_framerates (dc1394->camera, video_mode, 
     240            &frame_rates); 
     241    if (res != DC1394_SUCCESS || frame_rates.num == 0) { 
     242        av_log(c, AV_LOG_ERROR, "Cannot get frame rates for video mode.\n"); 
     243        goto out_camera; 
     244    } 
     245    if (!ap->time_base.num) { 
     246        /* If not specified, use the highest rate available. */ 
     247        frame_rate = frame_rates.framerates[frame_rates.num - 1]; 
     248    } else { 
     249        /* See if the requested frame rate is supported. */ 
     250        req_frame_rate = av_rescale(1000, ap->time_base.den, ap->time_base.num); 
     251        for (fr = dc1394_frame_rates; fr->frame_rate; fr++) { 
     252            if (fr->frame_rate == req_frame_rate) { 
     253                frame_rate = fr->frame_rate_id; 
     254                break; 
     255            } 
     256        } 
     257        if (!fr->frame_rate) { 
     258            av_log(c, AV_LOG_WARNING, 
     259                    "Requested frame rate is not supported, using fallback.\n"); 
     260            frame_rate = frame_rates.framerates[frame_rates.num - 1]; 
     261        } 
     262        /* Find the requested frame rate in the supported frame rates. */ 
     263        for (fr = dc1394_frame_rates; fr->frame_rate; fr++) { 
     264            if (fr->frame_rate_id == frame_rate) { 
     265                break; 
     266            } 
     267        } 
     268        if (!fr->frame_rate) { 
     269            /* Fall back to the best rate that was listed as supported. */ 
     270            av_log(c, AV_LOG_WARNING, 
     271                    "Requested frame rate is not available, using fallback.\n"); 
     272            frame_rate = frame_rates.framerates[frame_rates.num - 1]; 
     273        } 
     274    } 
     275    /* Get the final frame rate */ 
     276    for (fr = dc1394_frame_rates; fr->frame_rate; fr++) { 
     277        if (fr->frame_rate_id == frame_rate) { 
     278            final_frame_rate = fr->frame_rate; 
     279            break; 
     280        } 
     281    } 
     282 
     283    /* create a video stream */ 
     284    vst = av_new_stream(c, 0); 
     285    if (!vst) 
     286        goto out_camera; 
     287    av_set_pts_info(vst, 64, 1, 1000); 
     288    vst->codec->codec_type = AVMEDIA_TYPE_VIDEO; 
     289    vst->codec->codec_id = CODEC_ID_RAWVIDEO; 
     290    vst->codec->time_base.den = final_frame_rate; 
     291    vst->codec->time_base.num = 1000; 
     292    vst->codec->width = final_width; 
     293    vst->codec->height = final_height; 
     294    vst->codec->pix_fmt = final_pix_fmt; 
     295 
     296    /* packet init */ 
     297    av_init_packet(&dc1394->packet); 
     298    dc1394->packet.size = avpicture_get_size(final_pix_fmt, final_width, final_height); 
     299    dc1394->packet.stream_index = vst->index; 
     300    dc1394->packet.flags |= AV_PKT_FLAG_KEY; 
     301 
     302    dc1394->current_frame = 0; 
     303    dc1394->fps = final_frame_rate; 
     304 
     305    vst->codec->bit_rate = av_rescale(dc1394->packet.size * 8, final_frame_rate, 1000); 
     306 
    152307    /* Select MAX Speed possible from the cam */ 
    153308    if (dc1394->camera->bmode_capable>0) { 
    154309       dc1394_video_set_operation_mode(dc1394->camera, DC1394_OPERATION_MODE_1394B); 
    static int dc1394_read_header(AVFormatContext *c, AVFormatParameters * ap) 
    165320        goto out_camera; 
    166321    } 
    167322 
    168     if (dc1394_video_set_mode(dc1394->camera, fmt->frame_size_id) != DC1394_SUCCESS) { 
     323    if (dc1394_video_set_mode(dc1394->camera, video_mode) != DC1394_SUCCESS) { 
    169324        av_log(c, AV_LOG_ERROR, "Couldn't set video format\n"); 
    170325        goto out_camera; 
    171326    } 
    172327 
    173     if (dc1394_video_set_framerate(dc1394->camera,fps->frame_rate_id) != DC1394_SUCCESS) { 
    174         av_log(c, AV_LOG_ERROR, "Couldn't set framerate %d \n",fps->frame_rate); 
     328    if (dc1394_video_set_framerate(dc1394->camera, frame_rate) != DC1394_SUCCESS) { 
     329        av_log(c, AV_LOG_ERROR, "Could not set framerate %d.\n", final_frame_rate); 
    175330        goto out_camera; 
    176331    } 
    177332    if (dc1394_capture_setup(dc1394->camera, 10, DC1394_CAPTURE_FLAGS_DEFAULT)!=DC1394_SUCCESS) {