簡體   English   中英

ffmpeg mono8 / rgb24圖像到yuv420p到x264的轉換

[英]ffmpeg mono8/rgb24 images to yuv420p to x264 conversion

這可能是一個瑣碎的問題,但是我對這個(ffmpeg)框架感到瘋狂。 基於這篇文章( sws_scale YUV-> RGB失真圖像 )(以及更多搜索),我編寫了以下代碼,將char *指針帶到緩沖區圖像(Mono8或RGB24),然后轉換為YUV420P進行編碼x264。 我必須在兩台PC之間創建此圖像的流。

這是代碼:

bool compressImageX264(Frame *f, int size, char* image){
 codec = avcodec_find_encoder(AV_CODEC_ID_H264);
 if (!codec) {
  std::cout << "Codec not found" << std::endl;
  return false;
 }
 c = avcodec_alloc_context3(codec);
 if (!c) {
  std::cout << "Could not allocate video codec context" << std::endl;
  return false;
 }
 av_opt_set(c->priv_data, "preset", "veryfast", 0);
 av_opt_set(c->priv_data, "tune", "zerolatency", 0);
 c->width = std::stoi(f->width);
 c->height = std::stoi(f->height);
 c->gop_size = 10;
 c->max_b_frames = 1;
 EDIT: c->pix_fmt = AV_PIX_FMT_YUV420P;
 /* open it */
 if (avcodec_open2(c, codec, NULL) < 0) {
  std::cout << "Could not open codec" << std::endl;
  return false;
 }

 AVFrame *avFrameRGB = av_frame_alloc();
 if (!avFrameRGB) {
  std::cout << "Could not allocate video frame" << std::endl;
  return false;
 }
 avFrameRGB->format = std::stoi(f->channels) > 1 ? AV_PIX_FMT_RGB24 : AV_PIX_FMT_GRAY8;
 avFrameRGB->width = c->width;
 avFrameRGB->height = c->height;

 int ret = av_image_alloc(
   avFrameRGB->data, avFrameRGB->linesize,
   avFrameRGB->width, avFrameRGB->height, AVPixelFormat(avFrameRGB->format),
   32);
 if (ret < 0) {
  std::cout << "Could not allocate raw picture buffer" << std::endl;
  return false;
 }

 uint8_t *p = avFrameRGB->data[0];
 for (int i = 0; i < size; i++){
   *p++ = image[i];
 }
 AVFrame* avFrameYUV = av_frame_alloc();
 avFrameYUV->format = AV_PIX_FMT_YUV420P;
 avFrameYUV->width = c->width;
 avFrameYUV->height = c->height;
 ret = av_image_alloc(
    avFrameYUV->data, avFrameYUV->linesize,
    avFrameYUV->width, avFrameYUV->height, AVPixelFormat(avFrameYUV->format),
    32);

 SwsContext *img_convert_ctx = sws_getContext(c->width, c->height, AVPixelFormat(avFrameRGB->format),
   c->width, c->height, AV_PIX_FMT_YUV420P,
   SWS_FAST_BILINEAR, NULL, NULL, NULL);
 ret = sws_scale(img_convert_ctx, 
   avFrameRGB->data, avFrameRGB->linesize,
   0, c->height, 
   avFrameYUV->data, avFrameYUV->linesize);
 sws_freeContext(img_convert_ctx);

 AVPacket pkt;
 av_init_packet(&pkt);
 pkt.data = NULL; // packet data will be allocated by the encoder
 pkt.size = 0;

 avFrameYUV->pts = frameCount; frameCount++; //GLOBAL VARIABLE
 int got_output;
 ret = avcodec_encode_video2(c, &pkt, avFrameYUV, &got_output);
 if (ret < 0) { //<-- Where the code broke
   std::cout << "Error encoding frame" << std::endl;
   return false;
 }
 if (got_output) {
    std::cout << "Write frame " << frameCount - 1 << "(size = " << pkt.size << ")" << std::endl;
    char* buffer = new char[pkt.size];
    for (int i = 0; i < pkt.size; i++){
      buffer[i] = pkt.data[i];
    }
    f->buffer = buffer;
    f->size = std::to_string(pkt.size);
    f->compression = std::string("x264");
    av_free_packet(&pkt);
  }
  return true;
}

我知道這可能效率很低,但是現在我擔心要使其工作。 致電avcodec_encode_video2時失敗。 在控制台上,它顯示以下消息:“輸入圖片寬度(640)大於步幅(320)”。 我認為conversion依是刺客。 但是我不完全了解參數含義,謝謝您的所有幫助。

編輯:好的,我已經建立了“第一個”錯誤。 現在,轉換可以正常工作,並且avcodec_encode_video2返回0。現在的問題是,got_output始終等於零,並且在控制台上沒有任何可用。

我找到了這個解決方案: 在iOS上使用AVCodec將原始YUV420P編碼為h264

我可以以同步方式調用編碼嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM