Andrey, I finally managed to solve the issue! Thanks a lot :)
Here, I briefly report what I did (the complete code can be found in the
attached source file).
if (avcodec_copy_context(outputStream->codec, g_inputCodecContext))
{
printf("Codec context copy error! Exit!\n");
exit(1);
}
outputStream->pts = (AVFrac) {
g_copyStream->pts.val,
(int64_t)
g_inputCodecContext->time_base.num,
(int64_t)
g_inputCodecContext->time_base.den
};
outputStream->codec->time_base = g_copyStream->time_base;
outputStream->sample_aspect_ratio = g_copyStream->sample_aspect_ratio;
outputStream->codec->sample_aspect_ratio =
outputStream->sample_aspect_ratio;
outputStream->codec->codec_tag = 0;
First I copy the AVCodecContext from the source to the destination; then, I
setup the various fields required to have coherent information between the
stream and the codec.
Finally, I put codec_tag = 0 to avoid a segmentation fault, maybe due to a
wrong setup in the original coded file (it seems that the original coded
file has a codec_tag which is not compatible with the codec itself, i.e.,
h264).
Again, thanks a lot!
Best regards,
Alessandro
Il giorno 01 marzo 2012 16:51, ALESSANDRO PAGANELLI <
[email protected]> ha scritto:
> Again, thank you Andrey for your help.
> I'll try to search through your code to find a useful clue for my issues!
>
> Best regards,
> Alessandro
>
> Il giorno 01 marzo 2012 16:47, Andrey Utkin <
> [email protected]> ha scritto:
>
> 2012/3/1 ALESSANDRO PAGANELLI <[email protected]>:
>> > I tried to use avformat_find_stream_info() (I did not use it before)
>> but the
>> > program still fails, this time due to segmentation fault because
>> > g_inputFormatContext->streams[i]->info is NULL.
>> > Maybe I did something wrong when i produced the original mp4 file with
>> VLC.
>>
>> Fail you got may be caused by wrong invocation of the function, but it
>> is right way to go. I encourage you to use this function. The same
>> about avcodec_copy_context() - it is right to use it, but not to copy
>> everything manually, as you do now.
>>
>> You can take my remux app as an example. But watch out - it is not
>> general-purposed, but just for exact use case.
>> https://github.com/krieger-od/imgs2video/blob/master/cat.c
>>
>> Also there's very simple skeleton of remultiplexing:
>> https://gist.github.com/1950618
>>
>> --
>> Andrey Utkin
>> _______________________________________________
>> Libav-user mailing list
>> [email protected]
>> http://ffmpeg.org/mailman/listinfo/libav-user
>>
>
>
>
> --
> ______________________________________________
>
> Ing. Alessandro Paganelli, Ph. D. Student, 25th Cycle
>
> Department of Information Engineering
> University of Modena and Reggio Emilia
> via Vignolese 905, 41125 Modena (MO), ITALY
>
> E-mail: [email protected]
>
--
______________________________________________
Ing. Alessandro Paganelli, Ph. D. Student, 25th Cycle
Department of Information Engineering
University of Modena and Reggio Emilia
via Vignolese 905, 41125 Modena (MO), ITALY
E-mail: [email protected]
#include <stdio.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libavutil/mathematics.h>
#define _COPY_CONTEXT 1
void
InitForRead();
void
InitForWrite();
void
CopyContent();
AVFormatContext* g_inputFormatContext = NULL;
AVFormatContext* g_outputFormatContext = NULL;
AVOutputFormat* g_outputFormat = NULL;
AVCodecContext* g_inputCodecContext = NULL;
AVCodecContext* g_outputCodecContext = NULL;
AVStream* g_copyStream = NULL;
char g_filename[] = "../../temp/akiyo.mp4";
char g_outputFilename[] = "../../temp/akiyo.rebuild.mp4";
int
main()
{
printf("Init for read...\n");
InitForRead();
printf("Init for write...\n");
InitForWrite();
printf("Actual copy...\n");
CopyContent();
return 0;
}
void
InitForRead()
{
unsigned int streamNumber = -1;
unsigned int i = 0;
AVDictionary *options;
/* Initialize each output format */
av_register_all();
/* Open input file - FIXME: deprecated */
int ret = 0;
if ((ret = avformat_open_input(&g_inputFormatContext, g_filename, NULL, NULL)) < 0)
{
printf("Container: Cannot open input file\n");
exit(1);
}
/* Let's find out stream's information */
if ((ret = av_find_stream_info(g_inputFormatContext)) < 0)
{
printf("Container: Cannot find stream information\n");
exit(2);
}
/* Extract the audio stream's index */
for (i = 0; i < g_inputFormatContext->nb_streams; i++)
{
if (g_inputFormatContext->streams[i]->codec->codec_type
== AVMEDIA_TYPE_VIDEO)
{
streamNumber = i;
break;
}
}
if (streamNumber == -1)
{
printf("Container: Cannot find audio stream\n");
exit(3);
}
/* CodecContext extraction */
g_inputCodecContext = g_inputFormatContext->streams[streamNumber]->codec;
/* Stream extraction for possible further usage */
g_copyStream = g_inputFormatContext->streams[streamNumber];
/* Try to find out stream's info
* FIXME: this does not work for me!*/
// avformat_find_stream_info(g_inputFormatContext, &options);
}
void
InitForWrite()
{
AVStream* outputStream = NULL;
AVCodec* codec = NULL;
AVFrac tempPts;
int returnCode = 0;
/* After the basic initialization, I must initialize the actual context */
/* This means we need an output context */
/* Open the output format based on the outputFormatName variable */
g_outputFormat = av_guess_format("mp4", NULL, NULL);
if (!g_outputFormat)
{
printf("No suitable output format found\n");
exit(1);
}
g_outputFormat->video_codec = g_inputCodecContext->codec_id;
/* Create the output context */
g_outputFormatContext = avformat_alloc_context();
if (!g_outputFormatContext)
{
printf("I could not open the required output format context\n");
exit(1);
}
/* Assign the output format to the context */
g_outputFormatContext->oformat = g_outputFormat;
/* Assign the output name to the output context */
snprintf(g_outputFormatContext->filename,
sizeof(g_outputFormatContext->filename), "%s", g_filename);
/* Now the output format is OK. I need to add a multimedia stream to it */
outputStream = av_new_stream(g_outputFormatContext, 0);
/* Check the result */
if (!outputStream)
{
printf("I could not allocate the stream\n");
exit(1);
}
/* Start output stream configuration by means of STREAM COPY and CODEC CONTEXT COPY */
if (avcodec_copy_context(outputStream->codec, g_inputCodecContext))
{
printf("Codec context copy error! Exit!\n");
exit(1);
}
outputStream->pts = (AVFrac) {
g_copyStream->pts.val,
(int64_t) g_inputCodecContext->time_base.num,
(int64_t) g_inputCodecContext->time_base.den
};
outputStream->codec->time_base = g_copyStream->time_base;
outputStream->sample_aspect_ratio = g_copyStream->sample_aspect_ratio;
outputStream->codec->sample_aspect_ratio = outputStream->sample_aspect_ratio;
outputStream->codec->codec_tag = 0;
outputStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
/* Setup output parameters */
if (av_set_parameters(g_outputFormatContext, NULL) < 0)
{
printf("Invalid parameters\n");
exit(1);
}
av_dump_format(g_outputFormatContext, 0, g_outputFilename, 1);
if (!(g_outputFormat->flags & AVFMT_NOFILE))
{
if (avio_open(&g_outputFormatContext->pb, g_outputFilename, AVIO_FLAG_WRITE)
< 0)
{
printf("Could not open output file\n");
exit(1);
}
}
/* Write output file header - returns 0 on success (as in our case) */
returnCode = avformat_write_header(g_outputFormatContext, NULL);
}
void
CopyContent()
{
AVPacket readPacket;
AVPacket outputPacket;
AVStream currentStream;
int returnCode = 0;
currentStream = *(g_outputFormatContext->streams[0]);
while (1)
{
returnCode = av_read_frame(g_inputFormatContext, &readPacket);
if (returnCode != 0)
{
/* EOF has been reached - exit from the loop */
av_close_input_file(g_inputFormatContext);
break;
}
/* EOF has NOT been reached, continue */
av_init_packet(&outputPacket);
#if 0
if (g_outputCodecContext->coded_frame->pts != AV_NOPTS_VALUE)
outputPacket.pts= av_rescale_q(g_outputCodecContext->coded_frame->pts,
g_outputCodecContext->time_base, currentStream.time_base);
if (g_outputCodecContext->coded_frame->key_frame)
outputPacket.flags |= AV_PKT_FLAG_KEY;
#endif
outputPacket.pts = readPacket.pts;
outputPacket.dts = readPacket.dts;
outputPacket.stream_index= 0;
outputPacket.data= readPacket.data;
outputPacket.size= readPacket.size;
returnCode = av_write_frame(g_outputFormatContext, &outputPacket);
if (returnCode != 0)
{
printf("Error on write - exiting\n");
exit(1);
}
av_free_packet(&readPacket);
av_free_packet(&outputPacket);
}
/* Close everything */
av_write_trailer(g_outputFormatContext);
if (!(g_outputFormat->flags & AVFMT_NOFILE))
{
/* close the output file */
avio_close(g_outputFormatContext->pb);
}
av_free(g_outputFormatContext);
}
_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user