ffmpeg2theora.c 69.9 KB
Newer Older
1
/* -*- tab-width:4;c-file-style:"cc-mode"; -*- */
2
/*
Jan Gerber's avatar
Jan Gerber committed
3
 * ffmpeg2theora.c -- Convert ffmpeg supported a/v files to  Ogg Theora / Ogg Vorbis
Jan Gerber's avatar
Jan Gerber committed
4
 * Copyright (C) 2003-2008 <j@v2v.cc>
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Jan Gerber's avatar
Jan Gerber committed
19
 *
20
21
22
23
24
25
26
 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
27
#include <math.h>
28
#include <errno.h>
29

30
31
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
Jan Gerber's avatar
Jan Gerber committed
32
#include "libavformat/framehook.h"
33
34
#include "libswscale/swscale.h"
#include "libpostproc/postprocess.h"
35

36
37
38
39
#include "theora/theora.h"
#include "vorbis/codec.h"
#include "vorbis/vorbisenc.h"

40
41
42
43
#ifdef WIN32
#include "fcntl.h"
#endif

44
#include "theorautils.h"
45
46
#include "subtitles.h"
#include "ffmpeg2theora.h"
47

48
enum {
49
  NULL_FLAG,
50
51
52
53
54
55
56
57
58
59
60
  DEINTERLACE_FLAG,
  OPTIMIZE_FLAG,
  SYNC_FLAG,
  NOSOUND_FLAG,
  CROPTOP_FLAG,
  CROPBOTTOM_FLAG,
  CROPRIGHT_FLAG,
  CROPLEFT_FLAG,
  ASPECT_FLAG,
  INPUTFPS_FLAG,
  AUDIOSTREAM_FLAG,
61
62
63
64
  SUBTITLES_FLAG,
  SUBTITLES_ENCODING_FLAG,
  SUBTITLES_LANGUAGE_FLAG,
  SUBTITLES_CATEGORY_FLAG,
65
66
67
  VHOOK_FLAG,
  FRONTEND_FLAG,
  SPEEDLEVEL_FLAG,
68
  PP_FLAG,
69
  NOSKELETON
70
} F2T_FLAGS;
Jan Gerber's avatar
Jan Gerber committed
71

Jan Gerber's avatar
Jan Gerber committed
72
73
74
75
enum {
  V2V_PRESET_NONE,
  V2V_PRESET_PRO,
  V2V_PRESET_PREVIEW,
Jan Gerber's avatar
Jan Gerber committed
76
77
78
  V2V_PRESET_VIDEOBIN,
  V2V_PRESET_PADMA,
  V2V_PRESET_PADMASTREAM,
Jan Gerber's avatar
Jan Gerber committed
79
} F2T_PRESETS;
Jan Gerber's avatar
Jan Gerber committed
80

81

82
83
84
85
86
87
88
89
90
#define PAL_HALF_WIDTH 384
#define PAL_HALF_HEIGHT 288
#define NTSC_HALF_WIDTH 320
#define NTSC_HALF_HEIGHT 240

#define PAL_FULL_WIDTH 720
#define PAL_FULL_HEIGHT 576
#define NTSC_FULL_WIDTH 720
#define NTSC_FULL_HEIGHT 480
Jan Gerber's avatar
Jan Gerber committed
91

Jan Gerber's avatar
Jan Gerber committed
92
93
94

static int sws_flags = SWS_BICUBIC;

Jan Gerber's avatar
Jan Gerber committed
95
oggmux_info info;
96

97
98
99
static int using_stdin = 0;


100
/**
Jan Gerber's avatar
Jan Gerber committed
101
 * Allocate and initialise an AVFrame.
102
 */
103
static AVFrame *frame_alloc (int pix_fmt, int width, int height) {
Jan Gerber's avatar
Jan Gerber committed
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
    AVFrame *picture;
    uint8_t *picture_buf;
    int size;

    picture = avcodec_alloc_frame ();
    if (!picture)
        return NULL;
    size = avpicture_get_size (pix_fmt, width, height);
    picture_buf = av_malloc (size);
    if (!picture_buf){
        av_free (picture);
        return NULL;
    }
    avpicture_fill ((AVPicture *) picture, picture_buf,
            pix_fmt, width, height);
    return picture;
120
121
}

122
123
124
125
126
/**
 * Frees an AVFrame.
 */
static void frame_dealloc (AVFrame *frame) {
    if (frame) {
Jan Gerber's avatar
Jan Gerber committed
127
        avpicture_free((AVPicture*)frame);
128
129
130
131
        av_free(frame);
    }
}

132
133
134
135
/**
 * initialize ff2theora with default values
 * @return ff2theora struct
 */
136
static ff2theora ff2theora_init (){
Jan Gerber's avatar
Jan Gerber committed
137
138
139
140
141
142
143
144
145
    ff2theora this = calloc (1, sizeof (*this));
    if (this != NULL){
        this->disable_audio=0;
        this->video_index = -1;
        this->audio_index = -1;
        this->start_time=0;
        this->end_time=0; /* 0 denotes no end time set */

        // audio
146
147
        this->sample_rate = -1;  // samplerate hmhmhm
        this->channels = -1;
148
        this->audio_quality = 1.00;// audio quality 1
Jan Gerber's avatar
Jan Gerber committed
149
        this->audio_bitrate=0;
150
        this->audiostream = -1;
Jan Gerber's avatar
Jan Gerber committed
151

Jan Gerber's avatar
Jan Gerber committed
152
153
154
        // video
        this->picture_width=0;      // set to 0 to not resize the output
        this->picture_height=0;      // set to 0 to not resize the output
155
        this->video_quality=rint(5*6.3); // video quality 5
Jan Gerber's avatar
Jan Gerber committed
156
        this->video_bitrate=0;
Jan Gerber's avatar
Jan Gerber committed
157
        this->sharpness=0;
158
        this->keyint=64;
159
160
        this->force_input_fps.num = -1;
        this->force_input_fps.den = 1;
161
        this->sync=0;
Jan Gerber's avatar
Jan Gerber committed
162
163
164
        this->aspect_numerator=0;
        this->aspect_denominator=0;
        this->frame_aspect=0;
Jan Gerber's avatar
Jan Gerber committed
165
        this->deinterlace=0; // auto by default, if input is flaged as interlaced it will deinterlace.
Jan Gerber's avatar
Jan Gerber committed
166
        this->vhook=0;
167
168
        this->framerate_new.num = -1;
        this->framerate_new.den = 1;
Jan Gerber's avatar
Jan Gerber committed
169

Jan Gerber's avatar
Jan Gerber committed
170
171
172
173
        this->frame_topBand=0;
        this->frame_bottomBand=0;
        this->frame_leftBand=0;
        this->frame_rightBand=0;
Jan Gerber's avatar
Jan Gerber committed
174

175
176
177
        this->n_kate_streams=0;
        this->kate_streams=NULL;

Jan Gerber's avatar
Jan Gerber committed
178
        this->pix_fmt = PIX_FMT_YUV420P;
179
180
181
182
183
184
185
186
187

        // ffmpeg2theora --nosound -f dv -H 32000 -S 0 -v 8 -x 384 -y 288 -G 1.5 input.dv
        this->video_gamma  = 0.0;
        this->video_bright = 0.0;
        this->video_contr  = 0.0;
        this->video_satur  = 1.0;

        this->y_lut_used = 0;
        this->uv_lut_used = 0;
Jan Gerber's avatar
Jan Gerber committed
188
189
    }
    return this;
190
191
}

