TAO.ffmpeg output usage problem
I am trying to do a format converter tool with tao.ffmpeg.
All the examples that i have found are related to play and audio or video. I haven't found anything similar to what i am trying to do.
This is the code that i have done so far regarding the output.
IntPtr pavoutputformat = FFmpeg.guess_format("mpeg4", "", "");
FFmpeg.AVOutputFormat outputFormat = (FFmpeg.AVOutputFormat)Marshal.PtrToStructure(pavoutputformat, typeof(FFmpeg.AVOutputFormat));
outputFormat.name = "mp4";
outputFormat.long_name = "mp4 format";
outputFormat.audio_codec = FFmpeg.CodecID.CODEC_ID_MPEG4AAC;
outputFormat.video_codec = FFmpeg.CodecID.CODEC_ID_H264;
IntPtr poutputFormatContext = FFmpeg.av_alloc_format_context();
FFmpeg.AVFormatContext outputFormatContext = (FFmpeg.AVFormatContext)Marshal.PtrToStructure(poutputFormatContext, typeof(FFmpeg.AVFormatContext));
outputFormatContext.pAVOutputFormat = pavoutputformat;
int ret = FFmpeg.av_set_parameters(poutputFormatContext, IntPtr.Zero);
FFmpeg.dump_format(poutputFormatContext, 0, output, 1);
The problem is in the av_set_parameters that returns an exception "{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}
The function dump_format returns the same error.
Any help would be useful for me to be able to debug this problem.

First of all you probably
First of all you probably want to marshal your structures two ways: Marshal.PtrToStructure copies the structure to managed memory, so the assignments you do are only in the managed structure, you need to save them back to unmanaged memory using Marshal.StructureToPtr.
----------------------
Download Tao svn snapshot build
Experimental Tao rpms (OpenSUSE Build Service)
Thanks a lot for your quick
Thanks a lot for your quick reply. I have tested what you say.
This is the code:
//init output
IntPtr pavoutputformat = FFmpeg.guess_format("mpeg4", "", "");
FFmpeg.AVOutputFormat outputFormat = (FFmpeg.AVOutputFormat)Marshal.PtrToStructure(pavoutputformat, typeof(FFmpeg.AVOutputFormat));
outputFormat.name = "mp4";
outputFormat.long_name = "mp4 format";
outputFormat.audio_codec = FFmpeg.CodecID.CODEC_ID_MPEG4AAC;
outputFormat.video_codec = FFmpeg.CodecID.CODEC_ID_H264;
IntPtr poutputFormatContext = FFmpeg.av_alloc_format_context();
FFmpeg.AVFormatContext outputFormatContext = (FFmpeg.AVFormatContext)Marshal.PtrToStructure(poutputFormatContext, typeof(FFmpeg.AVFormatContext));
//unmanaged outputFormatContext
IntPtr poutputFormatContextUnmanaged = Marshal.AllocHGlobal(Marshal.SizeOf(outputFormatContext));
Marshal.StructureToPtr(outputFormatContext, poutputFormatContextUnmanaged, true);
//unamneged avoutputformat
IntPtr pavoutputformatUnmanaged = Marshal.AllocHGlobal(Marshal.SizeOf(outputFormat));
Marshal.StructureToPtr(outputFormat, pavoutputformatUnmanaged, true);
outputFormatContext.pAVOutputFormat = pavoutputformatUnmanaged;
ret = FFmpeg.av_set_parameters(poutputFormatContextUnmanaged, IntPtr.Zero);
FFmpeg.dump_format(poutputFormatContextUnmanaged, 0, output, 1);
I have allocated the necessary memory and copied the structures. But still i have the same error.
Try this: //init
Try this:
//init output
IntPtr pavoutputformat = FFmpeg.guess_format("mpeg4", "", "");
// MARHSAL GET OutputFormat
FFmpeg.AVOutputFormat outputFormat = (FFmpeg.AVOutputFormat)Marshal.PtrToStructure(pavoutputformat, typeof(FFmpeg.AVOutputFormat));
outputFormat.name = "mp4";
outputFormat.long_name = "mp4 format";
outputFormat.audio_codec = FFmpeg.CodecID.CODEC_ID_MPEG4AAC;
outputFormat.video_codec = FFmpeg.CodecID.CODEC_ID_H264;
// MARSHAL SET OutputFormat
Marshal.StructureToPtr(outputFormat, pavoutputformat, false);
IntPtr poutputFormatContext = FFmpeg.av_alloc_format_context();
// MARSHAL GET FormatContext
FFmpeg.AVFormatContext outputFormatContext = (FFmpeg.AVFormatContext)Marshal.PtrToStructure(poutputFormatContext, typeof(FFmpeg.AVFormatContext));
outputFormatContext.pAVOutputFormat = pavoutputformatUnmanaged;
// MARSHAL SET FormatContext
Marshal.StructureToPtr(outputFormatContext, poutputFormatContext, false);
ret = FFmpeg.av_set_parameters(poutputFormatContext, IntPtr.Zero);
FFmpeg.dump_format(poutputFormatContext, 0, output, 1);
----------------------
Download Tao svn snapshot build
Experimental Tao rpms (OpenSUSE Build Service)
Many thanks. That solved the
Many thanks. That solved the issue. But now i am trying to call av_write_header and it is returning the error "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
I writing this code based on "output_example.c" of ffmpeg.
Do you think i have to open the file with .net for writing, before av_write_header? If so how can do that.
public FFmpeg.AVStream add_audio_stream(IntPtr poutputFormatContext, FFmpeg.CodecID codecid)
{
FFmpeg.AVCodecContext c;
FFmpeg.AVStream st;
//allocate new strem
IntPtr avStreamPtr = FFmpeg.av_new_stream(poutputFormatContext, 1);
//get structure
st = (FFmpeg.AVStream)Marshal.PtrToStructure(avStreamPtr, typeof(FFmpeg.AVStream));
//update pointer to unmanaged
Marshal.StructureToPtr(st, avStreamPtr, false);
c = (FFmpeg.AVCodecContext) Marshal.PtrToStructure(st.codec, typeof(FFmpeg.AVCodecContext));
c.codec_id = codecid;
c.codec_type = FFmpeg.CodecType.CODEC_TYPE_AUDIO;
/* put sample parameters */
c.bit_rate = 128000;
c.sample_rate = 44100;
c.channels = 2;
return st;
}
public FFmpeg.AVStream add_video_stream(IntPtr poutputFormatContext, FFmpeg.CodecID codecid)
{
FFmpeg.AVCodecContext c;
FFmpeg.AVStream st;
//allocate new strem
IntPtr avStreamPtr = FFmpeg.av_new_stream(poutputFormatContext, 0);
//get structure
st = (FFmpeg.AVStream)Marshal.PtrToStructure(avStreamPtr, typeof(FFmpeg.AVStream));
//update pointer to unmanaged
Marshal.StructureToPtr(st, avStreamPtr, false);
c = (FFmpeg.AVCodecContext)Marshal.PtrToStructure(st.codec, typeof(FFmpeg.AVCodecContext));
c.codec_id = codecid;
c.codec_type = FFmpeg.CodecType.CODEC_TYPE_VIDEO;
/* put sample parameters */
c.bit_rate = 4000000;
/* resolution must be a multiple of two */
c.width = 352;
c.height = 288;
/* time base: this is the fundamental unit of time (in seconds) in terms
of which frame timestamps are represented. for fixed-fps content,
timebase should be 1/framerate and timestamp increments should be
identically 1. */
c.time_base.den = FFmpeg.DEFAULT_FRAME_RATE_BASE;
c.time_base.num = 1;
c.gop_size = 12; /* emit one intra frame every twelve frames at most */
c.pix_fmt = inputaudioCodecContext.pix_fmt;
if (c.codec_id == FFmpeg.CodecID.CODEC_ID_MPEG2VIDEO)
{
/* just for testing, we also add B frames */
c.max_b_frames = 2;
}
if (c.codec_id == FFmpeg.CodecID.CODEC_ID_MPEG1VIDEO)
{
/* Needed to avoid using macroblocks in which some coeffs overflow.
This does not happen with normal video, it just happens here as
the motion of the chroma plane does not match the luma plane. */
c.mb_decision=2;
}
// some formats want stream headers to be separate
FFmpeg.AVFormatContext outputformatContext = (FFmpeg.AVFormatContext)Marshal.PtrToStructure(poutputFormatContext,typeof(FFmpeg.AVFormatContext));
FFmpeg.AVOutputFormat outputFormat = (FFmpeg.AVOutputFormat)Marshal.PtrToStructure(outputformatContext.pAVOutputFormat, typeof(FFmpeg.AVOutputFormat));
if(outputFormat.name=="mp4" ||outputFormat.name=="mov" || outputFormat.name=="3gp")
c.flags |= FFmpeg.CODEC_FLAG_GLOBAL_HEADER;
return st;
}
//init output
IntPtr pavoutputformat = FFmpeg.guess_format("mpeg4", "", "");
// MARHSAL GET OutputFormat
FFmpeg.AVOutputFormat outputFormat = (FFmpeg.AVOutputFormat)Marshal.PtrToStructure(pavoutputformat, typeof(FFmpeg.AVOutputFormat));
outputFormat.name = "mp4";
outputFormat.long_name = "mp4 format";
outputFormat.audio_codec = FFmpeg.CodecID.CODEC_ID_MPEG4AAC;
outputFormat.video_codec = FFmpeg.CodecID.CODEC_ID_H264;
// MARSHAL SET OutputFormat
Marshal.StructureToPtr(outputFormat, pavoutputformat, false);
IntPtr poutputFormatContext = FFmpeg.av_alloc_format_context();
// MARSHAL GET FormatContext
FFmpeg.AVFormatContext outputFormatContext = (FFmpeg.AVFormatContext)Marshal.PtrToStructure(poutputFormatContext, typeof(FFmpeg.AVFormatContext));
outputFormatContext.pAVOutputFormat = pavoutputformat;
// MARSHAL SET FormatContext
Marshal.StructureToPtr(outputFormatContext, poutputFormatContext, false);
ret = FFmpeg.av_set_parameters(poutputFormatContext, IntPtr.Zero);
FFmpeg.dump_format(poutputFormatContext, 0, output, 1);
outputFormatContext.audio_codec_id = FFmpeg.CodecID.CODEC_ID_MPEG4AAC;
outputFormatContext.video_codec_id = FFmpeg.CodecID.CODEC_ID_H264;
FFmpeg.AVStream outputvideostream = this.add_video_stream(poutputFormatContext,FFmpeg.CodecID.CODEC_ID_H264);
FFmpeg.AVStream outputaudiostream = this.add_audio_stream(poutputFormatContext,FFmpeg.CodecID.CODEC_ID_MPEG4AAC);
FFmpeg.av_write_header(poutputFormatContext);
The code of add_video_strem and add_audio_strem is based on output_example.c
Unfortunately i am familiar with .net but no so familiar with marshalling objects to unmanaged memory. Your help has been great.
FFmpeg should be able to
FFmpeg should be able to handle files on itself, trying to do it with .NET would probably only complicate things (as you'd create another managed-native boundary to cross). A quick look at your code reveals this section:
outputFormatContext.audio_codec_id = FFmpeg.CodecID.CODEC_ID_MPEG4AAC;
outputFormatContext.video_codec_id = FFmpeg.CodecID.CODEC_ID_H264;
Here you're changing the AVFormatContext, that's saved just ABOVE in
// MARSHAL SET FormatContext
Marshal.StructureToPtr(outputFormatContext, poutputFormatContext, false);
so those changes aren't stored in the native structure (poutputFormatContext) that you're using in av_write_header. Any changes to the structure should be done before you save it with StructureToPtr.
----------------------
Download Tao svn snapshot build
Experimental Tao rpms (OpenSUSE Build Service)
Yes you are right. I have
Yes you are right. I have corrected that and modified the add_video_stream, add_audio_stream to guarantee that all pointers are updated with the last changes to the .net structures. Needless to say that this kind of programming is a pain.
Unfortunately with all these changes made to the code i have the same error. Your help has been great.
The code:
///
/// adds video stream to the format context
///
///
///
/// an updated pointer for the format context
public IntPtr add_audio_stream(IntPtr poutputFormatContext, FFmpeg.CodecID codecid, int index)
{
FFmpeg.AVCodecContext c;
FFmpeg.AVStream st;
FFmpeg.AVFormatContext formatContextTMP = (FFmpeg.AVFormatContext)Marshal.PtrToStructure(poutputFormatContext, typeof(FFmpeg.AVFormatContext));
//allocate new strem
IntPtr avStreamPtr = FFmpeg.av_new_stream(poutputFormatContext, index);
//get structure
st = (FFmpeg.AVStream)Marshal.PtrToStructure(avStreamPtr, typeof(FFmpeg.AVStream));
//update pointer to unmanaged
Marshal.StructureToPtr(st, avStreamPtr, false);
c = (FFmpeg.AVCodecContext)Marshal.PtrToStructure(st.codec, typeof(FFmpeg.AVCodecContext));
c.codec_id = codecid;
c.codec_type = FFmpeg.CodecType.CODEC_TYPE_AUDIO;
/* put sample parameters */
c.bit_rate = 128000;
c.sample_rate = 44100;
c.channels = 2;
//update AVCodecContext,AVStream,AVformatContext
Marshal.StructureToPtr(c, st.codec, false);
Marshal.StructureToPtr(st, avStreamPtr, false);
formatContextTMP.streams[index] = avStreamPtr;
Marshal.StructureToPtr(formatContextTMP, poutputFormatContext, false);
return poutputFormatContext;
}
///
/// adds video stream to the format context
///
///
///
/// an updated pointer for the format context
public IntPtr add_video_stream(IntPtr poutputFormatContext, FFmpeg.CodecID codecid, int index)
{
FFmpeg.AVCodecContext c;
FFmpeg.AVStream st;
//allocate new strem
IntPtr avStreamPtr = FFmpeg.av_new_stream(poutputFormatContext, index);
FFmpeg.AVFormatContext formatContextTMP = (FFmpeg.AVFormatContext)Marshal.PtrToStructure(poutputFormatContext, typeof(FFmpeg.AVFormatContext));
//get structure
st = (FFmpeg.AVStream)Marshal.PtrToStructure(avStreamPtr, typeof(FFmpeg.AVStream));
//update pointer to unmanaged
Marshal.StructureToPtr(st, avStreamPtr, false);
c = (FFmpeg.AVCodecContext)Marshal.PtrToStructure(st.codec, typeof(FFmpeg.AVCodecContext));
c.codec_id = codecid;
c.codec_type = FFmpeg.CodecType.CODEC_TYPE_VIDEO;
/* put sample parameters */
c.bit_rate = 4000000;
/* resolution must be a multiple of two */
c.width = 352;
c.height = 288;
/* time base: this is the fundamental unit of time (in seconds) in terms
of which frame timestamps are represented. for fixed-fps content,
timebase should be 1/framerate and timestamp increments should be
identically 1. */
c.time_base.den = FFmpeg.DEFAULT_FRAME_RATE_BASE;
c.time_base.num = 1;
c.gop_size = 12; /* emit one intra frame every twelve frames at most */
c.pix_fmt = inputaudioCodecContext.pix_fmt;
if (c.codec_id == FFmpeg.CodecID.CODEC_ID_MPEG2VIDEO)
{
/* just for testing, we also add B frames */
c.max_b_frames = 2;
}
if (c.codec_id == FFmpeg.CodecID.CODEC_ID_MPEG1VIDEO)
{
/* Needed to avoid using macroblocks in which some coeffs overflow.
This does not happen with normal video, it just happens here as
the motion of the chroma plane does not match the luma plane. */
c.mb_decision = 2;
}
// some formats want stream headers to be separate
FFmpeg.AVOutputFormat outputFormat = (FFmpeg.AVOutputFormat)Marshal.PtrToStructure(formatContextTMP.pAVOutputFormat, typeof(FFmpeg.AVOutputFormat));
if (outputFormat.name == "mp4" || outputFormat.name == "mov" || outputFormat.name == "3gp")
c.flags |= FFmpeg.CODEC_FLAG_GLOBAL_HEADER;
//update AVCodecContext,AVStream,AVformatContext
Marshal.StructureToPtr(c, st.codec, false);
Marshal.StructureToPtr(st, avStreamPtr, false);
formatContextTMP.streams[index] = avStreamPtr;
Marshal.StructureToPtr(formatContextTMP, poutputFormatContext, false);
return poutputFormatContext;
}
--------------------------
//init output
IntPtr pavoutputformat = FFmpeg.guess_format("mpeg4", "", "");
// MARHSAL GET OutputFormat
FFmpeg.AVOutputFormat outputFormat = (FFmpeg.AVOutputFormat)Marshal.PtrToStructure(pavoutputformat, typeof(FFmpeg.AVOutputFormat));
outputFormat.name = "mp4";
outputFormat.long_name = "mp4 format";
outputFormat.audio_codec = FFmpeg.CodecID.CODEC_ID_MPEG4AAC;
outputFormat.video_codec = FFmpeg.CodecID.CODEC_ID_H264;
// MARSHAL SET OutputFormat
Marshal.StructureToPtr(outputFormat, pavoutputformat, false);
IntPtr poutputFormatContext = FFmpeg.av_alloc_format_context();
// MARSHAL GET FormatContext
FFmpeg.AVFormatContext outputFormatContext = (FFmpeg.AVFormatContext)Marshal.PtrToStructure(poutputFormatContext, typeof(FFmpeg.AVFormatContext));
outputFormatContext.pAVOutputFormat = pavoutputformat;
outputFormatContext.audio_codec_id = FFmpeg.CodecID.CODEC_ID_MPEG4AAC;
outputFormatContext.video_codec_id = FFmpeg.CodecID.CODEC_ID_H264;
// MARSHAL SET FormatContext
Marshal.StructureToPtr(outputFormatContext, poutputFormatContext, false);
ret = FFmpeg.av_set_parameters(poutputFormatContext, IntPtr.Zero);
FFmpeg.dump_format(poutputFormatContext, 0, output, 1);
poutputFormatContext = this.add_video_stream(poutputFormatContext, FFmpeg.CodecID.CODEC_ID_H264,0);
poutputFormatContext = this.add_audio_stream(poutputFormatContext, FFmpeg.CodecID.CODEC_ID_MPEG4AAC, 1);
//guaranteed by the add stream methods that the pointers are OK
FFmpeg.av_write_header(poutputFormatContext);
Is there a way to debug the ffmpeg libraries in parallel with the debug in .net. For this to work i would need the exact code that generated the libraries avformat-51.dll,avcodec-51.dll and avutil-49.dll.
But i don't quite know how to do this kind of debug.
Is anyone using
Is anyone using av_write_header function of tao.ffmpeg? Does it work properly? what help can anyone provide to overcome this problem?