Revision 1e69ae95

View differences:

capture/Makefile
1
#
2
#  There exist several targets which are by default empty and which can be 
3
#  used for execution of your targets. These targets are usually executed 
4
#  before and after some main targets. They are: 
5
#
6
#     .build-pre:              called before 'build' target
7
#     .build-post:             called after 'build' target
8
#     .clean-pre:              called before 'clean' target
9
#     .clean-post:             called after 'clean' target
10
#     .clobber-pre:            called before 'clobber' target
11
#     .clobber-post:           called after 'clobber' target
12
#     .all-pre:                called before 'all' target
13
#     .all-post:               called after 'all' target
14
#     .help-pre:               called before 'help' target
15
#     .help-post:              called after 'help' target
16
#
17
#  Targets beginning with '.' are not intended to be called on their own.
18
#
19
#  Main targets can be executed directly, and they are:
20
#  
21
#     build                    build a specific configuration
22
#     clean                    remove built files from a configuration
23
#     clobber                  remove all built files
24
#     all                      build all configurations
25
#     help                     print help mesage
26
#  
27
#  Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
28
#  .help-impl are implemented in nbproject/makefile-impl.mk.
29
#
30
#  Available make variables:
31
#
32
#     CND_BASEDIR                base directory for relative paths
33
#     CND_DISTDIR                default top distribution directory (build artifacts)
34
#     CND_BUILDDIR               default top build directory (object files, ...)
35
#     CONF                       name of current configuration
36
#     CND_PLATFORM_${CONF}       platform name (current configuration)
37
#     CND_ARTIFACT_DIR_${CONF}   directory of build artifact (current configuration)
38
#     CND_ARTIFACT_NAME_${CONF}  name of build artifact (current configuration)
39
#     CND_ARTIFACT_PATH_${CONF}  path to build artifact (current configuration)
40
#     CND_PACKAGE_DIR_${CONF}    directory of package (current configuration)
41
#     CND_PACKAGE_NAME_${CONF}   name of package (current configuration)
42
#     CND_PACKAGE_PATH_${CONF}   path to package (current configuration)
43
#
44
# NOCDDL
45

  
46

  
47
# Environment 
48
MKDIR=mkdir
49
CP=cp
50
CCADMIN=CCadmin
51
RANLIB=ranlib
52

  
53

  
54
# build
55
build: .build-post
56

  
57
.build-pre:
58
# Add your pre 'build' code here...
59

  
60
.build-post: .build-impl
61
# Add your post 'build' code here...
62

  
63

  
64
# clean
65
clean: .clean-post
66

  
67
.clean-pre:
68
# Add your pre 'clean' code here...
69

  
70
.clean-post: .clean-impl
71
# Add your post 'clean' code here...
72

  
73

  
74
# clobber
75
clobber: .clobber-post
76

  
77
.clobber-pre:
78
# Add your pre 'clobber' code here...
79

  
80
.clobber-post: .clobber-impl
81
# Add your post 'clobber' code here...
82

  
83

  
84
# all
85
all: .all-post
86

  
87
.all-pre:
88
# Add your pre 'all' code here...
89

  
90
.all-post: .all-impl
91
# Add your post 'all' code here...
92

  
93

  
94
# help
95
help: .help-post
96

  
97
.help-pre:
98
# Add your pre 'help' code here...
99

  
100
.help-post: .help-impl
101
# Add your post 'help' code here...
102

  
103

  
104

  
105
# include project implementation makefile
106
include nbproject/Makefile-impl.mk
107

  
108
# include project make variables
109
include nbproject/Makefile-variables.mk
capture/audio.c
1
#include "audio.h"
2
#include "capture.h"
3

  
4
int init_audio(char* audio_dev_name)
5
{
6
    /* Open PCM device for recording (capture). */
7
    if ((err = snd_pcm_open (&capture_handle, audio_dev_name, SND_PCM_STREAM_CAPTURE, 0)) < 0)
8
    {
9
        fprintf (stderr, "cannot open audio device %s (%s)\n", audio_dev_name, snd_strerror (err));
10
        return err;
11
    }
12
    /* Allocate a hardware parameters object. */
13
    snd_pcm_hw_params_alloca(&hw_params);
14

  
15
    /* Fill it in with default values. */
16
    snd_pcm_hw_params_any(capture_handle, hw_params);
17

  
18
    /* Set the desired hardware parameters. */
19

  
20
    /* Interleaved mode */
21
    snd_pcm_hw_params_set_access(capture_handle, hw_params, AUDIO_INTERLEAVED);
22

  
23
    /* Signed 16-bit little-endian format */
24
    snd_pcm_hw_params_set_format(capture_handle, hw_params, AUDIO_FORMAT);
25

  
26
    /* Two channels (stereo) */
27
    snd_pcm_hw_params_set_channels(capture_handle, hw_params, AUDIO_CHANNELS);
28

  
29
    /* bits/second sampling rate */
30
    int val = AUDIO_SAMPLE_RATE;
31
    int dir;
32
    snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &val, &dir);
33

  
34
    /* Set period size to AUDIO_PERIOD frames. */
35
    frames = AUDIO_PERIOD;
36
    snd_pcm_hw_params_set_period_size_near(capture_handle, hw_params, &frames, &dir);
37

  
38
    /* Write the parameters to the driver */
39
    err = snd_pcm_hw_params(capture_handle, hw_params);
40
    if (err < 0) {
41
        fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(err));
42
        return err;
43
    }
44

  
45
    /* Use a buffer large enough to hold one period */
46
    snd_pcm_hw_params_get_period_size(hw_params, &frames, &dir);
47
    buffer_size = frames * 4; /* 2 bytes/sample, 2 channels */
48
    audio_buffer = (char *) malloc(buffer_size);
49

  
50
    snd_pcm_hw_params_get_period_time(hw_params, &val, &dir);
51

  
52
    audio_s_bit = snd_pcm_hw_params_get_sbits(hw_params);
