~ubuntu-branches/ubuntu/vivid/transcode/vivid

« back to all changes in this revision

Viewing changes to import/import_im.c

  • Committer: Bazaar Package Importer
  • Author(s): Iain Lane
  • Date: 2009-01-08 22:33:52 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090108223352-xzwpx7r22tzm7grp
Tags: 2:1.0.7-0ubuntu1
* New upstream release. (LP: #311202)
* debian/watch: Update 
* debian/patches/01_configure.dpatch, 03_imagemagick.dpatch,
  05_filter.c.dpatch, 06_libavcodec.dpatch: Dropped, applied upstream 
* debian/control: libmagickwand-dev, build-depend on new Imagemagick dev
  package.
* debian/patches/01_configure_magickcore.dpatch, 98_autoreconf.dpatch:
  Link against -lMagickCore instead of -lMagick, upstream changed name.
* debian/control: Bump s-v to 3.8.0, add homepage field 
* debian/control: Recommend mawk to run provided scripts 
* debian/control: linux -> Linux spelling fix (Lintian) 
* debian/control, debian/rules: Strip rpath from
  /usr/lib/transcode/export_fame.so 
* debian/transcode-doc.doc-base, debian/copyright, debian/changelog: Fix
  encoding.
* debian/transcode-doc.doc-base: Use valid section.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 *  import_im.c
3
3
 *
4
 
 *  Copyright (C) Thomas �streich - June 2001
 
4
 *  Copyright (C) Thomas Oestreich - June 2001
 
5
 *  port to MagickWand API:
 
6
 *  Copyright (C) Francesco Romani - July 2007
5
7
 *
6
8
 *  This file is part of transcode, a video stream processing tool
7
 
 *      
 
9
 *
8
10
 *  transcode is free software; you can redistribute it and/or modify
9
11
 *  it under the terms of the GNU General Public License as published by
10
12
 *  the Free Software Foundation; either version 2, or (at your option)
11
13
 *  any later version.
12
 
 *   
 
14
 *
13
15
 *  transcode is distributed in the hope that it will be useful,
14
16
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15
17
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
18
 *  GNU General Public License for more details.
17
 
 *   
 
19
 *
18
20
 *  You should have received a copy of the GNU General Public License
19
21
 *  along with GNU Make; see the file COPYING.  If not, write to
20
 
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 
22
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
23
 *
22
24
 */
23
25
 
24
26
#define MOD_NAME    "import_im.so"
25
 
#define MOD_VERSION "v0.0.4 (2003-09-15)"
 
27
#define MOD_VERSION "v0.1.1 (2007-08-08)"
26
28
#define MOD_CODEC   "(video) RGB"
27
29
 
 
30
#ifdef HAVE_CONFIG_H
 
31
# include "config.h"
 
32
#endif
 
33
 
 
34
/* Note: because of ImageMagick bogosity, this must be included first, so
 
35
 * we can undefine the PACKAGE_* symbols it splats into our namespace */
 
36
#ifdef HAVE_BROKEN_WAND
 
37
#include <wand/magick-wand.h>
 
38
#else /* we have a SANE wand header */
 
39
#include <wand/MagickWand.h>
 
40
#endif /* HAVE_BROKEN_WAND */
 
41
 
 
42
#undef PACKAGE_BUGREPORT
 
43
#undef PACKAGE_NAME
 
44
#undef PACKAGE_STRING
 
45
#undef PACKAGE_TARNAME
 
46
#undef PACKAGE_VERSION
 
47
 
28
48
#include "transcode.h"
29
49
 
 
50
#include <stdlib.h>
 
51
#include <stdio.h>
 
52
 
30
53
static int verbose_flag = TC_QUIET;
31
 
static int capability_flag = TC_CAP_RGB | TC_CAP_VID;
 
54
static int capability_flag = TC_CAP_RGB|TC_CAP_VID;
32
55
 
33
56
#define MOD_PRE im
34
57
#include "import_def.h"
37
60
#include <sys/types.h>
38
61
#include <regex.h>
39
62
 
40
 
/* transcode defines these as well as ImageMagick. */
41
 
#undef PACKAGE_NAME
42
 
#undef PACKAGE_TARNAME
43
 
#undef PACKAGE_VERSION
44
 
#undef PACKAGE_STRING
45
 
 
46
 
#include <magick/api.h>
47
 
 
48
 
 
49
 
extern int errno;
50
 
 
51
 
char
52
 
    *head = NULL,
53
 
    *tail = NULL;
54
 
 
55
 
int
56
 
    first_frame = 0,
57
 
    last_frame = 0,
58
 
    current_frame = 0,
59
 
    pad = 0;
60
 
 
61
 
  
62
 
/* ------------------------------------------------------------ 
 
63
 
 
64
static char *head = NULL, *tail = NULL;
 
65
static int first_frame = 0, current_frame = 0, pad = 0;
 
66
static int width = 0, height = 0;
 
67
static MagickWand *wand = NULL;
 
68
 
 
69
static int TCHandleMagickError(MagickWand *wand)
 
70
{
 
71
    ExceptionType severity;
 
72
    const char *description = MagickGetException(wand, &severity);
 
73
 
 
74
    fprintf(stderr, "[%s] %s\n", MOD_NAME, description);
 
75
 
 
76
    MagickRelinquishMemory((void*)description);
 
77
    return TC_IMPORT_ERROR;
 
78
}
 
79
 
 
80
 
 
81
/* ------------------------------------------------------------
63
82
 *
64
83
 * open stream
65
84
 *
66
85
 * ------------------------------------------------------------*/
67
86
 
 
87
 
 
88
/* I suspect we have a lot of potential memleaks in here -- FRomani */
68
89
MOD_open
69
90
{
70
 
  int
71
 
    result,
72
 
    string_length;
73
 
 
74
 
  long
75
 
    sret;
76
 
 
77
 
  char
78
 
      *regex,
79
 
      *frame,
80
 
      *filename;
81
 
 
82
 
  char
83
 
      printfspec[20];
84
 
 
85
 
  regex_t
86
 
        preg;
87
 
 
88
 
  regmatch_t
89
 
      pmatch[4];
90
 
 
91
 
  if(param->flag == TC_AUDIO) {
92
 
      return(TC_IMPORT_OK);
93
 
  }
94
 
 
95
 
  if(param->flag == TC_VIDEO) {
96
 
 
97
 
    param->fd = NULL;
98
 
 
99
 
    // get the frame name and range
100
 
    regex = "\\(.\\+[-._]\\)\\?\\([0-9]\\+\\)\\([-._].\\+\\)\\?";
101
 
    result = regcomp(&preg, regex, 0);
102
 
    if (result) {
103
 
        perror("ERROR:  Regex compile failed.\n");
104
 
        return(TC_IMPORT_ERROR);
105
 
    }
106
 
 
107
 
    result = regexec(&preg, vob->video_in_file, 4, pmatch, 0);
108
 
    if (result) {
109
 
        fprintf(stderr, "Regex match failed: no image sequence\n");
110
 
        string_length = strlen(vob->video_in_file) + 1;
111
 
        if ((head = malloc(string_length)) == NULL) {
112
 
            perror("filename head");
113
 
            return(TC_IMPORT_ERROR);
114
 
        }
115
 
        strlcpy(head, vob->video_in_file, string_length);
116
 
        tail = malloc(1);
117
 
        tail[0] = 0;
118
 
        first_frame = -1;
119
 
        last_frame = 0x7fffffff;
120
 
    }
121
 
    else {
122
 
        // split the name into head, frame number, and tail
123
 
        string_length = pmatch[1].rm_eo - pmatch[1].rm_so + 1;
124
 
        if ((head = malloc(string_length)) == NULL) {
125
 
            perror("filename head");
126
 
            return(TC_IMPORT_ERROR);
127
 
        }
128
 
        strlcpy(head, vob->video_in_file, string_length);
129
 
 
130
 
        string_length = pmatch[2].rm_eo - pmatch[2].rm_so + 1;
131
 
        if ((frame = malloc(string_length)) == NULL) {
132
 
            perror("filename frame");
133
 
            return(TC_IMPORT_ERROR);
134
 
        }
135
 
        strlcpy(frame, vob->video_in_file + pmatch[2].rm_so, string_length);
136
 
 
137
 
        // If the frame number is padded with zeros, record how many digits 
138
 
        // are actually being used.
139
 
        if (frame[0] == '0') {
140
 
            pad = pmatch[2].rm_eo - pmatch[2].rm_so;
141
 
        }
142
 
        first_frame = atoi(frame);
143
 
 
144
 
        string_length = pmatch[3].rm_eo - pmatch[3].rm_so + 1;
145
 
        if ((tail = malloc(string_length)) == NULL) {
146
 
            perror("filename tail");
147
 
            return(TC_IMPORT_ERROR);
148
 
        }
149
 
        strlcpy(tail, vob->video_in_file + pmatch[3].rm_so, string_length);
150
 
 
151
 
        // find the last frame by trying to open files
152
 
        last_frame = first_frame; 
153
 
        filename = malloc(strlen(head) + pad + strlen(tail) + 1);
154
 
        /* why remalloc frame? */
155
 
        /* frame = malloc(pad + 1); */
156
 
        do {
157
 
            last_frame++;
158
 
            snprintf(printfspec, sizeof(printfspec), "%%s%%0%dd%%s", pad);
159
 
            string_length = strlen(head) + pad + strlen(tail) + 1;
160
 
            sret = snprintf(filename, string_length, printfspec, head,
161
 
                                                      last_frame, tail);
162
 
            if (tc_test_string(__FILE__, __LINE__, string_length, sret, errno))
163
 
              return(TC_IMPORT_ERROR);
164
 
        } while (close(open(filename, O_RDONLY)) != -1); 
165
 
        last_frame--;
166
 
        free(filename);
167
 
        free(frame);
168
 
    }
169
 
 
170
 
    current_frame = first_frame;
171
 
 
172
 
    // initialize ImageMagick
173
 
    InitializeMagick("");
174
 
 
175
 
    return(TC_IMPORT_OK);
176
 
  }
177
 
 
178
 
  return(TC_IMPORT_ERROR);
 
91
    int result, slen = 0;
 
92
    char *regex = NULL, *frame = NULL;
 
93
    regex_t preg;
 
94
    regmatch_t pmatch[4];
 
95
 
 
96
    if (param->flag == TC_AUDIO) {
 
97
        return TC_IMPORT_OK;
 
98
    }
 
99
 
 
100
    if (param->flag == TC_VIDEO) {
 
101
        param->fd = NULL;
 
102
 
 
103
        // get the frame name and range
 
104
        regex = "\\([^0-9]\\+[-._]\\?\\)\\?\\([0-9]\\+\\)\\([-._].\\+\\)\\?";
 
105
        result = regcomp(&preg, regex, 0);
 
106
        if (result) {
 
107
            perror("regex compile");
 
108
            return TC_IMPORT_ERROR;
 
109
        }
 
110
 
 
111
        result = regexec(&preg, vob->video_in_file, 4, pmatch, 0);
 
112
        if (result) {
 
113
            fprintf(stderr, "[%s] regex match failed: no image sequence\n", MOD_NAME);
 
114
            slen = strlen(vob->video_in_file) + 1;
 
115
            head = malloc(slen);
 
116
            if (head == NULL) {
 
117
                perror("filename head");
 
118
                return TC_IMPORT_ERROR;
 
119
            }
 
120
            strlcpy(head, vob->video_in_file, slen);
 
121
            tail = malloc(1); /* URGH -- FRomani */
 
122
            tail[0] = 0;
 
123
            first_frame = -1;
 
124
        } else {
 
125
            // split the name into head, frame number, and tail
 
126
            slen = pmatch[1].rm_eo - pmatch[1].rm_so + 1;
 
127
            head = malloc(slen);
 
128
            if (head == NULL) {
 
129
                perror("filename head");
 
130
                return TC_IMPORT_ERROR;
 
131
            }
 
132
            strlcpy(head, vob->video_in_file, slen);
 
133
 
 
134
            slen = pmatch[2].rm_eo - pmatch[2].rm_so + 1;
 
135
            frame = malloc(slen);
 
136
            if (frame == NULL) {
 
137
                perror("filename frame");
 
138
                return TC_IMPORT_ERROR;
 
139
            }
 
140
            strlcpy(frame, vob->video_in_file + pmatch[2].rm_so, slen);
 
141
 
 
142
            // If the frame number is padded with zeros, record how many digits
 
143
            // are actually being used.
 
144
            if (frame[0] == '0') {
 
145
                pad = pmatch[2].rm_eo - pmatch[2].rm_so;
 
146
            }
 
147
            first_frame = atoi(frame);
 
148
 
 
149
            slen = pmatch[3].rm_eo - pmatch[3].rm_so + 1;
 
150
            tail = malloc(slen);
 
151
            if (tail == NULL) {
 
152
                perror("filename tail");
 
153
                return TC_IMPORT_ERROR;
 
154
            }
 
155
            strlcpy(tail, vob->video_in_file + pmatch[3].rm_so, slen);
 
156
 
 
157
            free(frame);
 
158
        }
 
159
 
 
160
        current_frame = first_frame;
 
161
 
 
162
        width = vob->im_v_width;
 
163
        height = vob->im_v_height;
 
164
 
 
165
        MagickWandGenesis();
 
166
        wand = NewMagickWand();
 
167
 
 
168
        if (wand == NULL) {
 
169
            fprintf(stderr, "[%s] cannot create magick wand\n", MOD_NAME);
 
170
            return TC_IMPORT_ERROR;
 
171
        }
 
172
 
 
173
        return TC_IMPORT_OK;
 
174
    }
 
175
 
 
176
    return TC_IMPORT_ERROR;
179
177
}
180
178
 
181
179
 
182
 
/* ------------------------------------------------------------ 
 
180
/* ------------------------------------------------------------
183
181
 *
184
182
 * decode  stream
185
183
 *
186
184
 * ------------------------------------------------------------*/
187
185
 
188
 
MOD_decode {
189
 
 
190
 
    ExceptionInfo
191
 
        exception_info;
192
 
 
193
 
    ImageInfo
194
 
        *image_info;
195
 
 
196
 
    Image
197
 
        *image;
198
 
 
199
 
    PixelPacket
200
 
        *pixel_packet;
201
 
 
202
 
    char
203
 
        *filename = NULL,
204
 
        *frame = NULL,
205
 
        *framespec = NULL;
206
 
 
207
 
    int
208
 
        column,
209
 
        row,
210
 
        string_length;
211
 
 
212
 
 
213
 
    if (current_frame > last_frame)
214
 
        return(TC_IMPORT_ERROR);
215
 
 
216
 
    // build the filename for the current frame
217
 
    string_length = strlen(head) + pad + strlen(tail) + 1;
218
 
    filename = malloc(string_length);
219
 
    if (pad) {
220
 
        frame = malloc(pad+1);
221
 
        framespec = malloc(10);
222
 
        snprintf(framespec, 10, "%%0%dd", pad);
223
 
        snprintf(frame, pad+1, framespec, current_frame);
224
 
        free(framespec);
225
 
        frame[pad] = '\0';
226
 
    }
227
 
    else if (first_frame >= 0) {
228
 
        frame = malloc(10);
229
 
        snprintf(frame, 10, "%d", current_frame);
230
 
    }
231
 
    strlcpy(filename, head, string_length);
232
 
    if (frame != NULL) {
233
 
        strlcat(filename, frame, string_length);
234
 
        free(frame);
235
 
        frame = NULL;
236
 
    }
237
 
    strlcat(filename, tail, string_length);
238
 
 
239
 
    // Have ImageMagick open the file and read in the image data.
240
 
    GetExceptionInfo(&exception_info);
241
 
    image_info=CloneImageInfo((ImageInfo *) NULL);
242
 
    (void) strlcpy(image_info->filename, filename, MaxTextExtent);
243
 
    image=ReadImage(image_info,&exception_info);
244
 
    if (image == (Image *) NULL) {
245
 
        MagickError(exception_info.severity,
246
 
                    exception_info.reason,
247
 
                    exception_info.description);
248
 
        // skip
249
 
        return (TC_IMPORT_ERROR);
250
 
    }
251
 
 
252
 
    /*
253
 
     * Copy the pixels into a buffer in RGB order
254
 
     */
255
 
    pixel_packet = GetImagePixels(image, 0, 0, image->columns, image->rows);
256
 
    for (row = 0; row < image->rows; row++) {
257
 
        for (column = 0; column < image->columns; column++) {
258
 
          /*
259
 
           * The bit-shift 8 in the following lines is to convert 
260
 
           * 16-bit-per-channel images that may be read by ImageMagick 
261
 
           * into the 8-bit-per-channel images that transcode uses.
262
 
           * The bit-shift is still valid for 8-bit-per-channel images 
263
 
           * because when ImageMagick handles 8-bit images it still uses 
264
 
           * unsigned shorts, but stores the same 8-bit value in both 
265
 
           * the low and high byte.
266
 
           */
267
 
          param->buffer[(row * image->columns + column) * 3 + 0] =
268
 
               (char) (pixel_packet[(image->rows - row - 1) * image->columns +
269
 
                                                            column].blue >> 8);
270
 
          param->buffer[(row * image->columns + column) * 3 + 1] =
271
 
               (char) (pixel_packet[(image->rows - row - 1) * image->columns +
272
 
                                                           column].green >> 8);
273
 
          param->buffer[(row * image->columns + column) * 3 + 2] =
274
 
               (char) (pixel_packet[(image->rows - row - 1) * image->columns +
275
 
                                                             column].red >> 8);
276
 
        }
277
 
    }
278
 
 
279
 
    if (current_frame == first_frame)
 
186
MOD_decode
 
187
{
 
188
    char *filename = NULL, *frame = NULL;
 
189
    int slen;
 
190
    MagickBooleanType status;
 
191
 
 
192
    if (param->flag == TC_AUDIO) {
 
193
        return TC_IMPORT_OK;
 
194
    }
 
195
 
 
196
    if (param->flag == TC_VIDEO) {
 
197
        // build the filename for the current frame
 
198
        slen = strlen(head) + pad + strlen(tail) + 1;
 
199
        filename = malloc(slen);
 
200
        if (pad) {
 
201
            char framespec[10];
 
202
            frame = malloc(pad+1);
 
203
            snprintf(framespec, 10, "%%0%dd", pad);
 
204
            snprintf(frame, pad+1, framespec, current_frame);
 
205
            frame[pad] = '\0';
 
206
        } else if (first_frame >= 0) {
 
207
            frame = malloc(10);
 
208
            snprintf(frame, 10, "%d", current_frame);
 
209
        }
 
210
        strlcpy(filename, head, slen);
 
211
        if (frame != NULL) {
 
212
            strlcat(filename, frame, slen);
 
213
            free(frame);
 
214
            frame = NULL;
 
215
        }
 
216
        strlcat(filename, tail, slen);
 
217
 
 
218
        ClearMagickWand(wand);
 
219
        /* 
 
220
         * This avoids IM to buffer all read images.
 
221
         * I'm quite sure that this can be done in a smarter way,
 
222
         * but I haven't yet figured out how. -- FRomani
 
223
         */
 
224
 
 
225
        status = MagickReadImage(wand, filename);
 
226
        if (status == MagickFalse) {
 
227
            /* let's assume that image sequence ends here */
 
228
            return TC_IMPORT_ERROR;
 
229
        }
 
230
 
 
231
        MagickSetLastIterator(wand);
 
232
 
 
233
        status =  MagickGetImagePixels(wand,
 
234
                                       0, 0, width, height,
 
235
                                       "RGB", CharPixel,
 
236
                                       param->buffer);
 
237
        /* param->size already set correctly by caller */
 
238
        if (status == MagickFalse) {
 
239
            return TCHandleMagickError(wand);
 
240
        }
 
241
 
280
242
        param->attributes |= TC_FRAME_IS_KEYFRAME;
281
243
 
282
 
    current_frame++;
283
 
 
284
 
    // How do we do this?  The next line is not right (segfaults)
285
 
    // I can't find a DestroyPixelPacket() method.
286
 
    //free(pixel_packet);
287
 
    DestroyImage(image);
288
 
    DestroyImageInfo(image_info);
289
 
    DestroyExceptionInfo(&exception_info);
290
 
    free(filename);
291
 
 
292
 
    return(TC_IMPORT_OK);
 
244
        current_frame++;
 
245
    
 
246
        free(filename);
 
247
 
 
248
        return TC_IMPORT_OK;
 
249
    }
 
250
    return TC_IMPORT_ERROR;
293
251
}
294
252
 
295
 
/* ------------------------------------------------------------ 
 
253
/* ------------------------------------------------------------
296
254
 *
297
255
 * close stream
298
256
 *
299
257
 * ------------------------------------------------------------*/
300
258
 
301
259
MOD_close
302
 
{  
303
 
  if (param->fd != NULL) pclose(param->fd);
304
 
  if (head != NULL) free(head);
305
 
  if (tail != NULL) free(tail);
306
 
 
307
 
  DestroyMagick();
308
 
 
309
 
  return(TC_IMPORT_OK);
 
260
{
 
261
    if (param->flag == TC_AUDIO) {
 
262
        return TC_IMPORT_OK;
 
263
    }
 
264
 
 
265
    if (param->flag == TC_VIDEO) {
 
266
        if (param->fd != NULL)
 
267
            pclose(param->fd);
 
268
        if (head != NULL)
 
269
            free(head);
 
270
        if (tail != NULL)
 
271
            free(tail);
 
272
 
 
273
        if (wand != NULL) {
 
274
            DestroyMagickWand(wand);
 
275
            MagickWandTerminus();
 
276
            wand = NULL;
 
277
        }
 
278
        return TC_IMPORT_OK;
 
279
    }
 
280
    return TC_IMPORT_ERROR;
310
281
}
311
282
 
 
283
/*************************************************************************/
312
284
 
 
285
/*
 
286
 * Local variables:
 
287
 *   c-file-style: "stroustrup"
 
288
 *   c-file-offsets: ((case-label . *) (statement-case-intro . *))
 
289
 *   indent-tabs-mode: nil
 
290
 * End:
 
291
 *
 
292
 * vim: expandtab shiftwidth=4:
 
293
 */