c++ - Decoding by libjpeg -> Encoding by x264, strange artefacts on frames -
i have collection of jpeg, must decoded lib jpeg, , after it, encoded x264 (after encoded packets streamed via rtmp). code used decoding:
struct my_error_mgr { struct jpeg_error_mgr pub; jmp_buf setjmp_buffer; }; typedef my_error_mgr *my_error_ptr; methoddef(void) my_error_exit (j_common_ptr cinfo) { my_error_ptr myerr = (my_error_ptr) cinfo->err; (*cinfo->err->output_message) (cinfo); longjmp(myerr->setjmp_buffer, 1); } void init_source(j_decompress_ptr ptr) { q_unused(ptr) } boolean fill_input_buffer(j_decompress_ptr ptr) { q_unused(ptr) return true; } void term_source(j_decompress_ptr ptr) { q_unused(ptr) } void skip_input_data(j_decompress_ptr ptr, long num_bytes) { if(num_bytes>0) { ptr->src->next_input_byte+=(size_t)num_bytes; ptr->src->bytes_in_buffer-=(size_t)num_bytes; } } etherdecoder::etherdecoder(qobject *parent): qobject(parent) { } void etherdecoder::datablockready(qbytearray data) { jpeg_decompress_struct decompressinfo; jpeg_create_decompress(&decompressinfo); my_error_mgr err; decompressinfo.do_fancy_upsampling = false; decompressinfo.src = (jpeg_source_mgr *) (*decompressinfo.mem->alloc_small) ((j_common_ptr) &decompressinfo, jpool_permanent, sizeof(jpeg_source_mgr)); decompressinfo.err = jpeg_std_error(&err.pub); err.pub.error_exit = my_error_exit; if (setjmp(err.setjmp_buffer)) { jpeg_destroy_decompress(&decompressinfo); return; } decompressinfo.src->init_source = init_source; decompressinfo.src->resync_to_restart = jpeg_resync_to_restart; decompressinfo.src->fill_input_buffer = fill_input_buffer; decompressinfo.src->skip_input_data = skip_input_data; decompressinfo.src->term_source = term_source; decompressinfo.src->next_input_byte = reinterpret_cast<const joctet*>(data.data()); decompressinfo.src->bytes_in_buffer = data.size(); jpeg_read_header(&decompressinfo, true); jpeg_start_decompress(&decompressinfo); int size = 0; int n_samples = 0; char *samples = new char[5242880]; char *reserv = samples; while (decompressinfo.output_scanline < decompressinfo.output_height) { n_samples = jpeg_read_scanlines(&decompressinfo, (jsamparray) &samples, 1); samples += n_samples * decompressinfo.image_width * decompressinfo.num_components; size += n_samples * decompressinfo.image_width * decompressinfo.num_components; } jpeg_finish_decompress(&decompressinfo); qbytearray output(reserv, size); emit frameready(output, decompressinfo.output_width, decompressinfo.output_height); jpeg_destroy_decompress(&decompressinfo); delete[] reserv; } when emit frameready signal, send data encoder, method, init encedor looks like:
bool etherencoder::initencoder(unsigned int width, unsigned int height) { x264_param_t param; x264_param_default_preset(¶m, "veryfast", "zerolatency"); param.i_width=width; param.i_height=height; param.i_frame_total=0; param.i_csp=x264_csp_i420; param.i_timebase_num=1; param.i_timebase_den=96000; param.b_annexb=true; param.b_repeat_headers=false; x264_param_apply_fastfirstpass(¶m); x264_param_apply_profile(¶m, "baseline"); _context=x264_encoder_open(¶m); if(!_context) return false; int nal_count; x264_nal_t *nals; if(x264_encoder_headers(_context, &nals, &nal_count)<0) { x264_encoder_close(_context); _context=0; return false; } _extradata=qbytearray(); _width=width; _height=height; if(nal_count>0) { _extradata=qbytearray( (const char *)nals[0].p_payload, nals[nal_count-1].p_payload+nals[nal_count-1].i_payload-nals[0].p_payload); } return true; } and encoding method:
void etherencoder::onframeready(qbytearray data, int width, int height) { while(data.size()>0) { if(!_context && initencoder(width, height)) { _timestampdelta=realtimestamp(); } if(_context) { x264_picture_t pic; x264_picture_init(&pic); pic.i_type=x264_type_auto; pic.i_pts=_timestampdelta*96000; pic.img.i_csp=x264_csp_i420; pic.img.i_plane=3; int planesize = width*height; uint8_t *p = (uint8_t*)data.data(); pic.img.plane[0]=p; p+=planesize; pic.img.plane[1]=p; p+=planesize/4; pic.img.plane[2]=p; pic.img.i_stride[0]=width; pic.img.i_stride[1]=width/2; pic.img.i_stride[2]=width/2; if(_forcekeyframe) { pic.i_type=x264_type_i; _forcekeyframe=false; } int nal_count; x264_nal_t *nals; int rc=x264_encoder_encode(_context, &nals, &nal_count, &pic, &pic); if(rc>0) { _mutex.lock(); _packets.push_back( packet( qbytearray( (const char *)nals[0].p_payload, nals[nal_count- 1].p_payload+nals[nal_count-1].i_payload-nals[0].p_payload), _timestampdelta/96.0, _timestampdelta/96.0, pic.b_keyframe)); _timestampdelta+=40; data.clear(); _mutex.unlock(); emit onpacketready(); } } } } decoding , encoding proceeds without errors, @ end valid video stream, but, seems in 1 of steps set invalid data decoder/encoder. 1/4 part of image (top-left, understood) , has invalid color , come color stripes. maybe set invalid strides , planes when encode frame, or maybe setting data libjpeg decoder incorrect.. please ask questions code, i'll try make explanations you. explodes brain.. thank you.
Comments
Post a Comment