简体   繁体   中英

libav - avcodec_video_encode2() + fwrite() = non functional files

I can't seem to get anything useful out of the AVPacket.data I'm writing. It's not generating valid video files and they're incredibly small. 4Mb converts to ~300Kb. They're not playing and VLC reports their formats as "undf" (missing headers?). I'm stuck and need some help moving on.

Here's the decode-encode snippet:

// initialize the output context
ctx_out = avformat_alloc_context();

// guess container format
ctx_out->oformat = av_guess_format(NULL, out_file_name, NULL);
snprintf(ctx_out->filename, sizeof(ctx_out->filename), "%s", out_file_name);

// .. stripped: creates video stream, encoder and its codec

if ((res = avio_open2(&ctx_out->pb, out_file_name, AVIO_FLAG_WRITE, NULL, NULL)) != 0) {
  callback_with_error(options, "Failed to open output file for writing (%s)", res);
  return;
}

if ((res = avformat_write_header(ctx_out, NULL)) != 0) {
  callback_with_error(options, "Failed to write output format header (%s)", res);
  return;
}

av_init_packet(&packet);
while (av_read_frame(ctx_format, &packet) >= 0) {
  frame_finished = 0;
  total_size    += packet.size;

  if (packet.stream_index == video_stream) {
    len = avcodec_decode_video2(decoder_video, frame, &frame_finished, &packet);

    if (len < 0) {
      callback_with_error(options, "Frame #%d video decoding error (%d)", current_frame, len);
      return;
    }

    if (frame_finished) {
      len = avcodec_encode_video2(encoder_video, &packet, frame, &frame_finished);

      if (len < 0) {
        continue; // dropped?
      }

      if (frame_finished) {
        if ((res = av_interleaved_write_frame(ctx_out, &packet)) != 0) {
          callback_with_error(options, "Output write error (%d).", res);
          return;
        }
      }
    }

    if (frame_finished) {
      current_frame++;
    }
  } else if (packet.stream_index == audio_stream) {
    // audio
  }
}
av_free_packet(&packet);
av_write_trailer(ctx_out);

for(i = 0; i < ctx_out->nb_streams; i++) {
  av_freep(&ctx_out->streams[i]->codec);
  av_freep(&ctx_out->streams[i]);
}

if (!(ctx_out->oformat->flags & AVFMT_NOFILE)) {
  avio_close(ctx_out->pb);
}
av_free(ctx_out);

I'm hoping there's someone on SO with a bit of knowledge about how LibAV works. I've looked at the examples and read various "articles" about how to use it. So, yeah, I'm stuck for now.

Thanks.

What you're currently doing here is writing the raw content of each video packet to the output file without any sort of container or framing. While this will sort of work for a few special formats (such as MPEG1 video and MP3 audio streams), it does not work in general -- you will need to open up an AVFormatContext (using avformat_write_header ), write each packet to the stream using av_interleaved_write_frame (or av_write_frame if your stream is already properly interleaved), then tie up all the loose ends using av_write_trailer .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM