static int libdirac_decode_frame(AVCodecContext *avccontext, void *data, int *data_size, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; int buf_size = avpkt->size; FfmpegDiracDecoderParams *p_dirac_params = avccontext->priv_data; AVPicture *picture = data; AVPicture pic; int pict_size; unsigned char *buffer[3]; *data_size = 0; if (buf_size > 0) { /* set data to decode into buffer */ dirac_buffer(p_dirac_params->p_decoder, buf, buf + buf_size); if ((buf[4] & 0x08) == 0x08 && (buf[4] & 0x03)) avccontext->has_b_frames = 1; } while (1) { /* parse data and process result */ DecoderState state = dirac_parse(p_dirac_params->p_decoder); switch (state) { case STATE_BUFFER: return buf_size; case STATE_SEQUENCE: { /* tell FFmpeg about sequence details */ dirac_sourceparams_t *src_params = &p_dirac_params->p_decoder->src_params; if (av_image_check_size(src_params->width, src_params->height, 0, avccontext) < 0) { av_log(avccontext, AV_LOG_ERROR, "Invalid dimensions (%dx%d)\n", src_params->width, src_params->height); avccontext->height = avccontext->width = 0; return -1; } avccontext->height = src_params->height; avccontext->width = src_params->width; avccontext->pix_fmt = GetFfmpegChromaFormat(src_params->chroma); if (avccontext->pix_fmt == PIX_FMT_NONE) { av_log(avccontext, AV_LOG_ERROR, "Dirac chroma format %d not supported currently\n", src_params->chroma); return -1; } avccontext->time_base.den = src_params->frame_rate.numerator; avccontext->time_base.num = src_params->frame_rate.denominator; /* calculate output dimensions */ avpicture_fill(&pic, NULL, avccontext->pix_fmt, avccontext->width, avccontext->height); pict_size = avpicture_get_size(avccontext->pix_fmt, avccontext->width, avccontext->height); /* allocate output buffer */ if (!p_dirac_params->p_out_frame_buf) p_dirac_params->p_out_frame_buf = av_malloc(pict_size); buffer[0] = p_dirac_params->p_out_frame_buf; buffer[1] = p_dirac_params->p_out_frame_buf + pic.linesize[0] * avccontext->height; buffer[2] = buffer[1] + pic.linesize[1] * src_params->chroma_height; /* tell Dirac about output destination */ dirac_set_buf(p_dirac_params->p_decoder, buffer, NULL); break; } case STATE_SEQUENCE_END: break; case STATE_PICTURE_AVAIL: /* fill picture with current buffer data from Dirac */ avpicture_fill(picture, p_dirac_params->p_out_frame_buf, avccontext->pix_fmt, avccontext->width, avccontext->height); *data_size = sizeof(AVPicture); return buf_size; case STATE_INVALID: return -1; default: break; } } return buf_size; }
static void DecodeDirac (const char *iname, const char *oname) { clock_t start_t, stop_t; dirac_decoder_t *decoder = NULL; FILE *ifp; FILE *fpdata; unsigned char buffer[8192]; int bytes = 0; int num_frames = 0; char infile_name[FILENAME_MAX]; char outfile_hdr[FILENAME_MAX]; char outfile_data[FILENAME_MAX]; dirac_decoder_state_t state = STATE_BUFFER; strncpy(infile_name, iname, sizeof(infile_name)); strncpy(outfile_data, oname, sizeof(outfile_data)); if ((ifp = fopen (infile_name, "rb")) ==NULL) { perror(iname); return; } if ((fpdata = fopen (outfile_data, "wb")) ==NULL) { perror(outfile_hdr); fclose(ifp); return; } /* initialise the decoder */ decoder = dirac_decoder_init(verbose); assert (decoder != NULL); start_t=clock(); do { /* parse the input data */ state = dirac_parse(decoder); switch (state) { case STATE_BUFFER: /* * parser is out of data. Read data from input stream and pass it * on to the parser */ bytes = fread (buffer, 1, sizeof(buffer), ifp); if (bytes) dirac_buffer (decoder, buffer, buffer + bytes); break; case STATE_SEQUENCE: { /* * Start of sequence detected. Allocate for the frame buffers and * pass this buffer to the parser */ unsigned char *buf[3]; if (verbose) { fprintf (stdout, "\nSEQUENCE : major_ver=%d minor_version=%d profile=%d level=%d width=%d height=%d chroma=%s chroma_width=%d chroma_height=%d frame_rate=%d/%d, source_sampling=%s topfieldfirst=%s", decoder->parse_params.major_ver, decoder->parse_params.minor_ver, decoder->parse_params.profile, decoder->parse_params.level, decoder->src_params.width, decoder->src_params.height, chroma2string(decoder->src_params.chroma), decoder->src_params.chroma_width, decoder->src_params.chroma_height, decoder->src_params.frame_rate.numerator, decoder->src_params.frame_rate.denominator, decoder->src_params.source_sampling == 0 ? "progressive" : ( decoder->src_params.source_sampling == 1 ? "interlaced" : "UNKNOWN" ), decoder->src_params.topfieldfirst ? "yes" : "no"); } FreeFrameBuffer(decoder); buf[0] = buf[1] = buf[2] = 0; buf[0] = (unsigned char *)malloc (decoder->src_params.width * decoder->src_params.height); buf[1] = (unsigned char *)malloc (decoder->src_params.chroma_width * decoder->src_params.chroma_height); buf[2] = (unsigned char *)malloc (decoder->src_params.chroma_width * decoder->src_params.chroma_height); dirac_set_buf (decoder, buf, NULL); } break; case STATE_SEQUENCE_END: /* * End of Sequence detected. Free the frame buffers */ if (verbose) fprintf (stdout, "\nSEQUENCE_END"); FreeFrameBuffer(decoder); break; case STATE_PICTURE_AVAIL: num_frames++; if (verbose) { fprintf (stdout, "\nFRAME_AVAIL : frame_num=%d", decoder->frame_num); } /* picture available for display */ if (!WritePicData(decoder, fpdata)) { perror("Write failed"); goto cleanup; } break; case STATE_INVALID: /* Invalid state. Stop all processing */ fprintf (stderr, "Error processing file %s\n", iname); break; default: continue; } } while (bytes > 0 && state != STATE_INVALID); cleanup: stop_t=clock(); if ( verbose ) fprintf (stdout, "\nTime per frame: %g", (double)(stop_t-start_t)/(double)(CLOCKS_PER_SEC*num_frames)); fclose(fpdata); fclose(ifp); /* free all resources */ FreeFrameBuffer(decoder); dirac_decoder_close(decoder); }