X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.0%2Fquicktime%2Fqth264.c;fp=cinelerra-5.0%2Fquicktime%2Fqth264.c;h=0000000000000000000000000000000000000000;hb=f9d0d999e813ae19965e07ae2f7da690b4e6fe45;hp=c9a7428e638c9de57d026d680f67d3e69454ab41;hpb=15359610833cd03c44fe47f5d002e643103610ec;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.0/quicktime/qth264.c b/cinelerra-5.0/quicktime/qth264.c deleted file mode 100644 index c9a7428e..00000000 --- a/cinelerra-5.0/quicktime/qth264.c +++ /dev/null @@ -1,393 +0,0 @@ -#include "libavcodec/avcodec.h" -#include "colormodels.h" -#include "funcprotos.h" -#include "qtffmpeg.h" -#include "quicktime.h" -#include "workarounds.h" -#include "x264.h" - -#include - -// This generates our own header using fixed parameters -//#define MANUAL_HEADER - - -typedef struct -{ -// Encoder side - x264_t *encoder[FIELDS]; - x264_picture_t *pic[FIELDS]; - x264_param_t param; - - int encode_initialized[FIELDS]; - -// Temporary storage for color conversions - char *temp_frame; -// Storage of compressed data - unsigned char *work_buffer; -// Amount of data in work_buffer - int buffer_size; - int total_fields; -// Set by flush - int flushing; - -// Decoder side - quicktime_ffmpeg_t *decoder; - -} quicktime_h264_codec_t; - -static pthread_mutex_t h264_lock = PTHREAD_MUTEX_INITIALIZER; - - -// Direct copy routines -int quicktime_h264_is_key(unsigned char *data, long size, char *codec_id) -{ - return 0; -} - - -static void delete_codec(quicktime_video_map_t *vtrack) -{ - int i; - quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; - - for(i = 0; i < codec->total_fields; i++) { - if( !codec->encode_initialized[i]) continue; - pthread_mutex_lock(&h264_lock); - if(codec->pic[i]) { - x264_picture_clean(codec->pic[i]); - free(codec->pic[i]); - } - if(codec->encoder[i]) { - x264_encoder_close(codec->encoder[i]); - } - pthread_mutex_unlock(&h264_lock); - } - - if(codec->temp_frame) free(codec->temp_frame); - if(codec->work_buffer) free(codec->work_buffer); - if(codec->decoder) quicktime_delete_ffmpeg(codec->decoder); - free(codec); -} - - - -static int encode(quicktime_t *file, unsigned char **row_pointers, int track) -{ -// int64_t offset = quicktime_position(file); - quicktime_video_map_t *vtrack = &(file->vtracks[track]); - quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; - quicktime_trak_t *trak = vtrack->track; - int width = quicktime_video_width(file, track); - int height = quicktime_video_height(file, track); - int w_2 = quicktime_quantize2(width); -// ffmpeg interprets the codec height as the presentation height - int h_2 = quicktime_quantize2(height); - int i; - int result = -1; - int is_keyframe = 0; - int frame_number = vtrack->current_position / codec->total_fields; - int current_field = vtrack->current_position % codec->total_fields; - quicktime_atom_t chunk_atom; - unsigned char header[1024]; - int header_size = 0; - int got_pps = 0; - int got_sps = 0; - quicktime_avcc_t *avcc = &trak->mdia.minf.stbl.stsd.table[0].avcc; - - pthread_mutex_lock(&h264_lock); - - if(!codec->encode_initialized[current_field]) - { - codec->encode_initialized[current_field] = 1; - codec->param.i_width = w_2; - codec->param.i_height = h_2; - codec->param.i_fps_num = quicktime_frame_rate_n(file, track); - codec->param.i_fps_den = quicktime_frame_rate_d(file, track); - -// Reset quantizer if fixed bitrate - x264_param_t default_params; - x264_param_default(&default_params); - if(codec->param.rc.i_qp_constant) - { - codec->param.rc.i_qp_constant = default_params.rc.i_qp_constant; - codec->param.rc.i_qp_min = default_params.rc.i_qp_min; - codec->param.rc.i_qp_max = default_params.rc.i_qp_max; - } - - if(file->cpus > 1) - { - codec->param.i_threads = file->cpus; - } - - codec->encoder[current_field] = x264_encoder_open(&codec->param); - codec->pic[current_field] = calloc(1, sizeof(x264_picture_t)); - x264_picture_init(codec->pic[current_field]); -//printf("encode 1 %d %d\n", codec->param.i_width, codec->param.i_height); - x264_picture_alloc(codec->pic[current_field], X264_CSP_I420, - codec->param.i_width, codec->param.i_height); - } - - x264_picture_t *pic = codec->pic[current_field]; - pic->i_type = X264_TYPE_AUTO; - pic->i_qpplus1 = X264_QP_AUTO; - pic->i_pts = frame_number; - - codec->buffer_size = 0; - int allocation = w_2 * h_2 * 3 + 100; - if( !codec->work_buffer ) { - codec->work_buffer = calloc(1, allocation); - } - - x264_picture_t pic_out; - x264_nal_t *nals; - int nnal = 0; - x264_t *h = codec->encoder[current_field]; - - if( !codec->flushing ) { - if( !row_pointers ) { - bzero(pic->img.plane[0], w_2 * h_2); - bzero(pic->img.plane[1], w_2 * h_2 / 4); - bzero(pic->img.plane[2], w_2 * h_2 / 4); - } - else if( file->color_model == BC_YUV420P ) { - memcpy(pic->img.plane[0], row_pointers[0], w_2 * h_2); - memcpy(pic->img.plane[1], row_pointers[1], w_2 * h_2 / 4); - memcpy(pic->img.plane[2], row_pointers[2], w_2 * h_2 / 4); - } - else { -//printf("encode 2 %p %p %p\n", pic->img.plane[0], pic->img.plane[1], pic->img.plane[2]); - cmodel_transfer(0, row_pointers, - pic->img.plane[0], pic->img.plane[1], pic->img.plane[2], - row_pointers[0], row_pointers[1], row_pointers[2], - 0, 0, width, height, 0, 0, width, height, - file->color_model, BC_YUV420P, - 0, width, pic->img.i_stride[0]); - } - - result = x264_encoder_encode(h, &nals, &nnal, pic, &pic_out); - if( result < 0 ) - printf("frame_num %d: nals=%d, ret=%d\n", frame_number, nnal, result); - } - else if( x264_encoder_delayed_frames(h) > 0 ) { - result = x264_encoder_encode(h, &nals, &nnal, 0, &pic_out); - if( result < 0 ) - printf("flushing %d: nals=%d, ret=%d\n", frame_number, nnal, result); - } -//printf("encode %d nnal=%d\n", __LINE__, nnal); - - for( i = 0; i < nnal; ++i ) { - int size = nals[i].i_payload; -//printf("encode %d size=%d\n", __LINE__, size); - if(size + codec->buffer_size > allocation) { - printf("qth264.c %d: overflow size=%d allocation=%d\n", - __LINE__, size, allocation); - break; - } - unsigned char *ptr = codec->work_buffer + codec->buffer_size; - memcpy(ptr, nals[i].p_payload, size); - codec->buffer_size += size; - if( avcc->data_size ) continue; -// Snoop NAL for avc - ptr += 4; size -= 4; -// Synthesize header. -// Hopefully all the parameter set NAL's are present in the first frame. - if( !header_size ) { - header[header_size++] = 0x01; - header[header_size++] = 0x4d; - header[header_size++] = 0x40; - header[header_size++] = 0x1f; - header[header_size++] = 0xff; - header[header_size++] = 0xe1; - } - - int nal_type = (*ptr & 0x1f); -// Picture parameter or sequence parameter set - switch( nal_type ) { - case 0x07: - if( got_sps ) continue; - got_sps = 1; - break; - case 0x08: - if( got_pps ) continue; - got_pps = 1; - header[header_size++] = 0x1; // Number of sps nal's. - break; - default: - continue; - } - - header[header_size++] = size >> 8; - header[header_size++] = size; - memcpy(&header[header_size], ptr, size); - header_size += size; - if( !got_sps || !got_pps ) continue; -// printf("encode %d\n", __LINE__); -// { int j; for(j = 0; j < header_size; j++) printf("%02x ", header[j]); } -// printf("\n"); -// Write header - quicktime_set_avcc_header(avcc, header, header_size); - } - - pthread_mutex_unlock(&h264_lock); - - if( codec->buffer_size > 0 ) { - if(pic_out.i_type == X264_TYPE_IDR || - pic_out.i_type == X264_TYPE_I) { - is_keyframe = 1; - } - - quicktime_write_chunk_header(file, trak, &chunk_atom); - result = !quicktime_write_data(file, - (char*)codec->work_buffer, - codec->buffer_size); - quicktime_write_chunk_footer(file, trak, - vtrack->current_chunk, &chunk_atom, 1); - - if(is_keyframe) { - quicktime_insert_keyframe(file, - vtrack->current_position, - track); - } - - vtrack->current_chunk++; - } - return result >= 0 ? 0 : -1; -} - - - - -static int decode(quicktime_t *file, unsigned char **row_pointers, int track) -{ - quicktime_video_map_t *vtrack = &(file->vtracks[track]); - quicktime_trak_t *trak = vtrack->track; - quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; - quicktime_stsd_table_t *stsd_table = &trak->mdia.minf.stbl.stsd.table[0]; - int width = trak->tkhd.track_width; - int height = trak->tkhd.track_height; - - if(!codec->decoder) - codec->decoder = quicktime_new_ffmpeg(file->cpus, - codec->total_fields, CODEC_ID_H264, width, height, stsd_table); - return !codec->decoder ? 1 : - quicktime_ffmpeg_decode(codec->decoder, file, row_pointers, track); -} - -static void flush(quicktime_t *file, int track) -{ - quicktime_video_map_t *vtrack = &(file->vtracks[track]); - quicktime_trak_t *trak = vtrack->track; - quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; -// trak->mdia.minf.stbl.stsd.table[0].version = 1; -// trak->mdia.minf.stbl.stsd.table[0].revision = 1; - quicktime_avcc_t *avcc = &trak->mdia.minf.stbl.stsd.table[0].avcc; - if( !avcc->data_size ) - encode(file, 0, track); - codec->flushing = 1; - while( !encode(file, 0, track) ); -} - - - -static int reads_colormodel(quicktime_t *file, - int colormodel, - int track) -{ - return (colormodel == BC_YUV420P); -} - -static int writes_colormodel(quicktime_t *file, - int colormodel, - int track) -{ - return (colormodel == BC_YUV420P); -} - -static int set_parameter(quicktime_t *file, - int track, - char *key, - void *value) -{ - quicktime_video_map_t *vtrack = &(file->vtracks[track]); - char *compressor = quicktime_compressor(vtrack->track); - - if(quicktime_match_32(compressor, QUICKTIME_H264) || - quicktime_match_32(compressor, QUICKTIME_HV64)) - { - quicktime_h264_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; - if(!strcasecmp(key, "h264_bitrate")) - { - if(quicktime_match_32(compressor, QUICKTIME_H264)) - codec->param.rc.i_bitrate = *(int*)value; - else - codec->param.rc.i_bitrate = *(int*)value / 2; - } - else - if(!strcasecmp(key, "h264_quantizer")) - { - codec->param.rc.i_qp_constant = - codec->param.rc.i_qp_min = - codec->param.rc.i_qp_max = *(int*)value; - } - else - if(!strcasecmp(key, "h264_fix_bitrate")) - { - codec->param.rc.i_qp_constant = (*(int*)value) / 1000; - } - } - return 0; -} - -static quicktime_h264_codec_t* init_common(quicktime_video_map_t *vtrack, - char *compressor, - char *title, - char *description) -{ - quicktime_codec_t *codec_base = (quicktime_codec_t*)vtrack->codec; - quicktime_h264_codec_t *codec; - - codec_base->priv = calloc(1, sizeof(quicktime_h264_codec_t)); - codec_base->delete_vcodec = delete_codec; - codec_base->decode_video = decode; - codec_base->encode_video = encode; - codec_base->flush = flush; - codec_base->reads_colormodel = reads_colormodel; - codec_base->writes_colormodel = writes_colormodel; - codec_base->set_parameter = set_parameter; - codec_base->fourcc = compressor; - codec_base->title = title; - codec_base->desc = description; - - - codec = (quicktime_h264_codec_t*)codec_base->priv; - x264_param_default(&codec->param); - codec->param.rc.i_rc_method = X264_RC_CQP; -// codec->param.i_log_level = 99; - return codec; -} - - -void quicktime_init_codec_h264(quicktime_video_map_t *vtrack) -{ - quicktime_h264_codec_t *result = init_common(vtrack, - QUICKTIME_H264, - "H.264", - "H.264"); - result->total_fields = 1; -} - - -// field based H.264 -void quicktime_init_codec_hv64(quicktime_video_map_t *vtrack) -{ - quicktime_h264_codec_t *result = init_common(vtrack, - QUICKTIME_HV64, - "Dual H.264", - "H.264 with two streams alternating every other frame. (Not standardized)"); - result->total_fields = 2; -} - - - -