LIBDE265_API de265_error de265_decode(de265_decoder_context* de265ctx, int* more) { decoder_context* ctx = (decoder_context*)de265ctx; // if the stream has ended, and no more NALs are to be decoded, flush all pictures if (ctx->NAL_queue_len == 0 && ctx->end_of_stream) { if (more) { *more=0; } // 0 if no more pictures in queue push_current_picture_to_output_queue(ctx); while (ctx->reorder_output_queue_length>0) { flush_next_picture_from_reorder_buffer(ctx); if (more) { *more=1; } } return DE265_OK; } // if NAL-queue is empty, we need more data // -> input stalled if (ctx->NAL_queue_len == 0) { if (more) { *more=1; } return DE265_ERROR_WAITING_FOR_INPUT_DATA; } // when there are no free image buffers in the DPB, pause decoding // -> output stalled if (!has_free_dpb_picture(ctx, false)) { if (more) *more = 1; return DE265_ERROR_IMAGE_BUFFER_FULL; } // decode one NAL from the queue NAL_unit* nal = pop_from_NAL_queue(ctx); assert(nal); de265_error err = de265_decode_NAL(de265ctx, nal); free_NAL_unit(ctx,nal); if (more) { // decoding error is assumed to be unrecoverable *more = (err==DE265_OK); } return err; }
static de265_error process_data(decoder_context* ctx, const uint8_t* data, int len, int* out_nBytesProcessed) { *out_nBytesProcessed=0; /* printf("len=%d\n",len); for (int i=0;i<16;i++) { printf("%02x ",data[i]); } printf("\n"); */ // Resize output buffer so that complete input would fit. // We add 3, because in the worst case 3 extra bytes are created for an input byte. rbsp_buffer_resize(&ctx->nal_data, ctx->nal_data.size + len + 3); unsigned char* out = ctx->nal_data.data + ctx->nal_data.size; for (int i=0;i<len;i++) { (*out_nBytesProcessed)++; /* printf("state=%d input=%02x (%p) (output size: %d)\n",ctx->input_push_state, *data, data, out - ctx->nal_data.data); */ switch (ctx->input_push_state) { case 0: case 1: if (*data == 0) { ctx->input_push_state++; } else { return DE265_ERROR_NO_STARTCODE; } break; case 2: if (*data == 1) { ctx->input_push_state=3; ctx->num_skipped_bytes=0; } else if (*data == 0) { } // *out++ = 0; } else { return DE265_ERROR_NO_STARTCODE; } break; case 3: /* *out++ = 0; *out++ = 0; *out++ = 1; */ *out++ = *data; ctx->input_push_state = 4; break; case 4: *out++ = *data; ctx->input_push_state = 5; break; case 5: if (*data==0) { ctx->input_push_state=6; } else { *out++ = *data; } break; case 6: if (*data==0) { ctx->input_push_state=7; } else { *out++ = 0; *out++ = *data; ctx->input_push_state=5; } break; case 7: if (*data==0) { *out++ = 0; } else if (*data==3) { *out++ = 0; *out++ = 0; ctx->input_push_state=5; // remember which byte we removed int* skipped = (int *)malloc((ctx->num_skipped_bytes+1) * sizeof(int)); if (ctx->num_skipped_bytes>0) { memcpy(skipped, ctx->skipped_bytes, ctx->num_skipped_bytes * sizeof(int)); } if (ctx->skipped_bytes) { free(ctx->skipped_bytes); } skipped[ctx->num_skipped_bytes] = (out - ctx->nal_data.data) + ctx->num_skipped_bytes; ctx->skipped_bytes = skipped; ctx->num_skipped_bytes++; } else if (*data==1) { // decode this NAL ctx->nal_data.size = out - ctx->nal_data.data; de265_error err = de265_decode_NAL((de265_decoder_context*)ctx, &ctx->nal_data); // clear buffer for next NAL ctx->nal_data.size = 0; out = ctx->nal_data.data; ctx->input_push_state=3; ctx->num_skipped_bytes=0; if (err != DE265_OK) { data++; return err; } // when there are no free image buffers in the DPB, pause decoding if (!has_free_dpb_picture(ctx)) { data++; return err; } } else { *out++ = 0; *out++ = 0; *out++ = *data; ctx->input_push_state=5; } break; } data++; /* for (int i=0;i<out - ctx->nal_data.data;i++) { printf("%02x ",ctx->nal_data.data[i]); } printf("\n"); */ } if (*out_nBytesProcessed == len && ctx->end_of_stream && ctx->input_push_state != 8) { if (ctx->input_push_state<5) { return DE265_ERROR_EOF; } else if (ctx->input_push_state==6) { *out++ = 0; } else if (ctx->input_push_state==7) { *out++ = 0; *out++ = 0; } ctx->input_push_state=8; // end of stream, stop all processing // decode data ctx->nal_data.size = out - ctx->nal_data.data; de265_error err = de265_decode_NAL((de265_decoder_context*)ctx, &ctx->nal_data); if (err != DE265_OK) { return err; } push_current_picture_to_output_queue(ctx); // clear buffer ctx->nal_data.size = 0; out = ctx->nal_data.data; return DE265_OK; } ctx->nal_data.size = out - ctx->nal_data.data; return DE265_OK; }