rmovie 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,49 @@
1
+ #ifndef QP_FRAME_H
2
+ #define QP_FRAME_H
3
+
4
+ #include "qp_util.h"
5
+
6
+ #include <ffmpeg/avcodec.h>
7
+ #include <ffmpeg/avformat.h>
8
+
9
+ /*
10
+ * Basic frame manipulation routines. This should remain general enough to
11
+ * be used in ffmpeg-php or rmovie.
12
+ */
13
+
14
+ typedef struct {
15
+ AVFrame *av_frame;
16
+ int width;
17
+ int height;
18
+ int pixel_format;
19
+ int keyframe;
20
+ int64_t pts;
21
+ } qp_frame_context;
22
+
23
+ int qp_get_frame_height(qp_frame_context *frame);
24
+ int qp_get_frame_width(qp_frame_context *frame);
25
+ const char* qp_get_frame_pixel_format_name(qp_frame_context *frame_ctx);
26
+
27
+ /* This should be static */
28
+ void qp_free_av_frame(AVFrame *av_frame);
29
+
30
+ qp_frame_context* qp_alloc_frame_ctx(qp_malloc_t malloc_func);
31
+ void qp_free_frame_ctx(qp_frame_context *frame_ctx, qp_free_t free_func);
32
+
33
+
34
+ int qp_convert_av_frame(AVFrame **av_frame, int pixel_format,
35
+ int new_format, int width, int height, int free_buffers);
36
+
37
+ int qp_convert_frame(qp_frame_context *frame, int new_fmt);
38
+ int qp_crop_frame(qp_frame_context *frame,
39
+ int crop_top, int crop_bottom, int crop_left, int crop_right);
40
+ int qp_resample_frame(qp_frame_context *frame,
41
+ int wanted_width, int wanted_height, int crop_top, int crop_bottom,
42
+ int crop_left, int crop_right);
43
+
44
+ int qp_output_frame_as_string(qp_frame_context *frame, unsigned char**);
45
+
46
+ double qp_get_pts(qp_frame_context *frame);
47
+ long qp_frame_is_keyframe(qp_frame_context *frame);
48
+
49
+ #endif
@@ -0,0 +1,1179 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+
4
+ #include "qp_util.h"
5
+ #include "qp_movie.h"
6
+ #include "qp_frame.h"
7
+
8
+ #define LRINT(x) ((long) ((x)+0.5))
9
+ #define MAX(a,b) ((a) > (b) ? (a) : (b))
10
+
11
+ #if LIBAVFORMAT_BUILD > 4628
12
+ #define GET_CODEC_FIELD(codec, field) codec->field
13
+ #define GET_CODEC_PTR(codec) codec
14
+ #else
15
+ #define GET_CODEC_FIELD(codec, field) codec.field
16
+ #define GET_CODEC_PTR(codec) &codec
17
+ #endif
18
+
19
+ #define MAX_AUDIO_PACKET_SIZE (128 * 1024)
20
+
21
+ /*
22
+ * TODO: this should return error as a string so that the calling
23
+ * program can decided how to display it.
24
+ */
25
+ /*
26
+ static void _php_print_av_error(const char *filename, int err)
27
+ {
28
+ char* err_string;
29
+ switch(err) {
30
+ case AVERROR_IO:
31
+ fprintf(stderr, "%s: I/O error.\n", filename);
32
+ break;
33
+ case AVERROR_NOMEM:
34
+ fprintf(stderr, "%s: Not enough memory.\n", filename);
35
+ break;
36
+ case AVERROR_NOTSUPP:
37
+ fprintf(stderr, "%s: Operation not supported.\n", filename);
38
+ break;
39
+
40
+ case AVERROR_NUMEXPECTED:
41
+ fprintf(stderr, "%s: Incorrect image filename syntax.\n", filename);
42
+ break;
43
+ case AVERROR_INVALIDDATA:
44
+ fprintf(stderr, "%s: Error while parsing header\n", filename);
45
+ break;
46
+ case AVERROR_NOFMT:
47
+ fprintf(stderr, "%s: Unknown format\n", filename);
48
+ case AVERROR_UNKNOWN:
49
+ // Fall thru to default case
50
+ default:
51
+ fprintf(stderr, "%s: Error while opening file (%d)\n", filename, err);
52
+ break;
53
+ }
54
+ }
55
+ */
56
+
57
+ int qp_open_movie_file(qp_movie_context *movie_ctx, const char* filename)
58
+ {
59
+ int ret;
60
+
61
+ if (movie_ctx->fmt_ctx) {
62
+ av_close_input_file(movie_ctx->fmt_ctx);
63
+ movie_ctx->fmt_ctx = NULL;
64
+ }
65
+
66
+ /* open the file with generic libav function */
67
+ ret = av_open_input_file(&(movie_ctx->fmt_ctx), filename, NULL, 0, NULL);
68
+
69
+ if (ret) {
70
+ return ret;
71
+ }
72
+
73
+ /* If not enough info to get the stream parameters, we decode the
74
+ * first frames to get it. */
75
+ if (av_find_stream_info(movie_ctx->fmt_ctx)) {
76
+ /* Don't fail here since this is not a problem for formats like .mov */
77
+ }
78
+ return 0;
79
+ }
80
+
81
+
82
+ void qp_free_movie_ctx(qp_movie_context *movie_ctx, qp_free_t free_func)
83
+ {
84
+ int i;
85
+ qp_free_t free_function = free_func ? free_func : free;
86
+
87
+ if (movie_ctx->codec_ctx) {
88
+ for (i = 0; i < MAX_STREAMS; i++) {
89
+ if (movie_ctx->codec_ctx[i]) {
90
+ avcodec_close(movie_ctx->codec_ctx[i]);
91
+ }
92
+ movie_ctx->codec_ctx[i] = NULL;
93
+ }
94
+ }
95
+
96
+ if (movie_ctx->fmt_ctx) {
97
+ av_close_input_file(movie_ctx->fmt_ctx);
98
+ }
99
+
100
+ free_function(movie_ctx);
101
+ }
102
+
103
+
104
+ qp_movie_context* qp_alloc_movie_ctx(qp_malloc_t malloc_func)
105
+ {
106
+ int i;
107
+ qp_movie_context *movie_ctx = NULL;
108
+
109
+ qp_malloc_t malloc_function = malloc_func ? malloc_func : malloc;
110
+
111
+ movie_ctx = (qp_movie_context *)malloc_function(sizeof(qp_movie_context));
112
+ movie_ctx->fmt_ctx = NULL;
113
+ movie_ctx->frame_number = 0;
114
+ movie_ctx->mode = QP_FRAME_BASED;
115
+
116
+ for (i = 0; i < MAX_STREAMS; i++) {
117
+ movie_ctx->codec_ctx[i] = NULL;
118
+ }
119
+
120
+ return movie_ctx;
121
+ }
122
+
123
+
124
+ static int get_stream_index(AVFormatContext *fmt_ctx, int type)
125
+ {
126
+ int i;
127
+
128
+ for (i = 0; i < fmt_ctx->nb_streams; i++) {
129
+ if (fmt_ctx->streams[i] &&
130
+ GET_CODEC_FIELD(fmt_ctx->streams[i]->codec, codec_type) == type) {
131
+ return i;
132
+ }
133
+ }
134
+ /* stream not found */
135
+ return -1;
136
+ }
137
+
138
+
139
+ static AVCodecContext* get_decoder_context(qp_movie_context *movie_ctx, int stream_type)
140
+ {
141
+ AVCodec *decoder;
142
+ int stream_index;
143
+
144
+ stream_index = get_stream_index(movie_ctx->fmt_ctx, stream_type);
145
+ if (stream_index < 0) {
146
+ return NULL;
147
+ }
148
+
149
+ /* check if the codec for this stream is already open */
150
+ if (!movie_ctx->codec_ctx[stream_index]) {
151
+
152
+ /* find the decoder */
153
+ decoder = avcodec_find_decoder(GET_CODEC_FIELD(
154
+ movie_ctx->fmt_ctx->streams[stream_index]->codec,
155
+ codec_id));
156
+
157
+ if (!decoder) {
158
+ return NULL;
159
+ }
160
+
161
+ movie_ctx->codec_ctx[stream_index] =
162
+ GET_CODEC_PTR(movie_ctx->fmt_ctx->streams[stream_index]->codec);
163
+
164
+ /* open the decoder */
165
+ if (avcodec_open(movie_ctx->codec_ctx[stream_index], decoder) < 0) {
166
+ return NULL;
167
+ }
168
+ }
169
+ return movie_ctx->codec_ctx[stream_index];
170
+ }
171
+
172
+
173
+ static AVStream *get_video_stream(AVFormatContext *fmt_ctx)
174
+ {
175
+ int i = get_stream_index(fmt_ctx, CODEC_TYPE_VIDEO);
176
+
177
+ return i < 0 ? NULL : fmt_ctx->streams[i];
178
+ }
179
+
180
+
181
+ static AVStream *get_audio_stream(AVFormatContext *fmt_ctx)
182
+ {
183
+ int i = get_stream_index(fmt_ctx, CODEC_TYPE_AUDIO);
184
+
185
+ return i < 0 ? NULL : fmt_ctx->streams[i];
186
+ }
187
+
188
+
189
+ float qp_get_frame_rate(qp_movie_context *movie_ctx)
190
+ {
191
+ AVStream *st = get_video_stream(movie_ctx->fmt_ctx);
192
+ float rate = 0.0f;
193
+
194
+ if (!st) {
195
+ return rate;
196
+ }
197
+
198
+ #if LIBAVCODEC_BUILD > 4753
199
+ if (GET_CODEC_FIELD(st->codec, codec_type) == CODEC_TYPE_VIDEO){
200
+ if (st->r_frame_rate.den && st->r_frame_rate.num) {
201
+ rate = av_q2d(st->r_frame_rate);
202
+ } else {
203
+ rate = 1 / av_q2d(GET_CODEC_FIELD(st->codec, time_base));
204
+ }
205
+ }
206
+ return (float)rate;
207
+ #else
208
+ return (float)GET_CODEC_FIELD(st->codec, frame_rate) /
209
+ GET_CODEC_FIELD(st->codec, frame_rate_base);
210
+ #endif
211
+ }
212
+
213
+
214
+ float qp_get_duration(qp_movie_context *movie_ctx)
215
+ {
216
+ float duration;
217
+
218
+ duration = (float)movie_ctx->fmt_ctx->duration / AV_TIME_BASE;
219
+
220
+ if (duration < 0) {
221
+ duration = 0.0f;
222
+ }
223
+ return duration;
224
+ }
225
+
226
+
227
+ long qp_get_frame_count(qp_movie_context *movie_ctx)
228
+ {
229
+ /* does this movie have a video stream? */
230
+ if (!get_video_stream(movie_ctx->fmt_ctx)) {
231
+ return 0;
232
+ }
233
+
234
+ return LRINT(qp_get_frame_rate(movie_ctx) *
235
+ qp_get_duration(movie_ctx));
236
+ }
237
+
238
+
239
+ char* qp_get_file_name(qp_movie_context *movie_ctx)
240
+ {
241
+ return movie_ctx->fmt_ctx->filename;
242
+ }
243
+
244
+
245
+ char* qp_get_comment(qp_movie_context *movie_ctx)
246
+ {
247
+ return movie_ctx->fmt_ctx->comment;
248
+ }
249
+
250
+
251
+ char* qp_get_title(qp_movie_context *movie_ctx)
252
+ {
253
+ return movie_ctx->fmt_ctx->title;
254
+ }
255
+
256
+
257
+ char* qp_get_author(qp_movie_context *movie_ctx)
258
+ {
259
+ return movie_ctx->fmt_ctx->author;
260
+ }
261
+
262
+
263
+ char* qp_get_copyright(qp_movie_context *movie_ctx)
264
+ {
265
+ return movie_ctx->fmt_ctx->author;
266
+ }
267
+
268
+
269
+ char* qp_get_album(qp_movie_context *movie_ctx)
270
+ {
271
+ return movie_ctx->fmt_ctx->album;
272
+ }
273
+
274
+
275
+ char* qp_get_genre(qp_movie_context *movie_ctx)
276
+ {
277
+ return movie_ctx->fmt_ctx->genre;
278
+ }
279
+
280
+
281
+ int qp_get_year(qp_movie_context *movie_ctx)
282
+ {
283
+ return movie_ctx->fmt_ctx->year;
284
+ }
285
+
286
+
287
+ int qp_get_track(qp_movie_context *movie_ctx)
288
+ {
289
+ return movie_ctx->fmt_ctx->track;
290
+ }
291
+
292
+
293
+ int qp_get_movie_width(qp_movie_context *movie_ctx)
294
+ {
295
+ AVStream *st = get_video_stream(movie_ctx->fmt_ctx);
296
+
297
+ if (!st) {
298
+ return 0;
299
+ }
300
+
301
+ return GET_CODEC_FIELD(st->codec, width);
302
+ }
303
+
304
+
305
+ int qp_get_movie_height(qp_movie_context *movie_ctx)
306
+ {
307
+ AVStream *st = get_video_stream(movie_ctx->fmt_ctx);
308
+
309
+ if (!st) {
310
+ return 0;
311
+ }
312
+
313
+ return GET_CODEC_FIELD(st->codec, height);
314
+ }
315
+
316
+
317
+ long qp_get_current_frame_number(qp_movie_context *movie_ctx)
318
+ {
319
+ AVCodecContext *decoder_ctx = NULL;
320
+
321
+ decoder_ctx = get_decoder_context(movie_ctx, CODEC_TYPE_VIDEO);
322
+ if (!decoder_ctx) {
323
+ return 0;
324
+ }
325
+
326
+ if (movie_ctx->frame_number <= 0) {
327
+ return 1; /* no frames read yet so return the first */
328
+ } else {
329
+ return movie_ctx->frame_number;
330
+ }
331
+ }
332
+
333
+
334
+ static int get_format_number(qp_movie_context *movie_ctx, int codec_type)
335
+ {
336
+ AVCodecContext *decoder_ctx = NULL;
337
+
338
+ decoder_ctx = get_decoder_context(movie_ctx, codec_type);
339
+
340
+ return decoder_ctx ? decoder_ctx->pix_fmt : 0;
341
+ }
342
+
343
+
344
+ const char* qp_get_movie_pixel_format_name(qp_movie_context *movie_ctx)
345
+ {
346
+ int pix_fmt;
347
+ const char *fmt = NULL;
348
+
349
+ pix_fmt = get_format_number(movie_ctx, CODEC_TYPE_VIDEO);
350
+ fmt = avcodec_get_pix_fmt_name(pix_fmt);
351
+
352
+ if (fmt) {
353
+ return fmt;
354
+ } else {
355
+ return NULL;
356
+ }
357
+ }
358
+
359
+
360
+ int qp_get_bit_rate(qp_movie_context *movie_ctx)
361
+ {
362
+ return movie_ctx->fmt_ctx->bit_rate;
363
+ }
364
+
365
+
366
+ const char* qp_get_codec_name(qp_movie_context *movie_ctx, int type)
367
+ {
368
+ AVCodecContext *decoder_ctx = NULL;
369
+ AVCodec *p = NULL;
370
+ const char *codec_name;
371
+ char buf1[32];
372
+
373
+ if (!qp_has_video(movie_ctx)) {
374
+ return NULL;
375
+ }
376
+
377
+ decoder_ctx = get_decoder_context(movie_ctx, type);
378
+ if (!decoder_ctx) {
379
+ return NULL;
380
+ }
381
+
382
+ p = avcodec_find_decoder(decoder_ctx->codec_id);
383
+
384
+ /* Copied from libavcodec/utils.c::avcodec_string */
385
+ if (p) {
386
+ codec_name = p->name;
387
+ if (decoder_ctx->codec_id == CODEC_ID_MP3) {
388
+ if (decoder_ctx->sub_id == 2)
389
+ codec_name = "mp2";
390
+ else if (decoder_ctx->sub_id == 1)
391
+ codec_name = "mp1";
392
+ }
393
+ } else if (decoder_ctx->codec_id == CODEC_ID_MPEG2TS) {
394
+ /* fake mpeg2 transport stream codec (currently not registered) */
395
+ codec_name = "mpeg2ts";
396
+ } else if (decoder_ctx->codec_name[0] != '\0') {
397
+ codec_name = decoder_ctx->codec_name;
398
+ } else {
399
+ /* output avi tags */
400
+ if (decoder_ctx->codec_type == CODEC_TYPE_VIDEO) {
401
+ snprintf(buf1, sizeof(buf1), "%c%c%c%c",
402
+ decoder_ctx->codec_tag & 0xff,
403
+ (decoder_ctx->codec_tag >> 8) & 0xff,
404
+ (decoder_ctx->codec_tag >> 16) & 0xff,
405
+ (decoder_ctx->codec_tag >> 24) & 0xff);
406
+ } else {
407
+ snprintf(buf1, sizeof(buf1), "0x%04x", decoder_ctx->codec_tag);
408
+ }
409
+ codec_name = buf1;
410
+ }
411
+
412
+ return codec_name;
413
+ }
414
+
415
+
416
+ int qp_has_audio(qp_movie_context *movie_ctx)
417
+ {
418
+ return get_audio_stream(movie_ctx->fmt_ctx) ? 1 : 0;
419
+ }
420
+
421
+
422
+ int qp_has_video(qp_movie_context *movie_ctx)
423
+ {
424
+ return get_video_stream(movie_ctx->fmt_ctx) ? 1 : 0;
425
+ }
426
+
427
+
428
+ int qp_get_num_audio_channels(qp_movie_context *movie_ctx)
429
+ {
430
+ AVCodecContext *decoder_ctx = NULL;
431
+
432
+ if (!qp_has_audio(movie_ctx)) {
433
+ return 0;
434
+ }
435
+
436
+ decoder_ctx = get_decoder_context(movie_ctx, CODEC_TYPE_AUDIO);
437
+ if (!decoder_ctx) {
438
+ return 0;
439
+ }
440
+
441
+ return decoder_ctx->channels;
442
+ }
443
+
444
+
445
+ int qp_get_codec_sample_rate(qp_movie_context *movie_ctx, int type)
446
+ {
447
+ AVCodecContext *decoder_ctx = NULL;
448
+
449
+ decoder_ctx = get_decoder_context(movie_ctx, type);
450
+ if (!decoder_ctx) {
451
+ return 0;
452
+ }
453
+
454
+ return decoder_ctx->sample_rate;
455
+ }
456
+
457
+ /* Returns the bit rate for codec of type. */
458
+ int qp_get_codec_bit_rate(qp_movie_context *movie_ctx, int type)
459
+ {
460
+ AVCodecContext *decoder_ctx = NULL;
461
+
462
+ decoder_ctx = get_decoder_context(movie_ctx, type);
463
+ if (!decoder_ctx) {
464
+ return 0;
465
+ }
466
+
467
+ return decoder_ctx->bit_rate;
468
+ }
469
+
470
+ /*
471
+ static int movie_get_buffer (AVCodecContext *context, AVFrame *picture)
472
+ {
473
+ char *buf = NULL;
474
+ long bufsize = 0;
475
+ int width;
476
+ int height;
477
+
478
+ width = context->width;
479
+ height = context->height;
480
+
481
+ if (avcodec_check_dimensions(context, width, height)) {
482
+ return -1;
483
+ }
484
+
485
+ switch (context->codec_type) {
486
+ case CODEC_TYPE_VIDEO:
487
+ avcodec_align_dimensions (context, &width, &height);
488
+
489
+ bufsize = avpicture_get_size (context->pix_fmt, width, height);
490
+
491
+ if (width != context->width || height != context->height) {
492
+ context->width = width;
493
+ context->height = height;
494
+
495
+ return avcodec_default_get_buffer (context, picture);
496
+ }
497
+
498
+ buf = av_mallocz(bufsize);
499
+ //printf("get buffer %p\n", buf);
500
+
501
+ avpicture_fill((AVPicture *) picture, buf,
502
+ context->pix_fmt, context->width, context->height);
503
+ break;
504
+ case CODEC_TYPE_AUDIO:
505
+ default:
506
+ //assert("movie_get_buffer: Not implemented for audio");
507
+ break;
508
+ }
509
+
510
+ // tell ffmpeg we own this buffer
511
+ picture->type = FF_BUFFER_TYPE_USER;
512
+
513
+ return 0;
514
+ }
515
+
516
+ static void movie_release_buffer(AVCodecContext *context, AVFrame *picture)
517
+ {
518
+ int i;
519
+ char *buf = NULL;
520
+
521
+ if (picture->type != FF_BUFFER_TYPE_USER) {
522
+ return;
523
+ }
524
+
525
+ buf = (char*) (picture->opaque);
526
+ if (buf == NULL) {
527
+ return;
528
+ }
529
+
530
+ av_free(buf);
531
+
532
+ picture->opaque = NULL;
533
+
534
+ // zero out the reference in ffmpeg
535
+ for (i = 0; i < 4; i++) {
536
+ picture->data[i] = NULL;
537
+ picture->linesize[i] = 0;
538
+ }
539
+ }
540
+ */
541
+
542
+ static void rewind_movie(qp_movie_context *movie_ctx) {
543
+ if (
544
+
545
+ #if LIBAVFORMAT_BUILD >= 4619
546
+ av_seek_frame(movie_ctx->fmt_ctx, -1, 0, 0)
547
+ #else
548
+ av_seek_frame(movie_ctx->fmt_ctx, -1, 0)
549
+ #endif
550
+ < 0) {
551
+
552
+ /* If we can't seek, fall back to reopening the file. */
553
+ qp_open_movie_file(movie_ctx, qp_get_file_name(movie_ctx));
554
+ }
555
+
556
+ movie_ctx->frame_number = 0;
557
+ }
558
+
559
+ /*
560
+ * get_av_frame()
561
+ * Returns an av_frame from the movie
562
+ */
563
+ static AVFrame* get_av_frame(qp_movie_context *movie_ctx,
564
+ int wanted_frame, int *is_keyframe, int64_t *pts)
565
+ {
566
+ AVCodecContext *decoder_ctx = NULL;
567
+ AVPacket packet;
568
+ AVFrame *frame = NULL;
569
+ int got_frame;
570
+ int video_stream;
571
+
572
+ video_stream = get_stream_index(movie_ctx->fmt_ctx,
573
+ CODEC_TYPE_VIDEO);
574
+ if (video_stream < 0) {
575
+ return NULL;
576
+ }
577
+
578
+ decoder_ctx = get_decoder_context(movie_ctx, CODEC_TYPE_VIDEO);
579
+ if (decoder_ctx == NULL) {
580
+ return NULL;
581
+ }
582
+
583
+ /* set buffer functions */
584
+ //decoder_ctx->get_buffer = movie_get_buffer;
585
+ //decoder_ctx->release_buffer = movie_release_buffer;
586
+
587
+ /* Rewind to the beginning of the stream if wanted frame already passed */
588
+ if (wanted_frame > 0 && wanted_frame <= movie_ctx->frame_number) {
589
+
590
+ rewind_movie(movie_ctx);
591
+
592
+ /* flush decoder buffers here */
593
+ avcodec_flush_buffers(decoder_ctx);
594
+ }
595
+
596
+ frame = avcodec_alloc_frame();
597
+
598
+ /* read frames looking for wanted_frame */
599
+ while (av_read_frame(movie_ctx->fmt_ctx, &packet) >= 0) {
600
+
601
+ /* hurry up if we're still a ways from the target frame */
602
+ if (wanted_frame != QP_GETFRAME_KEYFRAME &&
603
+ wanted_frame != QP_GETFRAME_NEXTFRAME &&
604
+ wanted_frame - movie_ctx->frame_number >
605
+ decoder_ctx->gop_size + 1) {
606
+ decoder_ctx->hurry_up = 1;
607
+ } else {
608
+ decoder_ctx->hurry_up = 0;
609
+ }
610
+
611
+ if (packet.stream_index == video_stream) {
612
+
613
+ avcodec_decode_video(decoder_ctx, frame, &got_frame,
614
+ packet.data, packet.size);
615
+
616
+ if (got_frame) {
617
+ movie_ctx->frame_number++;
618
+ /* FIXME:
619
+ * With the addition of the keyframe logic, this loop is
620
+ * getting a little too tricky. wanted_frame is way
621
+ * overloaded. Refactor to make clearer what is going on.
622
+ */
623
+
624
+ /*
625
+ * if caller wants next keyframe then get it and break out of
626
+ * loop.
627
+ */
628
+ if (wanted_frame == QP_GETFRAME_KEYFRAME &&
629
+ (packet.flags & PKT_FLAG_KEY)) {
630
+ /* free wanted frame packet */
631
+ *is_keyframe = 1;
632
+ *pts = packet.pts;
633
+ av_free_packet(&packet);
634
+ goto found_frame;
635
+ }
636
+
637
+ if (wanted_frame == QP_GETFRAME_NEXTFRAME ||
638
+ movie_ctx->frame_number == wanted_frame) {
639
+ /* free wanted frame packet */
640
+ *is_keyframe = (packet.flags & PKT_FLAG_KEY);
641
+ *pts = packet.pts;
642
+ av_free_packet(&packet);
643
+ goto found_frame;
644
+ }
645
+ }
646
+ }
647
+
648
+ /* free the packet allocated by av_read_frame */
649
+ av_free_packet(&packet);
650
+ }
651
+
652
+ /* free av_frame struct. Buffers are managed by the codec context
653
+ and will be freed when the codec is closed */
654
+ free(frame);
655
+ return NULL;
656
+
657
+ found_frame:
658
+ return frame;
659
+ }
660
+
661
+
662
+ int qp_get_frame(qp_movie_context *movie_ctx, int wanted_frame,
663
+ qp_frame_context **frame_ctx_handle) {
664
+ int is_keyframe = 0;
665
+ int64_t pts;
666
+ AVFrame *decoded_frame = NULL;
667
+ qp_frame_context *frame_ctx = NULL;
668
+
669
+ decoded_frame = get_av_frame(movie_ctx, wanted_frame, &is_keyframe, &pts);
670
+ if (!decoded_frame) {
671
+ fprintf(stderr, "Error getting av_frame\n");
672
+ return -1;
673
+ }
674
+
675
+ /* TODO: Create higher level function in qp_frame.c for this */
676
+ if (*frame_ctx_handle == NULL) {
677
+ *frame_ctx_handle = qp_alloc_frame_ctx(NULL);
678
+ if (*frame_ctx_handle == NULL) {
679
+ fprintf(stderr, "Error allocating frame context\n");
680
+ free(decoded_frame);
681
+ return -2;
682
+ }
683
+ }
684
+
685
+ frame_ctx = *frame_ctx_handle;
686
+
687
+ /* TODO: Provide function(s) for setting these in frame.c */
688
+ frame_ctx->width = qp_get_movie_width(movie_ctx);
689
+ frame_ctx->height = qp_get_movie_height(movie_ctx);
690
+ frame_ctx->pixel_format = get_format_number(movie_ctx, CODEC_TYPE_VIDEO);
691
+ frame_ctx->keyframe = is_keyframe;
692
+ frame_ctx->pts = pts;
693
+
694
+ frame_ctx->av_frame = avcodec_alloc_frame();
695
+ avpicture_alloc((AVPicture*)frame_ctx->av_frame, frame_ctx->pixel_format,
696
+ frame_ctx->width, frame_ctx->height);
697
+
698
+ /*
699
+ * FIXME: temporary hack until I figure out how to pass new buffers
700
+ * to the decoder
701
+ */
702
+ img_copy((AVPicture*)frame_ctx->av_frame,
703
+ (AVPicture *)decoded_frame, frame_ctx->pixel_format,
704
+ frame_ctx->width, frame_ctx->height);
705
+
706
+ free(decoded_frame);
707
+
708
+ return 0;
709
+ }
710
+
711
+
712
+ /*
713
+ * pre_read_frame()
714
+ * ffmpeg seems not to fill in some AVCodecContext fields until at least
715
+ * one frame is read. This function will read a frame without moving the
716
+ * frame counter.
717
+ */
718
+ static void pre_read_frame(qp_movie_context *movie_ctx) {
719
+ AVFrame *frame = NULL;
720
+ int is_keyframe;
721
+ int64_t pts;
722
+
723
+ frame = get_av_frame(movie_ctx, QP_GETFRAME_NEXTFRAME, &is_keyframe, &pts);
724
+
725
+ // We only get called if frames haven't been read so we can just
726
+ // rewind once we're through
727
+ rewind_movie(movie_ctx);
728
+ if (frame) {
729
+ free(frame);
730
+ }
731
+ }
732
+
733
+
734
+ double qp_get_pixel_aspect_ratio(qp_movie_context *movie_ctx)
735
+ {
736
+ AVCodecContext *decoder_ctx = NULL;
737
+
738
+ decoder_ctx = get_decoder_context(movie_ctx, CODEC_TYPE_VIDEO);
739
+ if (!decoder_ctx) {
740
+ return 0;
741
+ }
742
+
743
+ if (decoder_ctx->sample_aspect_ratio.num == 0 &&
744
+ movie_ctx->frame_number == 0) {
745
+ // pre read a frame so ffmpeg will fill in sample aspect ratio field.
746
+ pre_read_frame(movie_ctx);
747
+
748
+ if (decoder_ctx->sample_aspect_ratio.num == 0) {
749
+ return 0;
750
+ }
751
+ }
752
+
753
+ return av_q2d(decoder_ctx->sample_aspect_ratio);
754
+ }
755
+
756
+
757
+ // TODO: Make these fields in qp_movie_context struct
758
+ //int16_t *movie_ctx->audio_samples;
759
+ int audio_input_frame_size;
760
+
761
+
762
+ int open_audio(qp_movie_context *movie_ctx, AVFormatContext *oc, AVStream *st)
763
+ {
764
+ AVCodecContext *c;
765
+ AVCodec *codec;
766
+
767
+ c = st->codec;
768
+
769
+ /* find the audio encoder */
770
+ codec = avcodec_find_encoder(c->codec_id);
771
+ if (!codec) {
772
+ fprintf(stderr, "codec not found\n");
773
+ return 1;
774
+ }
775
+
776
+ /* open it */
777
+ if (avcodec_open(c, codec) < 0) {
778
+ fprintf(stderr, "could not open codec\n");
779
+ return 2;
780
+ }
781
+
782
+ movie_ctx->audio_outbuf_size = 4 * MAX_AUDIO_PACKET_SIZE;
783
+ movie_ctx->audio_outbuf = (uint8_t *)malloc(movie_ctx->audio_outbuf_size);
784
+
785
+ /* ugly hack for PCM codecs (will be removed ASAP with new PCM
786
+ support to compute the input frame size in movie_ctx->audio_samples */
787
+ if (c->frame_size <= 1) {
788
+ audio_input_frame_size = movie_ctx->audio_outbuf_size / c->channels;
789
+ switch(st->codec->codec_id) {
790
+ case CODEC_ID_PCM_S16LE:
791
+ case CODEC_ID_PCM_S16BE:
792
+ case CODEC_ID_PCM_U16LE:
793
+ case CODEC_ID_PCM_U16BE:
794
+ audio_input_frame_size >>= 1;
795
+ break;
796
+ default:
797
+ break;
798
+ }
799
+ } else {
800
+ audio_input_frame_size = c->frame_size;
801
+ }
802
+ movie_ctx->audio_samples = (int16_t *)malloc(audio_input_frame_size * 2 * c->channels);
803
+ return 0;
804
+ }
805
+
806
+
807
+
808
+ int write_audio_frame(qp_movie_context *movie_ctx, AVFormatContext *oc,
809
+ AVStream *st)
810
+ {
811
+ AVCodecContext *c;
812
+ AVPacket pkt;
813
+ av_init_packet(&pkt);
814
+
815
+ c = st->codec;
816
+
817
+ pkt.size = avcodec_encode_audio(c, movie_ctx->audio_outbuf,
818
+ movie_ctx->audio_outbuf_size, (short *)movie_ctx->audio_samples);
819
+
820
+ pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
821
+ pkt.flags |= PKT_FLAG_KEY;
822
+ pkt.stream_index= st->index;
823
+ pkt.data= movie_ctx->audio_outbuf;
824
+
825
+ /* write the compressed frame in the media file */
826
+ if (av_write_frame(oc, &pkt) != 0) {
827
+ fprintf(stderr, "Error while writing audio frame\n");
828
+ return 2;
829
+ }
830
+ return 0;
831
+ }
832
+
833
+ /*
834
+ * add an audio output stream
835
+ */
836
+ AVStream *add_audio_stream(AVCodecContext *icodec,
837
+ AVFormatContext *oc, int codec_id)
838
+ {
839
+ AVCodecContext *c;
840
+ AVStream *st;
841
+
842
+ st = av_new_stream(oc, 1);
843
+ if (!st) {
844
+ fprintf(stderr, "Could not alloc stream\n");
845
+ return NULL;
846
+ }
847
+
848
+ c = st->codec;
849
+ c->codec_id = codec_id;
850
+ c->codec_type = CODEC_TYPE_AUDIO;
851
+
852
+ /* put sample parameters */
853
+ c->bit_rate = icodec->bit_rate;
854
+ c->sample_rate = icodec->sample_rate;
855
+ c->channels = icodec->channels;
856
+ return st;
857
+ }
858
+
859
+
860
+ /* add a video output stream */
861
+ static AVStream *add_video_stream(qp_movie_context *movie_ctx,
862
+ AVFormatContext *oc, int codec_id)
863
+ {
864
+ AVCodecContext *c;
865
+ AVStream *st;
866
+
867
+ st = av_new_stream(oc, 0);
868
+ if (!st) {
869
+ fprintf(stderr, "Could not alloc stream\n");
870
+ return NULL;
871
+ }
872
+
873
+ c = st->codec;
874
+ c->codec_id = codec_id;
875
+ c->codec_type = CODEC_TYPE_VIDEO;
876
+
877
+ /* put sample parameters */
878
+ // TODO: This should be input video stream bitrate not total bit rate
879
+ c->bit_rate = qp_get_bit_rate(movie_ctx);
880
+ /* resolution must be a multiple of two */
881
+ c->width = qp_get_movie_width(movie_ctx);
882
+ c->height = qp_get_movie_height(movie_ctx);
883
+ /* time base: this is the fundamental unit of time (in seconds) in terms
884
+ of which frame timestamps are represented. for fixed-fps content,
885
+ timebase should be 1/framerate and timestamp increments should be
886
+ identically 1. */
887
+ //c->time_base.den = STREAM_FRAME_RATE;
888
+ // TODO: Should probably just pass num/den from decoder ctx
889
+ c->time_base.den = qp_get_frame_rate(movie_ctx);
890
+ c->time_base.num = 1;
891
+
892
+ c->gop_size = 12; /* emit one intra frame every twelve frames at most */
893
+ c->pix_fmt = PIX_FMT_YUV420P;
894
+ if (c->codec_id == CODEC_ID_MPEG2VIDEO) {
895
+ /* just for testing, we also add B frames */
896
+ c->max_b_frames = 2;
897
+ }
898
+ if (c->codec_id == CODEC_ID_MPEG1VIDEO){
899
+ /* needed to avoid using macroblocks in which some coeffs overflow
900
+ this doesnt happen with normal video, it just happens here as the
901
+ motion of the chroma plane doesnt match the luma plane */
902
+ c->mb_decision=2;
903
+ }
904
+ // some formats want stream headers to be seperate
905
+ if (!strcmp(oc->oformat->name, "mp4") ||
906
+ !strcmp(oc->oformat->name, "mov") ||
907
+ !strcmp(oc->oformat->name, "3gp")) {
908
+ c->flags |= CODEC_FLAG_GLOBAL_HEADER;
909
+ }
910
+
911
+ return st;
912
+ }
913
+
914
+
915
+ AVFrame *alloc_picture(int pix_fmt, int width, int height)
916
+ {
917
+ AVFrame *picture;
918
+ uint8_t *picture_buf;
919
+ int size;
920
+
921
+ picture = avcodec_alloc_frame();
922
+ if (!picture)
923
+ return NULL;
924
+ size = avpicture_get_size(pix_fmt, width, height);
925
+ picture_buf = (uint8_t *)malloc(size);
926
+ if (!picture_buf) {
927
+ av_free(picture);
928
+ return NULL;
929
+ }
930
+ avpicture_fill((AVPicture *)picture, picture_buf,
931
+ pix_fmt, width, height);
932
+ return picture;
933
+ }
934
+
935
+
936
+ static int write_video_frame(qp_movie_context *movie_ctx, AVFormatContext *oc,
937
+ AVStream *st, AVFrame *decoded_frame, int pixel_format)
938
+ {
939
+ int out_size, ret;
940
+ AVCodecContext *c;
941
+
942
+ c = st->codec;
943
+
944
+ // encode the image
945
+ out_size = avcodec_encode_video(c, movie_ctx->video_outbuf, movie_ctx->video_outbuf_size, decoded_frame);
946
+ // if zero size, it means the image was buffered
947
+ if (out_size > 0) {
948
+ AVPacket pkt;
949
+ av_init_packet(&pkt);
950
+
951
+ pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base);
952
+ if (c->coded_frame->key_frame) {
953
+ pkt.flags |= PKT_FLAG_KEY;
954
+ }
955
+ pkt.stream_index= st->index;
956
+ pkt.data= movie_ctx->video_outbuf;
957
+ pkt.size= out_size;
958
+
959
+ // write the compressed frame in the media file
960
+ ret = av_write_frame(oc, &pkt);
961
+ } else {
962
+ ret = 0;
963
+ }
964
+ if (ret != 0) {
965
+ fprintf(stderr, "Error while writing video frame\n");
966
+ }
967
+ return ret;
968
+ }
969
+
970
+
971
+ static void close_audio(qp_movie_context *movie_ctx, AVFormatContext *oc,
972
+ AVStream *st)
973
+ {
974
+ avcodec_close(st->codec);
975
+
976
+ av_free(movie_ctx->audio_samples);
977
+ av_free(movie_ctx->audio_outbuf);
978
+ }
979
+
980
+
981
+ int qp_export_movie(qp_movie_context *movie_ctx, const char *filename)
982
+ {
983
+ AVFrame *decoded_frame = NULL;
984
+ AVPacket packet;
985
+ AVCodecContext *video_decoder_ctx = NULL;
986
+ AVCodecContext *audio_decoder_ctx = NULL;
987
+ AVCodec *video_codec = NULL;
988
+ //AVCodec *input_audio_codec = NULL;
989
+ AVOutputFormat *fmt = NULL;
990
+ AVFormatContext *oc = NULL;
991
+ AVStream *video_st = NULL;
992
+ AVStream *audio_st = NULL;
993
+ int video_stream_index = -1;
994
+ int audio_stream_index = -1;
995
+ int i;
996
+ int got_frame;
997
+
998
+ /* auto detect the output format from the name. default is mpeg. */
999
+ fmt = guess_format(NULL, filename, NULL);
1000
+ if (!fmt) {
1001
+ printf("Could not deduce output format from file extension: using MPEG.\n");
1002
+ fmt = guess_format("mpeg", NULL, NULL);
1003
+ }
1004
+ if (!fmt) {
1005
+ fprintf(stderr, "Could not find suitable output format\n");
1006
+ return 1;
1007
+ }
1008
+
1009
+ /* allocate the output media context */
1010
+ oc = av_alloc_format_context();
1011
+ if (!oc) {
1012
+ fprintf(stderr, "Memory error\n");
1013
+ return 2;
1014
+ }
1015
+ oc->oformat = fmt;
1016
+ snprintf(oc->filename, sizeof(oc->filename), "%s", filename);
1017
+
1018
+ // add the audio and video streams using the default format codecs
1019
+ // and initialize the codecs
1020
+
1021
+ // create a video stream if the input has a video stream and the
1022
+ // output format supports video
1023
+ if (fmt->video_codec != CODEC_ID_NONE && qp_has_video(movie_ctx)) {
1024
+ video_stream_index = get_stream_index(movie_ctx->fmt_ctx,
1025
+ CODEC_TYPE_VIDEO);
1026
+ if (video_stream_index < 0) {
1027
+ fprintf(stderr, "can't find video stream index\n");
1028
+ return 3;
1029
+ }
1030
+
1031
+ video_st = add_video_stream(movie_ctx, oc, fmt->video_codec);
1032
+ video_decoder_ctx = get_decoder_context(movie_ctx, CODEC_TYPE_VIDEO);
1033
+ }
1034
+
1035
+ // create a audio stream if the input has a audio stream and the
1036
+ // output format supports audio
1037
+ if (fmt->audio_codec != CODEC_ID_NONE && qp_has_audio(movie_ctx)) {
1038
+ audio_stream_index = get_stream_index(movie_ctx->fmt_ctx,
1039
+ CODEC_TYPE_AUDIO);
1040
+ if (audio_stream_index < 0) {
1041
+ fprintf(stderr, "can't find audio stream index\n");
1042
+ return 4;
1043
+ }
1044
+ audio_st = add_audio_stream(movie_ctx->fmt_ctx->streams[audio_stream_index]->codec, oc, fmt->audio_codec);
1045
+ audio_decoder_ctx = get_decoder_context(movie_ctx, CODEC_TYPE_AUDIO);
1046
+ }
1047
+
1048
+ /* set the output parameters (must be done even if no parameters). */
1049
+ if (av_set_parameters(oc, NULL) < 0) {
1050
+ fprintf(stderr, "Invalid output format parameters\n");
1051
+ return 5;
1052
+ }
1053
+
1054
+ //dump_format(oc, 0, filename, 1);
1055
+
1056
+ /* now that all the parameters are set, we can open the audio and
1057
+ video codecs and allocate the necessary encode buffers */
1058
+
1059
+ /* find the video encoder */
1060
+ // TODO: Might have to do the default codec thing here
1061
+ if (video_st) {
1062
+ video_codec = avcodec_find_encoder(video_st->codec->codec_id);
1063
+ if (!video_codec) {
1064
+ fprintf(stderr, "codec not found\n");
1065
+ return 6;
1066
+ }
1067
+
1068
+ /* open the codec */
1069
+ if (avcodec_open(video_st->codec, video_codec) < 0) {
1070
+ fprintf(stderr, "could not open codec\n");
1071
+ return 7;
1072
+ }
1073
+
1074
+ movie_ctx->video_outbuf = NULL;
1075
+ // TODO: need to correctly handle raw picture as in
1076
+ // output_example.c
1077
+ if (!(oc->oformat->flags & AVFMT_RAWPICTURE)) {
1078
+ /* allocate output buffer */
1079
+ /* XXX: API change will be done */
1080
+ movie_ctx->video_outbuf_size = 200000;
1081
+ movie_ctx->video_outbuf = (uint8_t *)malloc(movie_ctx->video_outbuf_size);
1082
+ }
1083
+ }
1084
+
1085
+ if (audio_st) {
1086
+ open_audio(movie_ctx, oc, audio_st);
1087
+ }
1088
+
1089
+ /* open the output file, if needed */
1090
+ if (!(fmt->flags & AVFMT_NOFILE)) {
1091
+ if (url_fopen(&oc->pb, filename, URL_WRONLY) < 0) {
1092
+ fprintf(stderr, "Could not open '%s'\n", filename);
1093
+ return 9;
1094
+ }
1095
+ }
1096
+
1097
+ /* write the stream header, if any */
1098
+ av_write_header(oc);
1099
+
1100
+ rewind_movie(movie_ctx);
1101
+
1102
+ decoded_frame = avcodec_alloc_frame();
1103
+
1104
+ while (av_read_frame(movie_ctx->fmt_ctx, &packet) >= 0) {
1105
+ if (packet.stream_index == video_stream_index && video_st) {
1106
+
1107
+ avcodec_decode_video(video_decoder_ctx, decoded_frame,
1108
+ &got_frame, packet.data, packet.size);
1109
+
1110
+ if (got_frame) {
1111
+
1112
+ // TODO: this allocates a new frame buffer for each frame
1113
+ // conversion which is way inefficient.
1114
+ qp_convert_av_frame(&decoded_frame,
1115
+ get_format_number(movie_ctx, CODEC_TYPE_VIDEO),
1116
+ PIX_FMT_YUV420P,
1117
+ qp_get_movie_width(movie_ctx),
1118
+ qp_get_movie_height(movie_ctx), 0);
1119
+
1120
+ // TODO: Allow resizing movie during export
1121
+ //qp_resample_frame();
1122
+
1123
+ /* write interleaved audio and video frames */
1124
+ write_video_frame(movie_ctx, oc, video_st, decoded_frame,
1125
+ get_format_number(movie_ctx, CODEC_TYPE_VIDEO));
1126
+ }
1127
+ } else if (packet.stream_index == audio_stream_index && audio_st) {
1128
+ int out_size = 0;
1129
+
1130
+ movie_ctx->audio_samples =
1131
+ av_fast_realloc(movie_ctx->audio_samples,
1132
+ &movie_ctx->audio_samples_size,
1133
+ MAX(packet.size, AVCODEC_MAX_AUDIO_FRAME_SIZE));
1134
+
1135
+ avcodec_decode_audio(audio_decoder_ctx,
1136
+ movie_ctx->audio_samples, &out_size, packet.data,
1137
+ packet.size);
1138
+
1139
+ if (out_size > 0) {
1140
+ write_audio_frame(movie_ctx, oc, audio_st);
1141
+ }
1142
+ } else {
1143
+ // nop
1144
+ }
1145
+
1146
+ /* free the packet allocated by av_read_frame */
1147
+ av_free_packet(&packet);
1148
+ }
1149
+
1150
+ /* close each codec */
1151
+ if (video_st) {
1152
+ avcodec_close(video_st->codec);
1153
+ av_free(decoded_frame->data[0]);
1154
+ av_free(decoded_frame);
1155
+ av_free(movie_ctx->video_outbuf);
1156
+ }
1157
+
1158
+ if (audio_st) {
1159
+ close_audio(movie_ctx, oc, audio_st);
1160
+ }
1161
+
1162
+ /* write the trailer, if any */
1163
+ av_write_trailer(oc);
1164
+
1165
+ /* free the streams */
1166
+ for (i = 0; i < oc->nb_streams; i++) {
1167
+ av_freep(&oc->streams[i]);
1168
+ }
1169
+
1170
+ if (!(fmt->flags & AVFMT_NOFILE)) {
1171
+ /* close the output file */
1172
+ url_fclose(&oc->pb);
1173
+ }
1174
+
1175
+ /* free the stream */
1176
+ av_free(oc);
1177
+
1178
+ return 0;
1179
+ }