~ubuntu-branches/ubuntu/trusty/xvidcap/trusty

« back to all changes in this revision

Viewing changes to .pc/03_ffmpeg.diff/src/xtoffmpeg.c

  • Committer: Bazaar Package Importer
  • Author(s): Alessio Treglia, Brian Thomason, Alessio Treglia
  • Date: 2010-02-27 11:54:32 UTC
  • Revision ID: james.westby@ubuntu.com-20100227115432-937ezeyo6exkkm38
Tags: 1.1.7-0.2ubuntu8
[ Brian Thomason ]
* Added patch for header file rename in x11proto-xext-dev (LP: #528643)
  + debian/patches/05_shmchange.diff

[ Alessio Treglia ]
* Bump compat file.
* Update debian/copyright.
* Bump Standards.
* Switch to debian 3.0 (quilt) format, remove debian/README.source

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * \file xtoffmpeg.c
 
3
 *
 
4
 * This file contains the functions for encoding captured frames on-the-fly
 
5
 * using libavcodec/-format
 
6
 */
 
7
/*
 
8
 * Copyright (C) 2003-07 Karl H. Beckers, Frankfurt
 
9
 * EMail: khb@jarre-de-the.net
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 *
 
16
 * This program is distributed in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software
 
23
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
24
 *
 
25
 */
 
26
 
 
27
#ifndef DOXYGEN_SHOULD_SKIP_THIS
 
28
#ifdef HAVE_CONFIG_H
 
29
#include <config.h>
 
30
#endif     // HAVE_CONFIG_H
 
31
 
 
32
#define DEBUGFILE "xtoffmpeg.c"
 
33
#endif     // DOXYGEN_SHOULD_SKIP_THIS
 
34
 
 
35
#ifdef USE_FFMPEG
 
36
 
 
37
#include <stdio.h>
 
38
#include <stdlib.h>
 
39
#include <limits.h>
 
40
#include <sys/types.h>
 
41
#include <unistd.h>
 
42
#include <fcntl.h>
 
43
#include <string.h>
 
44
#include <sys/time.h>                  /* for timeval struct and related
 
45
                                        * functions */
 
46
#include <math.h>
 
47
 
 
48
#include <X11/Intrinsic.h>
 
49
 
 
50
// xvidcap specific
 
51
#include "app_data.h"
 
52
#include "job.h"
 
53
#include "colors.h"
 
54
#include "frame.h"
 
55
#include "codecs.h"
 
56
#include "xvidcap-intl.h"
 
57
 
 
58
// ffmpeg stuff
 
59
#include <ffmpeg/avcodec.h>
 
60
#include <ffmpeg/avformat.h>
 
61
#include <ffmpeg/avdevice.h>
 
62
//#include <ffmpeg/dsputil.h>
 
63
#include <ffmpeg/swscale.h>
 
64
#include <ffmpeg/rgb2rgb.h>
 
65
#include <ffmpeg/fifo.h>
 
66
#define swscale_isRGB(x) ((x)==PIX_FMT_BGR32 || (x)==PIX_FMT_RGB24 \
 
67
                        || (x)==PIX_FMT_RGB565 || (x)==PIX_FMT_RGB555 \
 
68
                        || (x)==PIX_FMT_RGB8 || (x)==PIX_FMT_RGB4 \
 
69
                        || (x)==PIX_FMT_RGB4_BYTE || (x)==PIX_FMT_MONOBLACK)
 
70
#define swscale_isBGR(x) ((x)==PIX_FMT_RGB32 || (x)==PIX_FMT_BGR24 \
 
71
                        || (x)==PIX_FMT_BGR565 || (x)==PIX_FMT_BGR555 \
 
72
                        || (x)==PIX_FMT_BGR8 || (x)==PIX_FMT_BGR4 \
 
73
                        || (x)==PIX_FMT_BGR4_BYTE || (x)==PIX_FMT_MONOBLACK)
 
74
#define swscale_isSupportedIn(x) ((x)==PIX_FMT_YUV420P || (x)==PIX_FMT_YUYV422 \
 
75
                        || (x)==PIX_FMT_UYVY422 || (x)==PIX_FMT_RGB32 \
 
76
                        || (x)==PIX_FMT_BGR24 || (x)==PIX_FMT_BGR565 \
 
77
                        || (x)==PIX_FMT_BGR555 || (x)==PIX_FMT_BGR32 \
 
78
                        || (x)==PIX_FMT_RGB24|| (x)==PIX_FMT_RGB565 \
 
79
                        || (x)==PIX_FMT_RGB555 || (x)==PIX_FMT_GRAY8 \
 
80
                        || (x)==PIX_FMT_YUV410P || (x)==PIX_FMT_GRAY16BE \
 
81
                        || (x)==PIX_FMT_GRAY16LE || (x)==PIX_FMT_YUV444P \
 
82
                        || (x)==PIX_FMT_YUV422P || (x)==PIX_FMT_YUV411P \
 
83
                        || (x)==PIX_FMT_PAL8 || (x)==PIX_FMT_BGR8 \
 
84
                        || (x)==PIX_FMT_RGB8 || (x)==PIX_FMT_BGR4_BYTE \
 
85
                        || (x)==PIX_FMT_RGB4_BYTE)
 
86
// added jpeg stuff myself (yuvj*) because swscale actually DOES
 
87
// accept them
 
88
#define swscale_isSupportedOut(x) ((x)==PIX_FMT_YUV420P \
 
89
                        || (x)==PIX_FMT_YUYV422 || (x)==PIX_FMT_UYVY422 \
 
90
                        || (x)==PIX_FMT_YUV444P || (x)==PIX_FMT_YUV422P \
 
91
                        || (x)==PIX_FMT_YUV411P || swscale_isRGB(x) \
 
92
                        || swscale_isBGR(x) || (x)==PIX_FMT_NV12 \
 
93
                        || (x)==PIX_FMT_NV21 || (x)==PIX_FMT_GRAY16BE \
 
94
                        || (x)==PIX_FMT_GRAY16LE || (x)==PIX_FMT_GRAY8 \
 
95
                        || (x)==PIX_FMT_YUV410P \
 
96
                        || (x)==PIX_FMT_YUVJ420P || (x)==PIX_FMT_YUVJ422P \
 
97
                        || (x)==PIX_FMT_YUVJ444P)
 
98
 
 
99
#define PIX_FMT_ARGB32 PIX_FMT_RGBA32  /* this is just my personal
 
100
                                        * convenience */
 
101
 
 
102
/*
 
103
 * file globals
 
104
 */
 
105
/** \brief params for the codecs video */
 
106
static AVCodec *codec;
 
107
 
 
108
/** \brief an AVFrame as wrapper around the original image data */
 
109
static AVFrame *p_inpic;
 
110
 
 
111
/** \brief and one for the image converted to yuv420p */
 
112
static AVFrame *p_outpic;
 
113
 
 
114
/** \brief data buffer for output frame */
 
115
static uint8_t *outpic_buf;
 
116
 
 
117
/** \brief output buffer for encoded frame */
 
118
static uint8_t *outbuf;
 
119
 
 
120
/** \brief the size of the outbuf may be other than image_size */
 
121
static int outbuf_size;
 
122
 
 
123
/** \brief output file via avformat */
 
124
static AVFormatContext *output_file;
 
125
 
 
126
/** \brief ... plus related data */
 
127
static AVOutputFormat *file_oformat;
 
128
static AVStream *out_st = NULL;
 
129
 
 
130
/** \brief context for image resampling */
 
131
static struct SwsContext *img_resample_ctx;
 
132
 
 
133
/** \brief size of yuv image */
 
134
static int image_size;
 
135
 
 
136
/** \brief pix_fmt of original image */
 
137
static int input_pixfmt;
 
138
 
 
139
/** \brief store current video_pts for a/v sync */
 
140
static double video_pts;
 
141
 
 
142
/** \brief buffer memory used during 8bit palette conversion */
 
143
static uint8_t *scratchbuf8bit;
 
144
 
 
145
/** \brief pointer to the XVC_CapTypeOptions representing the currently
 
146
 * active capture mode (which certainly is mf here) */
 
147
static XVC_CapTypeOptions *target = NULL;
 
148
 
 
149
#ifdef DEBUG
 
150
static void dump8bit (const XImage * image, const u_int32_t * ct);
 
151
static void dump32bit (const XImage * input, const ColorInfo * c_info);
 
152
 
 
153
/** \todo: what about const-correctness for the next line */
 
154
static void x2ffmpeg_dump_ximage_info (XImage * img, FILE * fp);
 
155
#endif     // DEBUG
 
156
 
 
157
#ifdef HAVE_FFMPEG_AUDIO
 
158
 
 
159
#define MAX_AUDIO_PACKET_SIZE (128 * 1024)
 
160
 
 
161
#include <pthread.h>
 
162
#include <signal.h>
 
163
 
 
164
/**
 
165
 * \brief AVOutputStream taken from ffmpeg.c
 
166
 */
 
167
typedef struct AVOutputStream
 
168
{
 
169
    int file_index; /* file index */
 
170
    int index;  /* stream index in the output file */
 
171
    int source_index;   /* AVInputStream index */
 
172
    AVStream *st;   /* stream in the output file */
 
173
    int encoding_needed;    /* true if encoding needed for this stream */
 
174
    int frame_number;
 
175
    /* input pts and corresponding output pts for A/V sync */
 
176
    struct AVInputStream *sync_ist; /* input stream to sync against */
 
177
    int64_t sync_opts;  /* output frame counter, could be changed
 
178
                         * to some true timestamp */
 
179
    /* video only */
 
180
    int video_resample;
 
181
    AVFrame pict_tmp;   /* temporary image for resampling */
 
182
    struct SwsContext *img_resample_ctx;    /* for image resampling */
 
183
    int resample_height;
 
184
 
 
185
    int video_crop;
 
186
    int topBand;    /* cropping area sizes */
 
187
    int leftBand;
 
188
 
 
189
    int video_pad;
 
190
    int padtop; /* padding area sizes */
 
191
    int padbottom;
 
192
    int padleft;
 
193
    int padright;
 
194
 
 
195
    /* audio only */
 
196
    int audio_resample;
 
197
    ReSampleContext *resample;  /* for audio resampling */
 
198
    AVFifoBuffer fifo;  /* for compression: one audio fifo per
 
199
                         * codec */
 
200
    FILE *logfile;
 
201
} AVOutputStream;
 
202
 
 
203
typedef struct AVInputStream
 
204
{
 
205
    int file_index;
 
206
    int index;
 
207
    AVStream *st;
 
208
    int discard;    /* true if stream data should be discarded
 
209
                     */
 
210
    int decoding_needed;    /* true if the packets must be decoded in
 
211
                             * 'raw_fifo' */
 
212
    int64_t sample_index;   /* current sample */
 
213
 
 
214
    int64_t start;  /* time when read started */
 
215
    unsigned long frame;    /* current frame */
 
216
    int64_t next_pts;   /* synthetic pts for cases where pkt.pts
 
217
                         * is not defined */
 
218
    int64_t pts;    /* current pts */
 
219
    int is_start;   /* is 1 at the start and after a
 
220
                     * discontinuity */
 
221
} AVInputStream;
 
222
 
 
223
// FIXME: check if this all needs to be static global
 
224
/** \brief audio codec */
 
225
static AVCodec *au_codec = NULL;
 
226
 
 
227
/** \brief audio codec context */
 
228
static AVCodecContext *au_c = NULL;
 
229
 
 
230
/** \brief format context for audio input */
 
231
static AVFormatContext *ic = NULL;
 
232
 
 
233
/** \brief audio output stream */
 
234
static AVOutputStream *au_out_st = NULL;
 
235
 
 
236
/** \brief audio input stream */
 
237
static AVInputStream *au_in_st = NULL;
 
238
 
 
239
/** \brief buffer used during audio capture */
 
240
static uint8_t *audio_buf = NULL;
 
241
 
 
242
/** \brief buffer used during audio encoding */
 
243
static uint8_t *audio_out = NULL;
 
244
 
 
245
/** \brief thread coordination variables for interleaving audio and video
 
246
 *      capture. This is the thread's attributes */
 
