2016-08-15 3 views
0

디코딩 된 ffmpeg 프레임에 내 자신의 알파 채널을 추가하는 빠른 방법을 찾고 있습니다.디코딩 된 ffmpeg 프레임에 알파 채널 작성

RGB 정보가 포함 된 AVI 파일이 있고 투명 알파 채널 (회색 음영)을 설명하는 동기화 된 비디오 스트림이 있습니다. ffmpeg를 사용하여 AVI 파일을 디코딩하는 동안 내 자신의 알파 정보를 추가하면서 출력 프레임을 RGBA로 변환하려고합니다. 결국, 나는 반투명 한 비디오 스트림을 얻을 것이다.

libswscale 또는 libswresample에 최적화 된 함수가 있습니까? 픽셀을 반복하는 것보다 더 나은 기능을 수행 할 수 있습니까? 나는이 작업을 수행하는 방법에 대한 두 가지 방법을 생각했습니다

void* FFmpegLib_nextFrame_withAlpha(void* _handle, uint8_t* my_alpha_channel) 
{ 
    FFmpegLibHandle* handle = (FFmpegLibHandle*)_handle; 
    AVPacket  packet; 
    int    frameFinished; 

    while(av_read_frame(handle->pFormatCtx, &packet) >= 0) { 
     // Is this a packet from the video stream? 
     if(packet.stream_index==handle->videoStream) { 
      // Decode video frame 
      avcodec_decode_video2(handle->pCodecCtx, handle->pFrame, &frameFinished, &packet); 
      // Did we get a video frame? 
      if(frameFinished) { 
       sws_scale_and_add_alpha 
       (
        handle->sws_ctx, 
        (uint8_t const * const *)handle->pFrame->data, 
        handle->pFrame->linesize, 
        0, 
        handle->pCodecCtx->height, 
        handle->pFrameARGB->data, 
        handle->pFrameARGB->linesize, 
        my_alpha_channel 
       ); 

       return handle->pFrameARGB->data; 
      } 
     } 
    } 

    return NULL; 
} 

답변

1

: 경우 sws_scale_and_add_alpha과 같은 기능이 있다면

기본적으로 나는 같은 기능을 쓸 수 있도록하고 싶습니다. 일반적으로 명령 줄에서 알파 채널을 병합하려는 경우 ffmpegalphamerge 필터를 제공합니다. 그리고 저는 C로 같은 일을 할 수 있다고 확신합니다. 프로그램하기가 어려울지라도 (ffmpeg 소스에 비디오 필터 예제조차도 있습니다.).

두 번째는 AVFrame 구조에 대해 직접 코딩하는 것입니다. AVFrame의 data 필드는 픽셀 정보를 보유합니다. 우리는 알파 채널을 그 안에 넣어야합니다.

// pFrameARGB should have been allocated and of pix_fmt `AV_PIX_FMT_ARGB` 
sws_scale(sws_ctx, pFrame->data, pFrame->linesize, 0, height, pFrameARGB->data, pFrameARGB->linesize); 

통상

AVFrame.data 같은 포장 ARGB에

먼저 변환 압축 영상 프레임은 다중 차원 배열이 다른 평면을 포함한다. 여기서 우리는 평면 ARGB 이미지가 아니라 포장 된 ARGB 이미지를 가지므로 data[0]에는 필요한 모든 픽셀이 포함되어 있습니다.

// cpp example, easy to convert to pure C 
auto p = pFrameARGB->data[0]; 
for (auto i = 0; i < width * height; i++) { 
    auto num = i * sizeof(uint8_t) * 4; 
    auto div_result = std::div(num, width * sizeof(uint8_t) * 4); 

    auto offset = pFrameARGB->linesize * div_result.quot + div_result.rem; 
    p[offset] = my_alpha_channel[i]; 
} 
+0

감사합니다. @halfelf. alphamerge 예제를 보았고 c 구현에 몰래 들어갔다. argb 이미지 픽셀을 반복하면서 실제로 두 번째 프로그래밍 옵션과 비슷합니다. 퍼포먼스의 이유로 한 번에, 알파 채널을 동시에 변환하고 추가 할 sws_scale 대체품을 사용하는 것이 좋습니다. 실제로 결국 저는 RGB 및 알파 채널을 OpenGL 쉐이더 텍스처로 사용하고 있기 때문에 쉐이더 내부에서 색상과 투명도를 결합하는 것이 가장 좋고 가장 유사한 옵션으로 보입니다. –

+0

@Mic 듣기 좋다. 실제로 CUDA에서 비슷한 일을 해왔습니다. 그 성능은 OpenGL만큼 좋다. – halfelf