53
}
54

  
55
void read_sample()
56
{
57
    int rc = snd_pcm_readi(capture_handle, audio_buffer, frames);
58
    if (rc == -EPIPE) {
59
      /* EPIPE means overrun */
60
      fprintf(stderr, "overrun occurred\n");
61
      snd_pcm_prepare(capture_handle);
62
    } else if (rc < 0) {
63
      fprintf(stderr, "error from read: %s\n", snd_strerror(rc));
64
    } else if (rc != (int)frames) {
65
      fprintf(stderr, "short read, read %d frames\n", rc);
66
    }
67
    else
68
    {
69
        //rc = write(1, audio_buffer, buffer_size);
70
        //if (rc != buffer_size) fprintf(stderr, "short write: wrote %d bytes\n", rc);
71

  
72
        int gotbytes = snd_pcm_frames_to_bytes(capture_handle, rc);
73
        process_sample(audio_buffer, gotbytes);
74
    }
75
}
76

  
77
void close_audio_device()
78
{
79
    snd_pcm_drain(capture_handle);
80
    snd_pcm_close(capture_handle);
81
    free(audio_buffer);
82
}
capture/audio.h
1
/* 
2
 * File:   audio.h
3
 * Author: carmelo
4
 *
5
 * Created on December 17, 2009, 12:32 PM
6
 */
7

  
8
#ifndef _AUDIO_H
9
#define	_AUDIO_H
10

  
11
#ifdef	__cplusplus
12
extern "C" {
13
#endif
14

  
15
#include <alsa/asoundlib.h>
16
#include <stdlib.h>
17

  
18
#define AUDIO_PERIOD 32
19

  
20
static int err;
21
static short buf[128];
22
static snd_pcm_t* capture_handle;
23
static snd_pcm_hw_params_t* hw_params;
24
static char* audio_buffer;
25
static int buffer_size;
26
static int frames;
27
int audio_s_bit;
28

  
29
void process_sample(unsigned char* buffer, int buffer_size);
30
int init_audio(char* audio_dev_name);
31
void close_audio_device();
32

  
33
#ifdef	__cplusplus
34
}
35
#endif
36

  
37
#endif	/* _AUDIO_H */
38

  
capture/capture.h
1
/* 
2
 * File:   capture.h
3
 * Author: carmelo
4
 *
5
 * Created on December 17, 2009, 6:20 PM
6
 */
