voidcopy(conststd::string&srcFileName,conststd::string&dstFileName){Timecodestart_timecode;uint32_tmax_samples_per_read=1;AppMXFFileFactoryfile_factory;bmx::ByteArraysound_buffer;bmx::ByteArraynormalized_buffer;bmx::ByteArraywrite_buffer;autoreader=std::make_shared<MXFFileReader>();reader->SetFileFactory(&file_factory,false);reader->GetPackageResolver()->SetFileFactory(&file_factory,false);MXFFileReader::OpenResultresult;result=reader->Open(srcFileName);intmxfVersion=reader->GetMXFVersion();if(result!=MXFFileReader::OpenResult::MXF_RESULT_SUCCESS){std::stringmsg=Poco::format("Unable to open source file. Status %d",result);throwstd::runtime_error(msg);}autoclipType=detectClipType(reader);//PrepareforwritingresultsClipWriterTrack*out_video_track=nullptr;ClipWriterTrack*out_anc_track=nullptr;std::map<int,ClipWriterTrack*>out_audio_tracks;mxfpp::File*file;try{file=file_factory.OpenNew(dstFileName);}catch(...){std::stringmsg=Poco::format("Unable to open destination file %s",dstFileName);throwstd::runtime_error(msg);}int16_tmxfFlavour;std::shared_ptr<ClipWriter>clip;if(clipType==ClipWriterType::CW_OP1A_CLIP_TYPE){mxfFlavour=OP1A_MIN_PARTITIONS_FLAVOUR;if(mxfVersion==MXF_PREFACE_VER(1,2)){mxfFlavour|=OP1A_377_2004_FLAVOUR;}clip.reset(ClipWriter::OpenNewOP1AClip(mxfFlavour,file,reader->GetEditRate()));autoop1a=clip->GetOP1AClip();op1a->SetAddSystemItem(true);}else{mxfFlavour=D10_DEFAULT_FLAVOUR;clip.reset(ClipWriter::OpenNewD10Clip(mxfFlavour,file,reader->GetEditRate()));}clip->ReserveHeaderMetadataSpace(16384);start_timecode.Init(reader->GetEditRate(),false);clip->SetStartTimecode(start_timecode);setProductInfo(clip);//Creatingtracksintaudio_track_index=0;for(inti=0;i<reader->GetNumTrackReaders();i++){MXFTrackReader*track_reader=reader->GetTrackReader(i);constMXFTrackInfo*input_track_info=track_reader->GetTrackInfo();bmx::EssenceTypeessenceType=input_track_info->essence_type;constMXFPictureTrackInfo*inputPictureInfo=nullptr;if(isSupportedVideoEssenceType(essenceType)){inputPictureInfo=dynamic_cast<constMXFPictureTrackInfo*>(input_track_info);}switch(essenceType){caseEssenceType::WAVE_PCM:caseEssenceType::D10_AES3_PCM:{ClipWriterTrack*track=clip->CreateTrack(EssenceType::WAVE_PCM);out_audio_tracks[audio_track_index]=track;constMXFSoundTrackInfo*input_sound_info=dynamic_cast<constMXFSoundTrackInfo*>(input_track_info);track->SetSamplingRate(input_sound_info->sampling_rate);track->SetQuantizationBits(input_sound_info->bits_per_sample);track->SetChannelCount(input_sound_info->channel_count);track->SetAES3Mapping(true);track->SetLocked(true);if(essenceType==EssenceType::WAVE_PCM){track->SetOutputTrackNumber(i+1);}audio_track_index++;}break;caseEssenceType::DV100_1080I:{out_video_track=clip->CreateTrack(essenceType);out_video_track->SetComponentDepth(10);}break;caseEssenceType::IEC_DV25:{out_video_track=clip->CreateTrack(essenceType);out_video_track->SetComponentDepth(8);}break;//D10-clipcaseEssenceType::D10_30:caseEssenceType::D10_40:caseEssenceType::D10_50:{out_video_track=clip->CreateTrack(essenceType);out_video_track->SetComponentDepth(8);out_video_track->SetAspectRatio(inputPictureInfo->aspect_ratio);}break;caseEssenceType::MPEG2LG_422P_HL_1080P:caseEssenceType::MPEG2LG_422P_HL_1080I:{out_video_track=clip->CreateTrack(essenceType);out_video_track->SetComponentDepth(8);}break;caseEssenceType::MPEG2LG_MP_HL_1920_1080I:caseEssenceType::MPEG2LG_MP_HL_1920_1080P:caseEssenceType::MPEG2LG_MP_HL_1440_1080I:caseEssenceType::MPEG2LG_MP_HL_1440_1080P:caseEssenceType::MPEG2LG_MP_H14_1080I:caseEssenceType::MPEG2LG_MP_H14_1080P:{out_video_track=clip->CreateTrack(essenceType);out_video_track->SetComponentDepth(8);}break;caseEssenceType::MPEG2_422P_ML_LongGOP:{out_video_track=clip->CreateTrack(essenceType);out_video_track->SetComponentDepth(inputPictureInfo->component_depth);}break;caseEssenceType::AVCI100_1080I:caseEssenceType::AVCI100_1080P:caseEssenceType::AVCI50_1080I:caseEssenceType::AVCI50_1080P:{out_video_track=clip->CreateTrack(essenceType);out_video_track->SetComponentDepth(10);}break;caseEssenceType::VC3_1080I_1242:{out_video_track=clip->CreateTrack(essenceType);out_video_track->SetComponentDepth(inputPictureInfo->component_depth);}break;caseEssenceType::ANC_DATA:{if(clipType==ClipWriterType::CW_D10_CLIP_TYPE){printf("Currently unable to write anc-data to d10-clips\n");//knownissuebreak;}reader->SetTemporaryFrameBuffer(true);out_anc_track=clip->CreateTrack(essenceType);uint32_tnum_read=reader->Read(max_samples_per_read);if(num_read){std::shared_ptr<Frame>anc_frame;anc_frame.reset(track_reader->GetFrameBuffer()->GetLastFrame(true));out_anc_track->SetConstantDataSize(anc_frame->GetSize());}reader->SetTemporaryFrameBuffer(false);reader->Seek(0);}break;default:{std::stringerrMsg("Unsupported essense format");errMsg+=" '"+std::string(essence_type_to_enum_string(essenceType))+"'";file->closeMemoryFile();/* file is automatically deleted by ClipWriter */throwstd::runtime_error(errMsg);}break;}}clip->PrepareHeaderMetadata();clip->PrepareWrite();longtotalRead=0l;audio_track_index=0;while(true){uint32_tnum_read=reader->Read(max_samples_per_read);if(num_read==0){if(reader->ReadError()){std::stringerrMsg=reader->ReadErrorMessage();throwstd::runtime_error(errMsg);}else{break;}}totalRead+=num_read;//Enumeratingtracksfor(inti=0;i<reader->GetNumTrackReaders();i++){MXFTrackReader*track_reader=reader->GetTrackReader(i);if(!track_reader->IsEnabled())continue;constMXFTrackInfo*input_track_info=track_reader->GetTrackInfo();bmx::EssenceTypeessenceType=input_track_info->essence_type;constMXFSoundTrackInfo*input_sound_info=dynamic_cast<constMXFSoundTrackInfo*>(input_track_info);if(essenceType==WAVE_PCM||essenceType==EssenceType::D10_AES3_PCM){Rationalsampling_rate=input_sound_info->sampling_rate;doublesamples_per_second=((double)sampling_rate.numerator)/sampling_rate.numerator;while(true){constMXFSoundTrackInfo*sound_info=dynamic_cast<constMXFSoundTrackInfo*>(input_track_info);std::shared_ptr<Frame>frame;frame.reset(reader->GetTrackReader(i)->GetFrameBuffer()->GetLastFrame(true));if(!frame){break;}if(frame->IsEmpty()){continue;}autobits_per_sample=input_sound_info->bits_per_sample;autochannel_block_align=(bits_per_sample+7)/8;uint32_ttrack_buffer_size=frame->GetSize();uint32_tchannel_buffer_size=frame->GetSize()/sound_info->channel_count;size_tnum_samples=channel_buffer_size/channel_block_align;sound_buffer.Grow(channel_buffer_size);sound_buffer.SetSize(channel_buffer_size);normalized_buffer.Reallocate(channel_buffer_size);write_buffer.Grow(track_buffer_size);ClipWriterTrack*track=out_audio_tracks[audio_track_index];for(intc=0;c<sound_info->channel_count;c++){//extractif(essenceType==EssenceType::D10_AES3_PCM){convert_aes3_to_pcm(frame->GetBytes(),track_buffer_size,true,bits_per_sample,c,sound_buffer.GetBytes(),channel_buffer_size);num_samples=get_aes3_sample_count(frame->GetBytes(),frame->GetSize());}else{deinterleave_audio(frame->GetBytes(),track_buffer_size,bits_per_sample,sound_info->channel_count,c,sound_buffer.GetBytes(),channel_buffer_size);}normalized_buffer.CopyBytes(sound_buffer.GetBytes(),channel_buffer_size);interleave_audio(normalized_buffer.GetBytes(),channel_buffer_size,bits_per_sample,sound_info->channel_count,c,write_buffer.GetBytes(),track_buffer_size);}track->WriteSamples(write_buffer.GetBytes(),track_buffer_size,num_samples);}audio_track_index++;}elseif(essenceType==EssenceType::ANC_DATA){if(clipType==ClipWriterType::CW_D10_CLIP_TYPE){printf("Anc-data tracks are not supported for d10-clips\n");//knownissuecontinue;}std::shared_ptr<Frame>frame;frame.reset(reader->GetTrackReader(i)->GetFrameBuffer()->GetLastFrame(true));if(out_anc_track){out_anc_track->WriteSamples((unsignedchar*)frame->GetBytes(),frame->GetSize(),1);}continue;}else{if(!isSupportedVideoEssenceType(essenceType)){printf("Unknown essence codec! %s\n",essence_type_to_string(essenceType));continue;}std::shared_ptr<Frame>frame;frame.reset(reader->GetTrackReader(i)->GetFrameBuffer()->GetLastFrame(true));if(out_video_track){out_video_track->WriteSamples((unsignedchar*)frame->GetBytes(),frame->GetSize(),1);}continue;}}audio_track_index=0;}//closeop1afileclip->CompleteWrite();if(!totalRead){throwstd::runtime_error("Unable to write file");}}
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I don't know what information mediainfo uses for the reported bit rate. When bmx transwraps an MXF file it will extract the bit rate metadata from the MPEG-2 video bitstream, ie. it will not copy across the input file's MXF metadata. My guess therefore is that the bitstream has bit rate metadata != 50Mb/s or no bit rate metadata.
You can check this by extracting frames from the input (eg. 30) and then running the parser utility showing what bmx has found:
In a frame with metadata sequence_header: true there will be a bit_rate (or not) which when multiplied by 400 gives you bit rate, eg. 125000 is for 50Mb/s.
The DVC-Pro HD 10 bit depth is hardcoded in your software: out_video_track->SetComponentDepth(10);.
Philip
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Thank you Philip.
Your advice had helped with bit depth issue of course.
Also I took advantage of your advice on the bit rate issue.
bmxparse had showed the equal results for the input and output file.
It looks like i need to get to MPEGVideoDescriptor.
Perhaps enough to copy value from the input's descriptor to the output's descriptor.
But i couldn't to figure out how to do it.
Point the right direction please.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
OK, so I assume that the last GOP in the file also has 105Mb/s set in the bitstream and that value is the last one extracted by the writer helper before it is set in the descriptor in the track writer.
In your code you have access to the MXF file descriptor via the MXFTrackReader::GetFileDescriptor() method. The output file descriptor is available through the output track ClipWriterTrack::GetMXFDescriptorHelper() and then calling GetFileDescriptor(). Cast the objects to the MPEGVideoDescriptor to get and set the bit rate property. You also need to modify the track writer so that it only sets the bit rate if it has not already been set (ie. by you) by using MPEGVideoDescriptor::haveBitRate().
Philip
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'm trying to copy a file.
Bit rate of video had changed in the copied file.
After copying another file, the bit depth changes.
Is there any way to fix this issues?
Source file1:
Copied file1:
Source file2:
Copied file2:
My code:
I don't know what information mediainfo uses for the reported bit rate. When bmx transwraps an MXF file it will extract the bit rate metadata from the MPEG-2 video bitstream, ie. it will not copy across the input file's MXF metadata. My guess therefore is that the bitstream has bit rate metadata != 50Mb/s or no bit rate metadata.
You can check this by extracting frames from the input (eg. 30) and then running the parser utility showing what bmx has found:
In a frame with metadata
sequence_header: truethere will be abit_rate(or not) which when multiplied by 400 gives you bit rate, eg. 125000 is for 50Mb/s.The DVC-Pro HD 10 bit depth is hardcoded in your software:
out_video_track->SetComponentDepth(10);.Philip
Thank you Philip.
Your advice had helped with bit depth issue of course.
Also I took advantage of your advice on the bit rate issue.
bmxparse had showed the equal results for the input and output file.
I looked at the output of MediaInfo in debug mode.
Source file:
Copied file:
It looks like i need to get to MPEGVideoDescriptor.
Perhaps enough to copy value from the input's descriptor to the output's descriptor.
But i couldn't to figure out how to do it.
Point the right direction please.
OK, so I assume that the last GOP in the file also has 105Mb/s set in the bitstream and that value is the last one extracted by the writer helper before it is set in the descriptor in the track writer.
In your code you have access to the MXF file descriptor via the MXFTrackReader::GetFileDescriptor() method. The output file descriptor is available through the output track ClipWriterTrack::GetMXFDescriptorHelper() and then calling GetFileDescriptor(). Cast the objects to the MPEGVideoDescriptor to get and set the bit rate property. You also need to modify the track writer so that it only sets the bit rate if it has not already been set (ie. by you) by using MPEGVideoDescriptor::haveBitRate().
Philip
Yes, you are right. First and last GOP has 105Mb/s. All others has 50Mb/s bitrate.
Thank you. This is the solution.