247
static pthread_attr_t tattr;
 
248
 
 
249
/** \brief thread coordination variables for interleaving audio and video
 
250
 *      capture. This is the mutex lock */
 
251
static pthread_mutex_t mp = PTHREAD_MUTEX_INITIALIZER;
 
252
 
 
253
/** \brief thread coordination variables for interleaving audio and video
 
254
 *      capture. This is the thread's id */
 
255
static pthread_t tid = 0;
 
256
 
 
257
static int audio_thread_running = FALSE;
 
258
 
 
259
/** \brief store current audio_pts for a/v sync */
 
260
static double audio_pts;
 
261
 
 
262
/*
 
263
 * functions ...
 
264
 *
 
265
 */
 
266
 
 
267
/**
 
268
 * \brief adds an audio stream to AVFormatContext output_file
 
269
 *
 
270
 * @param job the current job
 
271
 * @return 0 on success or smth. else on failure
 
272
 */
 
273
static int
 
274
add_audio_stream (Job * job)
 
275
{
 
276
#define DEBUGFUNCTION "add_audio_stream()"
 
277
    AVInputFormat *grab_iformat = NULL;
 
278
    Boolean grab_audio = TRUE;
 
279
    AVFormatParameters params, *ap = &params;   // audio stream params
 
280
    int err, ret;
 
281
 
 
282
#ifdef DEBUG
 
283
    printf ("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
 
284
#endif     // DEBUG
 
285
 
 
286
    if (!strcmp (job->snd_device, "-")) {
 
287
        job->snd_device = "pipe:";
 
288
        grab_audio = FALSE;
 
289
    } else {
 
290
        grab_audio = TRUE;
 
291
    }
 
292
 
 
293
    // prepare input stream
 
294
    memset (ap, 0, sizeof (*ap));
 
295
//    ap->device = job->snd_device;
 
296
 
 
297
    if (grab_audio) {
 
298
        ap->sample_rate = target->sndrate;
 
299
        ap->channels = target->sndchannels;
 
300
 
 
301
        grab_iformat = av_find_input_format ("oss");
 
302
#ifdef DEBUG
 
303
        printf ("%s %s: grab iformat %p\n", DEBUGFILE, DEBUGFUNCTION,
 
304
                grab_iformat);
 
305
        if (grab_iformat)
 
306
            printf ("%s %s: grab iformat name %s\n", DEBUGFILE,
 
307
                    DEBUGFUNCTION, grab_iformat->name);
 
308
#endif     // DEBUG
 
309
    }
 
310
 
 
311
    err =
 
312
        av_open_input_file (&ic, job->snd_device,
 
313
                            (grab_audio ? grab_iformat : NULL), 0, ap);
 
314
    if (err < 0) {
 
315
        fprintf (stderr, _("%s %s: error opening input file %s: %i\n"),
 
316
                 DEBUGFILE, DEBUGFUNCTION, job->snd_device, err);
 
317
        return 1;
 
318
    }
 
319
    au_in_st = av_mallocz (sizeof (AVInputStream));
 
320
    if (!au_in_st || !ic) {
 
321
        fprintf (stderr,
 
322
                 _("%s %s: Could not alloc input stream ... aborting\n"),
 
323
                 DEBUGFILE, DEBUGFUNCTION);
 
324
        return 1;
 
325
    }
 
326
    au_in_st->st = ic->streams[0];
 
327
 
 
328
    // If not enough info to get the stream parameters, we decode
 
329
    // the first frames to get it. (used in mpeg case for example)
 
330
    ret = av_find_stream_info (ic);
 
331
    if (ret < 0) {
 
332
        fprintf (stderr, _("%s %s: could not find codec parameters\n"),
 
333
                 DEBUGFILE, DEBUGFUNCTION);
 
334
        if (au_in_st) {
 
335
            av_free (au_in_st);
 
336
            au_in_st = NULL;
 
337
        }
 
338
        return 1;
 
339
    }
 
340
    // init pts stuff
 
341
    au_in_st->next_pts = 0;
 
342
    au_in_st->is_start = 1;
 
343
 
 
344
#ifdef DEBUG
 
345
    dump_format (ic, 0, job->snd_device, 0);
 
346
#endif     // DEBUG
 
347
 
 
348
    // OUTPUT
 
349
    // setup output codec
 
350
    au_c = avcodec_alloc_context ();
 
351
    if (!au_c) {
 
352
        fprintf (stderr,
 
353
                 _
 
354
                 ("%s %s: could not allocate audio output codec context\n"),
 
355
                 DEBUGFILE, DEBUGFUNCTION);
 
356
        if (au_in_st) {
 
357
            av_free (au_in_st);
 
358
            au_in_st = NULL;
 
359
        }
 
360
        return 1;
 
361
    }
 
362
    // put sample parameters
 
363
    au_c->codec_id = xvc_audio_codecs[job->au_targetCodec].ffmpeg_id;
 
364
    au_c->codec_type = CODEC_TYPE_AUDIO;
 
365
    au_c->bit_rate = target->sndsize;
 
366
    au_c->sample_rate = target->sndrate;
 
367
    au_c->channels = target->sndchannels;
 
368
    // au_c->debug = 0x00000FFF;
 
369
 
 
370
    // prepare output stream
 
371
    au_out_st = av_mallocz (sizeof (AVOutputStream));
 
372
    if (!au_out_st) {
 
373
        fprintf (stderr,
 
374
                 _("%s %s: Could not alloc stream ... aborting\n"),
 
375
                 DEBUGFILE, DEBUGFUNCTION);
 
376
        if (au_in_st) {
 
377
            av_free (au_in_st);
 
378
            au_in_st = NULL;
 
379
        }
 
380
        return 1;
 
381
    }
 
382
    au_out_st->st = av_new_stream (output_file, 1);
 
383
    if (!au_out_st->st) {
 
384
        fprintf (stderr, _("%s %s: Could not alloc stream\n"),
 
385
                 DEBUGFILE, DEBUGFUNCTION);
 
386
        if (au_in_st) {
 
387
            av_free (au_in_st);
 
388
            au_in_st = NULL;
 
389
        }
 
390
        return 1;
 
391
    }
 
392
    au_out_st->st->codec = au_c;
 
393
 
 
394
    if (av_fifo_init (&au_out_st->fifo, 2 * MAX_AUDIO_PACKET_SIZE)) {
 
395
        fprintf (stderr,
 
396
                 _("%s %s: Can't initialize fifo for audio recording\n"),
 
397
                 DEBUGFILE, DEBUGFUNCTION);
 
398
        if (au_in_st) {
 
399
            av_free (au_in_st);
 
400
            au_in_st = NULL;
 
401
        }
 
402
        return 1;
 
403
    }
 
404
    // This bit is important for inputs other than self-sampled.
 
405
    // The sample rates and no of channels a user asks for
 
406
    // are the ones he/she wants in the encoded mpeg. For self-
 
407
    // sampled audio, these are also the values used for sampling.
 
408
    // Hence there is no resampling necessary (case 1).
 
409
    // When dubbing from a pipe or a different
 
410
    // file, we might have different sample rates or no of
 
411
    // channels
 
412
    // in the input file.....
 
413
    if (au_c->channels == au_in_st->st->codec->channels &&
 
414
        au_c->sample_rate == au_in_st->st->codec->sample_rate) {
 
415
        au_out_st->audio_resample = 0;
 
416
    } else {
 
417
        if (au_c->channels != au_in_st->st->codec->channels &&
 
418
            au_in_st->st->codec->codec_id == CODEC_ID_AC3) {
 
419
            // Special case for 5:1 AC3 input
 
420
            // and mono or stereo output
 
421
            // Request specific number of channels
 
422
            au_in_st->st->codec->channels = au_c->channels;
 
423
            if (au_c->sample_rate == au_in_st->st->codec->sample_rate)
 
424
                au_out_st->audio_resample = 0;
 
425
            else {
 
426
                au_out_st->audio_resample = 1;
 
427
                au_out_st->resample =
 
428
                    audio_resample_init (au_c->channels,
 
429
                                         au_in_st->st->codec->
 
430
                                         channels,
 
431
                                         au_c->sample_rate,
 
432
                                         au_in_st->st->codec->sample_rate);
 
433
                if (!au_out_st->resample) {
 
434
                    printf (_("%s %s: Can't resample. Aborting.\n"),
 
435
                            DEBUGFILE, DEBUGFUNCTION);
 
436
                    if (au_in_st) {
 
437
                        av_free (au_in_st);
 
438
                        au_in_st = NULL;
 
439
                    }
 
440
                    return 1;
 
441
                }
 
442
            }
 
443
            // Request specific number of channels
 
444
            au_in_st->st->codec->channels = au_c->channels;
 
445
        } else {
 
446
            au_out_st->audio_resample = 1;
 
447
            au_out_st->resample =
 
448
                audio_resample_init (au_c->channels,
 
449
                                     au_in_st->st->codec->channels,
 
450
                                     au_c->sample_rate,
 
451
                                     au_in_st->st->codec->sample_rate);
 
452
            if (!au_out_st->resample) {
 
453
                printf (_("%s %s: Can't resample. Aborting.\n"), DEBUGFILE,
 
454
                        DEBUGFUNCTION);
 
455
                if (au_in_st) {
 
456
                    av_free (au_in_st);
 
457
                    au_in_st = NULL;
 
458
                }
 
459
                return 1;
 
460
            }
 
461
        }
 
462
    }
 
463
    au_in_st->decoding_needed = 1;
 
464
    au_out_st->encoding_needed = 1;
 
465
 
 
466
    // open encoder
 
467
    au_codec = avcodec_find_encoder (au_out_st->st->codec->codec_id);
 
468
    if (avcodec_open (au_out_st->st->codec, au_codec) < 0) {
 
469
        fprintf (stderr,
 
470
                 _("%s %s: Error while opening codec for output stream\n"),
 
471
                 DEBUGFILE, DEBUGFUNCTION);
 
472
        if (au_in_st) {
 
473
            av_free (au_in_st);
 
474
            au_in_st = NULL;
 
475
        }
 
476
        return 1;
 
477
    }
 
478
    // open decoder
 
479
    au_codec = avcodec_find_decoder (ic->streams[0]->codec->codec_id);
 
480
    if (!au_codec) {
 
481
        fprintf (stderr,
 
482
                 _("%s %s: Unsupported codec (id=%d) for input stream\n"),
 
483
                 DEBUGFILE, DEBUGFUNCTION, ic->streams[0]->codec->codec_id);
 
484
        if (au_in_st) {
 
485
            av_free (au_in_st);
 
486
            au_in_st = NULL;
 
487
        }
 
488
        return 1;
 
489
    }
 
490
    if (avcodec_open (ic->streams[0]->codec, au_codec) < 0) {
 
491
        fprintf (stderr,
 
492
                 _("%s %s: Error while opening codec for input stream\n"),
 
493
                 DEBUGFILE, DEBUGFUNCTION);
 
494
        if (au_in_st) {
 
495
            av_free (au_in_st);
 
496
            au_in_st = NULL;
 
497
        }
 
498
        return 1;
 
499
    }
 
500
#ifdef DEBUG
 
501
    printf ("%s %s: Leaving with %i streams in oc\n", DEBUGFILE,
 
502
            DEBUGFUNCTION, output_file->nb_streams);
 
503
#endif     // DEBUG
 
504
    return 0;
 
505
#undef DEBUGFUNCTION
 
506
}
 
507
 
 
508
/**
 
509
 * \brief encode and write audio samples
 
510
 *
 
511
 * @param s output format context (output_file)
 
512
 * @param ost pointer to audio output stream
 
513
 * @param ist input stream information
 
514
 * @param buf the actual data sampled
 
515
 * @param size the size of the data sampled
 
516
 */
 
517
static void
 
518
do_audio_out (AVFormatContext * s, AVOutputStream * ost,
 
519
              const AVInputStream * ist, unsigned char *buf, int size)
 
520
{
 
521
#define DEBUGFUNCTION "do_audio_out()"
 
522
    uint8_t *buftmp;
 
523
    const int audio_out_size = 4 * MAX_AUDIO_PACKET_SIZE;
 
524
    int size_out, frame_bytes;
 
525
    AVCodecContext *enc;
 
526
 
 
527
    // SC: dynamic allocation of buffers
 
528
    if (!audio_buf)
 
529
        audio_buf = av_malloc (2 * MAX_AUDIO_PACKET_SIZE);
 
530
    if (!audio_out)
 
531
        audio_out = av_malloc (audio_out_size);
 
532
    if (!audio_out || !audio_buf)
 
533
        return;                        // Should signal an error !
 
534
 
 
535
    enc = ost->st->codec;
 
536
 
 
537
    // resampling is only used for pipe input here
 
538
    if (ost->audio_resample) {
 
539
        buftmp = audio_buf;
 
540
        size_out =
 
541
            audio_resample (ost->resample, (short *) buftmp, (short *) buf,
 
542
                            size / (ist->st->codec->channels * 2));
 
543
        size_out = size_out * enc->channels * 2;
 
544
    } else {
 
545
        buftmp = buf;
 
546
        size_out = size;
 
547
    }
 
548
 
 
549
    // now encode as many frames as possible
 
550
    if (enc->frame_size > 1) {
 
551
        // output resampled raw samples
 
552
        av_fifo_write (&ost->fifo, buftmp, size_out);
 
553
        frame_bytes = enc->frame_size * 2 * enc->channels;
 
554
 
 
555
        while (av_fifo_read (&ost->fifo, audio_buf, frame_bytes) == 0) {
 
556
            AVPacket pkt;
 
557
 
 
558
            // initialize audio output packet
 
559
            av_init_packet (&pkt);
 
560
 
 
561
            pkt.size =
 
562
                avcodec_encode_audio (enc, audio_out, size_out,
 
563
                                      (short *) audio_buf);
 
564
 
 
565
            if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE) {
 
566
                pkt.pts =
 
567
                    av_rescale_q (enc->coded_frame->pts, enc->time_base,
 
568
                                  ost->st->time_base);
 
569
            }
 
570
            pkt.flags |= PKT_FLAG_KEY;
 
571
            pkt.stream_index = ost->st->index;
 
572
 
 
573
            pkt.data = audio_out;
 
574
            if (pthread_mutex_trylock (&mp) == 0) {
 
575
                // write the compressed frame in the media file
 
576
                if (av_interleaved_write_frame (s, &pkt) != 0) {
 
577
                    fprintf (stderr,
 
578
                             _("%s %s: Error while writing audio frame\n"),
 
579
                             DEBUGFILE, DEBUGFUNCTION);
 
580
                    // exit (1);
 
581
                    return;
 
582
                }
 
583
 
 
584
                if (pthread_mutex_unlock (&mp) > 0) {
 
585
                    fprintf (stderr,
 
586
                             _
 
587
                             ("%s %s: Couldn't unlock mutex lock for writing audio frame\n"),
 
588
                             DEBUGFILE, DEBUGFUNCTION);
 
589
                }
 
590
            }
 
591
        }
 
592
    } else {
 
593
        AVPacket pkt;
 
594
 
 
595
        av_init_packet (&pkt);
 
596
 
 
597
        /* output a pcm frame */
 
598
        /* XXX: change encoding codec API to avoid this ? */
 
599
        switch (enc->codec->id) {
 
600
        case CODEC_ID_PCM_S32LE:
 
601
        case CODEC_ID_PCM_S32BE:
 
602
        case CODEC_ID_PCM_U32LE:
 
603
        case CODEC_ID_PCM_U32BE:
 
604
            size_out = size_out << 1;
 
605
            break;
 
606
        case CODEC_ID_PCM_S24LE:
 
607
        case CODEC_ID_PCM_S24BE:
 
608
        case CODEC_ID_PCM_U24LE:
 
609
        case CODEC_ID_PCM_U24BE:
 
610
        case CODEC_ID_PCM_S24DAUD:
 
611
            size_out = size_out / 2 * 3;
 
612
            break;
 
613
        case CODEC_ID_PCM_S16LE:
 
614
        case CODEC_ID_PCM_S16BE:
 
615
        case CODEC_ID_PCM_U16LE:
 
616
        case CODEC_ID_PCM_U16BE:
 
617
            break;
 
618
        default:
 
619
            size_out = size_out >> 1;
 
620
            break;
 
621
        }
 
622
        pkt.size =
 
623
            avcodec_encode_audio (enc, audio_out, size_out, (short *) buftmp);
 
624
        pkt.stream_index = ost->st->index;
 
625
        pkt.data = audio_out;
 
626
        if (enc->coded_frame && enc->coded_frame->pts != AV_NOPTS_VALUE)
 
627
            pkt.pts =
 
628
                av_rescale_q (enc->coded_frame->pts, enc->time_base,
 
629
                              ost->st->time_base);
 
630
        pkt.flags |= PKT_FLAG_KEY;
 
631
        av_interleaved_write_frame (s, &pkt);
 
632
    }
 
633
 
 
634
#undef DEBUGFUNCTION
 
635
}
 