7

  
8
#ifndef _CAPTURE_H
9
#define	_CAPTURE_H
10

  
11
#ifdef	__cplusplus
12
extern "C" {
13
#endif
14

  
15
#include <stdio.h>
16
#include <stdlib.h>
17
#include <pthread.h>
18
#include <signal.h>
19

  
20
FILE * img;
21
unsigned int seq;
22
char filename[255];
23
static unsigned char* rgb_buffer = NULL;
24
pthread_t video_capure_thread;
25
pthread_t audio_capure_thread;
26
FILE* audio_output_file;
27
unsigned char running;
28

  
29
#define DEFAULT_VIDEO_FORMAT V4L2_PIX_FMT_YUYV
30
#define DEFAULT_VIDEO_DEVICE "/dev/video0"
31
#define DEFAULT_AUDIO_OUT_FILE "out.wav"
32
#define WIDTH 640
33
#define HEIGHT 480
34

  
35
#define AUDIO_SAMPLE_RATE 44100 // ( 44100 = CD quality)
36
#define AUDIO_CHANNELS 2
37
#define AUDIO_FORMAT SND_PCM_FORMAT_S16_LE
38
#define AUDIO_INTERLEAVED SND_PCM_ACCESS_RW_INTERLEAVED
39

  
40
/*
41
* The WAVE Header
42
*/
43
typedef struct wav_s {
44
	char chunk_id[4] ; /* "RIFF" */
45
	unsigned int chunk_size; /* n*4 + 36 */
46
	char format[4]; /* "WAVE" */
47
	char sub_chunk_id[4]; /* "fmt " */
48
	unsigned int sub_chunk_size; /* 16 */
49
	unsigned short audio_format; /* 1 */
50
	unsigned short num_channels; /* 2 */
51
	unsigned int sample_rate; /* 44100 */
52
	unsigned int byte_rate; /* 4*44100 */
53
	unsigned short block_alg; /* 4 */
54
	unsigned short bps; /* 16 */
55
	unsigned char sub_chunk2_id[4]; /* "data" */
56
	unsigned int sub_chunk2_size; /* n*4 */
57
} wav_t ;
58

  
59
void* video_capture(void* ThreadParams);
60
void* audio_capture(void* ThreadParams);
61
void terminate(int signum);
62

  
63
#ifdef	__cplusplus
64
}
65
#endif
66

  
67
#endif	/* _CAPTURE_H */
68

  
capture/main.c
1
#include "capture.h"
2
#include "video.h"
3
#include "audio.h"
4

  
5
void process_frame (unsigned char *p, int bytes, const struct v4l2_format* fmt)
6
{
7
    switch(fmt->fmt.pix.pixelformat)
8
    {
9
        case V4L2_PIX_FMT_JPEG:
10
            sprintf(filename, "frames/jpg/frame%d.jpg", seq++);
11
            img = fopen(filename,"w");
12
            fwrite(p, bytes, 1, img);
13
            fclose(img);
14
            break;
15
        case V4L2_PIX_FMT_YUYV:
16
            sprintf(filename, "frames/ppm/frame%d.ppm", seq++);
17
            img = fopen(filename,"w");
18

  
19
            // RGB
20
            //fprintf( img, "P6\r\n" );
21

  
22
            // GRAY
23
            fprintf( img, "P5\r\n" );
24

  
25
            fprintf( img, "# comment .\r\n" );
26
            fprintf( img, "%d %d\r\n", fmt->fmt.pix.width, fmt->fmt.pix.height );
27
            fprintf( img, "255\r\n" );
28

  
29
            unsigned int pixels = fmt->fmt.pix.width*fmt->fmt.pix.height;
30

  
31
            // YUYV 2 GRAY            
32
            int i;
33
            for(i=0; i<bytes; i+=2)
34
                fwrite(p+i, 1, 1, img);
35

  
36
            // YUYV 2 RGB24
37
            // todo
38

  
39
            fclose(img);
40
            break;
41
        case V4L2_PIX_FMT_MJPEG:
42
            sprintf(filename, "frames/jpg/frame%d.jpg", seq++);
43
            img = fopen(filename,"w");
44
            fwrite(p, bytes, 1, img);
45
            fclose(img);
46
            break;
47
    }
48
    
49
}
50

  
51
void process_sample(unsigned char* buffer, int buffer_size)
52
{
53
    fwrite(buffer, buffer_size, 1, audio_output_file);
54
}
55

  
56
void usage (FILE *fp, int argc, char **argv)
57
{
58
    fprintf (fp,
59
        "Usage: %s [options]\n\n"
60
        "Options:\n"
61
        "-v | --video-device    Video device name default=/dev/video0\n"
62
        "-a | --audio-device    Audio device name [hw:0,1|hw:0,2|...], default=default\n"
63
        "-h | --help            Print this message\n"
64
        //"-m | --mmap            Use memory mapped buffers\n"
65
        //"-r | --read            Use read() calls\n"
66
        //"-u | --userp           Use application allocated buffers\n"
67
        "--video-format         Video format [rgb24|yuyv|jpeg|mjpeg], default=yuyv\n\n"
68
        //"--audio-format         Audio format []\n\n"
69
        "",
70
        argv[0]);
71
}
72

  
73
int main (int argc, char **argv)
74
{
75
    // VIDEO
76
    seq = 0;
77
    video_dev_name = DEFAULT_VIDEO_DEVICE;
78
    io = IO_METHOD_MMAP;
79
    video_format = DEFAULT_VIDEO_FORMAT;
80
    fd = -1;
81
    buffers = NULL;
82
    n_buffers = 0;
83
    system("rm frames/ppm/* -f");
84

  
85
    // AUDIO
86
    char* audio_dev_name = "default";
87
    audio_output_file = fopen(DEFAULT_AUDIO_OUT_FILE, "w");
88

  
89
    for (;;)
90
    {
91
        int index;
92
        int c;
93
        const struct option long_options [] = {
94
            { "video-device",   required_argument,      NULL,           'v' },
95
            { "audio-device",   required_argument,      NULL,           'a' },
96
            { "help",           no_argument,            NULL,           'h' },
97
            { "mmap",           no_argument,            NULL,           'm' },
98
            { "read",           no_argument,            NULL,           'r' },
99
            { "userp",          no_argument,            NULL,           'u' },
100
            { "video-format",   required_argument,      NULL,           'x' },
101
            //{ "audio-format",   required_argument,      NULL,           'z' },
102
            { 0, 0, 0, 0 }
103
        };
104

  
105
        c = getopt_long (argc, argv, "v:a:hmrux:", long_options, &index);
106

  
107
        if (-1 == c)
108
            break;
109

  
110
        switch (c)
111
        {
112
            case 0: /* getopt_long() flag */
113
                break;
114

  
115
            case 'v':
116
                video_dev_name = optarg;
117
                break;
118

  
119
            case 'h':
120
                usage (stdout, argc, argv);
121
                exit (EXIT_SUCCESS);
122

  
123
            case 'x':                
124
                if(strcmp(optarg, "rgb24") == 0)
125
                    video_format = V4L2_PIX_FMT_RGB24;
126
                if(strcmp(optarg, "jpeg") == 0)
127
                    video_format = V4L2_PIX_FMT_JPEG;
128
                if(strcmp(optarg, "yuyv") == 0)
129
                    video_format = V4L2_PIX_FMT_YUYV;
130
                if(strcmp(optarg, "yuv32") == 0)
131
                    video_format = V4L2_PIX_FMT_YUV32;
132
                if(strcmp(optarg, "grey") == 0)
133
                    video_format = V4L2_PIX_FMT_GREY;
134
                if(strcmp(optarg, "mjpeg") == 0)
135
                    video_format = V4L2_PIX_FMT_MJPEG;
136
                break;
137

  
138
            case 'a':
139
                audio_dev_name = optarg;
140
                break;
141

  
142
            case 'm':
143
                io = IO_METHOD_MMAP;
144
                break;
145

  
146
            case 'r':
147
                io = IO_METHOD_READ;
148
                break;
149

  
150
            case 'u':
151
                io = IO_METHOD_USERPTR;
152
                break;
153

  
154
            default:
155
                usage (stderr, argc, argv);
156
                exit (EXIT_FAILURE);
157
        }
158
    }
159

  
160
    // VIDEO INIT
161
    //printf("opening video device...\n");
162
    open_video_device ();
163
    //printf("\t success\n\n");
164
    printf("initializing video device...\n");
165
    init_video_device ();
166
    start_video_capturing();
167
    printf("OK\n\n");
168

  
169
    // AUDIO INIT
170
    printf("initializing audio device...\n");
171
    int error = init_audio(audio_dev_name);
172
    if(error<0)
173
        exit(1);
174
    printf("OK\n\n");
175

  
176
    signal(SIGINT, terminate);
177

  
178
    running = 1;
179
    pthread_create(&video_capure_thread, NULL, video_capture, NULL);
180
    pthread_create(&audio_capure_thread, NULL, audio_capture, NULL);
181

  
182
    pthread_join(video_capure_thread, NULL);
183
    pthread_join(audio_capure_thread, NULL);
184

  
185
    printf("stopping video capture...\n");
186
    stop_video_capturing ();
187
    uninit_video_device ();
188
    close_video_device ();
189
    printf("STOPPED\n\n");
190

  
191
    printf("stopping audio capture...\n");
192
    fclose(audio_output_file);
193
    close_audio_device();
194
    printf("STOPPED\n\n");
195

  
196
    exit (EXIT_SUCCESS);
197

  
198
    return 0;
199
}
200

  
201
void terminate(int signum)
202
{
203
    printf("\nterminating...\n");
204
    running = 0;
205
}
206

  
207
void* video_capture(void* ThreadParams)
208
{
209
    printf("video capture started\n");
210
    while(running)
211
    {
212
        int r = poll_video_device();
213

  
214
        if (-1 == r) {
215
            if (EINTR == errno)
216
                continue;
217

  
218
            errno_exit ("select");
219
        }
220

  
221
        if (0 == r) {
222
            fprintf (stderr, "select timeout\n");
223
            exit (EXIT_FAILURE);
224
        }
225
        read_frame();
226
    }
227
}
228

  
229
void* audio_capture(void* ThreadParams)
230
{
231
    printf("audio capture started (%d bit)\n", audio_s_bit);
232
    wav_t head = {
233
            {'R','I','F','F'}
234
            ,(1<<28)+36,
235
            {'W','A','V','E'},
236
            {'f','m','t',' '},
237
            audio_s_bit,1,AUDIO_CHANNELS, AUDIO_SAMPLE_RATE,4*AUDIO_SAMPLE_RATE,4,audio_s_bit,
238
            {'d','a','t','a'},
239
            1<<30
240
    };
241

  
242
    fwrite(&head,sizeof(wav_t),1, audio_output_file);
243
    while(running)
244
    {
245
        read_sample();
246
    }
247
}
capture/readme.txt
1
Il programma salva i fotogrammi nella cartella frames e l'audio in formato PCM nel file out.wav.
2

  
3
Per compilare: make.
4

  
5
Dipendenze:
6
- alsa development libraries. Il pacchetto e' chiamato con un nome differente a seconda della distribuzione utilizzata. Tipicamente e' qualcosa tipo: "libasound-dev" o "alsa-lib-devel";
7
- L'header file di v4l2 (videodev2.h). Questo dovrebbe essere contenuto nei kernel headers del sistema.
8

  
9
Per visualizzare l'help, utilizzare il parametro "-h".
10

  
11
E' possibile specificare il formato video di acquisizione desiderato. Tuttavia, in base al driver della webcam utilizzato, alcuni formati potrebbero non essere disponibili.
12
Se appare un errore simile a "VIDIOC_S_FMT error 22, Invalid argument", riprovare cambiando il formato desiderato tramite i parametri da linea di comando.
13
Ho fatto in modo che possa essere scelto uno tra i formati piu' comuni.
14

  
15
Se dovessero apparire errori tipo "Input/output error", riprovare specificando un altro audio device tramite i parametri da linea di comando.
capture/video.c
1
#include "video.h"
2
#include "capture.h"
3

  
4
void errno_exit (const char * s)
5
{
6
    fprintf (stderr, "%s error %d, %s\n", s, errno, strerror (errno));
7
    exit (EXIT_FAILURE);
8
}
9

  
10
static int xioctl (int fd, int request, void *arg)
11
{
12
    int r;
13

  
14
    do r = ioctl (fd, request, arg);
15
    while (-1 == r && EINTR == errno);
16

  
17
    return r;
18
}
19

  
20
int read_frame(void)
21
{
22
    struct v4l2_buffer buf;
23
    unsigned int i;
24

  
25
    switch (io) {
26
        case IO_METHOD_READ:
27
            if (-1 == read (fd, buffers[0].start, buffers[0].length)) {
28
                switch (errno) {
29
                    case EAGAIN:
30
                        return 0;
31

  
32
                    case EIO:
33
                            /* Could ignore EIO, see spec. */
34

  
35
                            /* fall through */
36

  
37
                    default:
38
                        errno_exit ("read");
39
                }
40
            }
41

  
42
            process_frame (buffers[0].start, 0, &fmt);
43

  
44
            break;
45

  
46
        case IO_METHOD_MMAP:
47
            CLEAR (buf);
48

  
49
            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
50
            buf.memory = V4L2_MEMORY_MMAP;
51

  
52
            if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
53
                switch (errno) {
54
                    case EAGAIN:
55
                        return 0;
56

  
57
                    case EIO:
58
                            /* Could ignore EIO, see spec. */
59

  
60
                            /* fall through */
61

  
62
                    default:
63
                        errno_exit ("VIDIOC_DQBUF");
64
                }
65
            }
66

  
67
            assert (buf.index < n_buffers);
68

  
69
            process_frame (buffers[buf.index].start, buf.bytesused, &fmt);
70

  
71
            if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
72
                errno_exit ("VIDIOC_QBUF");
73

  
74
            break;
75

  
76
        case IO_METHOD_USERPTR:
77
            CLEAR (buf);
78

  
79
            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
80
            buf.memory = V4L2_MEMORY_USERPTR;
81

  
82
            if (-1 == xioctl (fd, VIDIOC_DQBUF, &buf)) {
83
                switch (errno) {
84
                    case EAGAIN:
85
                        return 0;
86

  
87
                    case EIO:
88
                            /* Could ignore EIO, see spec. */
89

  
90
                            /* fall through */
91

  
92
                    default:
93
                        errno_exit ("VIDIOC_DQBUF");
94
                }
95
            }
96

  
97
            for (i = 0; i < n_buffers; ++i)
98
                if (buf.m.userptr == (unsigned long) buffers[i].start && buf.length == buffers[i].length)
99
                    break;
100

  
101
            assert (i < n_buffers);
102

  
103
            process_frame ((void *) buf.m.userptr, buf.bytesused, &fmt);
104

  
105
            if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
106
                errno_exit ("VIDIOC_QBUF");
107

  
108
            break;
109
    }
