cth103/dcpomatic

Decryption of KDM

priyankoivan opened this issue · 5 comments

Hello,
I created a mxf player in cpp but I was not able to play an encrypted mxf file. i saw that dcp o matic player played an encrypted mxf file using kdm. i also saw the source code of the dcp-o-matic player where the decryption was done using libdcp but I was not able to understand that and was not able to integrate it into my mxf player.
please help me a little bit so that I can add decryption part to my mxf player

I guess there's two parts to it really, extracting the MXF key from the
KDM, and then using that key to decrypt the MXF (via asdcplib)... Are
you using asdcplib also? Which part are you stuck on?

Thank you .
i stack on decryption of MXF using key. i also share my mxf player code . but I not able to understand where and how I decrypt the MXF .

`
#include
#include

extern "C" {
#include <SDL.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/avutil.h>
#include <libavutil/opt.h>
}

int main(int argc, char* argv[]) {

int frameNumber = 0;

if (argc < 2) {
    std::cerr << "Usage: " << argv[0] << " <input file>" << std::endl;
    return -1;
}

const char* filename = argv[1];

// Initialize FFmpeg
avformat_network_init();

std::cout<<"runhere 1 \n";
AVFormatContext* pFormatCtx = nullptr;
if (avformat_open_input(&pFormatCtx, filename, nullptr, nullptr) != 0) {
    std::cerr << "Could not open file: " << filename << std::endl;
    return -1;
}
std::cout<<"runhere 2 \n"<<pFormatCtx<<std::endl;

if (avformat_find_stream_info(pFormatCtx, nullptr) < 0) {
    std::cerr << "Could not find stream information" << std::endl;
    avformat_close_input(&pFormatCtx);
    return -1;
}
std::cout<<"runhere 3 \n";
// Find the first video stream
int videoStream = -1;
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) {
    if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        videoStream = i;
        break;
    }
     std::cout<<"videoStream-> \n"<<videoStream<<std::endl;
}

std::cout<<"runhere 4 \n";
if (videoStream == -1) {
std::cerr << "Could not find video stream" << std::endl;
avformat_close_input(&pFormatCtx);
return -1;
}

AVCodecParameters* pCodecParams = pFormatCtx->streams[videoStream]->codecpar;
const AVCodec* pCodec = avcodec_find_decoder(pCodecParams->codec_id);
if (!pCodec) {
    std::cerr << "Unsupported codec!" << std::endl;
    avformat_close_input(&pFormatCtx);
    return -1;
}

AVCodecContext* pCodecCtx = avcodec_alloc_context3(pCodec);
if (avcodec_parameters_to_context(pCodecCtx, pCodecParams) < 0) {
    std::cerr << "Couldn't copy codec parameters to codec context" << std::endl;
    avcodec_free_context(&pCodecCtx);
    avformat_close_input(&pFormatCtx);
    return -1;
}

if (avcodec_open2(pCodecCtx, pCodec, nullptr) < 0) {
    std::cerr << "Could not open codec" << std::endl;
    avcodec_free_context(&pCodecCtx);
    avformat_close_input(&pFormatCtx);
    return -1;
}

// Initialize SDL
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
    std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
    avcodec_free_context(&pCodecCtx);
    avformat_close_input(&pFormatCtx);
    return -1;
}

SDL_Window* window = SDL_CreateWindow("MXF Player", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, pCodecCtx->width, pCodecCtx->height, SDL_WINDOW_SHOWN);
if (!window) {
    std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
    SDL_Quit();
    avcodec_free_context(&pCodecCtx);
    avformat_close_input(&pFormatCtx);
    return -1;
}

SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 0);
SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, pCodecCtx->width, pCodecCtx->height);

AVFrame* pFrame = av_frame_alloc();
AVFrame* pFrameYUV = av_frame_alloc();
uint8_t* buffer = nullptr;
int numBytes = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 32);
buffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t));
// av_image_fill_arrays(pFrameYUV->data, pFrameYUV->linesize, buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height, 32);

// AVCodecContext* pCodecCtx2=pCodecCtx;

struct SwsContext* sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
                                            pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P,
                                            SWS_BILINEAR, nullptr, nullptr, nullptr);

int response;
AVPacket packet;



while (av_read_frame(pFormatCtx, &packet) >= 0) {
    if (packet.stream_index == videoStream) {
        response = avcodec_send_packet(pCodecCtx, &packet);
        avcodec_send_packet(pCodecCtx,&packet);
        if (response < 0) {
            std::cerr << "Error while sending a packet to the decoder: " << response << std::endl;
            break;
        }
        // SaveFrameAsImage(*pCodecCtx,frameNumber++);


        while (response >= 0) {
            response = avcodec_receive_frame(pCodecCtx, pFrame);
            if (response == AVERROR(EAGAIN) || response == AVERROR_EOF) {
                break;
            } else if (response < 0) {
                std::cerr << "Error while receiving a frame from the decoder: " << response << std::endl;
                return -1;
            }

            sws_scale(sws_ctx, (uint8_t const* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height,
                      pFrameYUV->data, pFrameYUV->linesize);
        
            SDL_UpdateYUVTexture(texture, nullptr, pFrameYUV->data[0], pFrameYUV->linesize[0],
                                 pFrameYUV->data[1], pFrameYUV->linesize[1],
                                 pFrameYUV->data[2], pFrameYUV->linesize[2]);

            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, texture, nullptr, nullptr);
            SDL_RenderPresent(renderer);

            
            
            SDL_Event e;
            while (SDL_PollEvent(&e)) {
                if (e.type == SDL_QUIT) {
                    av_packet_unref(&packet);
                    goto end;
                }
            }
        }
    }
    av_packet_unref(&packet);
}

end:
av_frame_free(&pFrame);
av_frame_free(&pFrameYUV);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
av_free(buffer);
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();

return 0;

}
`

Are you working with MPEG2 MXFs? If so, the v1.9.x branch of libdcp is probably more informative. I think you basically need to extract and decrypt blocks of MPEG2 with asdcplib and then feed them to `ffmpeg.

I am working with jpeg2000 MXF.
i want use nvJPEG2000 not ffmpeg .
is it possible decrypt blocks of jpeg2000 with asdcplib and feed them to nvJPEG2000 ?

hello,
I need help from you on how I extract and decrypt blocks of jpeg2000 with asdcplib . can you give me the file name of the source code(DCP-o-matic) where asdcplib does decryption?