636
 
 
637
/**
 
638
 * \brief signal handler for stopping the audio capture thread which
 
639
 *      runs till sent a SIGUSR1 signal
 
640
 */
 
641
static void
 
642
cleanup_thread_when_stopped ()
 
643
{
 
644
#define DEBUGFUNCTION "cleanup_thread_when_stopped()"
 
645
    int ret;
 
646
    AVPacket pkt;
 
647
    int fifo_bytes;
 
648
    AVCodecContext *enc;
 
649
    int bit_buffer_size = 1024 * 256;
 
650
    uint8_t *bit_buffer = NULL;
 
651
    short *samples = NULL;
 
652
 
 
653
#ifdef DEBUG
 
654
    printf ("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
 
655
#endif     // DEBUG
 
656
 
 
657
    av_init_packet (&pkt);
 
658
//    pkt.stream_index= ost->index;
 
659
 
 
660
    enc = au_out_st->st->codec;
 
661
    samples = av_malloc (AVCODEC_MAX_AUDIO_FRAME_SIZE);
 
662
    bit_buffer = av_malloc (bit_buffer_size);
 
663
    fifo_bytes = av_fifo_size (&au_out_st->fifo);
 
664
    ret = 0;
 
665
 
 
666
    /* encode any samples remaining in fifo */
 
667
    if (fifo_bytes > 0 &&
 
668
        enc->codec->capabilities & CODEC_CAP_SMALL_LAST_FRAME &&
 
669
        bit_buffer && samples) {
 
670
        int fs_tmp = enc->frame_size;
 
671
 
 
672
        enc->frame_size = fifo_bytes / (2 * enc->channels);
 
673
        if (av_fifo_read (&au_out_st->fifo, (uint8_t *) samples, fifo_bytes) ==
 
674
            0) {
 
675
            ret =
 
676
                avcodec_encode_audio (enc, bit_buffer, bit_buffer_size,
 
677
                                      samples);
 
678
        }
 
679
        enc->frame_size = fs_tmp;
 
680
    }
 
681
    if (ret <= 0) {
 
682
        ret = avcodec_encode_audio (enc, bit_buffer, bit_buffer_size, NULL);
 
683
    }
 
684
    pkt.flags |= PKT_FLAG_KEY;
 
685
 
 
686
    if (samples) {
 
687
        av_free (samples);
 
688
        samples = NULL;
 
689
    }
 
690
    if (bit_buffer) {
 
691
        av_free (bit_buffer);
 
692
        bit_buffer = NULL;
 
693
    }
 
694
    if (audio_out) {
 
695
        av_free (audio_out);
 
696
        audio_out = NULL;
 
697
    }
 
698
    if (audio_buf) {
 
699
        av_free (audio_buf);
 
700
        audio_buf = NULL;
 
701
    }
 
702
    if (au_in_st) {
 
703
        av_free (au_in_st);
 
704
        au_in_st = NULL;
 
705
    }
 
706
 
 
707
    av_close_input_file (ic);
 
708
 
 
709
#ifdef DEBUG
 
710
    printf ("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
 
711
#endif     // DEBUG
 
712
 
 
713
    audio_thread_running = FALSE;
 
714
    pthread_exit (&ret);
 
715
#undef DEBUGFUNCTION
 
716
}
 
717
 
 
718
/**
 
719
 * \brief this function implements the thread doing the audio capture and
 
720
 *      interleaving the captured audio frames with the video output
 
721
 *
 
722
 * @param job the current job
 
723
 */
 
724
static void
 
725
capture_audio_thread (Job * job)
 
726
{
 
727
#define DEBUGFUNCTION "capture_audio_thread()"
 
728
    XVC_AppData *app = xvc_appdata_ptr ();
 
729
    unsigned long start, stop, start_s, stop_s;
 
730
    struct timeval thr_curr_time;
 
731
    long sleep;
 
732
    int ret, len, data_size;
 
733
    uint8_t *ptr, *data_buf;
 
734
    static unsigned int samples_size = 0;
 
735
    static short *samples = NULL;
 
736
    AVPacket pkt;
 
737
 
 
738
    audio_thread_running = TRUE;
 
739
    signal (SIGUSR1, cleanup_thread_when_stopped);
 
740
 
 
741
    while (TRUE) {
 
742
        // get start time
 
743
        gettimeofday (&thr_curr_time, NULL);
 
744
        start_s = thr_curr_time.tv_sec;
 
745
        start = thr_curr_time.tv_usec;
 
746
 
 
747
        if ((job->state & VC_PAUSE) && !(job->state & VC_STEP)) {
 
748
            pthread_mutex_lock (&(app->recording_paused_mutex));
 
749
            pthread_cond_wait (&(app->recording_condition_unpaused),
 
750
                               &(app->recording_paused_mutex));
 
751
            pthread_mutex_unlock (&(app->recording_paused_mutex));
 
752
        } else if (job->state == VC_REC) {
 
753
 
 
754
            audio_pts = (double)
 
755
                au_out_st->st->pts.val *
 
756
                au_out_st->st->time_base.num / au_out_st->st->time_base.den;
 
757
            video_pts =
 
758
                (double) out_st->pts.val * out_st->time_base.num /
 
759
                out_st->time_base.den;
 
760
 
 
761
            // sometimes we need to pause writing audio packets for a/v
 
762
            // sync (when audio_pts >= video_pts)
 
763
            // now, if we're reading from a file/pipe, we stop sampling or
 
764
            // else the audio track in the video would become choppy (packets
 
765
            // missing where they were read but not written)
 
766
            // for real-time sampling we can't do that because otherwise
 
767
            // the input packets queue up and will eventually be sampled
 
768
            // (only later) and lead to out-of-sync audio (video faster)
 
769
            if (audio_pts < video_pts) {
 
770
                // read a packet from it and output it in the fifo
 
771
                if (av_read_frame (ic, &pkt) < 0) {
 
772
                    fprintf (stderr,
 
773
                             _("%s %s: error reading audio packet\n"),
 
774
                             DEBUGFILE, DEBUGFUNCTION);
 
775
                }
 
776
                len = pkt.size;
 
777
                ptr = pkt.data;
 
778
                while (len > 0) {
 
779
                    // decode the packet if needed
 
780
                    data_buf = NULL;   /* fail safe */
 
781
                    data_size = 0;
 
782
 
 
783
                    if (au_in_st->decoding_needed) {
 
784
                        samples = av_fast_realloc (samples, &samples_size,
 
785
                                                   FFMAX (pkt.size,
 
786
                                                          AVCODEC_MAX_AUDIO_FRAME_SIZE));
 
787
                        data_size = samples_size;
 
788
                        /* XXX: could avoid copy if PCM 16 bits with same
 
789
                         * endianness as CPU */
 
790
                        ret =
 
791
                            avcodec_decode_audio2 (au_in_st->st->codec, samples,
 
792
                                                   &data_size, ptr, len);
 
793
                        if (ret < 0) {
 
794
                            fprintf (stderr,
 
795
                                     _
 
796
                                     ("%s %s: couldn't decode captured audio packet\n"),
 
797
                                     DEBUGFILE, DEBUGFUNCTION);
 
798
                            break;
 
799
                        }
 
800
                        ptr += ret;
 
801
                        len -= ret;
 
802
                        /* Some bug in mpeg audio decoder gives */
 
803
                        /* data_size < 0, it seems they are overflows */
 
804
                        if (data_size <= 0) {
 
805
                            /* no audio frame */
 
806
#ifdef DEBUG
 
807
                            fprintf (stderr, _("%s %s: no audio frame\n"),
 
808
                                     DEBUGFILE, DEBUGFUNCTION);
 
809
#endif     // DEBUG
 
810
                            continue;
 
811
                        }
 
812
                        data_buf = (uint8_t *) samples;
 
813
                        au_in_st->next_pts +=
 
814
                            ((int64_t) AV_TIME_BASE / 2 * data_size) /
 
815
                            (au_in_st->st->codec->sample_rate *
 
816
                             au_in_st->st->codec->channels);
 
817
                    } else {
 
818
                        // FIXME: dunno about the following
 
819
                        au_in_st->next_pts +=
 
820
                            ((int64_t) AV_TIME_BASE *
 
821
                             au_in_st->st->codec->frame_size) /
 
822
                            (au_in_st->st->codec->sample_rate *
 
823
                             au_in_st->st->codec->channels);
 
824
                        data_buf = ptr;
 
825
                        data_size = len;
 
826
                        ret = len;
 
827
                        len = 0;
 
828
                    }
 
829
 
 
830
                    do_audio_out (output_file, au_out_st, au_in_st,
 
831
                                  data_buf, data_size);
 
832
                }
 
833
                // discard packet
 
834
                av_free_packet (&pkt);
 
835
            }                          // end outside if pts ...
 
836
            else {
 
837
                if (strcmp (job->snd_device, "pipe:") < 0)
 
838
                    if (av_read_frame (ic, &pkt) < 0) {
 
839
                        fprintf (stderr, _("error reading audio packet\n"));
 
840
                    }
 
841
#ifdef DEBUG
 
842
                printf (_("%s %s: dropping audio frame %f %f\n"),
 
843
                        DEBUGFILE, DEBUGFUNCTION, audio_pts, video_pts);
 
844
#endif     // DEBUG
 
845
            }
 
846
        }                              // end if VC_REC
 
847
        // get end time
 
848
        gettimeofday (&thr_curr_time, NULL);
 
849
        stop_s = thr_curr_time.tv_sec;
 
850
        stop = thr_curr_time.tv_usec;
 
851
        stop += ((stop_s - start_s) * 1000000);
 
852
        sleep = (1000000 / target->sndrate) - (stop - start);
 
853
        /**
 
854
         * \todo perhaps this whole stuff is irrelevant. Haven't really
 
855
         *      seen a situation where the encoding was faster than the time
 
856
         *      needed for a decent frame-rate. need to look into more
 
857
         *      details about audio/video sync in libavcodec/-format
 
858
         *      the strange thing, however is: If I leave away the getting of
 
859
         *      start/end time and the usleep stuff, normal audio capture
 
860
         *      works, piped audio doesn't *BLINK*
 
861
         */
 
862
        if (sleep < 0)
 
863
            sleep = 0;
 
864
 
 
865
        usleep (sleep);
 
866
    }                                  // end while(TRUE) loop
 
867
    ret = 1;
 
868
    audio_thread_running = FALSE;
 
869
    pthread_exit (&ret);
 
870
#undef DEBUGFUNCTION
 
871
}
 
872
 
 
873
#endif     // HAVE_FFMPEG_AUDIO
 
874
 
 
875
/**
 
876
 * \brief write encoded video data
 
877
 *
 
878
 * @param s pointer to format context (output_file)
 
879
 * @param ost video output stream
 
880
 * @param buf buffer with actual data
 
881
 * @param size size of encoded data
 
882
 */
 
883
static void
 
884
do_video_out (AVFormatContext * s, AVStream * ost, unsigned char *buf, int size)
 
885
{
 
886
#define DEBUGFUNCTION "do_video_out()"
 
887
    AVCodecContext *enc;
 
888
    AVPacket pkt;
 
889
 
 
890
#ifdef DEBUG
 
891
    printf
 
892
        ("%s %s: Entering with format context %p output stream %p buffer %p size %i\n",
 
893
         DEBUGFILE, DEBUGFUNCTION, s, ost, buf, size);
 
894
#endif     // DEBUG
 
895
 
 
896
    enc = ost->codec;
 
897
 
 
898
    // initialize video output packet
 
899
    av_init_packet (&pkt);
 
900
 
 
901
    if (enc->coded_frame) {
 
902
        if (enc->coded_frame->pts != AV_NOPTS_VALUE) {
 
903
            pkt.pts =
 
904
                av_rescale_q (enc->coded_frame->pts, enc->time_base,
 
905
                              ost->time_base);
 
906
        }
 
907
        if (enc->coded_frame->key_frame)
 
908
            pkt.flags |= PKT_FLAG_KEY;
 
909
    }
 
910
 
 
911
    pkt.stream_index = ost->index;
 
912
    pkt.data = buf;
 
913
    pkt.size = size;
 
914
 
 
915
    if (av_interleaved_write_frame (s, &pkt) != 0) {
 
916
        fprintf (stderr, _("%s %s: Error while writing video frame\n"),
 
917
                 DEBUGFILE, DEBUGFUNCTION);
 
918
        // exit (1);
 
919
        return;
 
920
    }
 
921
#ifdef DEBUG
 
922
    printf ("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
 
923
#endif     // DEBUG
 
924
 
 
925
#undef DEBUGFUNCTION
 
926
}
 
927
 
 
928
/**
 
929
 * \brief convert bgra32 to rgba32
 
930
 *
 
931
 * needed on Solaris/SPARC because the ffmpeg version used doesn't know
 
932
 * PIX_FMT_ABGR32, i.e. byte ordering is not taken care of
 
933
 * @param image the XImage to convert
 
934
 */
 
935
static void
 
936
myABGR32toARGB32 (XImage * image)
 
937
{
 
938
#define DEBUGFUNCTION "myABGR32toARGB32()"
 
939
    char *pdata, *counter;
 
940
 
 
941
#ifdef DEBUG
 
942
    printf ("%s %s: Entering with image %p\n", DEBUGFILE, DEBUGFUNCTION, image);
 
943
#endif     // DEBUG
 
944
 
 
945
    pdata = image->data;
 
946
 
 
947
    for (counter = pdata;
 
948
         counter < (pdata + (image->width * image->height * 4)); counter += 4) {
 
949
        char swap;
 
950
 
 
951
        if (image->byte_order) {       // MSBFirst has order argb -> abgr
 
952
            // = rgba32
 
953
            swap = *(counter + 1);
 
954
            *(counter + 1) = *(counter + 3);
 
955
            *(counter + 3) = swap;
 
956
        } else {                       // LSBFirst has order bgra -> rgba
 
957
            swap = *counter;
 
958
            *counter = *(counter + 2);
 
959
            *(counter + 2) = swap;
 
960
        }
 
961
    }
 
962
 
 
963
#ifdef DEBUG
 
964
    printf ("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
 
965
#endif     // DEBUG
 
966
 
 
967
#undef DEBUGFUNCTION
 
968
}
 
969
 
 
970
/**
 
971
 * \brief convert pal8 to rgba32
 
972
 *
 
973
 * libswscale does not support pal8 input atm
 
974
 * @param image the XImage to convert
 
975
 * @param p_inpic pointer to a frame to where the converted output is written
 
976
 * @param job the current job
 
977
 * \todo very current ffmpeg versions seem to make this unneccessary
 
978
 */
 
979
static void
 
980
myPAL8toRGB24 (XImage * image, AVFrame * p_inpic, Job * job)
 
981
{
 
982
#define DEBUGFUNCTION "myABGR32toRGB24()"
 
983
 
 
984
    u_int32_t *color_table = job->color_table;
 
985
    int y = 0, x = 0;
 
986
    uint8_t *out_cursor = NULL;
 
987
    uint8_t *out = (uint8_t *) p_inpic->data[0];
 
988
 
 
989
    /**
 
990
     * 8bit pseudo-color images may have lines padded by excess bytes
 
991
     * these need to be removed before conversion
 
992
     * \todo other formats might also have this problem
 
993
     */
 
994
    for (y = 0; y < image->height; y++) {
 
995
        out_cursor = (uint8_t *) image->data + (y * image->bytes_per_line);
 
996
        for (x = 0; x < image->width; x++) {
 
997
            *out++ = ((color_table[*out_cursor] & 0x00FF0000) >> 16);
 
998
            *out++ = ((color_table[*out_cursor] & 0x0000FF00) >> 8);
 
999
            *out++ = (color_table[*out_cursor] & 0x000000FF);
 
1000
            out_cursor++;
 
1001
        }
 
1002
    }
 
1003
 
 
1004
#undef DEBUGFUNCTION
 
1005
}
 
1006
 
 
1007
/**
 
1008
 * \brief prepare the color table for pseudo color input to libavcodec's
 
1009
 *      imgconvert
 
1010
 *
 
1011
 * I'm downsampling the 16 bit color entries to 8 bit as it expects
 
1012
 * 32 bit (=4 * 8) from looking at imgconvert_template.c I'd say libavcodec
 
1013
 * expects argb logically, not byte-wise
 
1014
 * @param colors a pointer to the colors as contained in the captured XImage
 
1015
 * @param ncolors the number of colors present
 
1016
 * @return a pointer to the converted color table
 
1017
 */
 
1018
u_int32_t *
 
1019
xvc_ffmpeg_get_color_table (XColor * colors, int ncolors)
 
1020
{
 
1021
#define DEBUGFUNCTION "xvc_ffmpeg_get_color_table()"
 
1022
    u_int32_t *color_table, *pixel;
 
1023
    int i; // , n;
 
1024
 
 
1025
#ifdef DEBUG
 
1026
    printf ("%s %s: Entering with colors %p and %i colors\n",
 
1027
            DEBUGFILE, DEBUGFUNCTION, colors, ncolors);
 
1028
#endif     // DEBUG
 
1029
 
 
1030
    color_table = malloc (256 * 4);
 
1031
    if (!color_table)
 
1032
        return (NULL);
 
1033
 
 
1034
    pixel = color_table;
 
1035
    for (i = 0; i < ncolors; i++) {
 
1036
        u_int32_t color_table_entry, swap;
 
1037
 
 
1038
        color_table_entry = 0;
 
1039
        // alpha alway zero
 
1040
 
 
1041
        swap = colors[i].red;
 
1042
        swap &= 0x0000FF00;            // color is 16 bits, delete ls 8 bits
 
1043
        swap <<= 8;                    // then shift ms 8 bits into position
 
1044
        color_table_entry = (color_table_entry | swap);
 
1045
 
 
1046
        swap = colors[i].green;
 
1047
        swap &= 0x0000FF00;            /* color is 16 bits, ms 8 bits already
 
1048
                                        * in position, delete ls 8 bits */
 
1049
        color_table_entry = (color_table_entry | swap);
 
1050
 
 
1051
        swap = colors[i].blue;
 
1052
        swap >>= 8;
 
1053
        color_table_entry = (color_table_entry | swap);
 
1054
 
 
1055
        *pixel = color_table_entry;
 
1056
        pixel++;
 
1057
    }
 
1058
#ifdef DEBUG
 
1059
    printf ("%s %s: color_table pointer: %p\n",
 
1060
            DEBUGFILE, DEBUGFUNCTION, color_table);
 
1061
    printf ("%s %s: color_table third entry: 0x%.8X\n",
 
1062
            DEBUGFILE, DEBUGFUNCTION, *(color_table + 2));
 
1063
    // first and second black & white
 
1064
#endif     // DEBUG
 
1065
 
 
1066
#ifdef DEBUG
 
1067
    printf ("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
 
1068
#endif     // DEBUG
 
1069
 
 
1070
    return color_table;
 
1071
#undef DEBUGFUNCTION
 
1072
}
 
1073
 
 
1074
/**
 
1075
 * \brief prepare the output file or pipe
 
1076
 *
 
1077
 * need to determine which first and do things like making the filename
 
1078
 * absolute etc.
 
1079
 * @param jFileName the filename as contained in the current job
 
1080
 * @param oc output format context (output_file)
 
1081
 * @param number the movie number
 
1082
 */
 
1083
static void
 
1084
prepareOutputFile (char *jFileName, AVFormatContext * oc, int number)
 
1085
{
 
1086
#define DEBUGFUNCTION "prepareOutputFile()"
 
1087
 
 
1088
#ifdef DEBUG
 
1089
    printf
 
1090
        ("%s %s: Entering with filename %s format context %p and number %i\n",
 
1091
         DEBUGFILE, DEBUGFUNCTION, jFileName, oc, number);
 
1092
#endif     // DEBUG
 
1093
 
 
1094
    // prepare output file for format context
 
1095
 
 
1096
    if ((strcasecmp (jFileName, "-") == 0)
 
1097
        || (strcasecmp (jFileName, "pipe:") == 0)) {
 
1098
        jFileName = "pipe:";
 
1099
        snprintf (oc->filename, sizeof (oc->filename), "pipe:");
 
1100
        // register_protocol (&pipe_protocol);
 
1101
    } else {
 
1102
        char first;
 
1103
        char tmp_buf[PATH_MAX + 1];
 
1104
 
 
1105
        first = jFileName[0];
 
1106
        sprintf (tmp_buf, jFileName, number);
 
1107
 
 
1108
        // if the filename's first char is a / we have an absolute path
 
1109
        // and we want one for the file URL. If we don't have one, we
 
1110
        // construct one
 
1111
        if (first != '/') {
 
1112
            sprintf (oc->filename, "file://%s/%s", getenv ("PWD"), tmp_buf);
 
1113
        } else {
 
1114
            sprintf (oc->filename, "file://%s", tmp_buf);
 
1115
        }
 
1116
        // register_protocol (&file_protocol);
 
1117
    }
 
1118
 
 
1119
#ifdef DEBUG
 
1120
    printf ("%s %s: Leaving with filename %s\n", DEBUGFILE, DEBUGFUNCTION,
 
1121
            oc->filename);
 
1122
#endif     // DEBUG
 
1123
 
 
1124
#undef DEBUGFUNCTION
 
1125
}
 
1126
 
 
1127
/**
 
1128
 * \brief add a video output stream to the output format
 
1129
 *
 
1130
 * @param oc output format context (output_file)
 
1131
 * @param image captured XImage
 
1132
 * @param input_pixfmt picture format of the input picture
 
1133
 * @param codec_id libavcodec's codec id of the codec to use for encoding
 
1134
 * @param job pointer to the current job
 
1135
 * @return pointer to the AVStream that has been added to the output format
 
1136
 */
 
1137
static AVStream *
 
1138
add_video_stream (AVFormatContext * oc, const XImage * image,
 
1139
                  int input_pixfmt, int codec_id, Job * job)
 
1140
{
 
1141
#define DEBUGFUNCTION "add_video_stream()"
 
1142
    AVStream *st;
 
1143
    int pix_fmt_mask = 0, i = 0;
 
1144
    int quality = target->quality, qscale = 0;
 
1145
    XVC_AppData *app = xvc_appdata_ptr ();
 
1146
 
 
1147
#ifdef DEBUG
 
1148
    printf ("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
 
1149
#endif     // DEBUG
 
1150
 
 
1151
    st = av_new_stream (oc, 0);
 
1152
    if (!st) {
 
1153
        fprintf (stderr,
 
1154
                 _("%s %s: Could not alloc output stream\n"), DEBUGFILE,
 
1155
                 DEBUGFUNCTION);
 
1156
        exit (1);
 
1157
    }
 
1158
 
 
1159
    st->codec->codec_id = codec_id;
 
1160
    st->codec->codec_type = CODEC_TYPE_VIDEO;
 
1161
 
 
1162
    // find the video encoder
 
1163
    codec = avcodec_find_encoder (st->codec->codec_id);
 
1164
    if (!codec) {
 
1165
        fprintf (stderr, _("%s %s: video codec not found\n"),
 
1166
                 DEBUGFILE, DEBUGFUNCTION);
 
1167
        exit (1);
 
1168
    }
 
1169
    // put sample parameters
 
1170
    // resolution must be a multiple of two ... this is taken care of
 
1171
    // elsewhere but needs to be ensured for rescaled dimensions, too
 
1172
    if (app->rescale != 100) {
 
1173
        int n;
 
1174
        double r;
 
1175
 
 
1176
        r = sqrt ((double) app->rescale / 100.0);
 
1177
 
 
1178
        n = image->width * r;
 
1179
        if (n % 2 > 0)
 
1180
            n--;
 
1181
        st->codec->width = n;
 
1182
 
 
1183
        n = image->height * r;
 
1184
        if (n % 2 > 0)
 
1185
            n--;
 
1186
        st->codec->height = n;
 
1187
    } else {
 
1188
        st->codec->width = image->width;
 
1189
        st->codec->height = image->height;
 
1190
    }
 
1191
 
 
1192
    // mt init
 
1193
    if (codec_id == CODEC_ID_MPEG4 || codec_id == CODEC_ID_MPEG1VIDEO ||
 
1194
        codec_id == CODEC_ID_MPEG2VIDEO) {
 
1195
        // the max threads is taken from ffmpeg's mpegvideo.c
 
1196
        avcodec_thread_init (st->codec, XVC_MIN (4,
 
1197
                                                 (st->codec->height +
 
1198
                                                  15) / 16));
 
1199
    }
 
1200
    // time base: this is the fundamental unit of time (in seconds) in
 
1201
    // terms of which frame timestamps are represented. for fixed-fps
 
1202
    // content, timebase should be 1/framerate and timestamp increments
 
1203
    // should be identically 1.
 
1204
    st->codec->time_base.den = target->fps.num;
 
1205
    st->codec->time_base.num = target->fps.den;
 
1206
    // emit one intra frame every fifty frames at most
 
1207
    st->codec->gop_size = 50;
 
1208
    st->codec->mb_decision = 2;
 
1209
    st->codec->me_method = 1;
 
1210
 
 
1211
    // find suitable pix_fmt for codec
 
1212
    st->codec->pix_fmt = -1;
 
1213
    if (codec->pix_fmts != NULL) {
 
1214
        for (i = 0; codec->pix_fmts[i] != -1; i++) {
 
1215
            if (0 <= codec->pix_fmts[i] &&
 
1216
                codec->pix_fmts[i] < (sizeof (int) * 8))
 
1217
                pix_fmt_mask |= (1 << codec->pix_fmts[i]);
 
1218
        }
 
1219
        st->codec->pix_fmt =
 
1220
            avcodec_find_best_pix_fmt (pix_fmt_mask, input_pixfmt, FALSE, NULL);
 
1221
    }
 
1222
#ifdef DEBUG
 
1223
    printf
 
1224
        ("%s %s: pix_fmt_mask %i, has alpha %i, input_pixfmt %i, output pixfmt %i\n",
 
1225
         DEBUGFILE, DEBUGFUNCTION, pix_fmt_mask,
 
1226
         FALSE, input_pixfmt, st->codec->pix_fmt);
 
1227
#endif     // DEBUG
 
1228
 
 
1229
    if (!swscale_isSupportedIn (input_pixfmt)) {
 
1230
        fprintf (stderr,
 
1231
                 _
 
1232
                 ("%s %s: The picture format you are grabbing (%i) is not supported by libswscale ... aborting\n"),
 
1233
                 DEBUGFILE, DEBUGFUNCTION, input_pixfmt);
 
1234
        exit (1);
 
1235
    }
 
1236
    if (!swscale_isSupportedOut (st->codec->pix_fmt)) {
 
1237
        st->codec->pix_fmt = -1;
 
1238
    }
 
1239
    // fallback pix fmts
 
1240
    if (st->codec->pix_fmt < 0) {
 
1241
        if (job->target >= CAP_MF) {
 
1242
            st->codec->pix_fmt = PIX_FMT_YUV420P;
 
1243
        } else {
 
1244
            st->codec->pix_fmt = PIX_FMT_RGB24;
 
1245
        }
 
1246
    }
 
1247
    // flags
 
1248
    st->codec->flags |= CODEC_FLAG2_FAST;
 
1249
    // there is no trellis quantiser in libav* for mjpeg
 
1250
    if (st->codec->codec_id != CODEC_ID_MJPEG)
 
1251
        st->codec->flags |= CODEC_FLAG_TRELLIS_QUANT;
 
1252
    st->codec->flags &= ~CODEC_FLAG_OBMC;
 
1253
    // some formats want stream headers to be seperate
 
1254
    if (oc->oformat->flags & AVFMT_GLOBALHEADER)
 
1255
        st->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
 
1256
 
 
1257
    // quality through VBR
 
1258
    st->codec->flags |= CODEC_FLAG_QSCALE;
 
1259
    qscale = (100.0 - quality + 1.0) / 3.3;
 
1260
    st->codec->global_quality = st->quality = FF_QP2LAMBDA * qscale;
 
1261
    // 0.0 = default qscale
 
1262
    if (qscale > 0)
 
1263
        st->codec->qmin = st->codec->qmax = qscale;
 
1264
 
 
1265
#ifdef DEBUG
 
1266
    printf ("%s %s: Leaving with %i streams in oc, bitrate %i, and qscale %i\n",
 
1267
            DEBUGFILE, DEBUGFUNCTION, oc->nb_streams, st->codec->bit_rate,
 
1268
            qscale);
 
1269
#endif     // DEBUG
 
1270
 
 
1271
    return st;
 
1272
#undef DEBUGFUNCTION
 
1273
}
 
1274
 
 
1275
/**
 
1276
 * \brief guess the picture format of the captured image
 
1277
 *
 
1278
 * @param image captured XImage
 
1279
 * @param c_info needed for alpha channel info
 
1280
 * @return libavcodec's picture format
 
1281
 */
 
1282
static int
 
1283
guess_input_pix_fmt (const XImage * image, const ColorInfo * c_info)
 
1284
{
 
1285
#define DEBUGFUNCTION "guess_input_pix_fmt()"
 
1286
    int input_pixfmt;
 
1287
 
 
1288
    switch (image->bits_per_pixel) {
 
1289
    case 8:
 
1290
#ifdef DEBUG
 
1291
        printf ("%s %s: 8 bit pallete\n", DEBUGFILE, DEBUGFUNCTION);
 
1292
#endif     // DEBUG
 
1293
        input_pixfmt = PIX_FMT_PAL8;
 
1294
        break;
 
1295
    case 16:
 
1296
        if (image->red_mask == 0xF800 && image->green_mask == 0x07E0
 
1297
            && image->blue_mask == 0x1F) {
 
1298
#ifdef DEBUG
 
1299
            printf ("%s %s: 16 bit RGB565\n", DEBUGFILE, DEBUGFUNCTION);
 
1300
#endif     // DEBUG
 
1301
            input_pixfmt = PIX_FMT_BGR565;
 
1302
        } else if (image->red_mask == 0x7C00
 
1303
                   && image->green_mask == 0x03E0 && image->blue_mask == 0x1F) {
 
1304
#ifdef DEBUG
 
1305
            printf ("%s %s: 16 bit RGB555\n", DEBUGFILE, DEBUGFUNCTION);
 
1306
#endif     // DEBUG
 
1307
            input_pixfmt = PIX_FMT_BGR555;
 
1308
 
 
1309
        } else {
 
1310
            fprintf (stderr,
 
1311
                     _
 
1312
                     ("%s %s: rgb ordering at image depth %i not supported ... aborting\n"),
 
1313
                     DEBUGFILE, DEBUGFUNCTION, image->bits_per_pixel);
 
1314
            fprintf (stderr,
 
1315
                     "%s %s: color masks: r 0x%.6lX g 0x%.6lX b 0x%.6lX\n",
 
1316
                     DEBUGFILE, DEBUGFUNCTION, image->red_mask,
 
1317
                     image->green_mask, image->blue_mask);
 
1318
            exit (1);
 
1319
        }
 
1320
        break;
 
1321
    case 24:
 
1322
        if (image->red_mask == 0xFF0000 && image->green_mask == 0xFF00
 
1323
            && image->blue_mask == 0xFF) {
 
1324
            input_pixfmt = PIX_FMT_BGR24;
 
1325
        } else if (image->red_mask == 0xFF
 
1326
                   && image->green_mask == 0xFF00
 
1327
                   && image->blue_mask == 0xFF0000) {
 
1328
            input_pixfmt = PIX_FMT_RGB24;
 
1329
        } else {
 
1330
            fprintf (stderr,
 
1331
                     _
 
1332
                     ("%s %s: rgb ordering at image depth %i not supported ... aborting\n"),
 
1333
                     DEBUGFILE, DEBUGFUNCTION, image->bits_per_pixel);
 
1334
            fprintf (stderr,
 
1335
                     "%s %s: color masks: r 0x%.6lX g 0x%.6lX b 0x%.6lX\n",
 
1336
                     DEBUGFILE, DEBUGFUNCTION, image->red_mask,
 
1337
                     image->green_mask, image->blue_mask);
 
1338
            exit (1);
 
1339
        }
 
1340
        break;
 
1341
    case 32:
 
1342
        if (c_info->alpha_mask == 0xFF000000 && image->green_mask == 0xFF00) {
 
1343
            // byte order is relevant here, not endianness endianness is
 
1344
            // handled by avcodec, but atm no such thing as having ABGR,
 
1345
            // instead of ARGB in a word. Since we need this for
 
1346
            // Solaris/SPARC, but need to do the conversion
 
1347
            // for every frame we do it outside of this loop, cf.
 
1348
            // below this matches both ARGB32 and ABGR32
 
1349
            input_pixfmt = PIX_FMT_ARGB32;
 
1350
        } else {
 
1351
            fprintf (stderr,
 
1352
                     _
 
1353
                     ("%s %s: image depth %i not supported ... aborting\n"),
 
1354
                     DEBUGFILE, DEBUGFUNCTION, image->bits_per_pixel);
 
1355
            exit (1);
 
1356
        }
 
1357
        break;
 
1358
    default:
 
1359
        fprintf (stderr,
 
1360
                 _("%s %s: image depth %i not supported ... aborting\n"),
 
1361
                 DEBUGFILE, DEBUGFUNCTION, image->bits_per_pixel);
 
1362
        exit (1);
 
1363
    }
 
1364
 
 
1365
    return input_pixfmt;
 
1366
#undef DEBUGFUNCTION
 
1367
}
 
1368
 
 
1369
/**
 
1370
 * \brief main function to write ximage as video to 'fp'
 
1371
 *
 
1372
 * @param fp file handle, this, however, is not really used with xtoffmpeg
 
1373
 * @param image the captured XImage to save
 
1374
 * \todo remove fp from outside the save function. It is only needed in
 
1375
 *      xwd and should reside there
 
1376
 */
 
1377
void
 
1378
xvc_ffmpeg_save_frame (FILE * fp, XImage * image)
 
1379
{
 
1380
#define DEBUGFUNCTION "xvc_ffmpeg_save_frame()"
 
1381
    Job *job = xvc_job_ptr ();
 
1382
    XVC_AppData *app = xvc_appdata_ptr ();
 
1383
 
 
1384
    /* size of the encoded frame to write to file */
 
1385
    int out_size = -1;
 
1386
 
 
1387
#ifdef DEBUG
 
1388
    printf ("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
 
1389
#endif     // DEBUG
 
1390
 
 
1391
    // encoder needs to be prepared only once ..
 
1392
    if (job->state & VC_START) {       // it's the first call
 
1393
 
 
1394
#ifdef DEBUG
 
1395
        printf ("%s %s: doing x2ffmpeg init for targetCodec %i\n",
 
1396
                DEBUGFILE, DEBUGFUNCTION, job->targetCodec);
 
1397
#endif     // DEBUG
 
1398
 
 
1399
#ifdef USE_FFMPEG
 
1400
        if (app->current_mode > 0)
 
1401
            target = &(app->multi_frame);
 
1402
        else
 
1403
#endif     // USE_FFMPEG
 
1404
            target = &(app->single_frame);
 
1405
 
 
1406
#ifdef DEBUG
 
1407
        {
 
1408
            FILE *errout;
 
1409
 
 
1410
            printf ("%s %s: got color info\n", DEBUGFILE, DEBUGFUNCTION);
 
1411
            errout = fdopen (2, "w");
 
1412
            // x2ffmpeg_dump_ximage_info(image, errout);
 
1413
            printf ("%s %s: alpha_mask: 0x%.8X\n",
 
1414
                    DEBUGFILE, DEBUGFUNCTION, job->c_info->alpha_mask);
 
1415
            printf ("%s %s: alpha_shift: %li\n",
 
1416
                    DEBUGFILE, DEBUGFUNCTION, job->c_info->alpha_shift);
 
1417
            printf ("%s %s: red_shift: %li\n",
 
1418
                    DEBUGFILE, DEBUGFUNCTION, job->c_info->red_shift);
 
1419
            printf ("%s %s: green_shift: %li\n",
 
1420
                    DEBUGFILE, DEBUGFUNCTION, job->c_info->green_shift);
 
1421
            printf ("%s %s: blue_shift: %li\n",
 
1422
                    DEBUGFILE, DEBUGFUNCTION, job->c_info->blue_shift);
 
1423
        }
 
1424
#endif     // DEBUG
 
1425
 
 
1426
#ifdef DEBUG
 
1427
        printf ("%s %s: image->byte_order: %i, msb=%i, lsb=%i\n",
 
1428
                DEBUGFILE, DEBUGFUNCTION, image->byte_order, MSBFirst,
 
1429
                LSBFirst);
 
1430
#endif     // DEBUG
 
1431
 
 
1432
        // determine input picture format
 
1433
        input_pixfmt = guess_input_pix_fmt (image, job->c_info);
 
1434
 
 
1435
        // register all libav* related stuff
 
1436
        avdevice_register_all ();
 
1437
        av_register_all ();
 
1438
 
 
1439
        // guess AVOutputFormat
 
1440
        if (job->target >= CAP_MF)
 
1441
            file_oformat =
 
1442
                guess_format (xvc_formats[job->target].ffmpeg_name, NULL, NULL);
 
1443
        else {
 
1444
            char tmp_fn[30];
 
1445
 
 
1446
            snprintf (tmp_fn, 29, "test-%%d.%s",
 
1447
                      xvc_formats[job->target].extensions[0]);
 
1448
            file_oformat = guess_format (NULL, tmp_fn, NULL);
 
1449
        }
 
1450
        if (!file_oformat) {
 
1451
            fprintf (stderr,
 
1452
                     _
 
1453
                     ("%s %s: Couldn't determin output format ... aborting\n"),
 
1454
                     DEBUGFILE, DEBUGFUNCTION);
 
1455
            exit (1);
 
1456
        }
 
1457
#ifdef DEBUG
 
1458
        printf
 
1459
            ("%s %s: found AVOutputFormat %s it expects a number in the filename (0=no/1=yes) %i\n",
 
1460
             DEBUGFILE, DEBUGFUNCTION, file_oformat->name,
 
1461
             (file_oformat->flags & AVFMT_NEEDNUMBER));
 
1462
        printf
 
1463
            ("%s %s: found based on: target %i - targetCodec %i - ffmpeg codec id %i\n",
 
1464
             DEBUGFILE, DEBUGFUNCTION, job->target, job->targetCodec,
 
1465
             xvc_codecs[job->targetCodec].ffmpeg_id);
 
1466
#endif     // DEBUG
 
1467
 
 
1468
        // prepare AVFormatContext
 
1469
        output_file = av_alloc_format_context ();
 
1470
        if (!output_file) {
 
1471
            fprintf (stderr,
 
1472
                     _
 
1473
                     ("%s %s: Error allocating memory for format context ... aborting\n"),
 
1474
                     DEBUGFILE, DEBUGFUNCTION);
 
1475
            exit (1);
 
1476
        }
 
1477
        output_file->oformat = file_oformat;
 
1478
        if (output_file->oformat->priv_data_size > 0) {
 
1479
            output_file->priv_data =
 
1480
                av_mallocz (output_file->oformat->priv_data_size);
 
1481
            // FIXME: do I need to free this?
 
1482
            if (!output_file->priv_data) {
 
1483
                fprintf (stderr,
 
1484
                         _
 
1485
                         ("%s %s: Error allocating private data for format context ... aborting\n"),
 
1486
                         DEBUGFILE, DEBUGFUNCTION);
 
1487
                exit (1);
 
1488
            }
 
1489
        }
 
1490
        // output_file->packet_size= mux_packet_size;
 
1491
        // output_file->mux_rate= mux_rate;
 
1492
        output_file->preload = (int) (0.5 * AV_TIME_BASE);
 
1493
        output_file->max_delay = (int) (0.7 * AV_TIME_BASE);
 
1494
        // output_file->loop_output = loop_output;
 
1495
 
 
1496
        // add the video stream and initialize the codecs
 
1497
        //
 
1498
        // prepare stream
 
1499
        out_st =
 
1500
            add_video_stream (output_file, image,
 
1501
                              (input_pixfmt ==
 
1502
                               PIX_FMT_PAL8 ? PIX_FMT_RGB24 : input_pixfmt),
 
1503
                              xvc_codecs[job->targetCodec].ffmpeg_id, job);
 
1504
 
 
1505
        // FIXME: set params
 
1506
        // memset (p_fParams, 0, sizeof(*p_fParams));
 
1507
        // p_fParams->image_format = image_format;
 
1508
        // p_fParams->time_base.den = out_st->codec->time_base.den;
 
1509
        // p_fParams->time_base.num = out_st->codec->time_base.num;
 
1510
        // p_fParams->width = out_st->codec->width;
 
1511
        // p_fParams->height = out_st->codec->height;
 
1512
        // if (av_set_parameters (output_file, p_fParams) < 0) {
 
1513
        if (av_set_parameters (output_file, NULL) < 0) {
 
1514
            fprintf (stderr,
 
1515
                     _("%s %s: Invalid encoding parameters ... aborting\n"),
 
1516
                     DEBUGFILE, DEBUGFUNCTION);
 
1517
            exit (1);
 
1518
        }
 
1519
        // open the codec
 
1520
        if (avcodec_open (out_st->codec, codec) < 0) {
 
1521
            fprintf (stderr, _("%s %s: could not open video codec\n"),
 
1522
                     DEBUGFILE, DEBUGFUNCTION);
 
1523
            exit (1);
 
1524
        }
 
1525
#ifdef HAVE_FFMPEG_AUDIO
 
1526
        if ((job->flags & FLG_REC_SOUND) && (job->au_targetCodec > 0)) {
 
1527
            int au_ret = add_audio_stream (job);
 
1528
 
 
1529
            // initialize a mutex lock to its default value
 
1530
            pthread_mutex_init (&mp, NULL);
 
1531
 
 
1532
            if (au_ret == 0) {
 
1533
                int tret;
 
1534
 
 
1535
                // create and start capture thread
 
1536
                // initialized with default attributes
 
1537
                tret = pthread_attr_init (&tattr);
 
1538
 
 
1539
                // create the thread
 
1540
                tret =
 
1541
                    pthread_create (&tid, &tattr,
 
1542
                                    (void *) capture_audio_thread, job);
 
1543
            }
 
1544
        }
 
1545
#endif     // HAVE_FFMPEG_AUDIO
 
1546
 
 
1547
#ifdef DEBUG
 
1548
        dump_format (output_file, 0, output_file->filename, 1);
 
1549
#endif     // DEBUG
 
1550
 
 
1551
        /*
 
1552
         * prepare pictures
 
1553
         */
 
1554
        // input picture
 
1555
        p_inpic = avcodec_alloc_frame ();
 
1556
 
 
1557
        if (input_pixfmt == PIX_FMT_PAL8) {
 
1558
            scratchbuf8bit =
 
1559
                malloc (avpicture_get_size
 
1560
                        (PIX_FMT_RGB24, image->width, image->height));
 
1561
            if (!scratchbuf8bit) {
 
1562
                fprintf (stderr,
 
1563
                         "%s %s: Could not allocate buffer for 8bit palette conversion\n",
 
1564
                         DEBUGFILE, DEBUGFUNCTION);
 
1565
                exit (1);
 
1566
            }
 
1567
 
 
1568
            avpicture_fill ((AVPicture *) p_inpic, scratchbuf8bit,
 
1569
                            input_pixfmt, image->width, image->height);
 
1570
            p_inpic->data[0] = scratchbuf8bit;
 
1571
            p_inpic->linesize[0] = image->width * 3;
 
1572
        } else {
 
1573
            avpicture_fill ((AVPicture *) p_inpic, (uint8_t *) image->data,
 
1574
                            input_pixfmt, image->width, image->height);
 
1575
        }
 
1576
 
 
1577
        // output picture
 
1578
        p_outpic = avcodec_alloc_frame ();
 
1579
 
 
1580
        image_size =
 
1581
            avpicture_get_size (out_st->codec->pix_fmt,
 
1582
                                out_st->codec->width, out_st->codec->height);
 
1583
        outpic_buf = av_malloc (image_size);
 
1584
        if (!outpic_buf) {
 
1585
            fprintf (stderr,
 
1586
                     _
 
1587
                     ("%s %s: Could not allocate buffer for output frame! ... aborting\n"),
 
1588
                     DEBUGFILE, DEBUGFUNCTION);
 
1589
            exit (1);
 
1590
        }
 
1591
        avpicture_fill ((AVPicture *) p_outpic, outpic_buf,
 
1592
                        out_st->codec->pix_fmt, out_st->codec->width,
 
1593
                        out_st->codec->height);
 
1594
 
 
1595
        /*
 
1596
         * prepare output buffer for encoded frames
 
1597
         */
 
1598
        if ((image_size + 20000) < FF_MIN_BUFFER_SIZE)
 
1599
            outbuf_size = FF_MIN_BUFFER_SIZE;
 
1600
        else
 
1601
            outbuf_size = image_size + 20000;
 
1602
        outbuf = malloc (outbuf_size);
 
1603
        if (!outbuf) {
 
1604
            fprintf (stderr,
 
1605
                     _
 
1606
                     ("%s %s: Could not allocate buffer for encoded frame (outbuf)! ... aborting\n"),
 
1607
                     DEBUGFILE, DEBUGFUNCTION);
 
1608
            exit (1);
 
1609
        }
 
1610
        // img resampling
 
1611
        if (!img_resample_ctx) {
 
1612
            img_resample_ctx = sws_getContext (image->width,
 
1613
                                               image->height,
 
1614
                                               (input_pixfmt ==
 
1615
                                                PIX_FMT_PAL8 ? PIX_FMT_RGB24
 
1616
                                                : input_pixfmt),
 
1617
                                               out_st->codec->width,
 
1618
                                               out_st->codec->height,
 
1619
                                               out_st->codec->pix_fmt, 1,
 
1620
                                               NULL, NULL, NULL);
 
1621
            // sws_rgb2rgb_init(SWS_CPU_CAPS_MMX*0);
 
1622
        }
 
1623
        // file preparation needs to be done once for multi-frame capture
 
1624
        // and multiple times for single-frame capture
 
1625
        if (job->target >= CAP_MF) {
 
1626
            // prepare output filenames and register protocols
 
1627
            // after this output_file->filename should have the right
 
1628
            // filename
 
1629
            prepareOutputFile (job->file, output_file, job->movie_no);
 
1630
 
 
1631
            // open the file
 
1632
            if (url_fopen
 
1633
                (&output_file->pb, output_file->filename, URL_WRONLY) < 0) {
 
1634
                fprintf (stderr,
 
1635
                         _("%s %s: Could not open '%s' ... aborting\n"),
 
1636
                         DEBUGFILE, DEBUGFUNCTION, output_file->filename);
 
1637
                exit (1);
 
1638
            }
 
1639
 
 
1640
            if (av_write_header (output_file) < 0) {
 
1641
                dump_format (output_file, 0, output_file->filename, 1);
 
1642
                fprintf (stderr,
 
1643
                         _
 
1644
                         ("%s %s: Could not write header for output file (incorrect codec paramters ?) ... aborting\n"),
 
1645
                         DEBUGFILE, DEBUGFUNCTION);
 
1646
                exit (1);
 
1647
            }
 
1648
 
 
1649
        }
 
1650
#ifdef DEBUG
 
1651
        printf ("%s %s: leaving xffmpeg init\n", DEBUGFILE, DEBUGFUNCTION);
 
1652
 
 
1653
        printf ("%s %s: codec %p\n", DEBUGFILE, DEBUGFUNCTION, codec);
 
1654
        printf ("%s %s: p_inpic %p\n", DEBUGFILE, DEBUGFUNCTION, p_inpic);
 
1655
        printf ("%s %s: p_outpic %p\n", DEBUGFILE, DEBUGFUNCTION, p_outpic);
 
1656
        printf ("%s %s: outpic_buf %p\n", DEBUGFILE, DEBUGFUNCTION, outpic_buf);
 
1657
        printf ("%s %s: outbuf %p\n", DEBUGFILE, DEBUGFUNCTION, outbuf);
 
1658
 
 
1659
        printf ("%s %s: output_file %p\n", DEBUGFILE, DEBUGFUNCTION,
 
1660
                output_file);
 
1661
        printf ("%s %s: file_oformat %p\n", DEBUGFILE, DEBUGFUNCTION,
 
1662
                file_oformat);
 
1663
        printf ("%s %s: out_st %p\n", DEBUGFILE, DEBUGFUNCTION, out_st);
 
1664
 
 
1665
        printf ("%s %s: image size %i - input pixfmt %i - out_size %i\n",
 
1666
                DEBUGFILE, DEBUGFUNCTION, image_size, input_pixfmt, out_size);
 
1667
        printf ("%s %s: audio_pts %.f - video_pts %.f\n", DEBUGFILE,
 
1668
                DEBUGFUNCTION, audio_pts, video_pts);
 
1669
 
 
1670
        printf ("%s %s: c_info %p - scratchbuf8bit %p\n", DEBUGFILE,
 
1671
                DEBUGFUNCTION, job->c_info, scratchbuf8bit);
 
1672
#endif     // DEBUG
 
1673
    }
 
1674
 
 
1675
    if (job->target < CAP_MF) {
 
1676
        // prepare output filenames and register protocols
 
1677
        // after this output_file->filename should have the right filename
 
1678
        prepareOutputFile (job->file, output_file, job->pic_no);
 
1679
 
 
1680
        // open the file
 
1681
        if (url_fopen (&output_file->pb, output_file->filename, URL_WRONLY)
 
1682
            < 0) {
 
1683
            fprintf (stderr, _("%s %s: Could not open '%s' ... aborting\n"),
 
1684
                     DEBUGFILE, DEBUGFUNCTION, output_file->filename);
 
1685
            exit (1);
 
1686
        }
 
1687
 
 
1688
        if (av_write_header (output_file) < 0) {
 
1689
            dump_format (output_file, 0, output_file->filename, 1);
 
1690
            fprintf (stderr,
 
1691
                     _
 
1692
                     ("%s %s: Could not write header for output file (incorrect codec paramters ?) ... aborting\n"),
 
1693
                     DEBUGFILE, DEBUGFUNCTION);
 
1694
            exit (1);
 
1695
        }
 
1696
    }
 
1697
 
 
1698
    /*
 
1699
     * convert input pic to pixel format the encoder expects
 
1700
     */
 
1701
#ifdef DEBUG
 
1702
    if (input_pixfmt == PIX_FMT_ARGB32)
 
1703
        dump32bit (image, job->c_info);
 
1704
    if (input_pixfmt == PIX_FMT_PAL8)
 
1705
        dump8bit (image, (u_int32_t *) job->color_table);
 
1706
#endif     // DEBUG
 
1707
 
 
1708
    /** \todo test if the special image conversion for Solaris is still
 
1709
     *      necessary */
 
1710
    if (input_pixfmt == PIX_FMT_ARGB32 && job->c_info->alpha_mask == 0xFF000000
 
1711
        && image->red_mask == 0xFF && image->green_mask == 0xFF00
 
1712
        && image->blue_mask == 0xFF0000) {
 
1713
        myABGR32toARGB32 (image);
 
1714
    } else if (input_pixfmt == PIX_FMT_PAL8) {
 
1715
        myPAL8toRGB24 (image, p_inpic, job);
 
1716
    }
 
1717
    // img resampling and conversion
 
1718
    if (sws_scale (img_resample_ctx, p_inpic->data, p_inpic->linesize,
 
1719
                   0, image->height, p_outpic->data, p_outpic->linesize) < 0) {
 
1720
        fprintf (stderr,
 
1721
                 _
 
1722
                 ("%s %s: error converting or resampling frame: context %p, iwidth %i, iheight %i, owidth %i, oheight %i, inpfmt %i opfmt %i\n"),
 
1723
                 DEBUGFILE, DEBUGFUNCTION, img_resample_ctx, image->width,
 
1724
                 image->height, out_st->codec->width, out_st->codec->height,
 
1725
                 input_pixfmt, out_st->codec->pix_fmt);
 
1726
        exit (1);
 
1727
    }
 
1728
 
 
1729
    /*
 
1730
     * encode the image
 
1731
     */
 
1732
#ifdef DEBUG
 
1733
    printf
 
1734
        ("%s %s: calling encode_video with codec %p, outbuf %p, outbuf size %i, output frame %p\n",
 
1735
         DEBUGFILE, DEBUGFUNCTION, out_st->codec, outbuf, outbuf_size,
 
1736
         p_outpic);
 
1737
#endif     // DEBUG
 
1738
 
 
1739
    out_size =
 
1740
        avcodec_encode_video (out_st->codec, outbuf, outbuf_size, p_outpic);
 
1741
    if (out_size < 0) {
 
1742
        fprintf (stderr,
 
1743
                 _
 
1744
                 ("%s %s: error encoding frame: c %p, outbuf %p, size %i, frame %p\n"),
 
1745
                 DEBUGFILE, DEBUGFUNCTION, out_st->codec, outbuf,
 
1746
                 outbuf_size, p_outpic);
 
1747
        exit (1);
 
1748
    }
 
1749
#ifdef HAVE_FFMPEG_AUDIO
 
1750
    if (job->flags & FLG_REC_SOUND) {
 
1751
        if (pthread_mutex_lock (&mp) > 0) {
 
1752
            fprintf (stderr,
 
1753
                     _
 
1754
                     ("mutex lock for writing video frame failed ... aborting\n"));
 
1755
            exit (1);
 
1756
        }
 
1757
    }
 
1758
#endif     // HAVE_FFMPEG_AUDIO
 
1759
 
 
1760
    /*
 
1761
     * write frame to file
 
1762
     */
 
1763
    if (out_size > 0) {
 
1764
        do_video_out (output_file, out_st, outbuf, out_size);
 
1765
    }
 
1766
 
 
1767
    if (job->target < CAP_MF)
 
1768
        url_fclose (output_file->pb);
 
1769
 
 
1770
#ifdef HAVE_FFMPEG_AUDIO
 
1771
    /*
 
1772
     * release the mutex
 
1773
     */
 
1774
    if (job->flags & FLG_REC_SOUND) {
 
1775
        if (pthread_mutex_unlock (&mp) > 0) {
 
1776
            fprintf (stderr,
 
1777
                     _
 
1778
                     ("couldn't release the mutex for writing video frame ... aborting\n"));
 
1779
        }
 
1780
    }
 
1781
#endif     // HAVE_FFMPEG_AUDIO
 
1782
 
 
1783
#undef DEBUGFUNCTION
 
1784
}
 
1785
 
 
1786
/**
 
1787
 * \brief cleanup capture session
 
1788
 */
 
1789
void
 
1790
xvc_ffmpeg_clean ()
 
1791
{
 
1792
#define DEBUGFUNCTION "FFMPEGClean()"
 
1793
    Job *job = xvc_job_ptr ();
 
1794
 
 
1795
#ifdef DEBUG
 
1796
    printf ("%s %s: Entering\n", DEBUGFILE, DEBUGFUNCTION);
 
1797
#endif     // DEBUG
 
1798
 
 
1799
#ifdef HAVE_FFMPEG_AUDIO
 
1800
    if (job->flags & FLG_REC_SOUND && tid != 0) {
 
1801
        {
 
1802
            int tret;
 
1803
 
 
1804
            // wait till audio thread is actually running, or else
 
1805
            // the signal might kill xvidcap. we also cannot just
 
1806
            // drop sending the signal, because the audio thread
 
1807
            // might just be starting
 
1808
            while (!audio_thread_running) {
 
1809
                usleep (10);
 
1810
            }
 
1811
            tret = pthread_kill (tid, SIGUSR1);
 
1812
 
 
1813
            pthread_join (tid, NULL);
 
1814
            tid = 0;
 
1815
        }
 
1816
    }
 
1817
#endif     // HAVE_FFMPEG_AUDIO
 
1818
 
 
1819
    if (output_file) {
 
1820
        /*
 
1821
         * write trailer
 
1822
         */
 
1823
        av_write_trailer (output_file);
 
1824
    }
 
1825
 
 
1826
    if (output_file) {
 
1827
        int i;
 
1828
 
 
1829
        /*
 
1830
         * close file if multi-frame capture ... otherwise closed already
 
1831
         */
 
1832
        if (job->target >= CAP_MF)
 
1833
            url_fclose (output_file->pb);
 
1834
        /*
 
1835
         * free streams
 
1836
         */
 
1837
        for (i = 0; i < output_file->nb_streams; i++) {
 
1838
            if (output_file->streams[i]->codec) {
 
1839
                avcodec_close (output_file->streams[i]->codec);
 
1840
                av_free (output_file->streams[i]->codec);
 
1841
                output_file->streams[i]->codec = NULL;
 
1842
            }
 
1843
            av_free (output_file->streams[i]);
 
1844
        }
 
1845
        if (out_st)
 
1846
            out_st = NULL;
 
1847
#ifdef HAVE_FFMPEG_AUDIO
 
1848
        if (au_out_st)
 
1849
            au_out_st = NULL;
 
1850
#endif     // HAVE_FFMPEG_AUDIO
 
1851
        /*
 
1852
         * free format context
 
1853
         */
 
1854
        av_free (output_file->priv_data);
 
1855
        output_file->priv_data = NULL;
 
1856
        av_free (output_file);
 
1857
        output_file = NULL;
 
1858
    }
 
1859
 
 
1860
    if (img_resample_ctx) {
 
1861
        sws_freeContext (img_resample_ctx);
 
1862
        img_resample_ctx = NULL;
 
1863
    }
 
1864
 
 
1865
    if (outpic_buf) {
 
1866
        av_free (outpic_buf);
 
1867
        outpic_buf = NULL;
 
1868
    }
 
1869
    av_free (outbuf);                  /* avcodec seems to do that job */
 
1870
    outbuf = NULL;
 
1871
    av_free (p_inpic);
 
1872
    p_inpic = NULL;
 
1873
    av_free (outpic_buf);
 
1874
    outpic_buf = NULL;
 
1875
    av_free (p_outpic);
 
1876
    p_outpic = NULL;
 
1877
 
 
1878
    if (input_pixfmt == PIX_FMT_PAL8 && scratchbuf8bit) {
 
1879
        free (scratchbuf8bit);
 
1880
        scratchbuf8bit = NULL;
 
1881
    }
 
1882
 
 
1883
    codec = NULL;
 
1884
#ifdef HAVE_FFMPEG_AUDIO
 
1885
    au_codec = NULL;
 
1886
#endif     // HAVE_FFMPEG_AUDIO
 
1887
 
 
1888
#ifdef DEBUG
 
1889
    printf ("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
 
1890
#endif     // DEBUG
 
1891
 
 
1892
#undef DEBUGFUNCTION
 
1893
}
 
1894
 
 
1895
#ifdef DEBUG
 
1896
/**
 
1897
 * \brief dump info about XImage for debugging purposes
 
1898
 *
 
1899
 * @param img XImage to dump info about
 
1900
 * @param fp handle for the file pointer to dump info into
 
1901
 */
 
1902
static void
 
1903
x2ffmpeg_dump_ximage_info (XImage * img, FILE * fp)
 
1904
{
 
1905
#define DEBUGFUNCTION "x2ffmpeg_dump_ximage_info()"
 
1906
 
 
1907
#ifdef DEBUG
 
1908
    printf ("%s %s: Entering with image %p and file pointer %p\n",
 
1909
            DEBUGFILE, DEBUGFUNCTION, img, fp);
 
1910
#endif     // DEBUG
 
1911
 
 
1912
    fprintf (fp, " width %d\n", img->width);
 
1913
    fprintf (fp, " height %d\n", img->height);
 
1914
    fprintf (fp, " xoffset %d\n", img->xoffset);
 
1915
    fprintf (fp, " format %d\n", img->format);
 
1916
    fprintf (fp, " data addr 0x%X\n", (int) img->data);
 
1917
    fprintf (fp, " first four bytes of data 0x%X 0x%X 0x%X 0x%X\n",
 
1918
             (unsigned char) (img->data[0]), (unsigned char) (img->data[1]),
 
1919
             (unsigned char) img->data[2], (unsigned char) img->data[3]);
 
1920
    fprintf (fp, " byte_order %s\n", img->byte_order ? "MSBFirst" : "LSBFirst");
 
1921
    fprintf (fp, " bitmap_unit %d\n", img->bitmap_unit);
 
1922
    fprintf (fp, " bitmap_bit_order %s\n",
 
1923
             img->bitmap_bit_order ? "MSBFirst" : "LSBFirst");
 
1924
    fprintf (fp, " bitmap_pad %d\n", img->bitmap_pad);
 
1925
    fprintf (fp, " depth %d\n", img->depth);
 
1926
    fprintf (fp, " bytes_per_line %d\n", img->bytes_per_line);
 
1927
    fprintf (fp, " bits_per_pixel %d\n", img->bits_per_pixel);
 
1928
    fprintf (fp, " red_mask 0x%.8lX\n", img->red_mask);
 
1929
    fprintf (fp, " green_mask 0x%.8lX\n", img->green_mask);
 
1930
    fprintf (fp, " blue_mask 0x%.8lX\n", img->blue_mask);
 
1931
 
 
1932
#ifdef DEBUG
 
1933
    printf ("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
 
1934
#endif     // DEBUG
 
1935
 
 
1936
#undef DEBUGFUNCTION
 
1937
}
 
1938
 
 
1939
/**
 
1940
 * \brief dump 32bit image to pnm for debugging purposes. The file written
 
1941
 *      is /tmp/pic.rgb.pnm
 
1942
 *
 
1943
 * @param input XImage to dump to pnm
 
1944
 */
 
1945
static void
 
1946
dump32bit (const XImage * input, const ColorInfo * c_info)
 
1947
{
 
1948
#define DEBUGFUNCTION "dump32bit()"
 
1949
 
 
1950
    int row, col;
 
1951
    static char head[256];
 
1952
 
 
1953
    static FILE *fp2 = NULL;
 
1954
    uint8_t *ptr2, *output;
 
1955
    long size;
 
1956
 
 
1957
    register unsigned int
 
1958
        rm = input->red_mask,
 
1959
        gm = input->green_mask,
 
1960
        bm = input->blue_mask,
 
1961
        rs = c_info->red_shift,
 
1962
        gs = c_info->green_shift,
 
1963
        bs = c_info->blue_shift, *p32 = (unsigned int *) input->data;
 
1964
 
 
1965
#ifdef DEBUG
 
1966
    printf ("%s %s: Entering with image %p\n", DEBUGFILE, DEBUGFUNCTION, input);
 
1967
#endif     // DEBUG
 
1968
 
 
1969
    sprintf (head, "P6\n%d %d\n%d\n", input->width, input->height, 255);
 
1970
    size = ((input->bytes_per_line * input->height) / 4) * 3;
 
1971
    output = malloc (size);
 
1972
    ptr2 = output;
 
1973
 
 
1974
    for (row = 0; row < input->height; row++) {
 
1975
        for (col = 0; col < input->width; col++) {
 
1976
            *output++ = ((*p32 & rm) >> rs);
 
1977
            *output++ = ((*p32 & gm) >> gs);
 
1978
            *output++ = ((*p32 & bm) >> bs);
 
1979
            p32++;                     // ignore alpha values
 
1980
        }
 
1981
        //
 
1982
        // eat paded bytes, for better speed we use shifting,
 
1983
        // (bytes_per_line - bits_per_pixel / 8 * width ) / 4
 
1984
        //
 
1985
        p32 += (input->bytes_per_line - (input->bits_per_pixel >> 3)
 
1986
                * input->width) >> 2;
 
1987
    }
 
1988
 
 
1989
    fp2 = fopen ("/tmp/pic.rgb.pnm", "w");
 
1990
    fwrite (head, strlen (head), 1, fp2);
 
1991
    //
 
1992
    // x2ffmpeg_dump_ximage_info (input, fp2);
 
1993
    //
 
1994
    fwrite (ptr2, size, 1, fp2);
 
1995
    fclose (fp2);
 
1996
    free (ptr2);
 
1997
 
 
1998
#ifdef DEBUG
 
1999
    printf ("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
 
2000
#endif     // DEBUG
 
2001
 
 
2002
#undef DEBUGFUNCTION
 
2003
}
 
2004
 
 
2005
/**
 
2006
 * \brief dump 8bit image to ppm for debugging purposes. The file written
 
2007
 *      is /tmp/pic.rgb.pnm
 
2008
 *
 
2009
 * @param input XImage to dump to ppm
 
2010
 * @param ct pointer to color table
 
2011
 */
 
2012
static void
 
2013
dump8bit (const XImage * image, const u_int32_t * ct)
 
2014
{
 
2015
#define DEBUGFUNCTION "dump8bit()"
 
2016
 
 
2017
    static char head[256];
 
2018
    static unsigned int image_size;
 
2019
    register unsigned char *line_ptr, *col_ptr;
 
2020
    unsigned char *pnm_image = NULL;
 
2021
    int row, col;
 
2022
 
 
2023
    static FILE *fp2 = NULL;
 
2024
 
 
2025
#ifdef DEBUG
 
2026
    printf ("%s %s: Entering with image %p\n", DEBUGFILE, DEBUGFUNCTION, image);
 
2027
#endif     // DEBUG
 
2028
 
 
2029
    sprintf (head, "P6\n%d %d\n%d\n", image->width, image->height, 255);
 
2030
    image_size = image->width * 3 * image->height;  // RGB
 
2031
    pnm_image = (unsigned char *) malloc (image_size);
 
2032
 
 
2033
    fp2 = fopen ("/tmp/pic.rgb.pnm", "w");
 
2034
    fwrite (head, strlen (head), 1, fp2);
 
2035
 
 
2036
    line_ptr = pnm_image;
 
2037
    for (row = 0; row < image->height; row++) {
 
2038
        col_ptr = (unsigned char *) image->data + (row * image->bytes_per_line);
 
2039
        for (col = 0; col < image->width; col++) {
 
2040
            *line_ptr++ = ((ct[*col_ptr] & 0x00FF0000) >> 16);
 
2041
            *line_ptr++ = ((ct[*col_ptr] & 0x0000FF00) >> 8);
 
2042
            *line_ptr++ = (ct[*col_ptr] & 0x000000FF);
 
2043
            col_ptr++;
 
2044
        }
 
2045
    }
 
2046
    fwrite (pnm_image, image_size, 1, fp2);
 
2047
 
 
2048
    //
 
2049
    // x2ffmpeg_dump_ximage_info (input, fp2);
 
2050
    //
 
2051
    fclose (fp2);
 
2052
    free (pnm_image);
 
2053
 
 
2054
#ifdef DEBUG
 
2055
    printf ("%s %s: Leaving\n", DEBUGFILE, DEBUGFUNCTION);
 
2056
#endif     // DEBUG
 
2057
 
 
2058
#undef DEBUGFUNCTION
 
2059
}
 
2060
 
 
2061
#endif     // DEBUG
 
2062
 
 
2063
#endif     // USE_FFMPEG