110

  
111
    return 1;
112
}
113

  
114
void mainloop (void)
115
{
116
    while(1)
117
    {
118
        int r = poll_video_device();
119

  
120
        if (-1 == r) {
121
            if (EINTR == errno)
122
                continue;
123

  
124
            errno_exit ("select");
125
        }
126

  
127
        if (0 == r) {
128
            fprintf (stderr, "select timeout\n");
129
            exit (EXIT_FAILURE);
130
        }
131

  
132
        read_frame();
133

  
134
        /* EAGAIN - continue select loop. */
135
    }
136
}
137

  
138
int poll_video_device(void)
139
{
140
    fd_set fds;
141
    struct timeval tv;
142
    int r;
143

  
144
    FD_ZERO (&fds);
145
    FD_SET (fd, &fds);
146

  
147
    /* Timeout. */
148
    tv.tv_sec = 2;
149
    tv.tv_usec = 0;
150

  
151
    return select (fd + 1, &fds, NULL, NULL, &tv);
152
}
153

  
154
void stop_video_capturing(void)
155
{
156
    enum v4l2_buf_type type;
157

  
158
    switch (io) {
159
    case IO_METHOD_READ:
160
        /* Nothing to do. */
161
        break;
162

  
163
    case IO_METHOD_MMAP:
164
    case IO_METHOD_USERPTR:
165
        type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
166

  
167
        if (-1 == xioctl (fd, VIDIOC_STREAMOFF, &type))
168
            errno_exit ("VIDIOC_STREAMOFF");
169

  
170
        break;
171
    }
172
}
173

  
174
void start_video_capturing(void)
175
{
176
    unsigned int i;
177
    enum v4l2_buf_type type;
178

  
179
    switch (io)
180
    {
181
        case IO_METHOD_READ:
182
            /* Nothing to do. */
183
            break;
184

  
185
        case IO_METHOD_MMAP:
186
            for (i = 0; i < n_buffers; ++i) {
187
                struct v4l2_buffer buf;
188

  
189
                CLEAR (buf);
190

  
191
                buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
192
                buf.memory      = V4L2_MEMORY_MMAP;
193
                buf.index       = i;
194

  
195
                if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
196
                    errno_exit ("VIDIOC_QBUF");
197
            }
198

  
199
            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
200

  
201
            if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
202
                errno_exit ("VIDIOC_STREAMON");
203

  
204
            break;
205

  
206
        case IO_METHOD_USERPTR:
207
            for (i = 0; i < n_buffers; ++i) {
208
                struct v4l2_buffer buf;
209

  
210
                CLEAR (buf);
211

  
212
                buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
213
                buf.memory      = V4L2_MEMORY_USERPTR;
214
                buf.index       = i;
215
                buf.m.userptr	= (unsigned long) buffers[i].start;
216
                buf.length      = buffers[i].length;
217

  
218
                if (-1 == xioctl (fd, VIDIOC_QBUF, &buf))
219
                    errno_exit ("VIDIOC_QBUF");
220
            }
221

  
222
            type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
223

  
224
            if (-1 == xioctl (fd, VIDIOC_STREAMON, &type))
225
                errno_exit ("VIDIOC_STREAMON");
226

  
227
            break;
228
    }
229
}
230

  
231
void uninit_video_device (void)
232
{
233
    unsigned int i;
234

  
235
    switch (io) {
236
    case IO_METHOD_READ:
237
        free (buffers[0].start);
238
        break;
239

  
240
    case IO_METHOD_MMAP:
241
        for (i = 0; i < n_buffers; ++i)
242
            if (-1 == munmap (buffers[i].start, buffers[i].length))
243
                errno_exit ("munmap");
244
        break;
245

  
246
    case IO_METHOD_USERPTR:
247
        for (i = 0; i < n_buffers; ++i)
248
            free (buffers[i].start);
249
        break;
250
    }
251

  
252
    free (buffers);
253
}
254

  
255
static void init_read(unsigned int buffer_size)
256
{
257
    buffers = calloc (1, sizeof (*buffers));
258

  
259
    if (!buffers) {
260
        fprintf (stderr, "Out of memory\n");
261
        exit (EXIT_FAILURE);
262
    }
263

  
264
    buffers[0].length = buffer_size;
265
    buffers[0].start = malloc (buffer_size);
266

  
267
    if (!buffers[0].start) {
268
        fprintf (stderr, "Out of memory\n");
269
        exit (EXIT_FAILURE);
270
    }
271
}
272

  
273
static void init_mmap(void)
274
{
275
    struct v4l2_requestbuffers req;
276

  
277
    CLEAR (req);
278

  
279
    req.count               = 4;
280
    req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
281
    req.memory              = V4L2_MEMORY_MMAP;
282

  
283
    if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req)) {
284
        if (EINVAL == errno)
285
        {
286
            fprintf (stderr, "%s does not support memory mapping\n", video_dev_name);
287
            exit (EXIT_FAILURE);
288
        }
289
        else
290
        {
291
            errno_exit ("VIDIOC_REQBUFS");
292
        }
293
    }
294

  
295
    if (req.count < 2)
296
    {
297
        fprintf (stderr, "Insufficient buffer memory on %s\n", video_dev_name);
298
        exit (EXIT_FAILURE);
299
    }
300

  
301
    buffers = calloc (req.count, sizeof (*buffers));
302

  
303
    if (!buffers) {
304
        fprintf (stderr, "Out of memory\n");
305
        exit (EXIT_FAILURE);
306
    }
307

  
308
    for (n_buffers = 0; n_buffers < req.count; ++n_buffers) {
309
        struct v4l2_buffer buf;
310

  
311
        CLEAR (buf);
312

  
313
        buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
314
        buf.memory      = V4L2_MEMORY_MMAP;
315
        buf.index       = n_buffers;
316

  
317
        if (-1 == xioctl (fd, VIDIOC_QUERYBUF, &buf))
318
            errno_exit ("VIDIOC_QUERYBUF");
319

  
320
        buffers[n_buffers].length = buf.length;
321
        buffers[n_buffers].start = mmap (NULL /* start anywhere */,
322
            buf.length,
323
            PROT_READ | PROT_WRITE /* required */,
324
            MAP_SHARED /* recommended */,
325
            fd, buf.m.offset);
326

  
327
        if (MAP_FAILED == buffers[n_buffers].start)
328
            errno_exit ("mmap");
329
    }
