cth103 / dcpomatic

DCP-o-matic repository: main is the development branch (where v2.16.x versions are being made) and v2.17.x has the v2.17.x "unstable" versions (main is merged there every so often).
https://dcpomatic.com/
GNU General Public License v2.0
101 stars 24 forks source link

Decryption of KDM #26

Open priyankoivan opened 2 months ago

priyankoivan commented 2 months ago

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

cth103 commented 2 months ago

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?

priyankoivan commented 2 months ago

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

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;

} `

cth103 commented 2 months ago

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.

priyankoivan commented 1 month ago

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 ?

priyankoivan commented 1 month ago

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?