Ffmpeg解码器yuv420p

时间:2015-12-04 16:13:00

标签: c++ video ffmpeg yuv

我使用ffmpeg处理视频播放器yuv420p,但它无法正常工作,我无法找到原因。我整整一个星期都在上面......

所以我有一个测试,只是解码一些帧并读取它,但输出总是不同的,这真的很奇怪。

我使用了一个视频(mp4 yuv420p),每个帧中都有一个黑色像素:

对于视频,请将http://sendvid.com/b1sgf8r1放在http://www.telechargerunevideo.com/en/

等网站上

VideoContext 只是一个小结构:

struct  VideoContext {

unsigned int      currentFrame;
std::size_t       size;
int               width;
int               height;
bool              pause;
AVFormatContext*  formatCtx;
AVCodecContext*   codecCtxOrig;
AVCodecContext*   codecCtx;
int               streamIndex;
};

所以我有一个计算黑色像素数的功能:

std::size_t  checkFrameNb(const AVFrame* frame) {

    std::size_t  nb = 0;

    for (int y = 0; y < frame->height; ++y) {
      for (int x = 0 ; x < frame->width; ++x) {

        if (frame->data[0][(y * frame->linesize[0]) + x] == BLACK_FRAME.y
            && frame->data[1][(y / 2 * frame->linesize[1]) + x / 2] == BLACK_FRAME.u
            && frame->data[2][(y / 2 * frame->linesize[2]) + x / 2] == BLACK_FRAME.v)
          ++nb;
      }
    }
    return nb;
  }

这就是我解码一帧的方式:

const AVFrame*  VideoDecoder::nextFrame(entities::VideoContext& context) {

  int frameFinished;
  AVPacket packet;

  // Allocate video frame
  AVFrame*  frame = av_frame_alloc();
  if(frame == nullptr)
    throw;

  // Initialize frame->linesize
  avpicture_fill((AVPicture*)frame, nullptr, AV_PIX_FMT_YUV420P, context.width, context.height);

  while(av_read_frame(context.formatCtx, &packet) >= 0) {

    // Is this a packet from the video stream?
    if(packet.stream_index == context.streamIndex) {
      // Decode video frame
      avcodec_decode_video2(context.codecCtx, frame, &frameFinished, &packet);

      // Did we get a video frame?
      if(frameFinished) {

        // Free the packet that was allocated by av_read_frame
        av_free_packet(&packet);
        ++context.currentFrame;
        return frame;
      }
    }
  }

  // Free the packet that was allocated by av_read_frame
  av_free_packet(&packet);
  throw core::GlobalException("nextFrame", "Frame decode failed");
}

已经出现了问题?

也许上下文初始化会很有用:

entities::VideoContext  VideoLoader::loadVideoContext(const char* file,
                                                      const int width,
                                                      const int height) {

  entities::VideoContext  context;

  // Register all formats and codecs
  av_register_all();

  context.formatCtx = avformat_alloc_context();


  // Open video file
  if(avformat_open_input(&context.formatCtx, file, nullptr, 0) != 0)
    throw; // Couldn't open file

  // Retrieve stream information
  if(avformat_find_stream_info(context.formatCtx, nullptr) > 0)
    throw; // Couldn't find stream information

  // Dump information about file onto standard error
  //av_dump_format(m_formatCtx, 0, file, 1);


  // Find the first video stream because we don't need more
  for(unsigned int i = 0; i < context.formatCtx->nb_streams; ++i)
    if(context.formatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
      context.streamIndex = i;
      context.codecCtx = context.formatCtx->streams[i]->codec;
      break;
    }
  if(context.codecCtx == nullptr)
    throw; // Didn't find a video stream


  // Find the decoder for the video stream
  AVCodec*  codec = avcodec_find_decoder(context.codecCtx->codec_id);
  if(codec == nullptr)
    throw; // Codec not found
  // Copy context
  if ((context.codecCtxOrig = avcodec_alloc_context3(codec)) == nullptr)
    throw;
  if(avcodec_copy_context(context.codecCtxOrig, context.codecCtx) != 0)
    throw; // Error copying codec context
  // Open codec
  if(avcodec_open2(context.codecCtx, codec, nullptr) < 0)
    throw; // Could not open codec

  context.currentFrame = 0;
  decoder::VideoDecoder::setVideoSize(context);
  context.pause = false;
  context.width = width;
  context.height = height;

  return std::move(context);
}

我知道这不是一小段代码,如果你有任何想法也可以让一个例子更简洁,继续。

如果有人对这个问题有所了解,那就有我的输出:

9 - 10 - 12 - 4 - 10 - 14 - 11 - 8 - 9 - 10

但我想:

1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10

PS: 获取fps和视频大小是opencv的复制粘贴代码

0 个答案:

没有答案