int write_volumeindex(opendcp_t *opendcp) { xmlIndentTreeOutput = 1; xmlDocPtr doc; xmlTextWriterPtr xml; int rc; dcp_log(LOG_INFO,"Writing VOLINDEX file %.256s",opendcp->volindex.filename); /* create XML document */ xml = xmlNewTextWriterDoc(&doc,0); /* volumeindex XML Start */ rc = xmlTextWriterStartDocument(xml, NULL, XML_ENCODING, NULL); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterStartDocument failed"); return DCP_FATAL; } xmlTextWriterStartElement(xml, BAD_CAST "VolumeIndex"); xmlTextWriterWriteAttribute(xml, BAD_CAST "xmlns", BAD_CAST NS_AM[opendcp->ns]); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Index","%d",1); xmlTextWriterEndElement(xml); rc = xmlTextWriterEndDocument(xml); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterEndDocument failed %s",opendcp->volindex.filename); return DCP_FATAL; } xmlFreeTextWriter(xml); xmlSaveFormatFile(opendcp->volindex.filename, doc, 1); xmlFreeDoc(doc); return DCP_SUCCESS; }
int xmlsec_init() { /* init libxml lib */ xmlInitParser(); xmlIndentTreeOutput = 1; LIBXML_TEST_VERSION xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; xmlSubstituteEntitiesDefault(1); /* init xmlsec lib */ if(xmlSecInit() < 0) { dcp_log(OPENDCP_ERROR,"Error: xmlsec initialization failed."); return(OPENDCP_ERROR); } /* Check loaded library version */ if(xmlSecCheckVersion() != 1) { dcp_log(OPENDCP_ERROR, "Error: loaded xmlsec library version is not compatible."); return(OPENDCP_ERROR); } /* Init crypto library */ if(xmlSecCryptoAppInit(NULL) < 0) { dcp_log(OPENDCP_ERROR, "Error: crypto initialization failed."); return(OPENDCP_ERROR); } /* Init xmlsec-crypto library */ if(xmlSecCryptoInit() < 0) { dcp_log(OPENDCP_ERROR, "Error: xmlsec-crypto initialization failed."); return(OPENDCP_ERROR); } return(OPENDCP_NO_ERROR); }
int xmlsec_verify_init() { /* init libxml lib */ xmlInitParser(); xmlIndentTreeOutput = 1; LIBXML_TEST_VERSION xmlLoadExtDtdDefaultValue = XML_DETECT_IDS | XML_COMPLETE_ATTRS; xmlSubstituteEntitiesDefault(1); /* init xmlsec lib */ if(xmlSecInit() < 0) { dcp_log(DCP_FATAL,"xmlsec initialization failed"); return(DCP_FATAL); } /* Check loaded library version */ if(xmlSecCheckVersion() != 1) { dcp_log(DCP_FATAL, "loaded xmlsec library version is not compatible"); return(DCP_FATAL); } /* Init crypto library */ if(xmlSecCryptoAppInit(NULL) < 0) { dcp_log(DCP_FATAL, "crypto initialization failed"); return(DCP_FATAL); } /* Init xmlsec-crypto library */ if(xmlSecCryptoInit() < 0) { dcp_log(DCP_FATAL, "xmlsec-crypto initialization failed"); return(DCP_FATAL); } return(DCP_SUCCESS); }
int validate_reel(opendcp_t *opendcp, cpl_t *cpl, int reel) { int d = 0; int x,a; int picture = 0; int duration_mismatch = 0; dcp_log(LOG_INFO,"Validating Reel %d\n",reel+1); a = cpl->reel[reel].asset_count; /* check if reel has a picture track */ for (x=0;x<a;x++) { if (cpl->reel[reel].asset[x].essence_class == ACT_PICTURE) { picture++; } } if (picture < 1) { dcp_log(LOG_ERROR,"Reel %d has no picture track",reel); return DCP_NO_PICTURE_TRACK; } else if (picture > 1) { dcp_log(LOG_ERROR,"Reel %d has multiple picture tracks",reel); return DCP_MULTIPLE_PICTURE_TRACK; } d = cpl->reel[reel].asset[0].duration; /* check durations */ for (x=0;x<a;x++) { if (cpl->reel[reel].asset[x].duration) { if (cpl->reel[reel].asset[x].duration != d) { duration_mismatch = 1; if (cpl->reel[reel].asset[x].duration < d) { d = cpl->reel[reel].asset[x].duration; } } } else { dcp_log(LOG_ERROR,"Asset %s has no duration",cpl->reel[reel].asset[x].filename); return DCP_ASSET_NO_DURATION; } } if (duration_mismatch) { dcp_log(LOG_WARN,"Asset duration mismatch, adjusting all durations to shortest asset duration of %d frames", d); for (x=0;x<a;x++) { cpl->reel[reel].asset[x].duration = d; } } return DCP_SUCCESS; }
int build_filelist(char *input, char *output, filelist_t *filelist, int file_type) { struct dirent **files; int x = 0; struct stat st_in; if (stat(input, &st_in) != 0 ) { dcp_log(LOG_ERROR,"Could not open input file %s",input); return DCP_FATAL; } filelist->file_count = scandir(input,&files,(void *)file_filter,alphasort); if (filelist->file_count) { for (x=0;x<filelist->file_count;x++) { sprintf(filelist->in[x],"%s/%s",input,files[x]->d_name); if (file_type == J2K_INPUT) { sprintf(filelist->out[x],"%s/%s.j2c",output,get_basename(files[x]->d_name)); } } } for (x=0;x<filelist->file_count;x++) { free(files[x]); } free(files); return DCP_SUCCESS; }
int get_file_count(char *path, int file_type) { struct dirent **files; struct stat st_in; int x,count; filter = file_type; if (stat(path, &st_in) != 0 ) { dcp_log(LOG_ERROR,"Could not open input file %s",path); return DCP_FATAL; } if (S_ISDIR(st_in.st_mode)) { count = scandir(path,&files,(void *)file_filter,alphasort); for (x=0;x<count;x++) { free(files[x]); } free(files); } else { count = 1; } return count; }
/* convert opendcp to openjpeg image format */ int odcp_to_opj(odcp_image_t *odcp, opj_image_t **opj_ptr) { OPJ_COLOR_SPACE color_space; opj_image_cmptparm_t cmptparm[3]; opj_image_t *opj = NULL; int j,size; color_space = CLRSPC_SRGB; /* initialize image components */ memset(&cmptparm[0], 0, odcp->n_components * sizeof(opj_image_cmptparm_t)); for (j = 0;j < odcp->n_components;j++) { cmptparm[j].w = odcp->w; cmptparm[j].h = odcp->h; cmptparm[j].prec = odcp->precision; cmptparm[j].bpp = odcp->bpp; cmptparm[j].sgnd = odcp->signed_bit; cmptparm[j].dx = odcp->dx; cmptparm[j].dy = odcp->dy; } /* create the image */ opj = opj_image_create(odcp->n_components, &cmptparm[0], color_space); if(!opj) { dcp_log(LOG_ERROR,"Failed to create image"); return OPENDCP_ERROR; } /* set image offset and reference grid */ opj->x0 = odcp->x0; opj->y0 = odcp->y0; opj->x1 = odcp->x1; opj->y1 = odcp->y1; size = odcp->w * odcp->h; memcpy(opj->comps[0].data,odcp->component[0].data,size*sizeof(int)); memcpy(opj->comps[1].data,odcp->component[1].data,size*sizeof(int)); memcpy(opj->comps[2].data,odcp->component[2].data,size*sizeof(int)); *opj_ptr = opj; return OPENDCP_NO_ERROR; }
int xml_verify(char *filename) { xmlSecDSigCtxPtr dsig_ctx = NULL; xmlDocPtr doc = NULL; xmlNodePtr root_node; xmlNodePtr sign_node; xmlNodePtr cert_node; xmlNodePtr x509d_node; xmlNodePtr cur_node; int result = DCP_FATAL; xmlSecKeysMngrPtr key_manager; char cert[5000]; int cert_l; xmlsec_verify_init(); /* load doc file */ doc = xmlParseFile(filename); if (doc == NULL) { dcp_log(LOG_ERROR, "unable to parse file %s", filename); goto done; } /* find root node */ root_node = xmlDocGetRootElement(doc); if (root_node == NULL){ dcp_log(LOG_ERROR, "unable to find root node"); goto done; } /* find signature node */ sign_node = xmlSecFindNode(root_node, xmlSecNodeSignature, xmlSecDSigNs); if(sign_node == NULL) { dcp_log(LOG_ERROR, "signature node not found"); goto done; } /* create keys manager */ key_manager = load_certificates(); if (key_manager == NULL) { dcp_log(LOG_ERROR,"create key manager failed"); goto done; } /* find certificates */ cur_node = sign_node; while (x509d_node = xmlSecFindNode(cur_node, xmlSecNodeX509Data, xmlSecDSigNs)) { cert_node = xmlSecFindNode(x509d_node, xmlSecNodeX509Certificate, xmlSecDSigNs); if(cert_node == NULL) { dcp_log(LOG_ERROR, "X509certficate node not found"); goto done; } sprintf(cert,"-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----\n",xmlNodeGetContent(cert_node)); cert_l = strlen(cert); if (xmlSecCryptoAppKeysMngrCertLoadMemory(key_manager, cert, cert_l, xmlSecKeyDataFormatPem, xmlSecKeyDataTypeTrusted) < 0) { dcp_log(LOG_ERROR, "could read X509certificate node value"); goto done; } cur_node = xmlNextElementSibling(x509d_node); } /* create signature context */ dsig_ctx = xmlSecDSigCtxCreate(key_manager); if (dsig_ctx == NULL) { dcp_log(LOG_ERROR,"create signature opendcp failed"); goto done; } /* sign the template */ if (xmlSecDSigCtxVerify(dsig_ctx, sign_node) < 0) { dcp_log(LOG_ERROR,"signature verify failed"); goto done; } if (dsig_ctx->status != xmlSecDSigStatusSucceeded) { dcp_log(LOG_ERROR,"signature validation failed"); goto done; } /* success */ result = 0; done: /* destroy keys manager */ xmlSecKeysMngrDestroy(key_manager); /* destroy signature context */ if(dsig_ctx != NULL) { xmlSecDSigCtxDestroy(dsig_ctx); } /* destroy xml doc */ if(doc != NULL) { xmlFreeDoc(doc); } xmlsec_close(); return(result); }
int write_dsig_template(opendcp_t *opendcp, xmlTextWriterPtr xml) { BIO *bio[3]; X509 *x[3]; X509_NAME *issuer_xn[3]; X509_NAME *subject_xn[3]; char *cert[3]; int i; dcp_log(LOG_DEBUG, "xml_sign: write_dsig_template"); if (opendcp->xml_signature.use_external) { /* read certificates from file */ FILE *cp; cp = fopen(opendcp->xml_signature.signer,"rb"); if (cp) { x[0] = PEM_read_X509(cp,NULL,NULL,NULL); fclose(cp); } cp = fopen(opendcp->xml_signature.ca,"rb"); if (cp) { x[1] = PEM_read_X509(cp,NULL,NULL,NULL); fclose(cp); } cp = fopen(opendcp->xml_signature.root,"rb"); if (cp) { x[2] = PEM_read_X509(cp,NULL,NULL,NULL); fclose(cp); } cert[0] = strip_cert_file(opendcp->xml_signature.signer); cert[1] = strip_cert_file(opendcp->xml_signature.ca); cert[2] = strip_cert_file(opendcp->xml_signature.root); } else { /* read certificate from memory */ bio[0] = BIO_new_mem_buf((void *)opendcp_signer_cert, -1); bio[1] = BIO_new_mem_buf((void *)opendcp_ca_cert, -1); bio[2] = BIO_new_mem_buf((void *)opendcp_root_cert, -1); /* save a copy with the BEGIN/END stripped */ cert[0] = strip_cert(opendcp_signer_cert); cert[1] = strip_cert(opendcp_ca_cert); cert[2] = strip_cert(opendcp_root_cert); for (i=0;i<3;i++) { if (bio[i] == NULL) { dcp_log(LOG_ERROR,"Could allocate certificate from memory"); return OPENDCP_ERROR; } x[i] = PEM_read_bio_X509(bio[i], NULL, NULL, NULL); if (!BIO_set_close(bio[i], BIO_NOCLOSE)) { dcp_log(LOG_ERROR,"Could set BIO close flag"); return OPENDCP_ERROR; } if (x[i] == NULL) { dcp_log(LOG_ERROR,"Could not read certificate"); return OPENDCP_ERROR; } } } /* get issuer, subject */ for (i=0;i<3;i++) { issuer_xn[i] = X509_get_issuer_name(x[i]); subject_xn[i] = X509_get_subject_name(x[i]); if (issuer_xn[i] == NULL || subject_xn[i] == NULL) { dcp_log(LOG_ERROR,"Could not parse certificate data"); return OPENDCP_ERROR; } } dcp_log(LOG_DEBUG, "xml_sign: write_dsig_template: start signer"); /* signer */ xmlTextWriterStartElement(xml, BAD_CAST "Signer"); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509Data", NULL); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509IssuerSerial", NULL); xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509IssuerName", NULL, "%s", dn_oneline(issuer_xn[0])); xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509SerialNumber", NULL, "%ld", ASN1_INTEGER_get(X509_get_serialNumber(x[0]))); xmlTextWriterEndElement(xml); xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509SubjectName", NULL, "%s", dn_oneline(subject_xn[0])); xmlTextWriterEndElement(xml); xmlTextWriterEndElement(xml); /* template */ xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "Signature", NULL); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "SignedInfo", NULL); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "CanonicalizationMethod", NULL); xmlTextWriterWriteAttribute(xml, BAD_CAST "Algorithm", BAD_CAST DS_CMA); xmlTextWriterEndElement(xml); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "SignatureMethod", NULL); xmlTextWriterWriteAttribute(xml, BAD_CAST "Algorithm", BAD_CAST DS_SMA[opendcp->ns]); xmlTextWriterEndElement(xml); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "Reference", NULL); xmlTextWriterWriteAttribute(xml, BAD_CAST "URI", BAD_CAST NULL); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST"Transforms", NULL); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "Transform", NULL); xmlTextWriterWriteAttribute(xml, BAD_CAST "Algorithm", BAD_CAST DS_TMA); xmlTextWriterEndElement(xml); xmlTextWriterEndElement(xml); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "DigestMethod", NULL); xmlTextWriterWriteAttribute(xml, BAD_CAST "Algorithm", BAD_CAST DS_DMA); xmlTextWriterEndElement(xml); xmlTextWriterWriteElementNS(xml, BAD_CAST "dsig", BAD_CAST "DigestValue", NULL, BAD_CAST ""); xmlTextWriterEndElement(xml); xmlTextWriterEndElement(xml); xmlTextWriterWriteElementNS(xml, BAD_CAST "dsig", BAD_CAST "SignatureValue", NULL, BAD_CAST ""); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "KeyInfo", NULL); for (i=0;i<3;i++) { xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509Data", NULL); xmlTextWriterStartElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509IssuerSerial", NULL); xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509IssuerName", NULL, "%s", dn_oneline(issuer_xn[i])); xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509SerialNumber", NULL, "%ld", ASN1_INTEGER_get(X509_get_serialNumber(x[i]))); xmlTextWriterEndElement(xml); xmlTextWriterWriteFormatElementNS(xml, BAD_CAST "dsig", BAD_CAST "X509Certificate", NULL, "%s", cert[i]); xmlTextWriterEndElement(xml); } xmlTextWriterEndElement(xml); /* KeyInfo */ xmlTextWriterEndElement(xml); /* Signature */ if (subject_xn[0]) { free(subject_xn[0]); } for (i=0;i<3;i++) { if (issuer_xn[i]) { free(issuer_xn[i]); } } return OPENDCP_NO_ERROR; }
int xml_sign(opendcp_t *opendcp, char *filename) { xmlSecDSigCtxPtr dsig_ctx = NULL; xmlDocPtr doc = NULL; xmlNodePtr root_node; xmlNodePtr sign_node; FILE *fp; int result = OPENDCP_ERROR; xmlSecKeysMngrPtr key_manager = NULL; dcp_log(LOG_DEBUG, "xml_sign: xmlsec_init"); xmlsec_init(); /* load doc file */ dcp_log(LOG_DEBUG, "xml_sign: parse file"); doc = xmlParseFile(filename); if (doc == NULL) { dcp_log(OPENDCP_ERROR, "Error: unable to parse file %s", filename); goto done; } /* find root node */ root_node = xmlDocGetRootElement(doc); if (root_node == NULL){ dcp_log(OPENDCP_ERROR, "Error: unable to find root node"); goto done; } /* find signature node */ sign_node = xmlSecFindNode(root_node, xmlSecNodeSignature, xmlSecDSigNs); if(sign_node == NULL) { fprintf(stderr, "Error: start node not found"); goto done; } /* create keys manager */ key_manager = load_certificates_sign(opendcp); if (key_manager == NULL) { fprintf(stderr,"Error: failed to create key manager\n"); goto done; } /* create signature opendcp */ dsig_ctx = xmlSecDSigCtxCreate(key_manager); if(dsig_ctx == NULL) { fprintf(stderr,"Error: failed to create signature opendcp\n"); goto done; } /* sign the template */ if(xmlSecDSigCtxSign(dsig_ctx, sign_node) < 0) { fprintf(stderr,"Error: signature failed\n"); goto done; } /* open xml file */ fp = fopen(filename,"wb"); if (fp == NULL) { fprintf(stderr,"Error: could not open output file\n"); goto done; } /* write the xml file */ if (xmlDocDump(fp, doc) < 0) { fprintf(stderr,"Error: writing XML document failed\n"); goto done; } /* close the file */ fclose(fp); /* success */ result = 0; done: /* destroy keys manager */ xmlSecKeysMngrDestroy(key_manager); /* destroy signature context */ if(dsig_ctx != NULL) { xmlSecDSigCtxDestroy(dsig_ctx); } /* destroy xml doc */ if(doc != NULL) { xmlFreeDoc(doc); } xmlsec_close(); return(result); }
int main (int argc, char **argv) { int c,j; int reel_count=0; int height = 0; int width = 0; char buffer[80]; opendcp_t *opendcp; asset_list_t reel_list[MAX_REELS]; if ( argc <= 1 ) { dcp_usage(); } opendcp = create_opendcp(); /* parse options */ while (1) { static struct option long_options[] = { {"annotation", required_argument, 0, 'a'}, {"base", required_argument, 0, 'b'}, {"digest", no_argument, 0, 'd'}, {"duration", required_argument, 0, 'n'}, {"entry", required_argument, 0, 'e'}, {"help", no_argument, 0, 'h'}, {"issuer", required_argument, 0, 'i'}, {"kind", required_argument, 0, 'k'}, {"log_level", required_argument, 0, 'l'}, {"rating", required_argument, 0, 'm'}, {"reel", required_argument, 0, 'r'}, {"title", required_argument, 0, 't'}, {"root", required_argument, 0, '1'}, {"ca", required_argument, 0, '2'}, {"signer", required_argument, 0, '3'}, {"privatekey", required_argument, 0, 'p'}, {"sign", no_argument, 0, 's'}, {"height", required_argument, 0, 'y'}, {"width", required_argument, 0, 'x'}, {"version", no_argument, 0, 'v'}, {0, 0, 0, 0} }; /* getopt_long stores the option index here. */ int option_index = 0; c = getopt_long (argc, argv, "a:b:e:svdhi:k:r:l:m:n:t:x:y:p:1:2:3:", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; switch (c) { case 0: /* If this option set a flag, do nothing else now. */ if (long_options[option_index].flag != 0) break; break; case 'a': sprintf(opendcp->xml.annotation,"%.128s",optarg); break; case 'b': sprintf(opendcp->xml.basename,"%.80s",optarg); break; case 'd': opendcp->xml.digest_flag = 1; break; case 'e': opendcp->entry_point = atoi(optarg); break; case 'h': dcp_usage(); break; case 'i': sprintf(opendcp->xml.issuer,"%.80s",optarg); break; case 'k': sprintf(opendcp->xml.kind,"%.15s",optarg); break; case 'l': opendcp->log_level = atoi(optarg); break; case 'm': if ( !strcmp(optarg,"G") || !strcmp(optarg,"PG") || !strcmp(optarg,"PG-13") || !strcmp(optarg,"R") || !strcmp(optarg,"NC-17") ) { sprintf(opendcp->xml.rating,"%.5s",optarg); } else { sprintf(buffer,"Invalid rating %s\n",optarg); dcp_fatal(opendcp,buffer); } break; case 'n': opendcp->duration = atoi(optarg); break; case 'r': j = 0; optind--; while ( optind<argc && strncmp("-",argv[optind],1) != 0) { sprintf(reel_list[reel_count].asset_list[j++].filename,"%s",argv[optind++]); } reel_list[reel_count++].asset_count = j--; break; #ifdef XMLSEC case 's': opendcp->xml_signature.sign = 1; break; #endif case 't': sprintf(opendcp->xml.title,"%.80s",optarg); break; case 'x': width = atoi(optarg); break; case 'y': height = atoi(optarg); break; case '1': opendcp->xml_signature.root = optarg; opendcp->xml_signature.use_external = 1; break; case '2': opendcp->xml_signature.ca = optarg; opendcp->xml_signature.use_external = 1; break; case '3': opendcp->xml_signature.signer = optarg; opendcp->xml_signature.use_external = 1; break; case 'p': opendcp->xml_signature.private_key = optarg; opendcp->xml_signature.use_external = 1; break; case 'v': version(); break; default: dcp_usage(); } } /* set log level */ dcp_set_log_level(opendcp->log_level); if (opendcp->log_level > 0) { printf("\nOpenDCP XML %s %s\n\n",OPENDCP_VERSION,OPENDCP_COPYRIGHT); } if (reel_count < 1) { dcp_fatal(opendcp,"No reels supplied"); } /* check cert files */ if (opendcp->xml_signature.sign && opendcp->xml_signature.use_external == 1) { FILE *tp; if (opendcp->xml_signature.root) { tp = fopen(opendcp->xml_signature.root,"rb"); if (tp) { fclose(tp); } else { dcp_fatal(opendcp,"Could not read root certificate"); } } else { dcp_fatal(opendcp,"XML digital signature certifcates enabled, but root certificate file not specified"); } if (opendcp->xml_signature.ca) { tp = fopen(opendcp->xml_signature.ca,"rb"); if (tp) { fclose(tp); } else { dcp_fatal(opendcp,"Could not read ca certificate"); } } else { dcp_fatal(opendcp,"XML digital signature certifcates enabled, but ca certificate file not specified"); } if (opendcp->xml_signature.signer) { tp = fopen(opendcp->xml_signature.signer,"rb"); if (tp) { fclose(tp); } else { dcp_fatal(opendcp,"Could not read signer certificate"); } } else { dcp_fatal(opendcp,"XML digital signature certifcates enabled, but signer certificate file not specified"); } if (opendcp->xml_signature.private_key) { tp = fopen(opendcp->xml_signature.private_key,"rb"); if (tp) { fclose(tp); } else { dcp_fatal(opendcp,"Could not read private key file"); } } else { dcp_fatal(opendcp,"XML digital signature certifcates enabled, but private key file not specified"); } } /* set aspect ratio override */ if (width || height) { if (!height) { dcp_fatal(opendcp,"You must specify height, if you specify width"); } if (!width) { dcp_fatal(opendcp,"You must specify widht, if you specify height"); } sprintf(opendcp->xml.aspect_ratio,"%d %d",width,height); } /* add pkl to the DCP (only one PKL currently support) */ add_pkl(opendcp); /* add cpl to the DCP/PKL (only one CPL currently support) */ add_cpl(opendcp, &opendcp->pkl[0]); /* Add and validate reels */ for (c = 0;c<reel_count;c++) { if (add_reel(opendcp, &opendcp->pkl[0].cpl[0], reel_list[c]) != DCP_SUCCESS) { sprintf(buffer,"Could not add reel %d to DCP\n",c+1); dcp_fatal(opendcp,buffer); } if (validate_reel(opendcp, &opendcp->pkl[0].cpl[0], c) != DCP_SUCCESS) { sprintf(buffer,"Could validate reel %d\n",c+1); dcp_fatal(opendcp,buffer); } } /* set ASSETMAP/VOLINDEX path */ if (opendcp->ns == XML_NS_SMPTE) { sprintf(opendcp->assetmap.filename,"%s","ASSETMAP.xml"); sprintf(opendcp->volindex.filename,"%s","VOLINDEX.xml"); } else { sprintf(opendcp->assetmap.filename,"%s","ASSETMAP"); sprintf(opendcp->volindex.filename,"%s","VOLINDEX"); } /* Write XML Files */ if (write_cpl(opendcp, &opendcp->pkl[0].cpl[0]) != DCP_SUCCESS) dcp_fatal(opendcp,"Writing composition playlist failed"); if (write_pkl(opendcp, &opendcp->pkl[0]) != DCP_SUCCESS) dcp_fatal(opendcp,"Writing packing list failed"); if (write_volumeindex(opendcp) != DCP_SUCCESS) dcp_fatal(opendcp,"Writing volume index failed"); if (write_assetmap(opendcp) != DCP_SUCCESS) dcp_fatal(opendcp,"Writing asset map failed"); dcp_log(LOG_INFO,"DCP Complete"); if (opendcp->log_level > 0) { printf("\n"); } delete_opendcp(opendcp); exit(0); }
void print_bmp_header(bmp_image_t *bmp) { dcp_log(LOG_DEBUG,"%-15.15s: file size: %d","read_bmp",bmp->file.size); dcp_log(LOG_DEBUG,"%-15.15s: data offset: %d","read_bmp",bmp->file.offset); dcp_log(LOG_DEBUG,"%-15.15s: header_size: %d","read_bmp",bmp->image.header_size); dcp_log(LOG_DEBUG,"%-15.15s: width: %d","read_bmp",bmp->image.width); dcp_log(LOG_DEBUG,"%-15.15s: height: %d","read_bmp",bmp->image.height); dcp_log(LOG_DEBUG,"%-15.15s: planes: %d","read_bmp",bmp->image.planes); dcp_log(LOG_DEBUG,"%-15.15s: bpp: %d","read_bmp",bmp->image.bpp); dcp_log(LOG_DEBUG,"%-15.15s: compression: %d","read_bmp",bmp->image.compression); dcp_log(LOG_DEBUG,"%-15.15s: size: %d","read_bmp",bmp->image.image_size); dcp_log(LOG_DEBUG,"%-15.15s: x: %d","read_bmp",bmp->image.x_ppm); dcp_log(LOG_DEBUG,"%-15.15s: y: %d","read_bmp",bmp->image.y_ppm); dcp_log(LOG_DEBUG,"%-15.15s: colors_used: %d","read_bmp",bmp->image.colors_used); dcp_log(LOG_DEBUG,"%-15.15s: colors_impor: %d","read_bmp",bmp->image.colors_important); dcp_log(LOG_DEBUG,"%-15.15s: row_order: %d","read_bmp",bmp->row_order); }
int opendcp_decode_bmp(odcp_image_t **image_ptr, const char *infile) { bmp_magic_num_t magic; bmp_image_t bmp; FILE *bmp_fp; odcp_image_t *image = 00; int pixels = 0; int i,w,h; size_t readsize; /* open bmp using filename or file descriptor */ dcp_log(LOG_DEBUG,"%-15.15s: opening bmp file %s","read_bmp",infile); bmp_fp = fopen(infile, "rb"); if (!bmp_fp) { dcp_log(LOG_ERROR,"%-15.15s: opening bmp file %s","read_bmp",infile); return OPENDCP_FATAL; } readsize = fread(&magic, 1, sizeof(bmp_magic_num_t), bmp_fp); if (readsize != sizeof(bmp_magic_num_t)) { dcp_log(LOG_ERROR,"%-15.15s: failed to read magic number expected %d read %d","read_bmp", sizeof(bmp_magic_num_t), readsize); } readsize = fread(&bmp, 1, sizeof(bmp_image_t), bmp_fp); if (readsize != sizeof(bmp_image_t)) { dcp_log(LOG_ERROR,"%-15.15s: failed to header expected %d read %d","read_bmp", sizeof(bmp_image_t), readsize); } if (magic.magic_num != MAGIC_NUMBER) { dcp_log(LOG_ERROR,"%s is not a valid BMP file", infile); } if (bmp.image.height < 0) { bmp.row_order = BMP_TOP; } else { bmp.row_order = BMP_BOTTOM; } w = bmp.image.width; h = abs(bmp.image.height); pixels = w * h; print_bmp_header(&bmp); switch (bmp.image.compression) { case BMP_RGB: break; case BMP_RLE8: case BMP_RLE4: case BMP_BITFIELDS: case BMP_JPEG: case BMP_PNG: default: dcp_log(LOG_ERROR, "Unsupported image compression: %d", bmp.image.compression); return OPENDCP_FATAL; break; } /* apparently, some applications don't fill in the image size */ if (bmp.image.image_size == 0) { dcp_log(LOG_WARN, "BMP missing file size field, will attempt to calculate"); bmp.image.image_size = bmp.file.size - sizeof(bmp_magic_num_t) - sizeof(bmp_image_t); } if (bmp.image.bpp < 24 || bmp.image.bpp > 32) { dcp_log(LOG_ERROR, "%d-bit depth is not supported.",bmp.image.bpp); return OPENDCP_FATAL; } /* create the image */ dcp_log(LOG_DEBUG,"%-15.15s: allocating odcp image","read_bmp"); image = odcp_image_create(3, w, h); dcp_log(LOG_DEBUG,"%-15.15s: image allocated","read_bmp"); int row_size = ((bmp.image.bpp * w + 31) / 32) * 4; dcp_log(LOG_DEBUG, "%-15,15s: row size %d data size %d", "read_bmp", row_size, sizeof(uint8_t)); fseek(bmp_fp, bmp.file.offset, SEEK_SET); /* RGB(A) */ if (bmp.image.compression == BMP_RGB) { /* 16-bits per pixel */ if (bmp.image.bpp == 16 ) { uint8_t data[2]; for (i=0; i<pixels; i++) { fread(&data,sizeof(data),1,bmp_fp); int p = invert_row(bmp, i); image->component[BMP_B].data[p] = data[0] << 2; image->component[BMP_G].data[p] = data[0] << 4; image->component[BMP_R].data[p] = data[1] << 2; } /* 24-bits per pixel */ } else if (bmp.image.bpp == 24 ) { uint8_t data[3]; for (i=0; i<pixels; i++) { fread(&data, sizeof(uint8_t), sizeof(data), bmp_fp); int p = invert_row(bmp, i); image->component[BMP_B].data[p] = data[0] << 4; image->component[BMP_G].data[p] = data[1] << 4; image->component[BMP_R].data[p] = data[2] << 4;; } /* 32-bits per pixel */ } else if (bmp.image.bpp == 32 ) { uint8_t data[4]; for (i=0; i<pixels; i++) { fread(&data, sizeof(uint8_t), sizeof(data), bmp_fp); int p = invert_row(bmp, i); image->component[BMP_B].data[p] = data[0] << 4; image->component[BMP_G].data[p] = data[1] << 4; image->component[BMP_R].data[p] = data[2] << 4; } } } /* RGB(A) */ fclose(bmp_fp); dcp_log(LOG_DEBUG,"%-15.15s: BMP read complete","read_bmp"); *image_ptr = image; return OPENDCP_NO_ERROR; }
void dcp_fatal(opendcp_t *opendcp, char *error) { dcp_log(LOG_ERROR, "%s",error); exit(DCP_FATAL); }
int add_reel(opendcp_t *opendcp, cpl_t *cpl, asset_list_t reel) { int result; int x,r; FILE *fp; char *filename; asset_t asset; struct stat st; char uuid_s[40]; dcp_log(LOG_INFO,"Adding Reel"); r = cpl->reel_count; /* add reel uuid */ uuid_random(uuid_s); sprintf(cpl->reel[r].uuid,"%.36s",uuid_s); /* parse argument and read asset information */ for (x=0;x<reel.asset_count;x++) { filename=reel.asset_list[x].filename; init_asset(&asset); sprintf(asset.filename,"%s",filename); sprintf(asset.annotation,"%s",basename(filename)); /* check if file exists */ if ((fp = fopen(filename, "r")) == NULL) { dcp_log(LOG_ERROR,"add_reel: Could not open file: %s",filename); return DCP_FILE_OPEN_ERROR; } else { fclose (fp); } /* get file size */ stat(filename, &st); sprintf(asset.size,"%"PRIu64, st.st_size); /* read asset information */ dcp_log(LOG_INFO,"add_reel: Reading %s asset information",filename); result = read_asset_info(&asset); if (result == DCP_FATAL) { dcp_log(LOG_ERROR,"%s is not a proper essence file",filename); return DCP_INVALID_ESSENCE; } if (x == 0) { opendcp->ns = asset.xml_ns; dcp_log(LOG_DEBUG,"add_reel: Label type detected: %d",opendcp->ns); } else { if (opendcp->ns != asset.xml_ns) { dcp_log(LOG_ERROR,"Warning DCP specification mismatch in assets. Please make sure all assets are MXF Interop or SMPTE"); return DCP_SPECIFCATION_MISMATCH; } } /* force aspect ratio, if specified */ if (strcmp(opendcp->xml.aspect_ratio,"") ) { sprintf(asset.aspect_ratio,"%s",opendcp->xml.aspect_ratio); } /* Set duration, if specified */ if (opendcp->duration) { if (opendcp->duration<asset.duration) { asset.duration = opendcp->duration; } else { dcp_log(LOG_WARN,"Desired duration %d cannot be greater than assset duration %d, ignoring value",opendcp->duration,asset.duration); } } /* Set entry point, if specified */ if (opendcp->entry_point) { if (opendcp->entry_point<asset.duration) { asset.entry_point = opendcp->entry_point; } else { dcp_log(LOG_WARN,"Desired entry point %d cannot be greater than assset duration %d, ignoring value",opendcp->entry_point,asset.duration); } } /* calculate digest */ calculate_digest(filename,asset.digest); /* get asset type */ result = get_asset_type(asset); /* add asset to cpl */ cpl->reel[r].asset[x] = asset; cpl->reel[r].asset_count++; } cpl->reel_count++; return DCP_SUCCESS; }
int write_cpl(opendcp_t *opendcp, cpl_t *cpl) { int a,r, rc; struct stat st; xmlIndentTreeOutput = 1; xmlDocPtr doc; xmlTextWriterPtr xml; /* create XML document */ xml = xmlNewTextWriterDoc(&doc,0); /* cpl start */ rc = xmlTextWriterStartDocument(xml, NULL, XML_ENCODING, NULL); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterStartDocument failed"); return DCP_FATAL; } xmlTextWriterStartElement(xml, BAD_CAST "CompositionPlaylist"); xmlTextWriterWriteAttribute(xml, BAD_CAST "xmlns", BAD_CAST NS_CPL[opendcp->ns]); if (opendcp->xml_signature.sign) { xmlTextWriterWriteAttribute(xml, BAD_CAST "xmlns:dsig", BAD_CAST DS_DSIG); } /* cpl attributes */ xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",cpl->uuid); xmlTextWriterWriteFormatElement(xml, BAD_CAST "AnnotationText","%s",cpl->annotation); xmlTextWriterWriteFormatElement(xml, BAD_CAST "IssueDate","%s",cpl->timestamp); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Creator","%s",cpl->creator); xmlTextWriterWriteFormatElement(xml, BAD_CAST "ContentTitleText","%s",cpl->title); xmlTextWriterWriteFormatElement(xml, BAD_CAST "ContentKind","%s",cpl->kind); /* content version */ if (opendcp->ns == XML_NS_SMPTE) { xmlTextWriterStartElement(xml, BAD_CAST "ContentVersion"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s_%s","urn:uri:",cpl->uuid,cpl->timestamp); xmlTextWriterWriteFormatElement(xml, BAD_CAST "LabelText","%s_%s",cpl->uuid,cpl->timestamp); xmlTextWriterEndElement(xml); } /* rating */ xmlTextWriterStartElement(xml, BAD_CAST "RatingList"); if (strcmp(cpl->rating,"")) { xmlTextWriterWriteFormatElement(xml, BAD_CAST "Agency","%s",RATING_AGENCY[1]); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Label","%s",cpl->rating); } xmlTextWriterEndElement(xml); /* reel(s) Start */ xmlTextWriterStartElement(xml, BAD_CAST "ReelList"); for (r=0;r<cpl->reel_count;r++) { reel_t reel = cpl->reel[r]; xmlTextWriterStartElement(xml, BAD_CAST "Reel"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",reel.uuid); xmlTextWriterStartElement(xml, BAD_CAST "AssetList"); /* Asset(s) Start */ for (a=0;a<cpl->reel[r].asset_count;a++) { asset_t asset = cpl->reel[r].asset[a]; if (asset.essence_class == ACT_PICTURE) { if (asset.stereoscopic) { xmlTextWriterStartElement(xml, BAD_CAST "msp-cpl:MainStereoscopicPicture"); xmlTextWriterWriteAttribute(xml, BAD_CAST "xmlns:msp-cpl", BAD_CAST NS_CPL_3D[opendcp->ns]); } else { xmlTextWriterStartElement(xml, BAD_CAST "MainPicture"); } } if (asset.essence_class == ACT_SOUND) { xmlTextWriterStartElement(xml, BAD_CAST "MainSound"); } if (asset.essence_class == ACT_TIMED_TEXT) { xmlTextWriterStartElement(xml, BAD_CAST "MainSubtitle"); } xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",asset.uuid); xmlTextWriterWriteFormatElement(xml, BAD_CAST "AnnotationText","%s",asset.annotation); xmlTextWriterWriteFormatElement(xml, BAD_CAST "EditRate","%s",asset.edit_rate); xmlTextWriterWriteFormatElement(xml, BAD_CAST "IntrinsicDuration","%d",asset.intrinsic_duration); xmlTextWriterWriteFormatElement(xml, BAD_CAST "EntryPoint","%d",asset.entry_point); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Duration","%d",asset.duration); if (asset.essence_class == ACT_PICTURE) { xmlTextWriterWriteFormatElement(xml, BAD_CAST "FrameRate","%s",asset.frame_rate); if (opendcp->ns == XML_NS_SMPTE) { xmlTextWriterWriteFormatElement(xml, BAD_CAST "ScreenAspectRatio","%s",asset.aspect_ratio); } else { xmlTextWriterWriteFormatElement(xml, BAD_CAST "ScreenAspectRatio","%s",get_aspect_ratio(asset.aspect_ratio)); } } if ( opendcp->xml.digest_flag ) { xmlTextWriterWriteFormatElement(xml, BAD_CAST "Hash","%s",asset.digest); } xmlTextWriterEndElement(xml); /* end asset */ } xmlTextWriterEndElement(xml); /* end assetlist */ xmlTextWriterEndElement(xml); /* end reel */ } xmlTextWriterEndElement(xml); /* end reel list */ #ifdef XMLSEC if (opendcp->xml_signature.sign) { write_dsig_template(opendcp, xml); } #endif xmlTextWriterEndElement(xml); /* end compositionplaylist */ rc = xmlTextWriterEndDocument(xml); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterEndDocument failed %s",cpl->filename); return DCP_FATAL; } xmlFreeTextWriter(xml); xmlSaveFormatFile(cpl->filename, doc, 1); xmlFreeDoc(doc); #ifdef XMLSEC /* sign the XML file */ if (opendcp->xml_signature.sign) { xml_sign(opendcp, cpl->filename); } #endif /* store CPL file size */ dcp_log(LOG_INFO,"Writing CPL file info"); stat(cpl->filename, &st); sprintf(cpl->size,"%"PRIu64,st.st_size); calculate_digest(cpl->filename,cpl->digest); return DCP_SUCCESS; }
int convert_to_j2k(opendcp_t *opendcp, char *in_file, char *out_file, char *tmp_path) { odcp_image_t *odcp_image; int result = 0; if (tmp_path == NULL) { tmp_path = "./"; } dcp_log(LOG_DEBUG,"%-15.15s: reading input file %s","convert_to_j2k",in_file); #ifdef OPENMP #pragma omp critical #endif { result = read_image(&odcp_image,in_file); } if (result != OPENDCP_NO_ERROR) { dcp_log(LOG_ERROR,"Unable to read file %s",in_file); return OPENDCP_ERROR; } if (!odcp_image) { dcp_log(LOG_ERROR,"Unable to load file %s",in_file); return OPENDCP_ERROR; } /* verify image is dci compliant */ if (check_image_compliance(opendcp->cinema_profile, odcp_image, NULL) != OPENDCP_NO_ERROR) { dcp_log(LOG_WARN,"The image resolution of %s is not DCI Compliant",in_file); /* resize image */ if (opendcp->j2k.resize) { if (resize(&odcp_image, opendcp->cinema_profile, opendcp->j2k.resize) != OPENDCP_NO_ERROR) { odcp_image_free(odcp_image); return OPENDCP_ERROR; } } else { odcp_image_free(odcp_image); return OPENDCP_ERROR; } } if (opendcp->j2k.xyz) { dcp_log(LOG_INFO,"RGB->XYZ color conversion %s",in_file); if (rgb_to_xyz(odcp_image,opendcp->j2k.lut,opendcp->j2k.xyz_method)) { dcp_log(LOG_ERROR,"Color conversion failed %s",in_file); odcp_image_free(odcp_image); return OPENDCP_ERROR; } } if ( opendcp->j2k.encoder == J2K_KAKADU ) { char tempfile[255]; sprintf(tempfile,"%s/tmp_%s",tmp_path,basename(in_file)); dcp_log(LOG_DEBUG,"%-15.15s: Writing temporary tif %s","convert_to_j2k",tempfile); result = write_tif(odcp_image,tempfile,0); odcp_image_free(odcp_image); if (result != OPENDCP_NO_ERROR) { dcp_log(LOG_ERROR,"Writing temporary tif failed"); return OPENDCP_ERROR; } result = encode_kakadu(opendcp, tempfile, out_file); if ( result != OPENDCP_NO_ERROR) { dcp_log(LOG_ERROR,"Kakadu JPEG2000 conversion failed %s",in_file); remove(tempfile); return OPENDCP_ERROR; } remove(tempfile); } else { opj_image_t *opj_image; odcp_to_opj(odcp_image, &opj_image); odcp_image_free(odcp_image); if (encode_openjpeg(opendcp,opj_image,out_file) != OPENDCP_NO_ERROR) { dcp_log(LOG_ERROR,"OpenJPEG JPEG2000 conversion failed %s",in_file); opj_image_destroy(opj_image); return OPENDCP_ERROR; } opj_image_destroy(opj_image); } return OPENDCP_NO_ERROR; }
int write_assetmap(opendcp_t *opendcp) { xmlIndentTreeOutput = 1; xmlDocPtr doc; xmlTextWriterPtr xml; int a,c,r,rc; char uuid_s[40]; cpl_t cpl; reel_t reel; /* generate assetmap UUID */ uuid_random(uuid_s); dcp_log(LOG_INFO,"Writing ASSETMAP file %.256s",opendcp->assetmap.filename); /* create XML document */ xml = xmlNewTextWriterDoc(&doc,0); /* assetmap XML Start */ rc = xmlTextWriterStartDocument(xml, NULL, XML_ENCODING, NULL); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterStartDocument failed"); return DCP_FATAL; } xmlTextWriterStartElement(xml, BAD_CAST "AssetMap"); xmlTextWriterWriteAttribute(xml, BAD_CAST "xmlns", BAD_CAST NS_AM[opendcp->ns]); /* assetmap attributes */ xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",uuid_s); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Creator","%s",opendcp->xml.creator); xmlTextWriterWriteFormatElement(xml, BAD_CAST "VolumeCount","%d",1); xmlTextWriterWriteFormatElement(xml, BAD_CAST "IssueDate","%s",opendcp->xml.timestamp); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Issuer","%s",opendcp->xml.issuer); xmlTextWriterStartElement(xml, BAD_CAST "AssetList"); dcp_log(LOG_INFO,"Writing ASSETMAP PKL"); /* PKL */ xmlTextWriterStartElement(xml, BAD_CAST "Asset"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",opendcp->pkl[0].uuid); xmlTextWriterWriteFormatElement(xml, BAD_CAST "PackingList","%s","true"); xmlTextWriterStartElement(xml, BAD_CAST "ChunkList"); xmlTextWriterStartElement(xml, BAD_CAST "Chunk"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Path","%s",basename(opendcp->pkl[0].filename)); xmlTextWriterWriteFormatElement(xml, BAD_CAST "VolumeIndex","%d",1); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Offset","%d",0); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Length","%s",opendcp->pkl[0].size); xmlTextWriterEndElement(xml); /* end chunk */ xmlTextWriterEndElement(xml); /* end chunklist */ xmlTextWriterEndElement(xml); /* end pkl asset */ dcp_log(LOG_INFO,"Writing ASSETMAP CPLs"); /* CPL */ for (c=0;c<opendcp->pkl[0].cpl_count;c++) { cpl = opendcp->pkl[0].cpl[c]; xmlTextWriterStartElement(xml, BAD_CAST "Asset"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",cpl.uuid); xmlTextWriterStartElement(xml, BAD_CAST "ChunkList"); xmlTextWriterStartElement(xml, BAD_CAST "Chunk"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Path","%s",basename(cpl.filename)); xmlTextWriterWriteFormatElement(xml, BAD_CAST "VolumeIndex","%d",1); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Offset","%d",0); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Length","%s",cpl.size); xmlTextWriterEndElement(xml); /* end chunk */ xmlTextWriterEndElement(xml); /* end chunklist */ xmlTextWriterEndElement(xml); /* end cpl asset */ /* assets(s) start */ for (r=0;r<cpl.reel_count;r++) { reel = cpl.reel[r]; for (a=0;a<reel.asset_count;a++) { asset_t asset = reel.asset[a]; xmlTextWriterStartElement(xml, BAD_CAST "Asset"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",asset.uuid); xmlTextWriterStartElement(xml, BAD_CAST "ChunkList"); xmlTextWriterStartElement(xml, BAD_CAST "Chunk"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Path","%s",basename(asset.filename)); xmlTextWriterWriteFormatElement(xml, BAD_CAST "VolumeIndex","%d",1); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Offset","%d",0); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Length","%s",asset.size); xmlTextWriterEndElement(xml); /* end chunk */ xmlTextWriterEndElement(xml); /* end chunklist */ xmlTextWriterEndElement(xml); /* end cpl asset */ } } } xmlTextWriterEndElement(xml); /* end assetlist */ xmlTextWriterEndElement(xml); /* end assetmap */ rc = xmlTextWriterEndDocument(xml); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterEndDocument failed %s",opendcp->assetmap.filename); return DCP_FATAL; } xmlFreeTextWriter(xml); xmlSaveFormatFile(opendcp->assetmap.filename, doc, 1); xmlFreeDoc(doc); return DCP_SUCCESS; }
int write_pkl(opendcp_t *opendcp, pkl_t *pkl) { int a,r,c,rc; struct stat st; xmlIndentTreeOutput = 1; xmlDocPtr doc; xmlTextWriterPtr xml; /* create XML document */ xml = xmlNewTextWriterDoc(&doc,0); /* pkl start */ rc = xmlTextWriterStartDocument(xml, NULL, XML_ENCODING, NULL); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterStartDocument failed"); return DCP_FATAL; } xmlTextWriterStartElement(xml, BAD_CAST "PackingList"); xmlTextWriterWriteAttribute(xml, BAD_CAST "xmlns", BAD_CAST NS_PKL[opendcp->ns]); if (opendcp->xml_signature.sign) { xmlTextWriterWriteAttribute(xml, BAD_CAST "xmlns:dsig", BAD_CAST DS_DSIG); } /* cpl attributes */ xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",pkl->uuid); xmlTextWriterWriteFormatElement(xml, BAD_CAST "AnnotationText","%s",pkl->annotation); xmlTextWriterWriteFormatElement(xml, BAD_CAST "IssueDate","%s",opendcp->xml.timestamp); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Issuer","%s",opendcp->xml.issuer); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Creator","%s",opendcp->xml.creator); dcp_log(LOG_INFO,"CPLS: %d",pkl->cpl_count); /* asset(s) Start */ xmlTextWriterStartElement(xml, BAD_CAST "AssetList"); for (c=0;c<pkl->cpl_count;c++) { cpl_t cpl = pkl->cpl[c]; dcp_log(LOG_INFO,"REELS: %d",cpl.reel_count); for (r=0;r<cpl.reel_count;r++) { reel_t reel = cpl.reel[r]; for (a=0;a<reel.asset_count;a++) { asset_t asset = reel.asset[a]; xmlTextWriterStartElement(xml, BAD_CAST "Asset"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",asset.uuid); xmlTextWriterWriteFormatElement(xml, BAD_CAST "AnnotationText","%s",asset.annotation); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Hash","%s",asset.digest); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Size","%s",asset.size); if (opendcp->ns == XML_NS_SMPTE) { xmlTextWriterWriteFormatElement(xml, BAD_CAST "Type","%s","application/mxf"); } else { if (asset.essence_class == ACT_PICTURE) { xmlTextWriterWriteFormatElement(xml, BAD_CAST "Type","%s","application/x-smpte-mxf;asdcpKind=Picture"); } if (asset.essence_class == ACT_SOUND) { xmlTextWriterWriteFormatElement(xml, BAD_CAST "Type","%s","application/x-smpte-mxf;asdcpKind=Sound"); } if (asset.essence_class == ACT_TIMED_TEXT) { xmlTextWriterWriteFormatElement(xml, BAD_CAST "Type","%s","application/x-smpte-mxf;asdcpKind=Subtitle"); } } xmlTextWriterEndElement(xml); /* end asset */ } } /* cpl */ xmlTextWriterStartElement(xml, BAD_CAST "Asset"); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Id","%s%s","urn:uuid:",cpl.uuid); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Hash","%s",cpl.digest); xmlTextWriterWriteFormatElement(xml, BAD_CAST "Size","%s",cpl.size); if (opendcp->ns == XML_NS_SMPTE) { xmlTextWriterWriteFormatElement(xml, BAD_CAST "Type","%s","text/xml"); } else { xmlTextWriterWriteFormatElement(xml, BAD_CAST "Type","%s","text/xml;asdcpKind=CPL"); } xmlTextWriterEndElement(xml); /* end cpl asset */ } xmlTextWriterEndElement(xml); /* end assetlist */ #ifdef XMLSEC if (opendcp->xml_signature.sign) { write_dsig_template(opendcp, xml); } #endif xmlTextWriterEndElement(xml); /* end packinglist */ rc = xmlTextWriterEndDocument(xml); if (rc < 0) { dcp_log(LOG_ERROR,"xmlTextWriterEndDocument failed %s",pkl->filename); return DCP_FATAL; } xmlFreeTextWriter(xml); xmlSaveFormatFile(pkl->filename, doc, 1); xmlFreeDoc(doc); #ifdef XMLSEC /* sign the XML file */ if (opendcp->xml_signature.sign) { xml_sign(opendcp, pkl->filename); } #endif /* store PKL file size */ stat(pkl->filename, &st); sprintf(pkl->size,"%"PRIu64,st.st_size); return DCP_SUCCESS; }
int encode_openjpeg(opendcp_t *opendcp, opj_image_t *opj_image, char *out_file) { bool result; int codestream_length; int max_comp_size; int max_cs_len; opj_cparameters_t parameters; opj_cio_t *cio = NULL; opj_cinfo_t *cinfo = NULL; FILE *f = NULL; int bw; if (opendcp->j2k.bw) { bw = opendcp->j2k.bw; } else { bw = MAX_DCP_JPEG_BITRATE; } /* set the max image and component sizes based on frame_rate */ max_cs_len = ((float)bw)/8/opendcp->frame_rate; /* adjust cs for 3D */ if (opendcp->stereoscopic) { max_cs_len = max_cs_len/2; } max_comp_size = ((float)max_cs_len)/1.25; /* set encoding parameters to default values */ opj_set_default_encoder_parameters(¶meters); /* set default cinema parameters */ set_cinema_encoder_parameters(opendcp, ¶meters); parameters.cp_comment = (char*)malloc(strlen(OPENDCP_NAME)+1); sprintf(parameters.cp_comment,"%s", OPENDCP_NAME); /* adjust cinema enum type */ if (opendcp->cinema_profile == DCP_CINEMA4K) { parameters.cp_cinema = CINEMA4K_24; } else { parameters.cp_cinema = CINEMA2K_24; } /* Decide if MCT should be used */ parameters.tcp_mct = opj_image->numcomps == 3 ? 1 : 0; /* set max image */ parameters.max_comp_size = max_comp_size; parameters.tcp_rates[0]= ((float) (opj_image->numcomps * opj_image->comps[0].w * opj_image->comps[0].h * opj_image->comps[0].prec))/ (max_cs_len * 8 * opj_image->comps[0].dx * opj_image->comps[0].dy); /* get a J2K compressor handle */ dcp_log(LOG_DEBUG,"%-15.15s: creating compressor %s","encode_openjpeg",out_file); cinfo = opj_create_compress(CODEC_J2K); /* set event manager to null (openjpeg 1.3 bug) */ cinfo->event_mgr = NULL; /* setup the encoder parameters using the current image and user parameters */ dcp_log(LOG_DEBUG,"%-15.15s: setup J2k encoder %s","encode_openjpeg",out_file); opj_setup_encoder(cinfo, ¶meters, opj_image); /* open a byte stream for writing */ /* allocate memory for all tiles */ dcp_log(LOG_DEBUG,"%-15.15s: opening J2k output stream %s","encode_openjpeg",out_file); cio = opj_cio_open((opj_common_ptr)cinfo, NULL, 0); dcp_log(LOG_INFO,"Encoding file %s",out_file); result = opj_encode(cinfo, cio, opj_image, NULL); dcp_log(LOG_DEBUG,"%-15.15s: encoding file %s complete","encode_openjepg",out_file); if (!result) { dcp_log(LOG_ERROR,"Unable to encode jpeg2000 file %s",out_file); opj_cio_close(cio); opj_destroy_compress(cinfo); return OPENDCP_ERROR; } codestream_length = cio_tell(cio); f = fopen(out_file, "wb"); if (!f) { dcp_log(LOG_ERROR,"Unable to write jpeg2000 file %s",out_file); opj_cio_close(cio); opj_destroy_compress(cinfo); return OPENDCP_ERROR; } fwrite(cio->buffer, 1, codestream_length, f); fclose(f); /* free openjpeg structure */ opj_cio_close(cio); opj_destroy_compress(cinfo); /* free user parameters structure */ if(parameters.cp_comment) free(parameters.cp_comment); if(parameters.cp_matrice) free(parameters.cp_matrice); return OPENDCP_NO_ERROR; }