static int encode(quicktime_t *file, unsigned char **row_pointers, int track) { int bytes; quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_trak_t *trak = vtrack->track; quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; int result = 1; int width = vtrack->track->tkhd.track_width; int height = vtrack->track->tkhd.track_height; quicktime_atom_t chunk_atom; initialize(vtrack, codec, width, height); bytes = height * codec->bytes_per_line; cmodel_transfer(codec->rows, row_pointers, 0, 0, 0, row_pointers[0], row_pointers[1], row_pointers[2], 0, 0, width, height, 0, 0, width, height, file->color_model, BC_YUV422, 0, width, codec->coded_w); if( codec->is_2vuy ) convert_encode_2vuy(codec); else convert_encode_yuv2(codec); quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, (char*)codec->work_buffer, bytes); quicktime_write_chunk_footer(file, trak, vtrack->current_chunk, &chunk_atom, 1); vtrack->current_chunk++; return result; }
int FFMPEG::convert_cmodel_transfer(VFrame *frame_in, VFrame *frame_out) { // WARNING: cmodel_transfer is said to be broken with BC_YUV411P cmodel_transfer (// Packed data out frame_out->get_rows(), // Packed data in frame_in->get_rows(), // Planar data out frame_out->get_y(), frame_out->get_u(), frame_out->get_v(), // Planar data in frame_in->get_y(), frame_in->get_u(), frame_in->get_v(), // Dimensions in 0, 0, frame_in->get_w(), frame_in->get_h(), // Dimensions out 0, 0, frame_out->get_w(), frame_out->get_h(), // Color models frame_in->get_color_model(), frame_out->get_color_model(), // Background color 0, // Rowspans (of luma for YUV) frame_in->get_w(), frame_out->get_w() ); return 0; }
static int decode(quicktime_t *file, unsigned char **row_pointers, int track) { int bytes; quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_yuv2_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; int width = quicktime_video_width(file, track); int height = quicktime_video_height(file, track); int result = 0; initialize(vtrack, codec, width, height); quicktime_set_video_position(file, vtrack->current_position, track); bytes = quicktime_frame_size(file, vtrack->current_position, track); result = !quicktime_read_data(file, (char*)codec->work_buffer, bytes); if(codec->is_2vuy) convert_decode_2vuy(codec); else convert_decode_yuv2(codec); cmodel_transfer(row_pointers, codec->rows, row_pointers[0], row_pointers[1], row_pointers[2], 0, 0, 0, file->in_x, file->in_y, file->in_w, file->in_h, 0, 0, file->out_w, file->out_h, BC_YUV422, file->color_model, 0, codec->coded_w, file->out_w); return result; }
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_v308_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; quicktime_trak_t *trak = vtrack->track; int width = vtrack->track->tkhd.track_width; int height = vtrack->track->tkhd.track_height; int bytes = width * height * 3; int result = 0; unsigned char **output_rows; int i; quicktime_atom_t chunk_atom; if(!codec->work_buffer) codec->work_buffer = malloc(vtrack->track->tkhd.track_width * vtrack->track->tkhd.track_height * 3); output_rows = malloc(sizeof(unsigned char*) * height); for(i = 0; i < height; i++) output_rows[i] = codec->work_buffer + i * width * 3; cmodel_transfer(output_rows, row_pointers, 0, 0, 0, row_pointers[0], row_pointers[1], row_pointers[2], 0, 0, width, height, 0, 0, width, height, file->color_model, BC_VYU888, 0, width, width); quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, codec->work_buffer, bytes); quicktime_write_chunk_footer(file, trak, vtrack->current_chunk, &chunk_atom, 1); vtrack->current_chunk++; free(output_rows); return result; }
static int decode(quicktime_t *file, unsigned char **row_pointers, int track) { int i; int64_t bytes; int result = 0; quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_v308_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; int width = vtrack->track->tkhd.track_width; int height = vtrack->track->tkhd.track_height; unsigned char **input_rows; if(!codec->work_buffer) codec->work_buffer = malloc(vtrack->track->tkhd.track_width * vtrack->track->tkhd.track_height * 3); quicktime_set_video_position(file, vtrack->current_position, track); bytes = quicktime_frame_size(file, vtrack->current_position, track); result = !quicktime_read_data(file, codec->work_buffer, bytes); input_rows = malloc(sizeof(unsigned char*) * height); for(i = 0; i < height; i++) input_rows[i] = codec->work_buffer + i * width * 3; cmodel_transfer(row_pointers, input_rows, row_pointers[0], row_pointers[1], row_pointers[2], 0, 0, 0, file->in_x, file->in_y, file->in_w, file->in_h, 0, 0, file->out_w, file->out_h, BC_VYU888, file->color_model, 0, width, file->out_w); free(input_rows); return result; }
int FFMPEG::convert_cmodel(AVPicture *picture_in, PixelFormat pix_fmt_in, int width_in, int height_in, VFrame *frame_out) { // set up a temporary picture_out from frame_out AVPicture picture_out; init_picture_from_frame(&picture_out, frame_out); int cmodel_out = frame_out->get_color_model(); PixelFormat pix_fmt_out = color_model_to_pix_fmt(cmodel_out); #ifdef HAVE_SWSCALER // We need a context for swscale struct SwsContext *convert_ctx; #endif int result; #ifndef HAVE_SWSCALER // do conversion within libavcodec if possible if (pix_fmt_out != PIX_FMT_NB) { result = img_convert(&picture_out, pix_fmt_out, picture_in, pix_fmt_in, width_in, height_in); if (result) { printf("FFMPEG::convert_cmodel img_convert() failed\n"); } return result; } #else convert_ctx = sws_getContext(width_in, height_in,pix_fmt_in, frame_out->get_w(),frame_out->get_h(),pix_fmt_out, SWS_BICUBIC, NULL, NULL, NULL); if(convert_ctx == NULL) { printf("FFMPEG::convert_cmodel : swscale context initialization failed\n"); return 1; } result = sws_scale(convert_ctx, picture_in->data, picture_in->linesize, width_in, height_in, picture_out.data, picture_out.linesize); sws_freeContext(convert_ctx); if(result) { printf("FFMPEG::convert_cmodel sws_scale() failed\n"); } #endif // make an intermediate temp frame only if necessary int cmodel_in = pix_fmt_to_color_model(pix_fmt_in); if (cmodel_in == BC_TRANSPARENCY) { if (pix_fmt_in == PIX_FMT_RGB32) { // avoid infinite recursion if things are broken printf("FFMPEG::convert_cmodel pix_fmt_in broken!\n"); return 1; } // NOTE: choose RGBA8888 as a hopefully non-lossy colormodel VFrame *temp_frame = new VFrame(0, width_in, height_in, BC_RGBA8888); if (convert_cmodel(picture_in, pix_fmt_in, width_in, height_in, temp_frame)) { delete temp_frame; return 1; // recursed call will print error message } int result = convert_cmodel(temp_frame, frame_out); delete temp_frame; return result; } // NOTE: no scaling possible in img_convert() so none possible here if (frame_out->get_w() != width_in || frame_out->get_h() != height_in) { printf("scaling from %dx%d to %dx%d not allowed\n", width_in, height_in, frame_out->get_w(), frame_out->get_h()); return 1; } // if we reach here we know that cmodel_transfer() will work uint8_t *yuv_in[3] = {0,0,0}; uint8_t *row_pointers_in[height_in]; if (cmodel_is_planar(cmodel_in)) { yuv_in[0] = picture_in->data[0]; yuv_in[1] = picture_in->data[1]; yuv_in[2] = picture_in->data[2]; } else { // set row pointers for picture_in uint8_t *data = picture_in->data[0]; int bytes_per_line = cmodel_calculate_pixelsize(cmodel_in) * height_in; for (int i = 0; i < height_in; i++) { row_pointers_in[i] = data + i * bytes_per_line; } } cmodel_transfer (// Packed data out frame_out->get_rows(), // Packed data in row_pointers_in, // Planar data out frame_out->get_y(), frame_out->get_u(), frame_out->get_v(), // Planar data in yuv_in[0], yuv_in[1], yuv_in[2], // Dimensions in 0, 0, width_in, height_in, // NOTE: dimensions are same // Dimensions out 0, 0, width_in, height_in, // Color model in, color model out cmodel_in, cmodel_out, // Background color 0, // Rowspans in, out (of luma for YUV) width_in, width_in ); return 0; }
int FileFFMPEG::read_frame(VFrame *frame) { int error = 0; const int debug = 0; ffmpeg_lock->lock("FileFFMPEG::read_frame"); FileFFMPEGStream *stream = video_streams.get(0); if(debug) printf("FileFFMPEG::read_frame %d stream=%p stream->ffmpeg_file_contex=%p\n", __LINE__, stream, stream->ffmpeg_file_context); AVStream *ffmpeg_stream = ((AVFormatContext*)stream->ffmpeg_file_context)->streams[stream->index]; AVCodecContext *decoder_context = ffmpeg_stream->codec; if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); // if(file->current_frame == 100) // { // printf("FileFFMPEG::read_frame %d fake crash\n", __LINE__); // exit(1); // } //dump_context(stream->codec); if(stream->first_frame) { stream->first_frame = 0; int got_it = 0; while(!got_it && !error) { AVPacket packet; if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); error = av_read_frame((AVFormatContext*)stream->ffmpeg_file_context, &packet); if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); if(!error && packet.size > 0) { if(packet.stream_index == stream->index) { if(!ffmpeg_frame) ffmpeg_frame = avcodec_alloc_frame(); int got_picture = 0; if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); avcodec_get_frame_defaults((AVFrame*)ffmpeg_frame); if(debug) printf("FileFFMPEG::read_frame %d decoder_context=%p ffmpeg_frame=%p\n", __LINE__, decoder_context, ffmpeg_frame); int result = avcodec_decode_video( decoder_context, (AVFrame*)ffmpeg_frame, &got_picture, packet.data, packet.size); if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); if(((AVFrame*)ffmpeg_frame)->data[0] && got_picture) got_it = 1; if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); } } av_free_packet(&packet); } error = 0; } if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); #define SEEK_THRESHOLD 16 // printf("FileFFMPEG::read_frame %d current_frame=%lld file->current_frame=%lld\n", // __LINE__, // current_frame, // file->current_frame); if(stream->current_frame != file->current_frame && (file->current_frame < stream->current_frame || file->current_frame > stream->current_frame + SEEK_THRESHOLD)) { if(debug) printf("FileFFMPEG::read_frame %d stream->current_frame=%lld file->current_frame=%lld\n", __LINE__, (long long)stream->current_frame, (long long)file->current_frame); int64_t timestamp = (int64_t)((double)file->current_frame * ffmpeg_stream->time_base.den / ffmpeg_stream->time_base.num / asset->frame_rate); // Want to seek to the nearest keyframe and read up to the current frame // but ffmpeg doesn't support that kind of precision. // Also, basing all the seeking on the same stream seems to be required for synchronization. av_seek_frame((AVFormatContext*)stream->ffmpeg_file_context, /* stream->index */ 0, timestamp, AVSEEK_FLAG_ANY); stream->current_frame = file->current_frame - 1; } if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); int got_it = 0; // Read frames until we catch up to the current position. // if(current_frame >= file->current_frame - SEEK_THRESHOLD && // current_frame < file->current_frame - 1) // { // printf("FileFFMPEG::read_frame %d current_frame=%lld file->current_frame=%lld\n", // __LINE__, // current_frame, // file->current_frame); // } while(stream->current_frame < file->current_frame && !error) { got_it = 0; if(debug) printf("FileFFMPEG::read_frame %d stream->current_frame=%lld file->current_frame=%lld\n", __LINE__, (long long)stream->current_frame, (long long)file->current_frame); while(!got_it && !error) { AVPacket packet; error = av_read_frame((AVFormatContext*)stream->ffmpeg_file_context, &packet); if(!error && packet.size > 0) { if(packet.stream_index == stream->index) { if(!ffmpeg_frame) ffmpeg_frame = avcodec_alloc_frame(); int got_picture = 0; avcodec_get_frame_defaults((AVFrame*)ffmpeg_frame); // printf("FileFFMPEG::read_frame %d current_frame=%lld ffmpeg_frame=%p packet.data=%p packet.size=%d\n", // __LINE__, // file->current_frame, // ffmpeg_frame, // packet.data, // packet.size); // for(int i = 0; i < decoder_context->extradata_size; i++) // printf("0x%02x, ", decoder_context->extradata[i]); // printf("\n"); // // if(file->current_frame >= 200 && file->current_frame < 280) // { // char string[1024]; // sprintf(string, "/tmp/debug%03lld", file->current_frame); // FILE *out = fopen(string, "w"); // fwrite(packet.data, packet.size, 1, out); // fclose(out); // } int result = avcodec_decode_video( decoder_context, (AVFrame*)ffmpeg_frame, &got_picture, packet.data, packet.size); //printf("FileFFMPEG::read_frame %d result=%d\n", __LINE__, result); if(((AVFrame*)ffmpeg_frame)->data[0] && got_picture) got_it = 1; //printf("FileFFMPEG::read_frame %d result=%d got_it=%d\n", __LINE__, result, got_it); } } av_free_packet(&packet); } if(got_it) stream->current_frame++; } //PRINT_TRACE // printf("FileFFMPEG::read_frame %d current_frame=%lld file->current_frame=%lld got_it=%d\n", // __LINE__, // current_frame, // file->current_frame, // got_it); if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); // Convert colormodel if(got_it) { int input_cmodel; AVFrame *input_frame = (AVFrame*)ffmpeg_frame; switch(decoder_context->pix_fmt) { case PIX_FMT_YUV420P: input_cmodel = BC_YUV420P; break; #ifndef FFMPEG_2010 case PIX_FMT_YUV422: input_cmodel = BC_YUV422; break; #endif case PIX_FMT_YUV422P: input_cmodel = BC_YUV422P; break; case PIX_FMT_YUV410P: input_cmodel = BC_YUV9P; break; default: fprintf(stderr, "quicktime_ffmpeg_decode: unrecognized color model %d\n", decoder_context->pix_fmt); input_cmodel = BC_YUV420P; break; } unsigned char **input_rows = (unsigned char**)malloc(sizeof(unsigned char*) * decoder_context->height); for(int i = 0; i < decoder_context->height; i++) input_rows[i] = input_frame->data[0] + i * decoder_context->width * cmodel_calculate_pixelsize(input_cmodel); cmodel_transfer(frame->get_rows(), /* Leave NULL if non existent */ input_rows, frame->get_y(), /* Leave NULL if non existent */ frame->get_u(), frame->get_v(), input_frame->data[0], /* Leave NULL if non existent */ input_frame->data[1], input_frame->data[2], 0, /* Dimensions to capture from input frame */ 0, decoder_context->width, decoder_context->height, 0, /* Dimensions to project on output frame */ 0, frame->get_w(), frame->get_h(), input_cmodel, frame->get_color_model(), 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */ input_frame->linesize[0], /* For planar use the luma rowspan */ frame->get_w()); free(input_rows); } //PRINT_TRACE ffmpeg_lock->unlock(); if(debug) printf("FileFFMPEG::read_frame %d\n", __LINE__); return error; }
int dv_read_video(dv_t *dv, unsigned char **output_rows, unsigned char *data, long bytes, int color_model) { int dif = 0; int lost_coeffs = 0; long offset = 0; int isPAL = 0; int is61834 = 0; int numDIFseq; int ds; int i, v, b, m; dv_block_t *bl; long mb_offset; dv_sample_t sampling; dv_macroblock_t *mb; int pixel_size; int pitches[3]; int use_temp = color_model != BC_YUV422; unsigned char *pixels[3]; //printf("dv_read_video 1 %d\n", color_model); pthread_mutex_lock(&dv_lock); switch(bytes) { case DV_PAL_SIZE: break; case DV_NTSC_SIZE: break; default: return 1; break; } if(data[0] != 0x1f) return 1; pitches[0] = DV_WIDTH * 2; pitches[1] = 0; pitches[2] = 0; pixels[1] = 0; pixels[2] = 0; dv_parse_header(dv->decoder, data); if(!use_temp) { //printf("dv_read_video 1\n"); pixels[0] = output_rows[0]; dv_decode_full_frame(dv->decoder, data, e_dv_color_yuv, output_rows, pitches); //printf("dv_read_video 2\n"); } else { unsigned char *temp_rows[DV_HEIGHT]; if(!dv->temp_video) dv->temp_video = calloc(1, DV_WIDTH * DV_HEIGHT * 2); for(i = 0; i < DV_HEIGHT; i++) { temp_rows[i] = dv->temp_video + i * DV_WIDTH * 2; } pixels[0] = dv->temp_video; //printf("dv_read_video 3 %p\n", data); dv_decode_full_frame(dv->decoder, data, e_dv_color_yuv, pixels, pitches); //printf("dv_read_video 4\n"); cmodel_transfer(output_rows, temp_rows, output_rows[0], output_rows[1], output_rows[2], 0, 0, 0, 0, 0, DV_WIDTH, dv->decoder->height, 0, 0, DV_WIDTH, dv->decoder->height, BC_YUV422, color_model, 0, DV_WIDTH, DV_WIDTH); } dv->decoder->prev_frame_decoded = 1; pthread_mutex_unlock(&dv_lock); return 0; }
int FileThread::read_frame(VFrame *frame) { FileThreadFrame *local_frame = 0; int got_it = 0; int number = 0; //printf("FileThread::read_frame 1\n"); // Search thread for frame while(!got_it && !disable_read) { frame_lock->lock("FileThread::read_frame 1"); // printf("FileThread::read_frame: 1 read_position=%lld ", read_position); // for(int i = 0; i < total_frames; i++) // printf("%lld ", read_frames[i]->position); // printf("\n"); for(int i = 0; i < total_frames; i++) { local_frame = read_frames[i]; if(local_frame->position == read_position && local_frame->layer == layer && local_frame->frame && local_frame->frame->equal_stacks(frame)) { got_it = 1; number = i; //printf("FileThread::read_frame 1 %lld\n", local_frame->position); break; } } frame_lock->unlock(); // Not decoded yet but thread active if(!got_it && !disable_read) { user_wait_lock->lock("FileThread::read_frame"); } } //printf("FileThread::read_frame 2\n"); if(got_it) { // Copy image cmodel_transfer(frame->get_rows(), local_frame->frame->get_rows(), frame->get_y(), frame->get_u(), frame->get_v(), local_frame->frame->get_y(), local_frame->frame->get_u(), local_frame->frame->get_v(), 0, 0, local_frame->frame->get_w(), local_frame->frame->get_h(), 0, 0, frame->get_w(), frame->get_h(), local_frame->frame->get_color_model(), frame->get_color_model(), 0, local_frame->frame->get_w(), frame->get_w()); // Can't copy stacks because the stack is needed by the plugin requestor. frame->copy_params(local_frame->frame); // Recycle all frames before current one but not including current one. // This handles redrawing of a single frame but because FileThread has no // notion of a still frame, it has to call read_frame for those. frame_lock->lock("FileThread::read_frame 1"); FileThreadFrame *new_table[MAX_READ_FRAMES]; int k = 0; for(int j = number; j < total_frames; j++, k++) { new_table[k] = read_frames[j]; } for(int j = 0; j < number; j++, k++) { new_table[k] = read_frames[j]; } memcpy(read_frames, new_table, sizeof(FileThreadFrame*) * total_frames); total_frames -= number; start_position = read_position; read_position++; frame_lock->unlock(); read_wait_lock->unlock(); return 0; } else { // printf("FileThread::read_frame 1 color_model=%d disable_read=%d\n", // frame->get_color_model(), // disable_read); // Use traditional read function file->set_video_position(read_position, -1, 1); file->set_layer(layer, 1); read_position++; return file->read_frame(frame, 1); } //printf("FileThread::read_frame 100\n"); }
int FileTIFF::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit) { //printf("FileTIFF::write_frame 1\n"); FileTIFFUnit *tiff_unit = (FileTIFFUnit*)unit; int result = 0; TIFF *stream; tiff_unit->offset = 0; tiff_unit->data = data; tiff_unit->data->set_compressed_size(0); stream = TIFFClientOpen("FileTIFF", "w", (void*)tiff_unit, tiff_read, tiff_write, tiff_seek, tiff_close, tiff_size, tiff_mmap, tiff_unmap); int components, color_model, bits, type, compression; int sampleformat = SAMPLEFORMAT_UINT; int bytesperrow; switch(asset->tiff_cmodel) { case FileTIFF::RGB_888: components = 3; color_model = BC_RGB888; bits = 8; type = TIFF_BYTE; bytesperrow = 3 * asset->width; break; case FileTIFF::RGB_161616: components = 3; color_model = BC_RGB_FLOAT; bits = 16; type = TIFF_SHORT; bytesperrow = 6 * asset->width; break; case FileTIFF::RGBA_8888: components = 4; color_model = BC_RGBA8888; bits = 8; type = TIFF_BYTE; bytesperrow = 4 * asset->width; break; case FileTIFF::RGBA_16161616: components = 4; color_model = BC_RGBA_FLOAT; bits = 16; type = TIFF_SHORT; bytesperrow = 8 * asset->width; break; case FileTIFF::RGB_FLOAT: components = 3; color_model = BC_RGB_FLOAT; bits = 32; type = TIFF_FLOAT; sampleformat = SAMPLEFORMAT_IEEEFP; bytesperrow = 12 * asset->width; break; case FileTIFF::RGBA_FLOAT: components = 4; color_model = BC_RGBA_FLOAT; bits = 32; type = TIFF_FLOAT; sampleformat = SAMPLEFORMAT_IEEEFP; bytesperrow = 16 * asset->width; break; default: components = 3; color_model = BC_RGB888; bits = 8; type = TIFF_BYTE; bytesperrow = 3 * asset->width; break; } switch(asset->tiff_compression) { case FileTIFF::LZW: compression = COMPRESSION_LZW; break; case FileTIFF::PACK_BITS: compression = COMPRESSION_PACKBITS; break; case FileTIFF::DEFLATE: compression = COMPRESSION_DEFLATE; break; case FileTIFF::JPEG: compression = COMPRESSION_JPEG; break; default: compression = COMPRESSION_NONE; break; } TIFFSetField(stream, TIFFTAG_IMAGEWIDTH, asset->width); TIFFSetField(stream, TIFFTAG_IMAGELENGTH, asset->height); TIFFSetField(stream, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(stream, TIFFTAG_SAMPLESPERPIXEL, components); TIFFSetField(stream, TIFFTAG_BITSPERSAMPLE, bits); TIFFSetField(stream, TIFFTAG_SAMPLEFORMAT, sampleformat); TIFFSetField(stream, TIFFTAG_COMPRESSION, compression); TIFFSetField(stream, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(stream, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(stream, (uint32_t)-1)); // TIFFSetField(stream, TIFFTAG_ROWSPERSTRIP, // (8 * 1024) / bytesperrow); TIFFSetField(stream, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB); if(frame->get_color_model() == color_model) { for(int i = 0; i < asset->height; i++) { TIFFWriteScanline(stream, frame->get_rows()[i], i, 0); } } else { if(tiff_unit->temp && tiff_unit->temp->get_color_model() != color_model) { delete tiff_unit->temp; tiff_unit->temp = 0; } if(!tiff_unit->temp) { tiff_unit->temp = new VFrame(0, asset->width, asset->height, color_model); } cmodel_transfer(tiff_unit->temp->get_rows(), frame->get_rows(), tiff_unit->temp->get_y(), tiff_unit->temp->get_u(), tiff_unit->temp->get_v(), frame->get_y(), frame->get_u(), frame->get_v(), 0, 0, frame->get_w(), frame->get_h(), 0, 0, frame->get_w(), frame->get_h(), frame->get_color_model(), color_model, 0, frame->get_w(), frame->get_w()); for(int i = 0; i < asset->height; i++) { TIFFWriteScanline(stream, tiff_unit->temp->get_rows()[i], i, 0); } } TIFFClose(stream); //printf("FileTIFF::write_frame 10\n"); return result; }
int FilePNG::write_frame(VFrame *frame, VFrame *data, FrameWriterUnit *unit) { PNGUnit *png_unit = (PNGUnit*)unit; int result = 0; png_structp png_ptr; png_infop info_ptr; png_infop end_info = 0; VFrame *output_frame; data->set_compressed_size(0); //printf("FilePNG::write_frame 1\n"); png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); info_ptr = png_create_info_struct(png_ptr); png_set_write_fn(png_ptr, data, (png_rw_ptr)write_function, (png_flush_ptr)flush_function); png_set_compression_level(png_ptr, 9); png_set_IHDR(png_ptr, info_ptr, asset->width, asset->height, 8, asset->png_use_alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); png_write_info(png_ptr, info_ptr); //printf("FilePNG::write_frame 1\n"); native_cmodel = asset->png_use_alpha ? BC_RGBA8888 : BC_RGB888; if(frame->get_color_model() != native_cmodel) { if(!png_unit->temp_frame) png_unit->temp_frame = new VFrame(0, asset->width, asset->height, native_cmodel); cmodel_transfer(png_unit->temp_frame->get_rows(), /* Leave NULL if non existent */ frame->get_rows(), png_unit->temp_frame->get_y(), /* Leave NULL if non existent */ png_unit->temp_frame->get_u(), png_unit->temp_frame->get_v(), frame->get_y(), /* Leave NULL if non existent */ frame->get_u(), frame->get_v(), 0, /* Dimensions to capture from input frame */ 0, asset->width, asset->height, 0, /* Dimensions to project on output frame */ 0, asset->width, asset->height, frame->get_color_model(), png_unit->temp_frame->get_color_model(), 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */ asset->width, /* For planar use the luma rowspan */ asset->height); output_frame = png_unit->temp_frame; } else output_frame = frame; //printf("FilePNG::write_frame 2\n"); png_write_image(png_ptr, output_frame->get_rows()); png_write_end(png_ptr, info_ptr); png_destroy_write_struct(&png_ptr, &info_ptr); //printf("FilePNG::write_frame 3 %d\n", data->get_compressed_size()); return result; }
static int decode(quicktime_t *file, unsigned char **row_pointers, int track) { long bytes; quicktime_video_map_t *vtrack = &(file->vtracks[track]); quicktime_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; int width = vtrack->track->tkhd.track_width; int height = vtrack->track->tkhd.track_height; int result = 0; int i; int decode_colormodel = 0; int pitches[3] = { 720 * 2, 0, 0 }; quicktime_set_video_position(file, vtrack->current_position, track); bytes = quicktime_frame_size(file, vtrack->current_position, track); result = !quicktime_read_data(file, (char*)codec->data, bytes); if( codec->dv_decoder && codec->parameters_changed ) { dv_decoder_free( codec->dv_decoder ); codec->dv_decoder = NULL; codec->parameters_changed = 0; } if( ! codec->dv_decoder ) { pthread_mutex_lock( &libdv_init_mutex ); codec->dv_decoder = dv_decoder_new( codec->add_ntsc_setup, codec->clamp_luma, codec->clamp_chroma ); codec->dv_decoder->prev_frame_decoded = 0; codec->parameters_changed = 0; pthread_mutex_unlock( &libdv_init_mutex ); } if(codec->dv_decoder) { int is_sequential = check_sequentiality( row_pointers, 720 * cmodel_calculate_pixelsize(file->color_model), file->out_h ); codec->dv_decoder->quality = codec->decode_quality; dv_parse_header( codec->dv_decoder, codec->data ); // Libdv improperly decodes RGB colormodels. if((file->color_model == BC_YUV422 || file->color_model == BC_RGB888) && file->in_x == 0 && file->in_y == 0 && file->in_w == width && file->in_h == height && file->out_w == width && file->out_h == height && is_sequential) { if( file->color_model == BC_YUV422 ) { pitches[0] = 720 * 2; dv_decode_full_frame( codec->dv_decoder, codec->data, e_dv_color_yuv, row_pointers, pitches ); } else if( file->color_model == BC_RGB888) { pitches[0] = 720 * 3; dv_decode_full_frame( codec->dv_decoder, codec->data, e_dv_color_rgb, row_pointers, pitches ); } } else { if(!codec->temp_frame) { codec->temp_frame = malloc(720 * 576 * 2); codec->temp_rows = malloc(sizeof(unsigned char*) * 576); for(i = 0; i < 576; i++) codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i; } decode_colormodel = BC_YUV422; pitches[0] = 720 * 2; dv_decode_full_frame( codec->dv_decoder, codec->data, e_dv_color_yuv, codec->temp_rows, pitches ); cmodel_transfer(row_pointers, codec->temp_rows, row_pointers[0], row_pointers[1], row_pointers[2], codec->temp_rows[0], codec->temp_rows[1], codec->temp_rows[2], file->in_x, file->in_y, file->in_w, file->in_h, 0, 0, file->out_w, file->out_h, decode_colormodel, file->color_model, 0, width, file->out_w); } } //printf(__FUNCTION__ " 2\n"); return result; }
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_dv_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; quicktime_trak_t *trak = vtrack->track; int width = trak->tkhd.track_width; int height = trak->tkhd.track_height; int width_i = 720; int height_i = (height <= 480) ? 480 : 576; int i; unsigned char **input_rows; int is_pal = (height_i == 480) ? 0 : 1; int data_length = is_pal ? DV_PAL_SIZE : DV_NTSC_SIZE; int result = 0; dv_color_space_t encode_dv_colormodel = 0; quicktime_atom_t chunk_atom; if( codec->dv_encoder != NULL && codec->parameters_changed ) { dv_encoder_free( codec->dv_encoder ); codec->dv_encoder = NULL; codec->parameters_changed = 0; } if( ! codec->dv_encoder ) { pthread_mutex_lock( &libdv_init_mutex ); //printf( "dv.c encode: Alloc'ing encoder\n" ); codec->dv_encoder = dv_encoder_new( codec->rem_ntsc_setup, codec->clamp_luma, codec->clamp_chroma ); codec->parameters_changed = 0; pthread_mutex_unlock( &libdv_init_mutex ); } if(codec->dv_encoder) { int is_sequential = check_sequentiality( row_pointers, width_i * cmodel_calculate_pixelsize(file->color_model), height ); if( ( file->color_model == BC_YUV422 || file->color_model == BC_RGB888 ) && width == width_i && height == height_i && is_sequential ) { input_rows = row_pointers; switch( file->color_model ) { case BC_YUV422: encode_dv_colormodel = e_dv_color_yuv; //printf( "dv.c encode: e_dv_color_yuv\n" ); break; case BC_RGB888: encode_dv_colormodel = e_dv_color_rgb; //printf( "dv.c encode: e_dv_color_rgb\n" ); break; default: return 0; break; } } else { // The best colormodel for encoding is YUV 422 if(!codec->temp_frame) { codec->temp_frame = malloc(720 * 576 * 2); codec->temp_rows = malloc(sizeof(unsigned char*) * 576); for(i = 0; i < 576; i++) codec->temp_rows[i] = codec->temp_frame + 720 * 2 * i; } cmodel_transfer(codec->temp_rows, /* Leave NULL if non existent */ row_pointers, codec->temp_rows[0], /* Leave NULL if non existent */ codec->temp_rows[1], codec->temp_rows[2], row_pointers[0], /* Leave NULL if non existent */ row_pointers[1], row_pointers[2], 0, /* Dimensions to capture from input frame */ 0, MIN(width, width_i), MIN(height, height_i), 0, /* Dimensions to project on output frame */ 0, MIN(width, width_i), MIN(height, height_i), file->color_model, BC_YUV422, 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */ width, /* For planar use the luma rowspan */ width_i); input_rows = codec->temp_rows; encode_dv_colormodel = e_dv_color_yuv; } // Setup the encoder codec->dv_encoder->is16x9 = codec->anamorphic16x9; codec->dv_encoder->vlc_encode_passes = codec->vlc_encode_passes; codec->dv_encoder->static_qno = 0; codec->dv_encoder->force_dct = DV_DCT_AUTO; codec->dv_encoder->isPAL = is_pal; //printf("dv.c encode: 1 %d %d %d\n", width_i, height_i, encode_dv_colormodel); dv_encode_full_frame( codec->dv_encoder, input_rows, encode_dv_colormodel, codec->data ); //printf("dv.c encode: 2 %d %d\n", width_i, height_i); quicktime_write_chunk_header(file, trak, &chunk_atom); result = !quicktime_write_data(file, (char*)codec->data, data_length); quicktime_write_chunk_footer(file, trak, vtrack->current_chunk, &chunk_atom, 1); vtrack->current_chunk++; //printf("encode 3\n"); } return result; }
int FileList::read_frame(VFrame *frame) { int result = 0; if(file->current_frame < 0 || (asset->use_header && file->current_frame >= path_list.total && asset->format == list_type)) return 1; if(asset->format == list_type) { char string[BCTEXTLEN]; char *path; if(asset->use_header) { path = path_list.values[file->current_frame]; } else { path = calculate_path(file->current_frame, string); } FILE *in; // Fix path for VFS if(!strncmp(asset->path, RENDERFARM_FS_PREFIX, strlen(RENDERFARM_FS_PREFIX))) sprintf(string, "%s%s", RENDERFARM_FS_PREFIX, path); else strcpy(string, path); if(!(in = fopen(string, "rb"))) { eprintf("Error while opening \"%s\" for reading. \n%m\n", string); } else { struct stat ostat; stat(string, &ostat); switch(frame->get_color_model()) { case BC_COMPRESSED: frame->allocate_compressed_data(ostat.st_size); frame->set_compressed_size(ostat.st_size); fread(frame->get_data(), ostat.st_size, 1, in); break; default: data->allocate_compressed_data(ostat.st_size); data->set_compressed_size(ostat.st_size); fread(data->get_data(), ostat.st_size, 1, in); result = read_frame(frame, data); break; } fclose(in); } } else { // Allocate and decompress once into temporary //printf("FileList::read_frame %d\n", frame->get_color_model()); if(!temp || temp->get_color_model() != frame->get_color_model()) { if(temp) delete temp; temp = 0; FILE *fd = fopen(asset->path, "rb"); if(fd) { struct stat ostat; stat(asset->path, &ostat); switch(frame->get_color_model()) { case BC_COMPRESSED: frame->allocate_compressed_data(ostat.st_size); frame->set_compressed_size(ostat.st_size); fread(frame->get_data(), ostat.st_size, 1, fd); break; default: data->allocate_compressed_data(ostat.st_size); data->set_compressed_size(ostat.st_size); fread(data->get_data(), ostat.st_size, 1, fd); temp = new VFrame(0, asset->width, asset->height, frame->get_color_model()); read_frame(temp, data); break; } fclose(fd); } else { eprintf("Error while opening \"%s\" for reading. \n%m\n", asset->path); result = 1; } } if(!temp) return result; // printf("FileList::read_frame frame=%d temp=%d\n", // frame->get_color_model(), // temp->get_color_model()); if(frame->get_color_model() == temp->get_color_model()) { frame->copy_from(temp); } else { // Never happens cmodel_transfer(frame->get_rows(), /* Leave NULL if non existent */ temp->get_rows(), frame->get_y(), /* Leave NULL if non existent */ frame->get_u(), frame->get_v(), temp->get_y(), /* Leave NULL if non existent */ temp->get_u(), temp->get_v(), 0, /* Dimensions to capture from input frame */ 0, asset->width, asset->height, 0, /* Dimensions to project on output frame */ 0, asset->width, asset->height, temp->get_color_model(), frame->get_color_model(), 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */ temp->get_w(), /* For planar use the luma rowspan */ frame->get_w()); } } //printf("FileList::read_frame 5 %d\n", result); return result; }
static int decode(quicktime_t *file, unsigned char **row_pointers, int track) { quicktime_video_map_t *vtrack = &(file->vtracks[track]); initialize(vtrack); quicktime_jpeg_codec_t *codec = ((quicktime_codec_t*)vtrack->codec)->priv; quicktime_trak_t *trak = vtrack->track; mjpeg_t *mjpeg = codec->mjpeg; long size, field2_offset = 0; int track_height = trak->tkhd.track_height; int track_width = trak->tkhd.track_width; int result = 0; int field_dominance = trak->mdia.minf.stbl.stsd.table[0].field_dominance; mjpeg_set_cpus(codec->mjpeg, file->cpus); if(file->row_span) mjpeg_set_rowspan(codec->mjpeg, file->row_span); else mjpeg_set_rowspan(codec->mjpeg, 0); quicktime_set_video_position(file, vtrack->current_position, track); size = quicktime_frame_size(file, vtrack->current_position, track); codec->buffer_size = size; if(size > codec->buffer_allocated) { codec->buffer_allocated = size; codec->buffer = realloc(codec->buffer, codec->buffer_allocated); } result = !quicktime_read_data(file, (char*)codec->buffer, size); /* * printf("decode 1 %02x %02x %02x %02x %02x %02x %02x %02x\n", * codec->buffer[0], * codec->buffer[1], * codec->buffer[2], * codec->buffer[3], * codec->buffer[4], * codec->buffer[5], * codec->buffer[6], * codec->buffer[7] * ); */ if(!result) { if(mjpeg_get_fields(mjpeg) == 2) { if(file->use_avi) { field2_offset = mjpeg_get_avi_field2(codec->buffer, size, &field_dominance); } else { field2_offset = mjpeg_get_quicktime_field2(codec->buffer, size); // Sanity check if(!field2_offset) { printf("decode: FYI field2_offset=0\n"); field2_offset = mjpeg_get_field2(codec->buffer, size); } } } else field2_offset = 0; //printf("decode 2 %d\n", field2_offset); /* * printf("decode result=%d field1=%llx field2=%llx size=%d %02x %02x %02x %02x\n", * result, * quicktime_position(file) - size, * quicktime_position(file) - size + field2_offset, * size, * codec->buffer[0], * codec->buffer[1], * codec->buffer[field2_offset + 0], * codec->buffer[field2_offset + 1]); */ if(file->in_x == 0 && file->in_y == 0 && file->in_w == track_width && file->in_h == track_height && file->out_w == track_width && file->out_h == track_height) { mjpeg_decompress(codec->mjpeg, codec->buffer, size, field2_offset, row_pointers, row_pointers[0], row_pointers[1], row_pointers[2], file->color_model, file->cpus); } else { int i; unsigned char **temp_rows; int temp_cmodel = BC_YUV888; int temp_rowsize = cmodel_calculate_pixelsize(temp_cmodel) * track_width; if(!codec->temp_video) codec->temp_video = malloc(temp_rowsize * track_height); temp_rows = malloc(sizeof(unsigned char*) * track_height); for(i = 0; i < track_height; i++) temp_rows[i] = codec->temp_video + i * temp_rowsize; //printf("decode 10\n"); mjpeg_decompress(codec->mjpeg, codec->buffer, size, field2_offset, temp_rows, temp_rows[0], temp_rows[1], temp_rows[2], temp_cmodel, file->cpus); cmodel_transfer(row_pointers, temp_rows, row_pointers[0], row_pointers[1], row_pointers[2], temp_rows[0], temp_rows[1], temp_rows[2], file->in_x, file->in_y, file->in_w, file->in_h, 0, 0, file->out_w, file->out_h, temp_cmodel, file->color_model, 0, track_width, file->out_w); //printf("decode 30\n"); free(temp_rows); //printf("decode 40\n"); } } //printf("decode 2 %d\n", result); return result; }
int BC_Bitmap::read_frame(VFrame *frame, int in_x, int in_y, int in_w, int in_h, int out_x, int out_y, int out_w, int out_h) { switch(color_model) { // Hardware accelerated bitmap case BC_YUV420P: if(frame->get_color_model() == color_model) { memcpy(get_y_plane(), frame->get_y(), w * h); memcpy(get_u_plane(), frame->get_u(), w * h / 4); memcpy(get_v_plane(), frame->get_v(), w * h / 4); break; } case BC_YUV422P: if(frame->get_color_model() == color_model) { memcpy(get_y_plane(), frame->get_y(), w * h); memcpy(get_u_plane(), frame->get_u(), w * h / 2); memcpy(get_v_plane(), frame->get_v(), w * h / 2); break; } case BC_YUV422: if(frame->get_color_model() == color_model) { memcpy(get_data(), frame->get_data(), w * h + w * h); break; } // Software only default: // printf("BC_Bitmap::read_frame %d -> %d %d %d %d %d -> %d %d %d %d\n", // frame->get_color_model(), // color_model, // in_x, // in_y, // in_w, // in_h, // out_x, // out_y, // out_w, // out_h); //if(color_model == 6 && frame->get_color_model() == 19) //printf("BC_Bitmap::read_frame 1 %d %d %d %d\n", frame->get_w(), frame->get_h(), get_w(), get_h()); cmodel_transfer(row_data[current_ringbuffer], frame->get_rows(), get_y_plane(), get_u_plane(), get_v_plane(), frame->get_y(), frame->get_u(), frame->get_v(), in_x, in_y, in_w, in_h, out_x, out_y, out_w, out_h, frame->get_color_model(), color_model, bg_color, frame->get_w(), w); // color model transfer_*_to_TRANSPARENCY don't care about endianness // so buffer bitswaped here if needed. if ((color_model == BC_TRANSPARENCY) && (!top_level->server_byte_order)) transparency_bitswap(); //if(color_model == 6 && frame->get_color_model() == 19) //printf("BC_Bitmap::read_frame 2\n"); break; } return 0; }
int SvgMain::process_realtime(VFrame *input_ptr, VFrame *output_ptr) { int fh_lockfile; char filename_png[1024], filename_lock[1024]; struct stat st_svg, st_png; int result_stat_png; VFrame *input, *output; input = input_ptr; output = output_ptr; need_reconfigure |= load_configuration(); if (config.svg_file[0] == 0) { output->copy_from(input); return(0); } strcpy(filename_png, config.svg_file); strcat(filename_png, ".png"); // get the time of the last PNG change result_stat_png = stat (filename_png, &st_png); // printf("PNg mtime: %li, last_load: %li\n", st_png.st_mtime, config.last_load); if (need_reconfigure || result_stat_png || (st_png.st_mtime > config.last_load)) { if (temp_frame) delete temp_frame; temp_frame = 0; } need_reconfigure = 0; if(!temp_frame) { int result; VFrame *tmp2; // printf("PROCESSING: %s %li\n", filename_png, config.last_load); if (result = stat (config.svg_file, &st_svg)) { printf(_("Error calling stat() on svg file: %s\n"), config.svg_file); } if (force_png_render || result_stat_png || st_png.st_mtime < st_svg.st_mtime) { char command[1024]; sprintf(command, "sodipodi --export-png=%s --export-width=%i --export-height=%i %s", filename_png, (int)config.in_w, (int)config.in_h, config.svg_file); printf(_("Running command %s\n"), command); system(command); stat(filename_png, &st_png); force_png_render = 0; } // advisory lock, so we wait for sodipodi to finish strcpy(filename_lock, filename_png); strcat(filename_lock, ".lock"); // printf("Cinelerra locking %s\n", filename_lock); fh_lockfile = open (filename_lock, O_CREAT | O_RDWR); int res = lockf(fh_lockfile, F_LOCK, 10); // Blocking call - will wait for sodipodi to finish! // printf("Cinelerra: filehandle: %i, cineres: %i, errno: %i\n", fh_lockfile, res, errno); // perror("Cineerror"); int fh = open(filename_png, O_RDONLY); unsigned char *pngdata; // get the size again result_stat_png = fstat (fh, &st_png); pngdata = (unsigned char*) malloc(st_png.st_size + 4); *((int32_t *)pngdata) = st_png.st_size; // printf("PNG size: %i\n", st_png.st_size); result = read(fh, pngdata+4, st_png.st_size); close(fh); // unlock the file lockf(fh_lockfile, F_ULOCK, 0); close(fh_lockfile); // printf("Cinelerra unlocking\n"); config.last_load = st_png.st_mtime; // we just updated tmp2 = new VFrame(pngdata); temp_frame = new VFrame(0, tmp2->get_w(), tmp2->get_h(), output_ptr->get_color_model()); free (pngdata); cmodel_transfer(temp_frame->get_rows(), tmp2->get_rows(), 0, 0, 0, 0, 0, 0, 0, 0, tmp2->get_w(), tmp2->get_h(), 0, 0, temp_frame->get_w(), temp_frame->get_h(), tmp2->get_color_model(), temp_frame->get_color_model(), 0, tmp2->get_w(), temp_frame->get_w()); delete tmp2; } //printf("SvgMain::process_realtime 2 %p\n", input); if(!overlayer) { overlayer = new OverlayFrame(smp + 1); } // output->clear_frame(); // printf("SvgMain::process_realtime 3 output=%p input=%p config.w=%f config.h=%f" // "%f %f %f %f -> %f %f %f %f\n", // output, // input, // config.w, // config.h, // in_x1, // in_y1, // in_x2, // in_y2, // out_x1, // out_y1, // out_x2, // out_y2); output->copy_from(input); overlayer->overlay(output, temp_frame, config.in_x, config.in_y, config.in_x + config.in_w, config.in_y + config.in_h, config.out_x, config.out_y, config.out_x + config.out_w, config.out_y + config.out_h, 1, TRANSFER_NORMAL, get_interpolation_type()); return(0); }
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 = 0; int bytes = 0; int is_keyframe = 0; 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); #if X264_BUILD >= 48 codec->param.rc.i_rc_method = X264_RC_CQP; #endif // Reset quantizer if fixed bitrate x264_param_t default_params; x264_param_default(&default_params); #if X264_BUILD < 48 if(codec->param.rc.b_cbr) #else if(codec->param.rc.i_qp_constant) #endif { 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)); //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); } codec->pic[current_field]->i_type = X264_TYPE_AUTO; codec->pic[current_field]->i_qpplus1 = 0; if(codec->header_only) { bzero(codec->pic[current_field]->img.plane[0], w_2 * h_2); bzero(codec->pic[current_field]->img.plane[1], w_2 * h_2 / 4); bzero(codec->pic[current_field]->img.plane[2], w_2 * h_2 / 4); } else if(file->color_model == BC_YUV420P) { memcpy(codec->pic[current_field]->img.plane[0], row_pointers[0], w_2 * h_2); memcpy(codec->pic[current_field]->img.plane[1], row_pointers[1], w_2 * h_2 / 4); memcpy(codec->pic[current_field]->img.plane[2], row_pointers[2], w_2 * h_2 / 4); } else { //printf("encode 2 %p %p %p\n", codec->pic[current_field]->img.plane[0], codec->pic[current_field]->img.plane[1], codec->pic[current_field]->img.plane[2]); cmodel_transfer(0, /* Leave NULL if non existent */ row_pointers, codec->pic[current_field]->img.plane[0], /* Leave NULL if non existent */ codec->pic[current_field]->img.plane[1], codec->pic[current_field]->img.plane[2], row_pointers[0], /* Leave NULL if non existent */ row_pointers[1], row_pointers[2], 0, /* Dimensions to capture from input frame */ 0, width, height, 0, /* Dimensions to project on output frame */ 0, width, height, file->color_model, BC_YUV420P, 0, /* When transfering BC_RGBA8888 to non-alpha this is the background color in 0xRRGGBB hex */ width, /* For planar use the luma rowspan */ codec->pic[current_field]->img.i_stride[0]); } x264_picture_t pic_out; x264_nal_t *nals; int nnal = 0; do { x264_encoder_encode(codec->encoder[current_field], &nals, &nnal, codec->pic[current_field], &pic_out); //printf("encode %d nnal=%d\n", __LINE__, nnal); } while(codec->header_only && !nnal); int allocation = w_2 * h_2 * 3; if(!codec->work_buffer) { codec->work_buffer = calloc(1, allocation); } codec->buffer_size = 0; //printf("encode %d nnal=%d\n", __LINE__, nnal); for(i = 0; i < nnal; i++) { #if X264_BUILD >= 76 int size = nals[i].i_payload; memcpy(codec->work_buffer + codec->buffer_size, nals[i].p_payload, nals[i].i_payload); #else int size_return = 0; int size = x264_nal_encode(codec->work_buffer + codec->buffer_size, &size_return, 1, nals + i); #endif unsigned char *ptr = codec->work_buffer + codec->buffer_size; //printf("encode %d size=%d\n", __LINE__, size); if(size > 0) { if(size + codec->buffer_size > allocation) { printf("qth264.c %d: overflow size=%d allocation=%d\n", __LINE__, size, allocation); } // Size of NAL for avc uint64_t avc_size = size - 4; // Synthesize header. // Hopefully all the parameter set NAL's are present in the first frame. if(!avcc->data_size) { if(header_size < 6) { 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[4] & 0x1f); // Picture parameter or sequence parameter set if(nal_type == 0x7 && !got_sps) { got_sps = 1; header[header_size++] = (avc_size & 0xff00) >> 8; header[header_size++] = (avc_size & 0xff); memcpy(&header[header_size], ptr + 4, avc_size); header_size += avc_size; } else if(nal_type == 0x8 && !got_pps) { got_pps = 1; // Number of sps nal's. header[header_size++] = 0x1; header[header_size++] = (avc_size & 0xff00) >> 8; header[header_size++] = (avc_size & 0xff); memcpy(&header[header_size], ptr + 4, avc_size); header_size += avc_size; } // Write header if(got_sps && got_pps) { /* * printf("encode %d\n", __LINE__); * int j; * for(j = 0; j < header_size; j++) * { * printf("%02x ", header[j]); * } * printf("\n"); */ quicktime_set_avcc_header(avcc, header, header_size); } }