330
}
331

  
332
static void init_userp (unsigned int buffer_size)
333
{
334
    struct v4l2_requestbuffers req;
335
    unsigned int page_size;
336

  
337
    page_size = getpagesize ();
338
    buffer_size = (buffer_size + page_size - 1) & ~(page_size - 1);
339

  
340
    CLEAR (req);
341

  
342
    req.count               = 4;
343
    req.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
344
    req.memory              = V4L2_MEMORY_USERPTR;
345

  
346
    if (-1 == xioctl (fd, VIDIOC_REQBUFS, &req))
347
    {
348
        if (EINVAL == errno)
349
        {
350
            fprintf (stderr, "%s does not support user pointer i/o\n", video_dev_name);
351
                exit (EXIT_FAILURE);
352
        } else {
353
            errno_exit ("VIDIOC_REQBUFS");
354
        }
355
    }
356

  
357
    buffers = calloc (4, sizeof (*buffers));
358

  
359
    if (!buffers) {
360
        fprintf (stderr, "Out of memory\n");
361
        exit (EXIT_FAILURE);
362
    }
363

  
364
    for (n_buffers = 0; n_buffers < 4; ++n_buffers)
365
    {
366
        buffers[n_buffers].length = buffer_size;
367
        buffers[n_buffers].start = memalign (/* boundary */ page_size, buffer_size);
368

  
369
        if (!buffers[n_buffers].start) {
370
            fprintf (stderr, "Out of memory\n");
371
            exit (EXIT_FAILURE);
372
        }
373
    }
374
}
375

  
376
void init_video_device (void)
377
{
378
    struct v4l2_capability cap;
379
    struct v4l2_cropcap cropcap;
380
    struct v4l2_crop crop;
381
    unsigned int min;
382

  
383
    if (-1 == xioctl (fd, VIDIOC_QUERYCAP, &cap)) {
384
        if (EINVAL == errno) {
385
            fprintf (stderr, "%s is no V4L2 device\n", video_dev_name);
386
            exit (EXIT_FAILURE);
387
        } else {
388
            errno_exit ("VIDIOC_QUERYCAP");
389
        }
390
    }
391

  
392
    if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
393
        fprintf (stderr, "%s is no video capture device\n", video_dev_name);
394
        exit (EXIT_FAILURE);
395
    }
396

  
397
    switch (io) {
398
        case IO_METHOD_READ:
399
            if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
400
                fprintf (stderr, "%s does not support read i/o\n", video_dev_name);
401
                exit (EXIT_FAILURE);
402
            }
403

  
404
            break;
405

  
406
        case IO_METHOD_MMAP:
407
        case IO_METHOD_USERPTR:
408
            if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
409
                fprintf (stderr, "%s does not support streaming i/o\n", video_dev_name);
410
                exit (EXIT_FAILURE);
411
            }
412

  
413
            break;
414
    }
415

  
416

  
417
    /* Select video input, video standard and tune here. */
418

  
419

  
420
    CLEAR (cropcap);
421

  
422
    cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
423

  
424
    if (0 == xioctl (fd, VIDIOC_CROPCAP, &cropcap)) {
425
        crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
426
        crop.c = cropcap.defrect; /* reset to default */
427

  
428
        if (-1 == xioctl (fd, VIDIOC_S_CROP, &crop)) {
429
            switch (errno) {
430
                case EINVAL:
431
                    /* Cropping not supported. */
432
                    break;
433
                default:
434
                    /* Errors ignored. */
435
                    break;
436
            }
437
        }
438
    } else {
439
            /* Errors ignored. */
440
    }
441

  
442

  
443
    CLEAR (fmt);
444

  
445

  
446
/*
447
    fmt.pix.bytesperline    : 1280
448
    fmt.pix.sizeimage       : 4094874830
449
    fmt.pix.colorspace      : unknown
450
    fmt.pix.priv            : 0
451
*/
452

  
453

  
454
    fmt.type                = V4L2_BUF_TYPE_VIDEO_CAPTURE;
455
    fmt.fmt.pix.width       = WIDTH;
456
    fmt.fmt.pix.height      = HEIGHT;
457
    fmt.fmt.pix.pixelformat = video_format;
458
    fmt.fmt.pix.field       = V4L2_FIELD_ANY;
459

  
460
    //printf("trying %d, %d, %d, %d, %d\n", fmt.type, fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.pixelformat, fmt.fmt.pix.field);
461

  
462
    if (-1 == xioctl (fd, VIDIOC_S_FMT, &fmt))
463
        errno_exit ("VIDIOC_S_FMT");
464

  
465
    //printf("get %d, %d, %d, %d, %d\n", fmt.type, fmt.fmt.pix.width, fmt.fmt.pix.height, fmt.fmt.pix.pixelformat, fmt.fmt.pix.field);
466

  
467
    if (fmt.fmt.pix.pixelformat != video_format)
468
    {
469
        printf("Device driver didn't accept selected video format. Can't proceed.\n");
470
        exit(EXIT_FAILURE);
471
    }
472

  
473
    if ((fmt.fmt.pix.width != WIDTH) || (fmt.fmt.pix.height != HEIGHT))
474
        printf("Warning: driver is sending image at %dx%d\n", fmt.fmt.pix.width, fmt.fmt.pix.height);
475

  
476

  
477
    /* Note VIDIOC_S_FMT may change width and height. */
478

  
479
    /* Buggy driver paranoia. */
480
    min = fmt.fmt.pix.width * 2;
481
    if (fmt.fmt.pix.bytesperline < min)
482
        fmt.fmt.pix.bytesperline = min;
483
    min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height;
484
    if (fmt.fmt.pix.sizeimage < min)
485
        fmt.fmt.pix.sizeimage = min;
486

  
487
    switch (io)
488
    {
489
        case IO_METHOD_READ:
490
            init_read (fmt.fmt.pix.sizeimage);
491
            break;
492

  
493
        case IO_METHOD_MMAP:
494
            init_mmap ();
495
            break;
496

  
497
        case IO_METHOD_USERPTR:
498
            init_userp (fmt.fmt.pix.sizeimage);
499
            break;
500
    }
