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

Reply via email to