1 #include "colormodels.h"
2 #include "funcprotos.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
,
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
;
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
);
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;
57 avcodec_register_all();
60 for(i
= 0; i
< fields
; i
++)
62 ptr
->decoder
[i
] = avcodec_find_decoder(ptr
->ffmpeg_id
);
65 printf("quicktime_new_ffmpeg: avcodec_find_decoder returned NULL.\n");
66 quicktime_delete_ffmpeg(ptr
);
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
;
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
],
90 printf("quicktime_new_ffmpeg: avcodec_open failed.\n");
91 quicktime_delete_ffmpeg(ptr
);
94 pthread_mutex_unlock(&ffmpeg_lock
);
101 void quicktime_delete_ffmpeg(quicktime_ffmpeg_t
*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
);
128 static int decode_wrapper(quicktime_t
*file
,
129 quicktime_video_map_t
*vtrack
,
130 quicktime_ffmpeg_t
*ffmpeg
,
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);
160 memcpy(ffmpeg
->work_buffer
, stsd_table
->esds
.mpeg4_header
, header_bytes
);
162 if(!quicktime_read_data(file
,
163 ffmpeg
->work_buffer
+ header_bytes
,
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.
175 ffmpeg
->decoder_context
[current_field
]->skip_frame
= AVDISCARD_NONREF
;
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
],
182 bytes
+ header_bytes
);
186 if(ffmpeg
->picture
[current_field
].data
[0])
192 // ffmpeg can't recover if the first frame errored out, like in a direct copy
207 int quicktime_ffmpeg_decode(quicktime_ffmpeg_t
*ffmpeg
,
209 unsigned char **row_pointers
,
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
;
217 int seeking_done
= 0;
220 pthread_mutex_lock(&ffmpeg_lock
);
223 if(quicktime_has_keyframes(file
, track
) &&
224 vtrack
->current_position
!= ffmpeg
->last_frame
[current_field
] + ffmpeg
->fields
)
227 int frame2
= vtrack
->current_position
;
228 int current_frame
= frame2
;
231 // Get first keyframe of same field
234 frame1
= quicktime_get_keyframe_before(file
,
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
;
249 while(frame1
<= frame2
)
251 result
= decode_wrapper(file
,
260 // May need to do the first I frame twice.
263 result
= decode_wrapper(file
,
272 frame1
+= ffmpeg
->fields
;
275 vtrack
->current_position
= frame2
;
281 result
= decode_wrapper(file
,
284 vtrack
->current_position
,
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
;
301 input_cmodel
= BC_YUV422
;
303 case PIX_FMT_YUV422P
:
304 input_cmodel
= BC_YUV422P
;
306 case PIX_FMT_YUV410P
:
307 input_cmodel
= BC_YUV9P
;
311 "quicktime_ffmpeg_decode: unrecognized color model %d\n",
312 ffmpeg
->decoder_context
[current_field
]->pix_fmt
);
313 input_cmodel
= BC_YUV420P
;
317 if(ffmpeg
->picture
[current_field
].data
[0])
319 unsigned char **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] +
329 ffmpeg
->decoder_context
[current_field
]->width
*
330 cmodel_calculate_pixelsize(input_cmodel
);
333 cmodel_transfer(row_pointers
, /* Leave NULL if non existent */
335 row_pointers
[0], /* Leave NULL if non existent */
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 */
345 0, /* Dimensions to project on output frame */
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 */