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 //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
);
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;
58 avcodec_register_all();
61 for(i
= 0; i
< fields
; i
++)
63 ptr
->decoder
[i
] = avcodec_find_decoder(ptr
->ffmpeg_id
);
66 printf("quicktime_new_ffmpeg: avcodec_find_decoder returned NULL.\n");
67 quicktime_delete_ffmpeg(ptr
);
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
;
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
);
114 void quicktime_delete_ffmpeg(quicktime_ffmpeg_t
*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
);
141 static int decode_wrapper(quicktime_t
*file
,
142 quicktime_video_map_t
*vtrack
,
143 quicktime_ffmpeg_t
*ffmpeg
,
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);
174 memcpy(ffmpeg
->work_buffer
, stsd_table
->esds
.mpeg4_header
, header_bytes
);
176 if(!quicktime_read_data(file
,
177 ffmpeg
->work_buffer
+ header_bytes
,
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.
189 ffmpeg
->decoder_context
[current_field
]->skip_frame
= AVDISCARD_NONREF
/* AVDISCARD_BIDIR */;
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
],
196 bytes
+ header_bytes
);
200 if(ffmpeg
->picture
[current_field
].data
[0])
206 // ffmpeg can't recover if the first frame errored out, like in a direct copy
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
:
231 case PIX_FMT_YUV422P
:
234 case PIX_FMT_YUV410P
:
239 "get_chroma_factor: unrecognized color model %d\n",
240 ffmpeg
->decoder_context
[current_field
]->pix_fmt
);
246 int quicktime_ffmpeg_decode(quicktime_ffmpeg_t
*ffmpeg
,
248 unsigned char **row_pointers
,
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
;
256 int seeking_done
= 0;
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]);
270 // Codecs which work without locking:
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
,
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
;
298 // Seeking requires keyframes
299 if(quicktime_has_keyframes(file
, track
) &&
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
])
307 int frame2
= vtrack
->current_position
;
308 int current_frame
= frame2
;
311 // If an interleaved codec, the opposite field would have been decoded in the previous
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
,
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
,
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
;
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
,
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
,
373 ffmpeg
->picture
[current_field
].data
[0],
374 ffmpeg
->picture
[current_field
].data
[1],
375 ffmpeg
->picture
[current_field
].data
[2],
382 // may need to do the same frame twice if it is the first I frame.
385 result
= decode_wrapper(file
,
394 frame1
+= ffmpeg
->fields
;
397 vtrack
->current_position
= frame2
;
401 // Not decoded in seeking process
403 // Same frame not requested
404 vtrack
->current_position
!= ffmpeg
->last_frame
[current_field
])
406 result
= decode_wrapper(file
,
409 vtrack
->current_position
,
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
;
428 input_cmodel
= BC_YUV422
;
430 case PIX_FMT_YUV422P
:
431 input_cmodel
= BC_YUV422P
;
433 case PIX_FMT_YUV410P
:
434 input_cmodel
= BC_YUV9P
;
438 "quicktime_ffmpeg_decode: unrecognized color model %d\n",
439 ffmpeg
->decoder_context
[current_field
]->pix_fmt
);
440 input_cmodel
= BC_YUV420P
;
444 if(ffmpeg
->picture
[current_field
].data
[0])
446 unsigned char **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] +
456 ffmpeg
->decoder_context
[current_field
]->width
*
457 cmodel_calculate_pixelsize(input_cmodel
);
460 cmodel_transfer(row_pointers
, /* Leave NULL if non existent */
462 row_pointers
[0], /* Leave NULL if non existent */
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 */
472 0, /* Dimensions to project on output frame */
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 */