192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
// gamma lookup table code

static void y_lut_init(ff2theora this) {
    int i;
    double v;

    double c = this->video_contr;
    double b = this->video_bright;
    double g = this->video_gamma;
 
    if ((g < 0.01) || (g > 100.0)) g = 1.0;
    if ((c < 0.01) || (c > 100.0)) c = 1.0;
    if ((b < -1.0) || (b > 1.0))   b = 0.0;

    if (g == 1.0 && c == 1.0 && b == 0.0) return;
    this->y_lut_used = 1;

    printf("  Video correction: gamma=%g, contrast=%g, brightness=%g\n", g, c, b);

    g = 1.0 / g;    // larger values shall make brighter video.

    for (i = 0; i < 256; i++) {
        v = (double) i / 255.0;
        v = c * v + b * 0.1;
        if (v < 0.0) v = 0.0;
        v = pow(v, g) * 255.0;    // mplayer's vf_eq2.c multiplies with 256 here, strange...

        if (v >= 255)
            this->y_lut[i] = 255;
        else
            this->y_lut[i] = (unsigned char)(v+0.5);
    }
}


static void uv_lut_init(ff2theora this) {
    int i;
    double v, s;
    s = this->video_satur;

    if ((s < 0.0) || (s > 100.0)) s = 1.0;

    if (s == 1.0) return;
    this->uv_lut_used = 1;

    printf("  Color correction: saturation=%g\n", s);

    for (i = 0; i < 256; i++) {
        v = 127.0 + (s * ((double)i - 127.0));
        if (v < 0.0) v = 0.0;

        if (v >= 255.0)
            this->uv_lut[i] = 255;
        else
            this->uv_lut[i] = (unsigned char)(v+0.5);
    }
}

static void lut_init(ff2theora this) {
    y_lut_init(this);
    uv_lut_init(this);
}

static void lut_apply(unsigned char *lut, unsigned char *src, unsigned char *dst, int width, int height, int stride) {
    int x, y;

    for (y = 0; y < height; y++) {
        for (x = 0; x < width; x++) {
            dst[x] = lut[src[x]];
        }
        src += stride;
        dst += stride;
    }
}

267
static void prepare_yuv_buffer(ff2theora this, yuv_buffer *yuv, AVFrame *frame) {
Jan Gerber's avatar
Jan Gerber committed
268
269
270
    /* pysical pages */
    yuv->y_width = this->frame_width;
    yuv->y_height = this->frame_height;
271
    yuv->y_stride = frame->linesize[0];
Jan Gerber's avatar
Jan Gerber committed
272
273
274

    yuv->uv_width = this->frame_width / 2;
    yuv->uv_height = this->frame_height / 2;
275
    yuv->uv_stride = frame->linesize[1];
Jan Gerber's avatar
Jan Gerber committed
276

277
278
279
    yuv->y = frame->data[0];
    yuv->u = frame->data[1];
    yuv->v = frame->data[2];
280
281
    if (this->y_lut_used) {
        lut_apply(this->y_lut, yuv->y, yuv->y, yuv->y_width, yuv->y_height, yuv->y_stride);
Jan Gerber's avatar
Jan Gerber committed
282
    }
283
284
285
    if (this->uv_lut_used) {
        lut_apply(this->uv_lut, yuv->u, yuv->u, yuv->uv_width, yuv->uv_height, yuv->uv_stride);
        lut_apply(this->uv_lut, yuv->v, yuv->v, yuv->uv_width, yuv->uv_height, yuv->uv_stride);
Jan Gerber's avatar
Jan Gerber committed
286
287
288
    }
}

