r717: Made the highlighted text color of the menus WHITE
[cinelerra_cv/mob.git] / quicktime / qtffmpeg.c
blobc8cb944ad55a906c4bad1d76ea9b778830642fe5
1 #include "colormodels.h"
2 #include "funcprotos.h"
3 #include <pthread.h>
4 #include "quicktime.h"
5 #include "qtffmpeg.h"
6 #include "qtprivate.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 if(ffmpeg_id == CODEC_ID_SVQ1)
43 ptr->width_i = quicktime_quantize32(ptr->width);
44 ptr->height_i = quicktime_quantize32(ptr->height);
46 else
48 ptr->width_i = quicktime_quantize16(ptr->width);
49 ptr->height_i = quicktime_quantize16(ptr->height);
52 pthread_mutex_lock(&ffmpeg_lock);
53 if(!ffmpeg_initialized)
55 ffmpeg_initialized = 1;
56 avcodec_init();
57 avcodec_register_all();
60 for(i = 0; i < fields; i++)
62 ptr->decoder[i] = avcodec_find_decoder(ptr->ffmpeg_id);
63 if(!ptr->decoder[i])
65 printf("quicktime_new_ffmpeg: avcodec_find_decoder returned NULL.\n");
66 quicktime_delete_ffmpeg(ptr);
67 return 0;
69 ptr->decoder_context[i] = avcodec_alloc_context();
70 ptr->decoder_context[i]->width = w;
71 ptr->decoder_context[i]->height = h;
72 if(esds->mpeg4_header && esds->mpeg4_header_size)
74 ptr->decoder_context[i]->extradata = esds->mpeg4_header;
75 ptr->decoder_context[i]->extradata_size = esds->mpeg4_header_size;
77 if(avcc->data && avcc->data_size)
79 ptr->decoder_context[i]->extradata = avcc->data;
80 ptr->decoder_context[i]->extradata_size = avcc->data_size;
82 if(cpus > 1)
84 avcodec_thread_init(ptr->decoder_context[i], cpus);
85 ptr->decoder_context[i]->thread_count = cpus;
87 if(avcodec_open(ptr->decoder_context[i],
88 ptr->decoder[i]) < 0)
90 printf("quicktime_new_ffmpeg: avcodec_open failed.\n");
91 quicktime_delete_ffmpeg(ptr);
94 pthread_mutex_unlock(&ffmpeg_lock);
96 return ptr;
101 void quicktime_delete_ffmpeg(quicktime_ffmpeg_t *ptr)
103 int i;
104 if(ptr)
106 pthread_mutex_lock(&ffmpeg_lock);
107 for(i = 0; i < ptr->fields; i++)
109 if(ptr->decoder_context[i])
111 avcodec_close(ptr->decoder_context[i]);
112 free(ptr->decoder_context[i]);
115 pthread_mutex_unlock(&ffmpeg_lock);
119 if(ptr->temp_frame) free(ptr->temp_frame);
120 if(ptr->work_buffer) free(ptr->work_buffer);
123 free(ptr);
128 static int decode_wrapper(quicktime_t *file,
129 quicktime_video_map_t *vtrack,
130 quicktime_ffmpeg_t *ffmpeg,
131 int frame_number,
132 int current_field,
133 int track,
134 int drop_it)
136 int got_picture = 0;
137 int result = 0;
138 int bytes = 0;
139 int header_bytes = 0;
140 char *compressor = vtrack->track->mdia.minf.stbl.stsd.table[0].format;
141 quicktime_trak_t *trak = vtrack->track;
142 quicktime_stsd_table_t *stsd_table = &trak->mdia.minf.stbl.stsd.table[0];
144 quicktime_set_video_position(file, frame_number, track);
146 bytes = quicktime_frame_size(file, frame_number, track);
147 if(frame_number == 0)
149 header_bytes = stsd_table->esds.mpeg4_header_size;
152 if(!ffmpeg->work_buffer || ffmpeg->buffer_size < bytes + header_bytes)
154 if(ffmpeg->work_buffer) free(ffmpeg->work_buffer);
155 ffmpeg->buffer_size = bytes + header_bytes;
156 ffmpeg->work_buffer = calloc(1, ffmpeg->buffer_size + 100);
159 if(header_bytes)
160 memcpy(ffmpeg->work_buffer, stsd_table->esds.mpeg4_header, header_bytes);
162 if(!quicktime_read_data(file,
163 ffmpeg->work_buffer + header_bytes,
164 bytes))
165 result = -1;
168 if(!result)
172 // No way to determine if there was an error based on nonzero status.
173 // Need to test row pointers to determine if an error occurred.
174 if(drop_it)
175 ffmpeg->decoder_context[current_field]->skip_frame = AVDISCARD_NONREF;
176 else
177 ffmpeg->decoder_context[current_field]->skip_frame = AVDISCARD_DEFAULT;
178 result = avcodec_decode_video(ffmpeg->decoder_context[current_field],
179 &ffmpeg->picture[current_field],
180 &got_picture,
181 ffmpeg->work_buffer,
182 bytes + header_bytes);
186 if(ffmpeg->picture[current_field].data[0])
188 result = 0;
190 else
192 // ffmpeg can't recover if the first frame errored out, like in a direct copy
193 // sequence.
194 result = 1;
197 #ifdef ARCH_X86
198 asm("emms");
199 #endif
202 return result;
207 int quicktime_ffmpeg_decode(quicktime_ffmpeg_t *ffmpeg,
208 quicktime_t *file,
209 unsigned char **row_pointers,
210 int track)
212 quicktime_video_map_t *vtrack = &(file->vtracks[track]);
213 quicktime_trak_t *trak = vtrack->track;
214 int current_field = vtrack->current_position % ffmpeg->fields;
215 int input_cmodel;
216 int result = 0;
217 int seeking_done = 0;
218 int i;
220 pthread_mutex_lock(&ffmpeg_lock);
222 // Handle seeking
223 if(quicktime_has_keyframes(file, track) &&
224 vtrack->current_position != ffmpeg->last_frame[current_field] + ffmpeg->fields)
226 int frame1;
227 int frame2 = vtrack->current_position;
228 int current_frame = frame2;
229 int do_i_frame = 1;
231 // Get first keyframe of same field
234 frame1 = quicktime_get_keyframe_before(file,
235 current_frame--,
236 track);
237 }while(frame1 > 0 && (frame1 % ffmpeg->fields) != current_field);
239 // Keyframe is before last decoded frame and current frame is after last decoded
240 // frame, so instead of rerendering from the last keyframe we can rerender from
241 // the last decoded frame.
242 if(frame1 < ffmpeg->last_frame[current_field] &&
243 frame2 > ffmpeg->last_frame[current_field])
245 frame1 = ffmpeg->last_frame[current_field] + ffmpeg->fields;
246 do_i_frame = 0;
249 while(frame1 <= frame2)
251 result = decode_wrapper(file,
252 vtrack,
253 ffmpeg,
254 frame1,
255 current_field,
256 track,
257 (frame1 < frame2));
260 // May need to do the first I frame twice.
261 if(do_i_frame)
263 result = decode_wrapper(file,
264 vtrack,
265 ffmpeg,
266 frame1,
267 current_field,
268 track,
270 do_i_frame = 0;
272 frame1 += ffmpeg->fields;
275 vtrack->current_position = frame2;
276 seeking_done = 1;
279 if(!seeking_done)
281 result = decode_wrapper(file,
282 vtrack,
283 ffmpeg,
284 vtrack->current_position,
285 current_field,
286 track,
290 pthread_mutex_unlock(&ffmpeg_lock);
293 ffmpeg->last_frame[current_field] = vtrack->current_position;
295 switch(ffmpeg->decoder_context[current_field]->pix_fmt)
297 case PIX_FMT_YUV420P:
298 input_cmodel = BC_YUV420P;
299 break;
300 case PIX_FMT_YUV422:
301 input_cmodel = BC_YUV422;
302 break;
303 case PIX_FMT_YUV422P:
304 input_cmodel = BC_YUV422P;
305 break;
306 case PIX_FMT_YUV410P:
307 input_cmodel = BC_YUV9P;
308 break;
309 default:
310 fprintf(stderr,
311 "quicktime_ffmpeg_decode: unrecognized color model %d\n",
312 ffmpeg->decoder_context[current_field]->pix_fmt);
313 input_cmodel = BC_YUV420P;
314 break;
317 if(ffmpeg->picture[current_field].data[0])
319 unsigned char **input_rows;
321 input_rows =
322 malloc(sizeof(unsigned char*) *
323 ffmpeg->decoder_context[current_field]->height);
326 for(i = 0; i < ffmpeg->decoder_context[current_field]->height; i++)
327 input_rows[i] = ffmpeg->picture[current_field].data[0] +
328 i *
329 ffmpeg->decoder_context[current_field]->width *
330 cmodel_calculate_pixelsize(input_cmodel);
333 cmodel_transfer(row_pointers, /* Leave NULL if non existent */
334 input_rows,
335 row_pointers[0], /* Leave NULL if non existent */
336 row_pointers[1],
337 row_pointers[2],
338 ffmpeg->picture[current_field].data[0], /* Leave NULL if non existent */
339 ffmpeg->picture[current_field].data[1],
340 ffmpeg->picture[current_field].data[2],
341 file->in_x, /* Dimensions to capture from input frame */
342 file->in_y,
343 file->in_w,
344 file->in_h,
345 0, /* Dimensions to project on output frame */
347 file->out_w,
348 file->out_h,
349 input_cmodel,
350 file->color_model,
351 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */
352 ffmpeg->picture[current_field].linesize[0], /* For planar use the luma rowspan */
353 ffmpeg->width);
354 free(input_rows);
358 return result;