501
}
502

  
503
void close_video_device (void)
504
{
505
    if (-1 == close (fd))
506
        errno_exit ("close");
507

  
508
    fd = -1;
509
}
510

  
511
void open_video_device (void)
512
{
513
    struct stat st;
514

  
515
    if (-1 == stat (video_dev_name, &st)) {
516
        fprintf (stderr, "Cannot identify '%s': %d, %s\n",video_dev_name, errno, strerror (errno));
517
        exit (EXIT_FAILURE);
518
    }
519

  
520
    if (!S_ISCHR (st.st_mode)) {
521
        fprintf (stderr, "%s is no device\n", video_dev_name);
522
        exit (EXIT_FAILURE);
523
    }
524

  
525
    fd = open (video_dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
526

  
527
    if (-1 == fd)
528
    {
529
        fprintf (stderr, "Cannot open '%s': %d, %s\n", video_dev_name, errno, strerror (errno));
530
        exit (EXIT_FAILURE);
531
    }
532
}
capture/video.h
1
/* 
2
 * File:   capture.h
3
 * Author: carmelo
4
 *
5
 * Created on December 12, 2009, 7:58 PM
6
 */
7

  
8
#ifndef _VIDEO_H
9
#define	_VIDEO_H
10

  
11
#ifdef	__cplusplus
12
extern "C" {
13
#endif
14

  
15
#include <stdio.h>
16
#include <stdlib.h>
17
#include <string.h>
18
#include <assert.h>
19

  
20
#include <getopt.h>             /* getopt_long() */
21

  
22
#include <fcntl.h>              /* low-level i/o */
23
#include <unistd.h>
24
#include <errno.h>
25
#include <malloc.h>
26
#include <sys/stat.h>
27
#include <sys/types.h>
28
#include <sys/time.h>
29
#include <sys/mman.h>
30
#include <sys/ioctl.h>
31

  
32
#include <asm/types.h>          /* for videodev2.h */
33

  
34
#include <linux/videodev2.h>
35

  
36
#define CLEAR(x) memset (&(x), 0, sizeof (x))
37

  
38
typedef enum {
39
    IO_METHOD_READ,
40
    IO_METHOD_MMAP,
41
    IO_METHOD_USERPTR,
42
} io_method;
43

  
44
struct buffer{
45
    void * start;
46
    size_t length;
47
};
48

  
49
char* video_dev_name;
50
io_method io;
51
int fd;;
52
struct buffer * buffers;
53
unsigned int n_buffers;
54
struct v4l2_format fmt;
55
__u32 video_format;
56

  
57
void errno_exit (const char * s);
58
static int xioctl (int fd, int request, void *arg);
59
void process_frame (unsigned char *p, int bytes, const struct v4l2_format* fmt);
60
int read_frame(void);
61
int poll_video_device(void);
62
void mainloop (void);
63
void stop_video_capturing(void);
64
void start_video_capturing(void);
65
void uninit_video_device (void);
66
static void init_read(unsigned int buffer_size);
67
static void init_mmap(void);
68
static void init_userp (unsigned int buffer_size);
69
void init_video_device (void);
70
void close_video_device (void);
71
void open_video_device (void);
72

  
73
#ifdef	__cplusplus
74
}
75
#endif
76

  
77
#endif	/* _VIDEO_H */
78

  
chunk_puller.c
1
#include <platform.h>
2
#include <microhttpd.h>
3

  
4
#include <http_default_urls.h>
5

  
6
struct connection_info_struct {
7
  uint8_t *block;
8
  int block_size;
9
};
10

  
11
void request_completed(void *cls, struct MHD_Connection *connection,
12
                       void **con_cls, enum MHD_RequestTerminationCode toe) {
13
  struct connection_info_struct *con_info = (struct connection_info_struct *)*con_cls;
14
  if(NULL == con_info)
15
    return;
16
  if(con_info->block)
17
    free (con_info->block);
18
  free(con_info);
19
  *con_cls = NULL;
20
}
21

  
22
int send_response(struct MHD_Connection *connection, unsigned int code) {
23
  int ret;
24
  struct MHD_Response *response;
25

  
26
  response = MHD_create_response_from_data(0, NULL, MHD_NO, MHD_NO);
27
  if(!response)
28
    return MHD_NO;
29

  
30
  ret = MHD_queue_response(connection, code, response);
31
  MHD_destroy_response (response);
32

  
33
  return ret;
34
}
35

  
36
int answer_to_connection(void *cls, struct MHD_Connection *connection,
37
                         const char *url, const char *method,
38
                         const char *version, const char *upload_data,
39
                         size_t *upload_data_size, void **con_cls) {
40
  struct connection_info_struct *con_info = NULL;
41
  uint8_t *block = NULL;
42

  
43
  if(*con_cls==NULL) {
44
    con_info = malloc(sizeof(struct connection_info_struct));
45
    if(con_info == NULL)
46
      return MHD_NO;
47

  
48
    con_info->block = NULL;
49
    con_info->block_size = 0; 
50
    *con_cls = (void *)con_info;
51

  
52
    return MHD_YES;
53
  }
54

  
55
  if(0 == strcmp (method, "GET")) {
56
    return send_response(connection, MHD_HTTP_BAD_REQUEST);
57
  }
58

  
59
  if(0 == strcmp(method, "POST")) {
60
    if(0 == strcmp(url, UL_DEFAULT_EXTERNALPLAYER_PATH)) {
61
      con_info = (struct connection_info_struct *)*con_cls;
62
      if(*upload_data_size > 0) {
63
        block = (uint8_t *)malloc(con_info->block_size+*upload_data_size);
64

  
65
        if(!block)
66
          return MHD_NO;
67

  
68
        memcpy(block, con_info->block, con_info->block_size);
69
        memcpy(block+con_info->block_size, upload_data, *upload_data_size);
70
        con_info->block = block;
71
        con_info->block_size += *upload_data_size;
72
        *upload_data_size = 0;
73
        return MHD_YES;
74
      }
75
      else {
76
				// i do not mind about return value or problems into the enqueueBlock()
77
        enqueueBlock(con_info->block, con_info->block_size); //this might take some time
78
        return send_response(connection, MHD_HTTP_OK);
79
      }
80
    }
81
    else
82
      return send_response(connection, MHD_HTTP_NOT_FOUND);
83
  }
84
  return send_response(connection, MHD_HTTP_BAD_REQUEST);
85
}
86

  
87

  
88
struct MHD_Daemon *initChunkPuller() {
89
  return MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_DEBUG, UL_DEFAULT_EXTERNALPLAYER_PORT,
90
                          NULL, NULL,
91
                          &answer_to_connection, NULL, MHD_OPTION_END);
92
}
93

  
94
void finalizeChunkPuller(struct MHD_Daemon *daemon) {
95
  MHD_stop_daemon(daemon);
96
}
97

  
chunk_pusher.c
1
#include <stdlib.h>
2
#include <string.h>
3
#include <curl/curl.h>
4

  
5
#include "external_chunk_transcoding.h"
6
#include "chunker_streamer.h"
7

  
8
void initChunkPusher();
9
void finalizeChunkPusher();
10
int pushChunkHttp(ExternalChunk *echunk, char *url);
11
void *chunkToAttributes(ExternalChunk *echunk, size_t attr_size);
12
static inline void bit32_encoded_push(uint32_t v, uint8_t *p);
13
void chunker_logger(const char *s);
14

  
15

  
16
void initChunkPusher() {	
17
	/* In windows, this will init the winsock stuff */ 
18
	curl_global_init(CURL_GLOBAL_ALL);
19
}
20

  
21
void finalizeChunkPusher() {
22
	curl_global_cleanup();
23
}
24

  
25
int pushChunkHttp(ExternalChunk *echunk, char *url) {
26
	//MAKE THE CURL EASY HANDLE GLOBAL? TO REUSE IT?
27
	CURL *curl_handle;
28
	struct curl_slist *headers=NULL;
29
	void *grapes_chunk_attributes_block=NULL;
30
	uint8_t *buffer=NULL;
31
	static size_t attr_size = 0;
32
	size_t buffer_size = 0;
33
	double ts1e3 = 0.0;
34
	double tus3e1 = 0.0;
35
	int ret = STREAMER_FAIL_RETURN;
36
	
37
	attr_size = 5*sizeof(int) + 2*sizeof(time_t) + 2*sizeof(suseconds_t) + 1*sizeof(double);
38

  
39
	/* first pack the chunk info that we get from the streamer into an "attributes" block of a regular GRAPES chunk */
40
	if(	(grapes_chunk_attributes_block = packExternalChunkToAttributes(echunk, attr_size)) != NULL ) {
41
		/* then fill-up a proper GRAPES chunk */
42
		Chunk gchunk;
43
		gchunk.id = echunk->seq;
44
		gchunk.size = echunk->payload_len;
45
		/* convert external_chunk start_time in milliseconds and put it in grapes chunk */
46
		ts1e3 = (double)(echunk->start_time.tv_sec*1e3);
47
		tus3e1 = (double)(echunk->start_time.tv_usec/1e3);
48
		gchunk.timestamp = ts1e3+tus3e1;
49
		gchunk.attributes = grapes_chunk_attributes_block;
50
		gchunk.attributes_size = attr_size;
51
		gchunk.data = echunk->data;
52

  
53
		/* 20 bytes are needed to put the chunk header info on the wire */
54
		buffer_size = GRAPES_ENCODED_CHUNK_HEADER_SIZE + attr_size + echunk->payload_len;
55
		if( (buffer = malloc(buffer_size)) != NULL) {
56
			/* encode the GRAPES chunk into network bytes */
57
			encodeChunk(&gchunk, buffer, buffer_size);
58
			/* get a curl handle */ 
59
			curl_handle = curl_easy_init();
60
			if(curl_handle) {
61
				curl_easy_setopt(curl_handle, CURLOPT_URL, url);
62
				/* fill the headers */
63
//				headers = curl_slist_append(headers, "Content-Type: application/octet-stream");
64
				/* post binary data */
65
				curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, buffer);
66
				/* set the size of the postfields data */
67
				curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDSIZE, buffer_size);
68
				/* pass our list of custom made headers */
69
//				curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
70
//print_block(buffer, buffer_size);
71
				curl_easy_perform(curl_handle); /* post away! */
72
//				curl_slist_free_all(headers); /* free the header list */
73
				ret = STREAMER_OK_RETURN;
74
			}
75
			/* always cleanup curl */ 
76
			curl_easy_cleanup(curl_handle);
77
			free(buffer);
78
			free(grapes_chunk_attributes_block);
79
			return ret;
80
		}
