Merge branch 'ct' of git.pipapo.org:cinelerra-ct into ct
[cinelerra_cv/ct.git] / quicktime / qtffmpeg.c
blob594a2130d94450b9d4f912b335057bf6a5b8a44b
1 #include "colormodels.h"
2 #include "funcprotos.h"
3 #include <pthread.h>
4 #include "quicktime.h"
5 #include "qtffmpeg.h"
6 #include "qtprivate.h"
7 #include <string.h>
8 // FFMPEG front end for quicktime.
17 int ffmpeg_initialized = 0;
18 pthread_mutex_t ffmpeg_lock = PTHREAD_MUTEX_INITIALIZER;
25 quicktime_ffmpeg_t* quicktime_new_ffmpeg(int cpus,
26 int fields,
27 int ffmpeg_id,
28 int w,
29 int h,
30 quicktime_stsd_table_t *stsd_table)
32 quicktime_ffmpeg_t *ptr = calloc(1, sizeof(quicktime_ffmpeg_t));
33 quicktime_esds_t *esds = &stsd_table->esds;
34 quicktime_avcc_t *avcc = &stsd_table->avcc;
35 int i;
37 ptr->fields = fields;
38 ptr->width = w;
39 ptr->height = h;
40 ptr->ffmpeg_id = ffmpeg_id;
41 //printf("quicktime_new_ffmpeg 1 %d\n", ptr->ffmpeg_id);
42 if(ffmpeg_id == CODEC_ID_SVQ1)
44 ptr->width_i = quicktime_quantize32(ptr->width);
45 ptr->height_i = quicktime_quantize32(ptr->height);
47 else
49 ptr->width_i = quicktime_quantize16(ptr->width);
50 ptr->height_i = quicktime_quantize16(ptr->height);
53 pthread_mutex_lock(&ffmpeg_lock);
54 if(!ffmpeg_initialized)
56 ffmpeg_initialized = 1;
57 avcodec_init();
58 avcodec_register_all();
61 for(i = 0; i < fields; i++)
63 ptr->decoder[i] = avcodec_find_decoder(ptr->ffmpeg_id);
64 if(!ptr->decoder[i])
66 printf("quicktime_new_ffmpeg: avcodec_find_decoder returned NULL.\n");
67 quicktime_delete_ffmpeg(ptr);
68 return 0;
71 AVCodecContext *context = ptr->decoder_context[i] = avcodec_alloc_context();
72 static char fake_data[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
73 context->width = ptr->width_i;
74 context->height = ptr->height_i;
75 // context->width = w;
76 // context->height = h;
77 context->extradata = fake_data;
78 context->extradata_size = 0;
79 if(esds->mpeg4_header && esds->mpeg4_header_size)
81 context->extradata = esds->mpeg4_header;
82 context->extradata_size = esds->mpeg4_header_size;
84 if(avcc->data && avcc->data_size)
86 context->extradata = avcc->data;
87 context->extradata_size = avcc->data_size;
89 if(cpus > 1 &&
90 (ffmpeg_id == CODEC_ID_MPEG4 ||
91 ffmpeg_id == CODEC_ID_MPEG1VIDEO ||
92 ffmpeg_id == CODEC_ID_MPEG2VIDEO ||
93 ffmpeg_id == CODEC_ID_H263P ||
94 ffmpeg_id == CODEC_FLAG_H263P_SLICE_STRUCT))
96 avcodec_thread_init(context, cpus);
97 context->thread_count = cpus;
99 if(avcodec_open(context,
100 ptr->decoder[i]) < 0)
102 printf("quicktime_new_ffmpeg: avcodec_open failed.\n");
103 quicktime_delete_ffmpeg(ptr);
105 ptr->last_frame[i] = -1;
107 pthread_mutex_unlock(&ffmpeg_lock);
109 return ptr;
114 void quicktime_delete_ffmpeg(quicktime_ffmpeg_t *ptr)
116 int i;
117 if(ptr)
119 pthread_mutex_lock(&ffmpeg_lock);
120 for(i = 0; i < ptr->fields; i++)
122 if(ptr->decoder_context[i])
124 avcodec_close(ptr->decoder_context[i]);
125 free(ptr->decoder_context[i]);
128 pthread_mutex_unlock(&ffmpeg_lock);
132 if(ptr->temp_frame) free(ptr->temp_frame);
133 if(ptr->work_buffer) free(ptr->work_buffer);
136 free(ptr);
141 static int decode_wrapper(quicktime_t *file,
142 quicktime_video_map_t *vtrack,
143 quicktime_ffmpeg_t *ffmpeg,
144 int frame_number,
145 int current_field,
146 int track,
147 int drop_it)
149 int got_picture = 0;
150 int result = 0;
151 int bytes = 0;
152 int header_bytes = 0;
153 char *compressor = vtrack->track->mdia.minf.stbl.stsd.table[0].format;
154 quicktime_trak_t *trak = vtrack->track;
155 quicktime_stsd_table_t *stsd_table = &trak->mdia.minf.stbl.stsd.table[0];
157 //printf("decode_wrapper %d\n", frame_number);
158 quicktime_set_video_position(file, frame_number, track);
160 bytes = quicktime_frame_size(file, frame_number, track);
161 if(frame_number == 0)
163 header_bytes = stsd_table->esds.mpeg4_header_size;
166 if(!ffmpeg->work_buffer || ffmpeg->buffer_size < bytes + header_bytes)
168 if(ffmpeg->work_buffer) free(ffmpeg->work_buffer);
169 ffmpeg->buffer_size = bytes + header_bytes;
170 ffmpeg->work_buffer = calloc(1, ffmpeg->buffer_size + 100);
173 if(header_bytes)
174 memcpy(ffmpeg->work_buffer, stsd_table->esds.mpeg4_header, header_bytes);
176 if(!quicktime_read_data(file,
177 ffmpeg->work_buffer + header_bytes,
178 bytes))
179 result = -1;
182 if(!result)
186 // No way to determine if there was an error based on nonzero status.
187 // Need to test row pointers to determine if an error occurred.
188 if(drop_it)
189 ffmpeg->decoder_context[current_field]->skip_frame = AVDISCARD_NONREF /* AVDISCARD_BIDIR */;
190 else
191 ffmpeg->decoder_context[current_field]->skip_frame = AVDISCARD_DEFAULT;
192 result = avcodec_decode_video(ffmpeg->decoder_context[current_field],
193 &ffmpeg->picture[current_field],
194 &got_picture,
195 ffmpeg->work_buffer,
196 bytes + header_bytes);
200 if(ffmpeg->picture[current_field].data[0])
202 result = 0;
204 else
206 // ffmpeg can't recover if the first frame errored out, like in a direct copy
207 // sequence.
208 result = 1;
211 #ifdef ARCH_X86
212 asm("emms");
213 #endif
216 return result;
219 // Get amount chroma planes are downsampled from luma plane.
220 // Used for copying planes into cache.
221 static int get_chroma_factor(quicktime_ffmpeg_t *ffmpeg, int current_field)
223 switch(ffmpeg->decoder_context[current_field]->pix_fmt)
225 case PIX_FMT_YUV420P:
226 return 4;
227 break;
228 case PIX_FMT_YUV422:
229 return 2;
230 break;
231 case PIX_FMT_YUV422P:
232 return 2;
233 break;
234 case PIX_FMT_YUV410P:
235 return 9;
236 break;
237 default:
238 fprintf(stderr,
239 "get_chroma_factor: unrecognized color model %d\n",
240 ffmpeg->decoder_context[current_field]->pix_fmt);
241 return 9;
242 break;
246 int quicktime_ffmpeg_decode(quicktime_ffmpeg_t *ffmpeg,
247 quicktime_t *file,
248 unsigned char **row_pointers,
249 int track)
251 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
252 quicktime_trak_t *trak = vtrack->track;
253 int current_field = vtrack->current_position % ffmpeg->fields;
254 int input_cmodel;
255 int result = 0;
256 int seeking_done = 0;
257 int i;
259 // Try frame cache
260 result = quicktime_get_frame(vtrack->frame_cache,
261 vtrack->current_position,
262 &ffmpeg->picture[current_field].data[0],
263 &ffmpeg->picture[current_field].data[1],
264 &ffmpeg->picture[current_field].data[2]);
267 // Didn't get frame
268 if(!result)
270 // Codecs which work without locking:
271 // H264
272 // MPEG-4
273 // pthread_mutex_lock(&ffmpeg_lock);
275 //printf("quicktime_ffmpeg_decode 1 %d\n", ffmpeg->last_frame[current_field]);
277 if(ffmpeg->last_frame[current_field] == -1 &&
278 ffmpeg->ffmpeg_id != CODEC_ID_H264)
280 int current_frame = vtrack->current_position;
281 // For certain codecs,
282 // must decode frame with stream header first but only the first frame in the
283 // field sequence has a stream header.
284 result = decode_wrapper(file,
285 vtrack,
286 ffmpeg,
287 current_field,
288 current_field,
289 track,
291 // Reset position because decode wrapper set it
292 quicktime_set_video_position(file, current_frame, track);
293 ffmpeg->last_frame[current_field] = current_field;
297 // Handle seeking
298 // Seeking requires keyframes
299 if(quicktime_has_keyframes(file, track) &&
300 // Not next frame
301 vtrack->current_position != ffmpeg->last_frame[current_field] + ffmpeg->fields &&
302 // Same frame requested twice
303 vtrack->current_position != ffmpeg->last_frame[current_field])
305 int frame1;
306 int first_frame;
307 int frame2 = vtrack->current_position;
308 int current_frame = frame2;
309 int do_i_frame = 1;
311 // If an interleaved codec, the opposite field would have been decoded in the previous
312 // seek.
313 if(!quicktime_has_frame(vtrack->frame_cache, vtrack->current_position + 1))
314 quicktime_reset_cache(vtrack->frame_cache);
316 // Get first keyframe of same field
317 frame1 = current_frame;
320 frame1 = quicktime_get_keyframe_before(file,
321 frame1 - 1,
322 track);
323 }while(frame1 > 0 && (frame1 % ffmpeg->fields) != current_field);
324 //printf("quicktime_ffmpeg_decode 1 %d\n", frame1);
326 // For MPEG-4, get another keyframe before first keyframe.
327 // The Sanyo tends to glitch with only 1 keyframe.
328 // Not enough memory.
329 if( 0 /* frame1 > 0 && ffmpeg->ffmpeg_id == CODEC_ID_MPEG4 */)
333 frame1 = quicktime_get_keyframe_before(file,
334 frame1 - 1,
335 track);
336 }while(frame1 > 0 && (frame1 & ffmpeg->fields) != current_field);
337 //printf("quicktime_ffmpeg_decode 2 %d\n", frame1);
340 // Keyframe is before last decoded frame and current frame is after last decoded
341 // frame, so instead of rerendering from the last keyframe we can rerender from
342 // the last decoded frame.
343 if(frame1 < ffmpeg->last_frame[current_field] &&
344 frame2 > ffmpeg->last_frame[current_field])
346 frame1 = ffmpeg->last_frame[current_field] + ffmpeg->fields;
347 do_i_frame = 0;
350 first_frame = frame1;
352 //printf("quicktime_ffmpeg_decode 2 %d\n", ffmpeg->last_frame[current_field]);
353 while(frame1 <= frame2)
355 result = decode_wrapper(file,
356 vtrack,
357 ffmpeg,
358 frame1,
359 current_field,
360 track,
361 // Don't drop if we want to cache it
362 0 /* (frame1 < frame2) */);
364 if(ffmpeg->picture[current_field].data[0] &&
365 // FFmpeg seems to glitch out if we include the first frame.
366 frame1 > first_frame)
368 int y_size = ffmpeg->picture[current_field].linesize[0] * ffmpeg->height_i;
369 int u_size = y_size / get_chroma_factor(ffmpeg, current_field);
370 int v_size = y_size / get_chroma_factor(ffmpeg, current_field);
371 quicktime_put_frame(vtrack->frame_cache,
372 frame1,
373 ffmpeg->picture[current_field].data[0],
374 ffmpeg->picture[current_field].data[1],
375 ffmpeg->picture[current_field].data[2],
376 y_size,
377 u_size,
378 v_size);
381 // For some codecs,
382 // may need to do the same frame twice if it is the first I frame.
383 if(do_i_frame)
385 result = decode_wrapper(file,
386 vtrack,
387 ffmpeg,
388 frame1,
389 current_field,
390 track,
392 do_i_frame = 0;
394 frame1 += ffmpeg->fields;
397 vtrack->current_position = frame2;
398 seeking_done = 1;
401 // Not decoded in seeking process
402 if(!seeking_done &&
403 // Same frame not requested
404 vtrack->current_position != ffmpeg->last_frame[current_field])
406 result = decode_wrapper(file,
407 vtrack,
408 ffmpeg,
409 vtrack->current_position,
410 current_field,
411 track,
415 // pthread_mutex_unlock(&ffmpeg_lock);
418 ffmpeg->last_frame[current_field] = vtrack->current_position;
421 // Hopefully this setting will be left over if the cache was used.
422 switch(ffmpeg->decoder_context[current_field]->pix_fmt)
424 case PIX_FMT_YUV420P:
425 input_cmodel = BC_YUV420P;
426 break;
427 case PIX_FMT_YUV422:
428 input_cmodel = BC_YUV422;
429 break;
430 case PIX_FMT_YUV422P:
431 input_cmodel = BC_YUV422P;
432 break;
433 case PIX_FMT_YUV410P:
434 input_cmodel = BC_YUV9P;
435 break;
436 default:
437 fprintf(stderr,
438 "quicktime_ffmpeg_decode: unrecognized color model %d\n",
439 ffmpeg->decoder_context[current_field]->pix_fmt);
440 input_cmodel = BC_YUV420P;
441 break;
444 if(ffmpeg->picture[current_field].data[0])
446 unsigned char **input_rows;
448 input_rows =
449 malloc(sizeof(unsigned char*) *
450 ffmpeg->decoder_context[current_field]->height);
453 for(i = 0; i < ffmpeg->decoder_context[current_field]->height; i++)
454 input_rows[i] = ffmpeg->picture[current_field].data[0] +
455 i *
456 ffmpeg->decoder_context[current_field]->width *
457 cmodel_calculate_pixelsize(input_cmodel);
460 cmodel_transfer(row_pointers, /* Leave NULL if non existent */
461 input_rows,
462 row_pointers[0], /* Leave NULL if non existent */
463 row_pointers[1],
464 row_pointers[2],
465 ffmpeg->picture[current_field].data[0], /* Leave NULL if non existent */
466 ffmpeg->picture[current_field].data[1],
467 ffmpeg->picture[current_field].data[2],
468 file->in_x, /* Dimensions to capture from input frame */
469 file->in_y,
470 file->in_w,
471 file->in_h,
472 0, /* Dimensions to project on output frame */
474 file->out_w,
475 file->out_h,
476 input_cmodel,
477 file->color_model,
478 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
479 ffmpeg->picture[current_field].linesize[0], /* For planar use the luma rowspan */
480 ffmpeg->width);
481 free(input_rows);
485 return result;