289
void ff2theora_output(ff2theora this) {
Jan Gerber's avatar
Jan Gerber committed
290
291
292
293
294
295
296
    int i;
    AVCodecContext *aenc = NULL;
    AVCodecContext *venc = NULL;
    AVStream *astream = NULL;
    AVStream *vstream = NULL;
    AVCodec *acodec = NULL;
    AVCodec *vcodec = NULL;
297
298
    pp_mode_t *ppMode = NULL;
    pp_context_t *ppContext = NULL;
Jan Gerber's avatar
Jan Gerber committed
299
    float frame_aspect = 0;
300
    double fps = 0.0;
Jan Gerber's avatar
Jan Gerber committed
301

Jan Gerber's avatar
Jan Gerber committed
302
    if(this->audiostream >= 0 && this->context->nb_streams > this->audiostream) {
303
        AVCodecContext *enc = this->context->streams[this->audiostream]->codec;
304
305
        if (enc->codec_type == CODEC_TYPE_AUDIO) {
            this->audio_index = this->audiostream;
Jan Gerber's avatar
Jan Gerber committed
306
            fprintf(stderr,"  Using stream #0.%d as audio input\n",this->audio_index);
307
308
309
310
311
        }
        else {
            fprintf(stderr,"  The selected stream is not audio, falling back to automatic selection\n");
        }
    }
Jan Gerber's avatar
Jan Gerber committed
312

Jan Gerber's avatar
Jan Gerber committed
313
    for (i = 0; i < this->context->nb_streams; i++){
314
        AVCodecContext *enc = this->context->streams[i]->codec;
Jan Gerber's avatar
Jan Gerber committed
315
        switch (enc->codec_type){
316
317
318
319
320
321
322
323
324
325
            case CODEC_TYPE_VIDEO:
              if (this->video_index < 0)
                    this->video_index = i;
                break;
            case CODEC_TYPE_AUDIO:
                if (this->audio_index < 0 && !this->disable_audio)
                    this->audio_index = i;
                break;
            default:
                break;
Jan Gerber's avatar
Jan Gerber committed
326
327
328
329
330
        }
    }

    if (this->video_index >= 0){
        vstream = this->context->streams[this->video_index];
331
        venc = this->context->streams[this->video_index]->codec;
Jan Gerber's avatar
Jan Gerber committed
332
333
        vcodec = avcodec_find_decoder (venc->codec_id);

334
        fps = (double) vstream->r_frame_rate.num / vstream->r_frame_rate.den;
Jan Gerber's avatar
Jan Gerber committed
335
336
337
        if (fps > 10000)
            fps /= 1000;

338
339
        if(this->force_input_fps.num > 0)
            fps=(double)this->force_input_fps.num / this->force_input_fps.den;
340
        if (vcodec == NULL || avcodec_open (venc, vcodec) < 0) {
Jan Gerber's avatar
Jan Gerber committed
341
            this->video_index = -1;
342
        }
Jan Gerber's avatar
Jan Gerber committed
343
        this->fps = fps;
344

345

346
        if(this->preset == V2V_PRESET_PREVIEW){
Jan Gerber's avatar
Jan Gerber committed
347
            if(abs(this->fps-30)<1 && (venc->width!=NTSC_HALF_WIDTH || venc->height!=NTSC_HALF_HEIGHT) ){
348
349
                this->picture_width=NTSC_HALF_WIDTH;
                this->picture_height=NTSC_HALF_HEIGHT;
Jan Gerber's avatar
Jan Gerber committed
350
            }
Jan Gerber's avatar
Jan Gerber committed
351
352
353
354
            else {
                this->picture_width=PAL_HALF_WIDTH;
                this->picture_height=PAL_HALF_HEIGHT;
            }
Jan Gerber's avatar
Jan Gerber committed
355
        }
Jan Gerber's avatar
Jan Gerber committed
356
        else if(this->preset == V2V_PRESET_PRO){
Jan Gerber's avatar
Jan Gerber committed
357
            if(abs(this->fps-30)<1 && (venc->width!=NTSC_FULL_WIDTH || venc->height!=NTSC_FULL_HEIGHT) ){
358
359
                this->picture_width=NTSC_FULL_WIDTH;
                this->picture_height=NTSC_FULL_HEIGHT;
Jan Gerber's avatar
Jan Gerber committed
360
            }
Jan Gerber's avatar
Jan Gerber committed
361
362
363
364
            else {
                this->picture_width=PAL_FULL_WIDTH;
                this->picture_height=PAL_FULL_HEIGHT;
            }
Jan Gerber's avatar
Jan Gerber committed
365
        }
Jan Gerber's avatar
Jan Gerber committed
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
         else if(this->preset == V2V_PRESET_PADMA){
             int width=venc->width-this->frame_leftBand-this->frame_rightBand;
             int height=venc->height-this->frame_topBand-this->frame_bottomBand;
             if(venc->sample_aspect_ratio.den!=0 && venc->sample_aspect_ratio.num!=0) {
               height=((float)venc->sample_aspect_ratio.den/venc->sample_aspect_ratio.num) * height;
             }
             if(this->frame_aspect == 0)
               this->frame_aspect = (float)width/height;
             if(this->frame_aspect <= 1.5) {
               if(width > 640 || height > 480) {
                 //4:3 640 x 480
                 this->picture_width=640;
                 this->picture_height=480;
               }
               else {
                 this->picture_width=width;
                 this->picture_height=height;
               }
             }
             else {
               if(width > 640 || height > 360) {
                 //16:9 640 x 360
                 this->picture_width=640;
                 this->picture_height=360;
               }
               else {
                 this->picture_width=width;
                 this->picture_height=height;
               }
             }

         }
         else if(this->preset == V2V_PRESET_PADMASTREAM){
             int width=venc->width-this->frame_leftBand-this->frame_rightBand;
             int height=venc->height-this->frame_topBand-this->frame_bottomBand;
             if(venc->sample_aspect_ratio.den!=0 && venc->sample_aspect_ratio.num!=0) {
               height=((float)venc->sample_aspect_ratio.den/venc->sample_aspect_ratio.num) * height;
             }
             if(this->frame_aspect == 0)
               this->frame_aspect = (float)width/height;
             if(this->frame_aspect <= 1.5) {
                 this->picture_width=128;
                 this->picture_height=96;
             }
             else {
                 this->picture_width=128;
                 this->picture_height=72;
             }
         }
Jan Gerber's avatar
Jan Gerber committed
415
416
417
418
        else if(this->preset == V2V_PRESET_VIDEOBIN){
            int width=venc->width-this->frame_leftBand-this->frame_rightBand;
            int height=venc->height-this->frame_topBand-this->frame_bottomBand;
            if(venc->sample_aspect_ratio.den!=0 && venc->sample_aspect_ratio.num!=0) {
Jan Gerber's avatar
Jan Gerber committed
419
              height=((float)venc->sample_aspect_ratio.den/venc->sample_aspect_ratio.num) * height;
Jan Gerber's avatar
Jan Gerber committed
420
            }
421
            if( ((float)width /height) <= 1.5) {
Jan Gerber's avatar
Jan Gerber committed
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
              if(width > 448) {
                //4:3 448 x 336
                this->picture_width=448;
                this->picture_height=336;
              }
              else {
                this->picture_width=width;
                this->picture_height=height;
              }
            }
            else {
              if(width > 512) {
                //16:9 512 x 288
                this->picture_width=512;
                this->picture_height=288;
              }
              else {
                this->picture_width=width;
                this->picture_height=height;
              }
            }
Jan Gerber's avatar
Jan Gerber committed
443

Jan Gerber's avatar
Jan Gerber committed
444
        }
Jan Gerber's avatar
Jan Gerber committed
445
        if(this->picture_height==0 &&
Jan Gerber's avatar
Jan Gerber committed
446
447
448
449
            (this->frame_leftBand || this->frame_rightBand || this->frame_topBand || this->frame_bottomBand) ){
            this->picture_height=venc->height-
                    this->frame_topBand-this->frame_bottomBand;
        }
Jan Gerber's avatar
Jan Gerber committed
450
        if(this->picture_width==0 &&
Jan Gerber's avatar
Jan Gerber committed
451
452
453
454
455
            (this->frame_leftBand || this->frame_rightBand || this->frame_topBand || this->frame_bottomBand) ){
            this->picture_width=venc->width-
                    this->frame_leftBand-this->frame_rightBand;
        }
        //so frame_aspect is set on the commandline
456
457
458
459
460
461
462
463
464
465
466
        if(this->frame_aspect != 0){
            if(this->picture_height){
                this->aspect_numerator = 10000*this->frame_aspect*this->picture_height;
                this->aspect_denominator = 10000*this->picture_width;
            }
            else{
                this->aspect_numerator = 10000*this->frame_aspect*venc->height;
                this->aspect_denominator = 10000*venc->width;
            }
            av_reduce(&this->aspect_numerator,&this->aspect_denominator,this->aspect_numerator,this->aspect_denominator,10000);
            frame_aspect=this->frame_aspect;
Jan Gerber's avatar
Jan Gerber committed
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
        }
        if(venc->sample_aspect_ratio.num!=0 && this->frame_aspect==0){
            // just use the ratio from the input
            this->aspect_numerator=venc->sample_aspect_ratio.num;
            this->aspect_denominator=venc->sample_aspect_ratio.den;
            // or we use ratio for the output
            if(this->picture_height){
                int width=venc->width-this->frame_leftBand-this->frame_rightBand;
                int height=venc->height-this->frame_topBand-this->frame_bottomBand;
                av_reduce(&this->aspect_numerator,&this->aspect_denominator,
                venc->sample_aspect_ratio.num*width*this->picture_height,
                venc->sample_aspect_ratio.den*height*this->picture_width,10000);
                frame_aspect=(float)(this->aspect_numerator*this->picture_width)/
                                (this->aspect_denominator*this->picture_height);
            }
            else{
                frame_aspect=(float)(this->aspect_numerator*venc->width)/
                                (this->aspect_denominator*venc->height);
            }
        }
Jan Gerber's avatar
Jan Gerber committed
487
488
489
490
491
492
        if((float)this->aspect_numerator/this->aspect_denominator < 1.09){
          this->aspect_numerator = 1;
          this->aspect_denominator = 1;
          frame_aspect=(float)(this->aspect_numerator*this->picture_width)/
                          (this->aspect_denominator*this->picture_height);
        }
Jan Gerber's avatar
Jan Gerber committed
493
494
495
496
497
        if(this->aspect_denominator && frame_aspect){
            fprintf(stderr,"  Pixel Aspect Ratio: %.2f/1 ",(float)this->aspect_numerator/this->aspect_denominator);
            fprintf(stderr,"  Frame Aspect Ratio: %.2f/1\n",frame_aspect);
        }

498
499
500
501
502
503
504
505
506
        if (this->deinterlace==1)
            fprintf(stderr,"  Deinterlace: on\n");

        if (strcmp(this->pp_mode, "")) {
          ppContext = pp_get_context(venc->width, venc->height, PP_FORMAT_420);
          ppMode = pp_get_mode_by_name_and_quality(this->pp_mode, PP_QUALITY_MAX);
          fprintf(stderr,"  Postprocessing: %s\n", this->pp_mode);
        }

Jan Gerber's avatar
Jan Gerber committed
507
        if(!this->picture_width)
Jan Gerber's avatar
Jan Gerber committed
508
509
510
            this->picture_width = venc->width;
        if(!this->picture_height)
            this->picture_height = venc->height;
511

512
513
514
515
        /* Theora has a divisible-by-sixteen restriction for the encoded video size */
        /* scale the frame size up to the nearest /16 and calculate offsets */
        this->frame_width = ((this->picture_width + 15) >>4)<<4;
        this->frame_height = ((this->picture_height + 15) >>4)<<4;
Jan Gerber's avatar
Jan Gerber committed
516
517
518

        this->frame_x_offset = 0;
        this->frame_y_offset = 0;
Jan Gerber's avatar
Jan Gerber committed
519
520

        if(this->frame_width > 0 || this->frame_height > 0){
Jan Gerber's avatar
Jan Gerber committed
521
522
523
524
525
526
            this->sws_colorspace_ctx = sws_getContext(
                          venc->width, venc->height, venc->pix_fmt,
                          venc->width, venc->height, this->pix_fmt,
                          sws_flags, NULL, NULL, NULL
            );
            this->sws_scale_ctx = sws_getContext(
Jan Gerber's avatar
Jan Gerber committed
527
528
                          venc->width  - (this->frame_leftBand + this->frame_rightBand),
                          venc->height  - (this->frame_topBand + this->frame_bottomBand),
Jan Gerber's avatar
Jan Gerber committed
529
530
531
532
                          this->pix_fmt,
                          this->frame_width, this->frame_height, this->pix_fmt,
                          sws_flags, NULL, NULL, NULL
            );
Jan Gerber's avatar
Jan Gerber committed
533
534
535
536
537
538
539
            fprintf(stderr,"  Resize: %dx%d",venc->width,venc->height);
            if(this->frame_topBand || this->frame_bottomBand ||
            this->frame_leftBand || this->frame_rightBand){
                fprintf(stderr," => %dx%d",
                    venc->width-this->frame_leftBand-this->frame_rightBand,
                    venc->height-this->frame_topBand-this->frame_bottomBand);
            }
Jan Gerber's avatar
Jan Gerber committed
540
            if(this->picture_width != (venc->width-this->frame_leftBand - this->frame_rightBand)
Jan Gerber's avatar
Jan Gerber committed
541
542
543
544
                || this->picture_height != (venc->height-this->frame_topBand-this->frame_bottomBand))
                fprintf(stderr," => %dx%d",this->picture_width, this->picture_height);
            fprintf(stderr,"\n");
        }
545

546
        lut_init(this);
Jan Gerber's avatar
Jan Gerber committed
547
    }
548
    if (this->framerate_new.num > 0 && this->fps != (double)this->framerate_new.num / this->framerate_new.den) {
Jan Gerber's avatar
Jan Gerber committed
549
        fprintf(stderr,"  Resample Framerate: %0.2f => %0.2f\n",
550
                        this->fps, (double)this->framerate_new.num / this->framerate_new.den);
551
    }
Jan Gerber's avatar
Jan Gerber committed
552
553
    if (this->audio_index >= 0){
        astream = this->context->streams[this->audio_index];
554
        aenc = this->context->streams[this->audio_index]->codec;
Jan Gerber's avatar
Jan Gerber committed
555
        acodec = avcodec_find_decoder (aenc->codec_id);
556
        if (this->channels < 1) {
557
558
559
560
            if (aenc->channels > 2)
                this->channels = 2;
            else
                this->channels = aenc->channels;
561
562
563
564
        }
        if(this->sample_rate==-1) {
            this->sample_rate = aenc->sample_rate;
        }
Jan Gerber's avatar
Jan Gerber committed
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
        if (this->channels != aenc->channels && aenc->codec_id == CODEC_ID_AC3)
            aenc->channels = this->channels;

        if (acodec != NULL && avcodec_open (aenc, acodec) >= 0){
            if(this->sample_rate != aenc->sample_rate || this->channels != aenc->channels){
                this->audio_resample_ctx = audio_resample_init (this->channels,aenc->channels,this->sample_rate,aenc->sample_rate);
                if(this->sample_rate!=aenc->sample_rate)
                    fprintf(stderr,"  Resample: %dHz => %dHz\n",aenc->sample_rate,this->sample_rate);
                if(this->channels!=aenc->channels)
                    fprintf(stderr,"  Channels: %d => %d\n",aenc->channels,this->channels);
            }
            else{
                this->audio_resample_ctx=NULL;
            }
        }
        else{
            this->audio_index = -1;
        }
    }
584

585
    if (this->video_index >= 0 || this->audio_index >= 0){
Jan Gerber's avatar
Jan Gerber committed
586
        AVFrame *frame=NULL;
587
        AVFrame *frame_p=NULL;
Jan Gerber's avatar
Jan Gerber committed
588
        AVFrame *output=NULL;
589
590
        AVFrame *output_p=NULL;
        AVFrame *output_tmp_p=NULL;
Jan Gerber's avatar
Jan Gerber committed
591
        AVFrame *output_tmp=NULL;
592
        AVFrame *output_resized_p=NULL;
Jan Gerber's avatar
Jan Gerber committed
593
        AVFrame *output_resized=NULL;
594
        AVFrame *output_buffered_p=NULL;
Jan Gerber's avatar
Jan Gerber committed
595
        AVFrame *output_buffered=NULL;
Jan Gerber's avatar
Jan Gerber committed
596

Jan Gerber's avatar
Jan Gerber committed
597
598
599
600
601
        AVPacket pkt;
        int len;
        int len1;
        int got_picture;
        int first = 1;
602
        int e_o_s = 0;
Jan Gerber's avatar
Jan Gerber committed
603
604
        int ret;
        uint8_t *ptr;
605
606
        int16_t *audio_buf=av_malloc(4*AVCODEC_MAX_AUDIO_FRAME_SIZE);
        int16_t *resampled=av_malloc(4*AVCODEC_MAX_AUDIO_FRAME_SIZE);
Jan Gerber's avatar
Jan Gerber committed
607
        int16_t *audio_p=NULL;
608
        int no_frames;
Jan Gerber's avatar
Jan Gerber committed
609

Jan Gerber's avatar
Jan Gerber committed
610
        double framerate_add = 0;
611
        double framerate_tmpcount = 0;
Jan Gerber's avatar
Jan Gerber committed
612

Jan Gerber's avatar
Jan Gerber committed
613
614
615
616
        if(this->video_index >= 0)
            info.audio_only=0;
        else
            info.audio_only=1;
Jan Gerber's avatar
Jan Gerber committed
617

Jan Gerber's avatar
Jan Gerber committed
618
619
620
621
        if(this->audio_index>=0)
            info.video_only=0;
        else
            info.video_only=1;
Jan Gerber's avatar
Jan Gerber committed
622

Jan Gerber's avatar
Jan Gerber committed
623
        if(!info.audio_only){
624
            frame_p = frame = frame_alloc(vstream->codec->pix_fmt,
625
                            vstream->codec->width,vstream->codec->height);
626
            output_tmp_p = output_tmp = frame_alloc(this->pix_fmt,
627
                            vstream->codec->width,vstream->codec->height);
628
            output_p = output = frame_alloc(this->pix_fmt,
629
                            vstream->codec->width,vstream->codec->height);
630
            output_resized_p = output_resized = frame_alloc(this->pix_fmt,
Jan Gerber's avatar
Jan Gerber committed
631
                            this->frame_width, this->frame_height);
632
            output_buffered_p = output_buffered = frame_alloc(this->pix_fmt,
Jan Gerber's avatar
Jan Gerber committed
633
                            this->frame_width, this->frame_height);
Jan Gerber's avatar
Jan Gerber committed
634
635
636

            /* video settings here */
            /* config file? commandline options? v2v presets? */
Jan Gerber's avatar
Jan Gerber committed
637

Jan Gerber's avatar
Jan Gerber committed
638
            theora_info_init (&info.ti);
Jan Gerber's avatar
Jan Gerber committed
639

Jan Gerber's avatar
Jan Gerber committed
640
641
642
643
644
645
            info.ti.width = this->frame_width;
            info.ti.height = this->frame_height;
            info.ti.frame_width = this->picture_width;
            info.ti.frame_height = this->picture_height;
            info.ti.offset_x = this->frame_x_offset;
            info.ti.offset_y = this->frame_y_offset;
646
647
648
649
650
            if (this->framerate_new.num > 0) {
                // new framerate is interger only right now,
                // so denominator is always 1
                info.ti.fps_numerator = this->framerate_new.num;
                info.ti.fps_denominator = this->framerate_new.den;
Jan Gerber's avatar
Jan Gerber committed
651
652
            }
            else {
653
654
                info.ti.fps_numerator=vstream->r_frame_rate.num;
                info.ti.fps_denominator = vstream->r_frame_rate.den;
Jan Gerber's avatar
Jan Gerber committed
655
656
657
658
659
660
            }
            /* this is pixel aspect ratio */
            info.ti.aspect_numerator=this->aspect_numerator;
            info.ti.aspect_denominator=this->aspect_denominator;
            // FIXME: is all input material with fps==25 OC_CS_ITU_REC_470BG?
            // guess not, commandline option to select colorspace would be the best.
Jan Gerber's avatar
Jan Gerber committed
661
            if((this->fps-25)<1)
Jan Gerber's avatar
Jan Gerber committed
662
663
664
665
666
667
                info.ti.colorspace = OC_CS_ITU_REC_470BG;
            else if(abs(this->fps-30)<1)
                info.ti.colorspace = OC_CS_ITU_REC_470M;
            else
                info.ti.colorspace = OC_CS_UNSPECIFIED;

Jan Gerber's avatar
Jan Gerber committed
668
            info.ti.target_bitrate = this->video_bitrate;
Jan Gerber's avatar
Jan Gerber committed
669
            info.ti.quality = this->video_quality;
670
            info.ti.dropframes_p = 0;
Jan Gerber's avatar
Jan Gerber committed
671
            info.ti.keyframe_auto_p = 1;
672
673
            info.ti.keyframe_frequency = this->keyint;
            info.ti.keyframe_frequency_force = this->keyint;
Jan Gerber's avatar
Jan Gerber committed
674
675
676
677
678
679
            info.ti.keyframe_data_target_bitrate = info.ti.target_bitrate * 1.5;
            info.ti.keyframe_auto_threshold = 80;
            info.ti.keyframe_mindistance = 8;
            info.ti.noise_sensitivity = 1;
            // range 0-2, 0 sharp, 2 less sharp,less bandwidth
            info.ti.sharpness = this->sharpness;
Jan Gerber's avatar
Jan Gerber committed
680

Jan Gerber's avatar
Jan Gerber committed
681
682
683
684
        }
        /* audio settings here */
        info.channels = this->channels;
        info.sample_rate = this->sample_rate;
685
        info.vorbis_quality = this->audio_quality * 0.1;
Jan Gerber's avatar
Jan Gerber committed
686
        info.vorbis_bitrate = this->audio_bitrate;
687
688
689
690
691
        /* subtitles */
#ifdef HAVE_KATE
        for (i=0; i<this->n_kate_streams; ++i) {
            ff2theora_kate_stream *ks = this->kate_streams+i;
            kate_info *ki = &info.kate_streams[i].ki;
Jan Gerber's avatar
Jan Gerber committed
692
            kate_info_init(ki);
693
694
695
            if (ks->num_subtitles > 0) {
                kate_info_set_language(ki, ks->subtitles_language);
                kate_info_set_category(ki, ks->subtitles_category[0]?ks->subtitles_category:"subtitles");
696
697
698
                if(this->force_input_fps.num > 0) {
                    ki->gps_numerator = this->force_input_fps.num;    /* fps= numerator/denominator */
                    ki->gps_denominator = this->force_input_fps.den;
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
                }
                else {
                    if (this->framerate_new.num > 0) {
                        // new framerate is interger only right now, 
                        // so denominator is always 1
                        ki->gps_numerator = this->framerate_new.num;
                        ki->gps_denominator = this->framerate_new.den;
                    } 
                    else {
                        ki->gps_numerator=vstream->r_frame_rate.num;
                        ki->gps_denominator = vstream->r_frame_rate.den;
                    }
                }
                ki->granule_shift = 32;
            }
        }
#endif
Jan Gerber's avatar
Jan Gerber committed
716
        oggmux_init (&info);
Jan Gerber's avatar
Jan Gerber committed
717
718
719
        /*seek to start time*/
        if(this->start_time) {
          av_seek_frame( this->context, -1, (int64_t)AV_TIME_BASE*this->start_time, 1);
720
721
722
723
724
725
726
727
728
          /* discard subtitles by their end time, so we still have those that start before the start time,
             but end after it */
          for (i=0; i<this->n_kate_streams; ++i) {
              ff2theora_kate_stream *ks=this->kate_streams+i;
              while (ks->subtitles_count < ks->num_subtitles && ks->subtitles[ks->subtitles_count].t1 <= this->start_time) {
                  /* printf("skipping subtitle %u\n", ks->subtitles_count); */
                  ks->subtitles_count++;
              }
          }
Jan Gerber's avatar
Jan Gerber committed
729
        }
730

Jan Gerber's avatar
Jan Gerber committed
731
        if(info.audio_only && (this->end_time>0 || this->start_time>0)){
732
            fprintf(stderr,"Sorry, right now start/end time does not work for audio only files.\n");
Jan Gerber's avatar
Jan Gerber committed
733
734
            exit(1);
        }
735
736
737
738
739
740
741
742

        if (this->framerate_new.num > 0) {
            double framerate_new = (double)this->framerate_new.num / this->framerate_new.den;
            framerate_add = framerate_new/this->fps;
            //fprintf(stderr,"calculating framerate addition to %f\n",framerate_add);
            this->fps = framerate_new;
        }

743
744
745
746
747
748
        /*check for end time and calculate number of frames to encode*/
        no_frames = this->fps*(this->end_time - this->start_time);
        if(this->end_time > 0 && no_frames <= 0){
            fprintf(stderr,"End time has to be bigger than start time.\n");
            exit(1);
        }
Jan Gerber's avatar
Jan Gerber committed
749
        /* main decoding loop */
Jan Gerber's avatar
Jan Gerber committed
750
        do{
Jan Gerber's avatar
Jan Gerber committed
751
            if(no_frames > 0){
752
                if(this->frame_count > no_frames){
Jan Gerber's avatar
Jan Gerber committed
753
754
755
756
757
758
759
                    break;
                }
            }
            ret = av_read_frame(this->context,&pkt);
            if(ret<0){
                e_o_s=1;
            }
Jan Gerber's avatar
Jan Gerber committed
760

Jan Gerber's avatar
Jan Gerber committed
761
762
            ptr = pkt.data;
            len = pkt.size;
Jan Gerber's avatar
Jan Gerber committed
763
            if ((e_o_s && !info.audio_only) || (ret >= 0 && pkt.stream_index == this->video_index)){
Jan Gerber's avatar
Jan Gerber committed
764
765
766
767
                if(len == 0 && !first && !e_o_s){
                    fprintf (stderr, "no frame available\n");
                }
                while(e_o_s || len > 0){
768
                    int dups = 0;
769
                    yuv_buffer yuv;
770
771
                    len1 = avcodec_decode_video(vstream->codec, frame, &got_picture, ptr, len);
                    if(len1>=0) {
Jan Gerber's avatar
Jan Gerber committed
772
                        if(got_picture){
773
774
775
                            // this is disabled by default since it does not work
                            // for all input formats the way it should.
                            if(this->sync == 1) {
Jan Gerber's avatar
Jan Gerber committed
776
777
                                double delta = ((double) pkt.dts /
                                    AV_TIME_BASE - this->pts_offset) *
778
779
                                    this->fps - this->frame_count;
                                /* 0.7 is an arbitrary value */
Jan Gerber's avatar
Jan Gerber committed
780
                                /* it should be larger than half a frame to
781
782
                                 avoid excessive dropping and duplicating */
                                if (delta < -0.7) {
783
#ifdef DEBUG
784
785
                                    fprintf(stderr,
                                          "Frame dropped to maintain sync\n");
786
#endif
787
788
789
                                    break;
                                }
                                if (delta > 0.7) {
790
791
                                    //dups = lrintf(delta);
                                    dups = (int)delta;
792
#ifdef DEBUG
793
794
795
                                    fprintf(stderr,
                                      "%d duplicate %s added to maintain sync\n",
                                      dups, (dups == 1) ? "frame" : "frames");
796
#endif
797
                                }
798
                            }
Jan Gerber's avatar
Jan Gerber committed
799

800
801
802
                            if (this->framerate_new.num > 0) {
                                framerate_tmpcount += framerate_add;
                                if (framerate_tmpcount < (double)(this->frame_count+1)) {
803
                                    got_picture = 0;
Jan Gerber's avatar
Jan Gerber committed
804
                                }
805
806
807
808
                                else {
                                    dups = 0;
                                    while (framerate_tmpcount >= (double)(this->frame_count+2+dups)) {
                                        dups += 1;
Jan Gerber's avatar
Jan Gerber committed
809
                                    }
810
811
                                }
                            }
Jan Gerber's avatar
Jan Gerber committed
812

Jan Gerber's avatar
Jan Gerber committed
813
                            //For audio only files command line option"-e" will not work
814
                            //as we don't increment frame_count in audio section.
Jan Gerber's avatar
Jan Gerber committed
815

Jan Gerber's avatar
Jan Gerber committed
816
817
818
819
                            if(venc->pix_fmt != this->pix_fmt) {
                               sws_scale(this->sws_colorspace_ctx,
                                 frame->data, frame->linesize, 0, venc->height,
                                 output_tmp->data, output_tmp->linesize);
Jan Gerber's avatar
Jan Gerber committed
820

Jan Gerber's avatar
Jan Gerber committed
821
822
823
824
825
                            }
                            else{
                                output_tmp = frame;
                            }
                            if(frame->interlaced_frame || this->deinterlace){
Jan Gerber's avatar
Jan Gerber committed
826
                                if(avpicture_deinterlace((AVPicture *)output,(AVPicture *)output_tmp,this->pix_fmt,venc->width,venc->height)<0){
827
828
                                        fprintf(stderr,"Deinterlace failed.\n");
                                        exit(1);
Jan Gerber's avatar
Jan Gerber committed
829
830
831
832
833
834
                                }
                            }
                            else{
                                output=output_tmp;
                            }
                            // now output
Jan Gerber's avatar
Jan Gerber committed
835

836
837
838
839
840
841
                            if(ppMode)
                                pp_postprocess(output->data, output->linesize,
                                               output->data, output->linesize,
                                               venc->width, venc->height,
                                               output->qscale_table, output->qstride,
                                               ppMode, ppContext, this->pix_fmt);
842
                            if(this->vhook)
Jan Gerber's avatar
Jan Gerber committed
843
                                frame_hook_process((AVPicture *)output, this->pix_fmt, venc->width,venc->height, 0);
844

Jan Gerber's avatar
Jan Gerber committed
845
                            if (this->frame_topBand || this->frame_leftBand) {
Jan Gerber's avatar
Jan Gerber committed
846
                                if (av_picture_crop((AVPicture *)output_tmp, (AVPicture *)output,
Jan Gerber's avatar
Jan Gerber committed
847
848
849
850
851
852
853
854
855
                                    this->pix_fmt, this->frame_topBand, this->frame_leftBand) < 0) {
                                    av_log(NULL, AV_LOG_ERROR, "error cropping picture\n");
                                }
                                output = output_tmp;
                            }
                            if(this->sws_scale_ctx){
                              sws_scale(this->sws_scale_ctx,
                                output->data, output->linesize, 0, venc->height - (this->frame_topBand + this->frame_bottomBand),
                                output_resized->data, output_resized->linesize);
Jan Gerber's avatar
Jan Gerber committed
856
                            }
Jan Gerber's avatar
Jan Gerber committed
857
858
859
                            else{
                                output_resized=output;
                            }
Jan Gerber's avatar
Jan Gerber committed
860

Jan Gerber's avatar
Jan Gerber committed
861
862
863
                        }
                        ptr += len1;
                        len -= len1;
864
                    }
Jan Gerber's avatar
Jan Gerber committed
865
                    //now output_resized
Jan Gerber's avatar
Jan Gerber committed
866

867
868
                    if(!first) {
                      if(got_picture || e_o_s) {
Jan Gerber's avatar
Jan Gerber committed
869
                        prepare_yuv_buffer(this, &yuv, output_buffered);
870
871
872
873
874
875
876
877
878
879
                        do {
                          oggmux_add_video(&info, &yuv, e_o_s);
                          this->frame_count++;
                        } while(dups--);
                      }
                    }
                    if(got_picture) {
                      first=0;
                      av_picture_copy ((AVPicture *)output_buffered, (AVPicture *)output_resized, this->pix_fmt, this->frame_width, this->frame_height);
                    }
880
                    if(!got_picture){
Jan Gerber's avatar
Jan Gerber committed
881
882
883
                        break;
                    }
                }
Jan Gerber's avatar
Jan Gerber committed
884

Jan Gerber's avatar
Jan Gerber committed
885
            }
Jan Gerber's avatar
Jan Gerber committed
886
            if((e_o_s && !info.video_only)
Jan Gerber's avatar
Jan Gerber committed
887
                     || (ret >= 0 && pkt.stream_index == this->audio_index)){
Jan Gerber's avatar
Jan Gerber committed
888
                this->pts_offset = (double) pkt.pts / AV_TIME_BASE -
889
                    (double) this->sample_count / this->sample_rate;
Jan Gerber's avatar
Jan Gerber committed
890
891
892
                while(e_o_s || len > 0 ){
                    int samples=0;
                    int samples_out=0;
893
                    int data_size = 4*AVCODEC_MAX_AUDIO_FRAME_SIZE;
Jan Gerber's avatar
Jan Gerber committed
894
                    if(len > 0){
Jan Gerber's avatar
Jan Gerber committed
895
                        len1 = avcodec_decode_audio2(astream->codec, audio_buf, &data_size, ptr, len);
Jan Gerber's avatar
Jan Gerber committed
896
897
898
899
900
901
902
903
                        if (len1 < 0){
                            /* if error, we skip the frame */
                            break;
                        }
                        len -= len1;
                        ptr += len1;
                        if(data_size >0){
                            samples =data_size / (aenc->channels * 2);
Jan Gerber's avatar
Jan Gerber committed
904

Jan Gerber's avatar
Jan Gerber committed
905
906
907
                            samples_out = samples;
                            if(this->audio_resample_ctx){
                                samples_out = audio_resample(this->audio_resample_ctx, resampled, audio_buf, samples);
908
                                audio_p = resampled;
Jan Gerber's avatar
Jan Gerber committed
909
910
                            }
                            else
911
                                audio_p = audio_buf;
Jan Gerber's avatar
Jan Gerber committed
912
913
                        }
                    }
914
                    oggmux_add_audio(&info, audio_p,
Jan Gerber's avatar
Jan Gerber committed
915
                        samples_out *(this->channels),samples_out,e_o_s);
916
                    this->sample_count += samples_out;
Jan Gerber's avatar
Jan Gerber committed
917
918
919
920
921
922
                    if(e_o_s && len <= 0){
                        break;
                    }
                }

            }
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945

            /* if we have subtitles starting before then, add it */
            if (info.with_kate) {
                double avtime = info.audio_only ? info.audiotime :
                    info.video_only ? info.videotime :
                    info.audiotime < info.videotime ? info.audiotime : info.videotime;
                for (i=0; i<this->n_kate_streams; ++i) {
                    ff2theora_kate_stream *ks = this->kate_streams+i;
                    if (ks->num_subtitles > 0) {
                        ff2theora_subtitle *sub = ks->subtitles+ks->subtitles_count;
                        /* we encode a bit in advance so we're sure to hit the time, the packet will
                           be held till the right time. If we don't do that, we can insert late and
                           oggz-validate moans */
                        while (ks->subtitles_count < ks->num_subtitles && sub->t0-1.0 <= avtime+this->start_time) {
                            int eos = (ks->subtitles_count == ks->num_subtitles-1);
                            oggmux_add_kate_text(&info, i, sub->t0, sub->t1, sub->text, sub->len, eos);
                            ks->subtitles_count++;
                            ++sub;
                        }
                    }
                }
            }

Jan Gerber's avatar
Jan Gerber committed
946
            /* flush out the file */
Jan Gerber's avatar
Jan Gerber committed
947
            oggmux_flush (&info, e_o_s);
Jan Gerber's avatar
Jan Gerber committed
948
949
950
            av_free_packet (&pkt);
        }
        while (ret >= 0);
Jan Gerber's avatar
Jan Gerber committed
951

952
953
954
955
956
957
958
959
960
        for (i=0; i<this->n_kate_streams; ++i) {
            ff2theora_kate_stream *ks = this->kate_streams+i;
            if (ks->num_subtitles > 0 && ks->subtitles_count<ks->num_subtitles) {
                double t = (info.videotime<info.audiotime?info.audiotime:info.videotime)+this->start_time;
                oggmux_add_kate_end_packet(&info, i, t);
                oggmux_flush (&info, e_o_s);
            }
        }

961
962
963
964
        if (this->video_index >= 0) {
            avcodec_close(venc);
        }
        if (this->audio_index >= 0) {
965
966
            if (this->audio_resample_ctx)
              audio_resample_close(this->audio_resample_ctx);
967
968
            avcodec_close(aenc);
        }
Jan Gerber's avatar
Jan Gerber committed
969
        oggmux_close (&info);
970
971
        if(ppContext)
            pp_free_context(ppContext);
972
        if (!info.audio_only) {
Jan Gerber's avatar
Jan Gerber committed
973
            av_free(frame_p);
974
975
976
977
            frame_dealloc(output_p);
            frame_dealloc(output_tmp_p);
            frame_dealloc(output_resized_p);
            frame_dealloc(output_buffered_p);
978
979
980
        }
        av_free(audio_buf);
        av_free(resampled);
981
    }
Jan Gerber's avatar
Jan Gerber committed
982
    else{
983
        fprintf (stderr, "No video or audio stream found.\n");
Jan Gerber's avatar
Jan Gerber committed
984
    }
985
986
987
}

void ff2theora_close (ff2theora this){
988
989
    sws_freeContext(this->sws_colorspace_ctx);
    sws_freeContext(this->sws_scale_ctx);
Jan Gerber's avatar
Jan Gerber committed
990
    /* clear out state */
991
    free_subtitles(this);
Jan Gerber's avatar
Jan Gerber committed
992
    av_free (this);
993
994
}

995
996
997
998
999
1000
double aspect_check(const char *arg)
{
    int x = 0, y = 0;
    double ar = 0;
    const char *p;