81
		free(grapes_chunk_attributes_block);
82
		return ret;
83
	}
84
	return ret;
85
}
86

  
chunker_metadata.c
1
// chunkbuffer.c
2
// Author 
3
// Giuseppe Tropea
4
//
5
// Use the file compile to compile the program to build (assuming libavformat and libavcodec are 
6
// correctly installed your system).
7
//
8
// Run using
9
//
10
// ingestion myvideofile.mpg
11

  
12

  
13
#include "chunker_metadata.h"
14

  
15

  
16
void chunker_trim(char *s) {
17
	// Trim spaces and tabs from beginning:
18
	int i=0,j;
19
	while((s[i]==' ')||(s[i]=='\t')) {
20
		i++;
21
	}
22
	if(i>0) {
23
		for(j=0;j<strlen(s);j++) {
24
			s[j]=s[j+i];
25
		}
26
		s[j]='\0';
27
	}
28

  
29
	// Trim spaces and tabs from end:
30
	i=strlen(s)-1;
31
	while((s[i]==' ')||(s[i]=='\t') || s[i]=='\n') {
32
		i--;
33
	}
34
	if(i<(strlen(s)-1)) {
35
		s[i+1]='\0';
36
	}
37
}
38

  
39
/* Read config file for chunk strategy [numframes:num|size:num] and create a new chunk_buffer object
40
	numframes:num	fill each chunk with the same number of frame
41
	size:num	fill each chunk with the size of bytes no bigger than num
42
*/
43
struct chunker_metadata *chunkerInit(const char *config) {
44
	int isstrategy;
45
	char str[1000];
46
	char *p;
47
	printf("Calling chunkerInit...\n");
48
	FILE *fp = fopen(config,"r");
49
	ChunkerMetadata *cmeta = (ChunkerMetadata *)malloc(sizeof(ChunkerMetadata));
50
	cmeta->echunk = NULL;
51
	cmeta->size = 0;
52
	cmeta->val_strategy = 0;
53
	while(fgets(str,100,fp)!=NULL) {
54
		chunker_trim(str);
55
		if(str[0]=='#')
56
			continue;
57
		if(!strcmp(str,"[strategy]")) {
58
			isstrategy=1;
59
			continue;
60
		}
61
		if(isstrategy==1) {
62
			p = strtok(str,":");
63
			chunker_trim(p);
64
			if(!(strcmp(p,"numframes")))
65
				cmeta->strategy=0;
66
			if(!(strcmp(p,"size")))
67
				cmeta->strategy=1;
68
			p = strtok(NULL,":");
69
			sscanf(p,"%d",&cmeta->val_strategy);
70
			isstrategy=0;
71
		}
72
	}
73
	fclose(fp);
74
	printf("done!\n");
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff