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, 8 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) {