nengel@2: /* nengel@2: * H.26L/H.264/AVC/JVT/14496-10/... encoder/decoder nengel@2: * Copyright (c) 2003 Michael Niedermayer nengel@2: * nengel@2: * This file is part of FFmpeg. nengel@2: * nengel@2: * FFmpeg is free software; you can redistribute it and/or nengel@2: * modify it under the terms of the GNU Lesser General Public nengel@2: * License as published by the Free Software Foundation; either nengel@2: * version 2.1 of the License, or (at your option) any later version. nengel@2: * nengel@2: * FFmpeg is distributed in the hope that it will be useful, nengel@2: * but WITHOUT ANY WARRANTY; without even the implied warranty of nengel@2: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU nengel@2: * Lesser General Public License for more details. nengel@2: * nengel@2: * You should have received a copy of the GNU Lesser General Public nengel@2: * License along with FFmpeg; if not, write to the Free Software nengel@2: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA nengel@2: */ nengel@2: #include "h264_types.h" nengel@2: #include "h264_parser.h" nengel@2: #include "h264_nal.h" nengel@2: #include "h264_entropy.h" nengel@2: #include "h264_rec.h" nengel@2: #include "h264_pred_mode.h" nengel@2: #include "h264_misc.h" nengel@2: // #undef NDEBUG nengel@2: #include nengel@3: #include "VSs_impl/VSs.h" nengel@2: nengel@3: typedef struct{ nengel@3: ParserContext *pc; nengel@3: NalContext *nc; nengel@3: SliceBufferEntry *sbe; nengel@3: H264Context *h; nengel@3: } parse_taskArgs; nengel@3: nengel@9: int32 parse_taskArgTypes[3] = {INOUT, INOUT, OUTPUT}; nengel@9: size_t parse_taskArgSizes[3] = {sizeof(ParserContext), sizeof(NalContext), sizeof(SliceBufferEntry)}; nengel@3: nengel@3: //#pragma omp task inout(*pc, *nc) output(*sbe) nengel@7: static void parse_task(void *_data){ nengel@3: parse_taskArgs* args = (parse_taskArgs*) _data; nengel@3: ParserContext *pc = args->pc; nengel@3: NalContext *nc = args->nc; nengel@3: SliceBufferEntry *sbe = args->sbe; nengel@3: H264Context *h = args->h; nengel@2: H264Slice *s; nengel@2: nengel@2: if (!sbe->initialized){ nengel@2: init_sb_entry(h, sbe); nengel@2: sbe->lines_total=h->mb_height; nengel@2: } nengel@2: nengel@2: av_read_frame_internal(pc, &sbe->gb); nengel@2: s = &sbe->slice; nengel@2: nengel@2: decode_nal_units(nc, s, &sbe->gb); nengel@3: nengel@8: return; nengel@2: } nengel@2: nengel@3: VSsTaskType parse_taskType = { nengel@3: .fn = &parse_task, nengel@9: .numDeps = 3, nengel@3: .sizeOfArgs = sizeof(parse_taskArgs), nengel@9: .depsTypes = parse_taskArgTypes, nengel@9: .depsSizes = parse_taskArgSizes}; nengel@3: nengel@3: nengel@3: typedef struct{ nengel@3: EntropyContext *ec; nengel@3: SliceBufferEntry *sbe; nengel@3: H264Context *h; nengel@3: } decode_slice_entropy_taskArgs; nengel@3: nengel@9: int32 decode_slice_entropy_taskArgTypes[2] = {INOUT, INOUT}; nengel@9: size_t decode_slice_entropy_taskArgSizes[2] = {sizeof(EntropyContext), sizeof(SliceBufferEntry)}; nengel@3: nengel@3: //#pragma omp task inout(*ec) inout(*sbe) nengel@7: static void decode_slice_entropy_task(void *_data){ nengel@3: decode_slice_entropy_taskArgs* args = (decode_slice_entropy_taskArgs*) _data; nengel@3: EntropyContext *ec = args->ec; nengel@3: SliceBufferEntry *sbe = args->sbe; nengel@3: H264Context *h = args->h; nengel@2: int i,j; nengel@2: H264Slice *s = &sbe->slice; nengel@2: GetBitContext *gb = &sbe->gb; nengel@2: H264Mb *mbs = sbe->mbs; nengel@2: // GetBitContext *gb = s->gb; nengel@2: CABACContext *c = &ec->c; nengel@2: nengel@2: if( !s->pps.cabac ){ nengel@2: av_log(AV_LOG_ERROR, "Only cabac encoded streams are supported\n"); nengel@8: return; nengel@2: } nengel@2: nengel@2: init_dequant_tables(s, ec); nengel@2: ec->curr_qscale = s->qscale; nengel@2: ec->last_qscale_diff = 0; nengel@2: ec->chroma_qp[0] = get_chroma_qp((H264Slice *) s, 0, s->qscale); nengel@2: ec->chroma_qp[1] = get_chroma_qp((H264Slice *) s, 1, s->qscale); nengel@2: nengel@2: /* realign */ nengel@2: align_get_bits( gb ); nengel@2: /* init cabac */ nengel@2: ff_init_cabac_decoder( c, gb->buffer + get_bits_count(gb)/8, (get_bits_left(gb) + 7)/8); nengel@2: nengel@2: ff_h264_init_cabac_states(ec, s, c); nengel@2: nengel@2: for(j=0; jmb_height; j++){ nengel@2: init_entropy_buf(ec, s, j); nengel@2: for(i=0; imb_width; i++){ nengel@2: int eos,ret; nengel@2: H264Mb *m = &mbs[i + j*ec->mb_width]; nengel@2: m->mb_x=i; nengel@2: m->mb_y=j; nengel@2: ec->m = m; nengel@2: nengel@2: ret = ff_h264_decode_mb_cabac(ec, s, c); nengel@2: eos = get_cabac_terminate( c); nengel@2: (void) eos; nengel@2: if( ret < 0 || c->bytestream > c->bytestream_end + 2) { nengel@2: av_log(AV_LOG_ERROR, "error while decoding MB %d %d, bytestream (%td)\n", m->mb_x, m->mb_y, c->bytestream_end - c->bytestream); nengel@8: return; nengel@2: } nengel@2: } nengel@2: } nengel@8: return; nengel@2: } nengel@2: nengel@3: VSsTaskType decode_slice_entropy_taskType = { nengel@3: .fn = &decode_slice_entropy_task, nengel@9: .numDeps = 2, nengel@3: .sizeOfArgs = sizeof(decode_slice_entropy_taskArgs), nengel@9: .depsTypes = decode_slice_entropy_taskArgTypes, nengel@9: .depsSizes = decode_slice_entropy_taskArgSizes}; nengel@3: nengel@3: nengel@2: static void decode_super_mb_block(MBRecContext *d, H264Slice *s, SuperMBContext *smbc, H264Mb *mbs, int smb_x, int smb_y){ nengel@2: MBRecState mrs; nengel@2: // memset(&mrs, 0, sizeof(MBRecState)); nengel@2: nengel@2: for (int k=0, i= smb_y; i< smb_y + smbc->smb_height; i++, k++){ nengel@2: init_mbrec_context(d, &mrs, s, i); nengel@2: for (int j= smb_x -k ; j< smb_x - k + smbc->smb_width; j++){ nengel@2: if (i< d->mb_height && j >= 0 && j < d->mb_width){ nengel@2: h264_decode_mb_internal (d, &mrs, s, &mbs[i*d->mb_width+j]); nengel@2: } nengel@2: } nengel@2: } nengel@2: } nengel@2: nengel@3: typedef struct{ nengel@3: MBRecContext *d; nengel@3: SliceBufferEntry *sbe; nengel@3: SuperMBTask *ml; nengel@3: SuperMBTask *mur; nengel@3: SuperMBTask *m; nengel@3: SuperMBContext *smbc; nengel@3: } decode_super_mb_taskArgs; nengel@3: nengel@9: int32 decode_super_mb_taskArgTypes[5] = {IN, IN, IN, IN, INOUT}; nengel@9: size_t decode_super_mb_taskArgSizes[5] = {sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask), sizeof(SuperMBTask), sizeof(SuperMBTask)}; nengel@3: nengel@3: //#pragma omp task input(*d, *sbe, *ml, *mur) inout(*m) nengel@7: static void decode_super_mb_task(void *_data){ nengel@3: decode_super_mb_taskArgs* args = (decode_super_mb_taskArgs*) _data; nengel@3: MBRecContext *d = args->d; nengel@3: SliceBufferEntry *sbe = args->sbe; nengel@3: SuperMBTask *ml = args->ml; nengel@3: SuperMBTask *mur = args->mur; nengel@3: SuperMBTask *m = args->m; nengel@3: SuperMBContext *smbc = args->smbc; nengel@2: H264Slice *s = &sbe->slice; nengel@2: H264Mb *mbs = sbe->mbs; nengel@2: decode_super_mb_block(d, s, smbc, mbs, m->smb_x, m->smb_y); nengel@8: return; nengel@2: } nengel@2: nengel@3: VSsTaskType decode_super_mb_taskType = { nengel@3: .fn = &decode_super_mb_task, nengel@9: .numDeps = 5, nengel@3: .sizeOfArgs = sizeof(decode_super_mb_taskArgs), nengel@9: .depsTypes = decode_super_mb_taskArgTypes, nengel@9: .depsSizes = decode_super_mb_taskArgSizes}; nengel@3: nengel@3: nengel@3: nengel@3: typedef struct{ nengel@3: MBRecContext *d; nengel@3: SliceBufferEntry *sbe; nengel@3: SuperMBTask *sm; nengel@3: SuperMBContext *smbc; nengel@3: int* line; nengel@3: } draw_edges_taskArgs; nengel@3: nengel@9: int32 draw_edges_taskArgTypes[3] = {IN, IN, INOUT}; nengel@9: size_t draw_edges_taskArgSizes[3] = {sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask)}; nengel@3: nengel@3: //#pragma omp task input(*d, *sbe) inout(*sm) nengel@7: static void draw_edges_task(void *_data){ nengel@3: draw_edges_taskArgs* args = (draw_edges_taskArgs*) _data; nengel@3: MBRecContext *d = args->d; nengel@3: SliceBufferEntry *sbe = args->sbe; nengel@3: SuperMBTask *sm = args->sm; nengel@3: SuperMBContext *smbc = args->smbc; nengel@3: int line = *(args->line); nengel@2: H264Slice *s = &sbe->slice; nengel@2: for (int i=line*smbc->smb_height; i< (line+1)*smbc->smb_height && i< d->mb_height; i++) nengel@2: draw_edges(d, s, i); nengel@6: VMS_App__free(args->line); nengel@8: return; nengel@2: } nengel@3: VSsTaskType draw_edges_taskType = { nengel@3: .fn = &draw_edges_task, nengel@9: .numDeps = 3, nengel@3: .sizeOfArgs = sizeof(draw_edges_taskArgs), nengel@9: .depsTypes = draw_edges_taskArgTypes, nengel@9: .depsSizes = draw_edges_taskArgSizes}; nengel@2: nengel@3: nengel@7: static void decode_mb_in_slice(H264Context *h, MBRecContext *d, SliceBufferEntry *sbe){ nengel@2: int i,j; nengel@2: nengel@2: SuperMBContext *smbc = acquire_smbc(h); nengel@2: int smb_height =smbc->nsmb_height, smb_width= smbc->nsmb_width; nengel@2: SuperMBTask *smbs = smbc->smbs[0]; nengel@2: nengel@2: SuperMBTask *sm=NULL, *sml, *smur; nengel@2: for(j=0; j< smb_height; j++){ nengel@2: for(i=0; i< smb_width; i++){ nengel@2: sm = smbs + j*smb_width + i; nengel@2: sml = sm - ((i > 0) ? 1: 0); nengel@2: smur = sm + (((i < smb_width-1) && (j >0)) ? -smb_width+1: 0); nengel@3: decode_super_mb_taskArgs decode_super_mb_task_args; nengel@3: decode_super_mb_task_args.d = d; nengel@3: decode_super_mb_task_args.sbe = sbe; nengel@3: decode_super_mb_task_args.smbc = smbc; nengel@3: decode_super_mb_task_args.ml = sml; nengel@3: decode_super_mb_task_args.mur = smur; nengel@3: decode_super_mb_task_args.m = sm; nengel@9: void** depsAddrs = malloc(decode_super_mb_taskType.numDeps * sizeof(void*)); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask), sizeof(SuperMBTask), sizeof(SuperMBTask)*/ nengel@9: depsAddrs[0] = d; nengel@9: depsAddrs[1] = sbe; nengel@9: depsAddrs[2] = sml; nengel@9: depsAddrs[3] = smur; nengel@9: depsAddrs[4] = sm; nengel@9: VSs__submit_task(&decode_super_mb_taskType, &decode_super_mb_task_args, depsAddrs); nengel@2: } nengel@3: draw_edges_taskArgs draw_edges_task_args; nengel@3: draw_edges_task_args.d = d; nengel@3: draw_edges_task_args.sbe = sbe; nengel@3: draw_edges_task_args.sm = sm; nengel@3: draw_edges_task_args.smbc = smbc; nengel@3: draw_edges_task_args.line = VMS_App__malloc( sizeof(int) ); nengel@3: *(draw_edges_task_args.line) = j; nengel@9: void** depsAddrs = malloc(sizeof (void*) * draw_edges_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask)*/ nengel@9: depsAddrs[0] = d; nengel@9: depsAddrs[1] = sbe; nengel@9: depsAddrs[2] = sm; nengel@9: VSs__submit_task(&draw_edges_taskType, &draw_edges_task_args, depsAddrs); nengel@2: } nengel@7: VSs__taskwait_on(sm); nengel@3: //#pragma omp taskwait on(*sm) nengel@2: nengel@2: release_smbc(h, smbc); nengel@2: } nengel@2: nengel@3: typedef struct{ nengel@3: MBRecContext *d; nengel@3: SliceBufferEntry *sbe; nengel@3: H264Context *h; nengel@3: } decode_slice_mb_taskArgs; nengel@3: nengel@9: int32 decode_slice_mb_taskArgTypes[2] = {INOUT, INOUT}; nengel@9: size_t decode_slice_mb_taskArgSizes[2] = {sizeof(MBRecContext), sizeof(SliceBufferEntry)}; nengel@3: nengel@3: //#pragma omp task inout(*d) inout(*sbe) nengel@7: static void decode_slice_mb_task(void *_data){ nengel@3: decode_slice_mb_taskArgs* args = (decode_slice_mb_taskArgs*) _data; nengel@3: MBRecContext *d = args->d; nengel@3: SliceBufferEntry *sbe = args->sbe; nengel@3: H264Context *h = args->h; nengel@3: nengel@2: H264Slice *s = &sbe->slice; nengel@2: nengel@2: for (int i=0; i<2; i++){ nengel@2: for(int j=0; j< s->ref_count[i]; j++){ nengel@2: if (s->ref_list_cpn[i][j] ==-1) nengel@2: continue; nengel@2: int k; nengel@2: for (k=0; k< h->max_dpb_cnt; k++){ nengel@2: if(h->dpb[k].reference >= 2 && h->dpb[k].cpn == s->ref_list_cpn[i][j]){ nengel@2: s->dp_ref_list[i][j] = &h->dpb[k]; nengel@2: break; nengel@2: } nengel@2: } nengel@2: } nengel@2: } nengel@2: nengel@3: //#pragma omp critical (dpb) nengel@7: VSs__start_critical(0); nengel@2: get_dpb_entry(h, s); nengel@7: VSs__end_critical(0); nengel@3: nengel@2: if (!h->no_mbd){ nengel@7: decode_mb_in_slice (h, d, sbe); nengel@2: } nengel@2: nengel@2: for (int i=0; irelease_cnt; i++){ nengel@2: for(int j=0; jmax_dpb_cnt; j++){ nengel@2: if(h->dpb[j].cpn== s->release_ref_cpn[i]){ nengel@3: //#pragma omp critical (dpb) nengel@7: VSs__start_critical(0); nengel@2: release_dpb_entry(h, &h->dpb[j], 2); nengel@7: VSs__end_critical(0); nengel@2: break; nengel@2: } nengel@2: } nengel@2: } nengel@2: s->release_cnt=0; nengel@8: return; nengel@2: } nengel@2: nengel@3: VSsTaskType decode_slice_mb_taskType = { nengel@3: .fn = &decode_slice_mb_task, nengel@9: .numDeps = 2, nengel@3: .sizeOfArgs = sizeof(decode_slice_mb_taskArgs), nengel@9: .depsTypes = decode_slice_mb_taskArgTypes, nengel@9: .depsSizes = decode_slice_mb_taskArgSizes}; nengel@3: nengel@2: // for static 3d wave nengel@2: /*-------------------------------------------------------------------------------*/ nengel@3: typedef struct{ nengel@3: MBRecContext *d; nengel@3: SliceBufferEntry *sbe; nengel@3: SuperMBTask *ml; nengel@3: SuperMBTask *mur; nengel@3: SuperMBTask *mprev; nengel@3: SuperMBTask *m; nengel@3: SuperMBContext *smbc; nengel@3: } decode_3dwave_super_mb_taskArgs; nengel@3: nengel@9: int32 decode_3dwave_super_mb_taskArgTypes[6] = {IN, IN, IN, IN, IN, INOUT}; nengel@9: size_t decode_3dwave_super_mb_taskArgSizes[6] = {sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask), nengel@9: sizeof(SuperMBTask), sizeof(SuperMBTask), sizeof(SuperMBTask)}; nengel@3: nengel@3: //#pragma omp task input(*d, *sbe, *ml, *mur, *mprev) inout(*m) nengel@7: static void decode_3dwave_super_mb_task(void *_data){ nengel@3: decode_3dwave_super_mb_taskArgs* args = (decode_3dwave_super_mb_taskArgs*) _data; nengel@3: MBRecContext *d = args->d; nengel@3: SliceBufferEntry *sbe = args->sbe; nengel@3: SuperMBTask *ml = args->ml; nengel@3: SuperMBTask *mur = args->mur; nengel@3: SuperMBTask *mprev = args->mprev; nengel@3: SuperMBTask *m = args->m; nengel@3: SuperMBContext *smbc = args->smbc; nengel@3: nengel@2: H264Slice *s = &sbe->slice; nengel@2: H264Mb *mbs = sbe->mbs; nengel@2: nengel@2: decode_super_mb_block(d, s, smbc, mbs, m->smb_x, m->smb_y); nengel@8: return; nengel@2: } nengel@2: nengel@3: VSsTaskType decode_3dwave_super_mb_taskType = { nengel@3: .fn = &decode_3dwave_super_mb_task, nengel@9: .numDeps = 6, nengel@3: .sizeOfArgs = sizeof(decode_3dwave_super_mb_taskArgs), nengel@9: .depsTypes = decode_3dwave_super_mb_taskArgTypes, nengel@9: .depsSizes = decode_3dwave_super_mb_taskArgSizes}; nengel@3: nengel@2: // int init_ref_count=0; nengel@3: typedef struct{ nengel@3: MBRecContext *d; nengel@3: SliceBufferEntry *sbe; nengel@3: int* init; nengel@3: H264Context *h; nengel@3: } init_ref_list_and_get_dpb_taskArgs; nengel@3: nengel@9: int32 init_ref_list_and_get_dpb_taskArgTypes[3] = {INOUT, INOUT, INOUT}; nengel@9: size_t init_ref_list_and_get_dpb_taskArgSizes[3] = {sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(int)}; nengel@3: nengel@3: //#pragma omp task inout(*d, *sbe, *init) nengel@7: static void init_ref_list_and_get_dpb_task(void *_data){ nengel@3: init_ref_list_and_get_dpb_taskArgs* args = (init_ref_list_and_get_dpb_taskArgs*) _data; nengel@3: MBRecContext *d = args->d; nengel@3: SliceBufferEntry *sbe = args->sbe; nengel@3: int* initp = args->init; nengel@3: H264Context *h = args->h; nengel@3: nengel@2: H264Slice *s = &sbe->slice; nengel@2: for (int i=0; i<2; i++){ nengel@2: for(int j=0; j< s->ref_count[i]; j++){ nengel@2: if (s->ref_list_cpn[i][j] ==-1) nengel@2: continue; nengel@2: int k; nengel@2: for (k=0; kmax_dpb_cnt; k++){ nengel@2: if(h->dpb[k].reference >= 2 && h->dpb[k].cpn == s->ref_list_cpn[i][j]){ nengel@2: s->dp_ref_list[i][j] = &h->dpb[k]; nengel@2: break; nengel@2: } nengel@2: } nengel@2: } nengel@2: } nengel@2: nengel@3: //#pragma omp critical (dpb) nengel@7: VSs__start_critical(0); nengel@2: get_dpb_entry(h, s); nengel@7: VSs__end_critical(0); nengel@3: nengel@8: return; nengel@2: } nengel@2: nengel@3: VSsTaskType init_ref_list_and_get_dpb_taskType = { nengel@3: .fn = &init_ref_list_and_get_dpb_task, nengel@9: .numDeps = 3, nengel@3: .sizeOfArgs = sizeof(init_ref_list_and_get_dpb_taskArgs), nengel@9: .depsTypes = init_ref_list_and_get_dpb_taskArgTypes, nengel@9: .depsSizes = init_ref_list_and_get_dpb_taskArgSizes}; nengel@3: nengel@7: static SuperMBTask* add_decode_slice_3dwave_tasks(MBRecContext *d, SliceBufferEntry *sbe, SuperMBContext *smbc, int k){ nengel@2: int i,j; nengel@2: nengel@5: int32* taskID; nengel@5: nengel@2: int smb_3d_height =smbc->nsmb_3dheight; nengel@2: int smb_height =smbc->nsmb_height, smb_width= smbc->nsmb_width; nengel@2: int smb_diff_prev = smb_height - smb_3d_height; nengel@2: SuperMBTask *sm=NULL, *sml, *smur, *smprev; nengel@2: nengel@2: SuperMBTask *smbs = smbc->smbs[smbc->index++]; smbc->index%=2; nengel@2: SuperMBTask *smbs_prev = smbc->smbs[smbc->index]; // index rotates -> next == prev nengel@2: nengel@2: for(j=0; j 0) ? 1: 0); nengel@2: smur = sm + (((i < smb_width-1) && (j >0)) ? -smb_width+1: 0); nengel@2: smprev = smbs_prev + (j + smb_diff_prev+1)*smb_width -1; nengel@3: decode_3dwave_super_mb_taskArgs decode_3dwave_super_mb_task_args; nengel@3: decode_3dwave_super_mb_task_args.d = d; nengel@3: decode_3dwave_super_mb_task_args.sbe = sbe; nengel@3: decode_3dwave_super_mb_task_args.smbc = smbc; nengel@3: decode_3dwave_super_mb_task_args.ml = sml; nengel@3: decode_3dwave_super_mb_task_args.mur = smur; nengel@3: decode_3dwave_super_mb_task_args.mprev = smprev; nengel@3: decode_3dwave_super_mb_task_args.m = sm; nengel@7: taskID = VSs__create_taskID_of_size(3 ); nengel@9: void** depsAddrs = malloc(sizeof(void*) * decode_3dwave_super_mb_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask), nengel@9: sizeof(SuperMBTask), sizeof(SuperMBTask), sizeof(SuperMBTask)*/ nengel@9: depsAddrs[0] = d; nengel@9: depsAddrs[1] = sbe; nengel@9: depsAddrs[2] = sml; nengel@9: depsAddrs[3] = smur; nengel@9: depsAddrs[4] = smprev; nengel@5: taskID[1] = k; nengel@5: taskID[2] = j; nengel@5: taskID[3] = i; nengel@9: VSs__submit_task_with_ID(&decode_3dwave_super_mb_taskType, &decode_3dwave_super_mb_task_args, depsAddrs, taskID); nengel@2: } nengel@3: draw_edges_taskArgs draw_edges_task_args; nengel@3: draw_edges_task_args.d = d; nengel@3: draw_edges_task_args.sbe = sbe; nengel@3: draw_edges_task_args.sm = sm; nengel@3: draw_edges_task_args.smbc = smbc; nengel@3: draw_edges_task_args.line = VMS_App__malloc( sizeof(int) ); nengel@3: *(draw_edges_task_args.line) = j; nengel@9: void** depsAddrs = malloc(sizeof (void*) * draw_edges_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask)*/ nengel@9: depsAddrs[0] = d; nengel@9: depsAddrs[1] = sbe; nengel@9: depsAddrs[2] = sm; nengel@7: taskID = VSs__create_taskID_of_size(3); nengel@5: taskID[1] = k; nengel@5: taskID[2] = j; nengel@5: taskID[3] = i; nengel@9: VSs__submit_task_with_ID(&draw_edges_taskType, &draw_edges_task_args, depsAddrs, taskID); nengel@2: } nengel@2: nengel@2: for(; j< smb_height; j++){ nengel@2: for(i=0; i< smb_width; i++){ nengel@2: sm = smbs + j*smb_width + i; nengel@2: sml = sm - ((i > 0) ? 1: 0); nengel@2: smur = sm + (((i < smb_width-1) && (j >0)) ? -smb_width+1: 0); nengel@3: decode_super_mb_taskArgs decode_super_mb_task_args; nengel@3: decode_super_mb_task_args.d = d; nengel@3: decode_super_mb_task_args.sbe = sbe; nengel@3: decode_super_mb_task_args.smbc = smbc; nengel@3: decode_super_mb_task_args.ml = sml; nengel@3: decode_super_mb_task_args.mur = smur; nengel@3: decode_super_mb_task_args.m = sm; nengel@9: void** depsAddrs = malloc(sizeof(void*) * decode_super_mb_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask), sizeof(SuperMBTask), sizeof(SuperMBTask)*/ nengel@9: depsAddrs[0] = d; nengel@9: depsAddrs[1] = sbe; nengel@9: depsAddrs[2] = sml; nengel@9: depsAddrs[3] = smur; nengel@9: depsAddrs[4] = sm; nengel@7: taskID = VSs__create_taskID_of_size(3 ); nengel@5: taskID[1] = k; nengel@5: taskID[2] = j; nengel@5: taskID[3] = i; nengel@9: VSs__submit_task_with_ID(&decode_super_mb_taskType, &decode_super_mb_task_args, depsAddrs, taskID); nengel@2: } nengel@3: draw_edges_taskArgs draw_edges_task_args; nengel@3: draw_edges_task_args.d = d; nengel@3: draw_edges_task_args.sbe = sbe; nengel@3: draw_edges_task_args.sm = sm; nengel@3: draw_edges_task_args.smbc = smbc; nengel@3: draw_edges_task_args.line = VMS_App__malloc( sizeof(int) ); nengel@3: *(draw_edges_task_args.line) = j; nengel@9: void** depsAddrs = malloc(sizeof (void*) * draw_edges_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask)*/ nengel@9: depsAddrs[0] = d; nengel@9: depsAddrs[1] = sbe; nengel@9: depsAddrs[2] = sm; nengel@7: taskID = VSs__create_taskID_of_size(3); nengel@5: taskID[1] = k; nengel@5: taskID[2] = j; nengel@5: taskID[3] = i; nengel@9: VSs__submit_task_with_ID(&draw_edges_taskType, &draw_edges_task_args, depsAddrs, taskID); nengel@2: } nengel@2: return sm; nengel@2: } nengel@2: nengel@3: typedef struct{ nengel@3: MBRecContext *d; nengel@3: SliceBufferEntry *sbe; nengel@3: SuperMBTask *lastsmb; nengel@3: int* release; nengel@3: H264Context *h; nengel@3: SuperMBContext *smbc; nengel@3: } release_ref_list_taskArgs; nengel@3: nengel@9: int32 release_ref_list_taskArgTypes[4] = {INOUT, INOUT, IN, INOUT}; nengel@9: size_t release_ref_list_taskArgSizes[4] = {sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask), sizeof(int)}; nengel@3: nengel@3: //#pragma omp task inout(*d, *sbe, *release) input (*lastsmb) nengel@7: static void release_ref_list_task(void *_data){ nengel@3: release_ref_list_taskArgs* args = (release_ref_list_taskArgs*) _data; nengel@3: MBRecContext *d = args->d; nengel@3: SliceBufferEntry *sbe = args->sbe; nengel@3: SuperMBTask *lastsmb = args->lastsmb; nengel@3: int* releasep = args->release; nengel@3: H264Context *h = args->h; nengel@3: SuperMBContext *smbc = args->smbc; nengel@3: nengel@2: H264Slice *s = &sbe->slice; nengel@2: for (int i=0; irelease_cnt; i++){ nengel@2: for(int j=0; jmax_dpb_cnt; j++){ nengel@2: if(h->dpb[j].cpn== s->release_ref_cpn[i]){ nengel@3: //#pragma omp critical (dpb) nengel@7: VSs__start_critical(0); nengel@2: release_dpb_entry(h, &h->dpb[j], 2); nengel@7: VSs__end_critical(0); nengel@2: break; nengel@2: } nengel@2: } nengel@2: } nengel@2: s->release_cnt=0; nengel@2: nengel@2: release_smbc(h, smbc); nengel@2: nengel@8: return; nengel@2: } nengel@2: nengel@3: VSsTaskType release_ref_list_taskType = { nengel@3: .fn = &release_ref_list_task, nengel@9: .numDeps = 4, nengel@3: .sizeOfArgs = sizeof(release_ref_list_taskArgs), nengel@9: .depsTypes = release_ref_list_taskArgTypes, nengel@9: .depsSizes = release_ref_list_taskArgSizes}; nengel@3: nengel@2: // static void decode_mb_static_3dwave(H264Context *h, int mb_height, int mb_width, MBRecContext *d, H264Slice *s, H264Mb *mbs, SuperMBTask *smbs, SuperMBTask *smbs_prev){ nengel@2: // nengel@2: // } nengel@2: /*-------------------------------------------------------------------------------*/ nengel@2: //end for static 3d wave nengel@2: nengel@3: typedef struct{ nengel@3: OutputContext *oc; nengel@3: SliceBufferEntry *sbe; nengel@3: H264Context *h; nengel@3: } output_taskArgs; nengel@3: nengel@9: int32 output_taskArgTypes[2] = {INOUT, IN}; nengel@9: size_t output_taskArgSizes[2] = {sizeof(OutputContext), sizeof(SliceBufferEntry)}; nengel@3: nengel@3: //#pragma omp task inout (*oc) input(*sbe) nengel@7: static void output_task(void *_data){ nengel@3: output_taskArgs* args = (output_taskArgs*) _data; nengel@3: OutputContext *oc = args->oc; nengel@3: SliceBufferEntry *sbe = args->sbe; nengel@3: H264Context *h = args->h; nengel@3: nengel@2: DecodedPicture* out =output_frame(h, oc, sbe->slice.curr_pic, h->ofile, h->frame_width, h->frame_height); nengel@2: if (out){ nengel@3: //#pragma omp critical (dpb) nengel@7: VSs__start_critical(0); nengel@2: release_dpb_entry(h, out, 1); nengel@7: VSs__end_critical(0); nengel@2: } nengel@6: //print_report(oc->frame_number, oc->video_size, 0, h->verbose); nengel@3: nengel@8: return; nengel@2: } nengel@2: nengel@3: VSsTaskType output_taskType = { nengel@3: .fn = &output_task, nengel@9: .numDeps = 2, nengel@3: .sizeOfArgs = sizeof(output_taskArgs), nengel@9: .depsTypes = output_taskArgTypes, nengel@9: .depsSizes = output_taskArgSizes}; nengel@3: nengel@2: /* nengel@2: * The following code is the main loop of the file converter nengel@2: */ nengel@3: nengel@7: int h264_decode_ompss( H264Context *h) { nengel@3: nengel@2: const int bufs = h->pipe_bufs; nengel@2: nengel@2: ParserContext *pc; nengel@2: NalContext *nc; nengel@2: EntropyContext *ec[bufs]; nengel@2: MBRecContext *rc[2]; nengel@2: OutputContext *oc; nengel@2: SliceBufferEntry *sbe; nengel@2: SuperMBContext *smbc; nengel@2: nengel@2: DecodedPicture *out; nengel@2: int frames=0; nengel@4: nengel@4: int32* taskID; nengel@9: void** depsAddrs; nengel@2: nengel@2: #if HAVE_LIBSDL2 nengel@2: pthread_t sdl_thr; nengel@2: if (h->display){ nengel@2: pthread_create(&sdl_thr, NULL, sdl_thread, h); nengel@2: } nengel@2: #endif nengel@3: /*sbe= VMS_WL__malloc(sizeof(SliceBufferEntry) * bufs); nengel@3: if (sbe) nengel@3: memset(sbe, 0, sizeof(SliceBufferEntry) * bufs);*/ nengel@2: sbe= av_mallocz(sizeof(SliceBufferEntry) * bufs); nengel@2: nengel@2: pc = get_parse_context(h->ifile); nengel@2: nc = get_nal_context(h->width, h->height); nengel@2: nengel@2: for(int i=0; istatic_3d && bufs < h->num_frames ){ nengel@2: int num_pre_ed =0; nengel@2: for (num_pre_ed=0; num_pre_ed< bufs -1 && !pc->final_frame; num_pre_ed++){ nengel@3: parse_taskArgs parse_task_args; nengel@3: parse_task_args.h = h; nengel@3: parse_task_args.pc = pc; nengel@3: parse_task_args.nc = nc; nengel@3: parse_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * parse_taskType.numDeps); nengel@9: /*sizeof(ParserContext), sizeof(NalContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = pc; nengel@9: depsAddrs[1] = nc; nengel@9: depsAddrs[2] = &sbe[k%bufs]; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 1; nengel@5: taskID[2] = k; nengel@9: VSs__submit_task_with_ID(&parse_taskType, &parse_task_args, depsAddrs, taskID); nengel@3: nengel@3: decode_slice_entropy_taskArgs decode_slice_entropy_task_args; nengel@3: decode_slice_entropy_task_args.h = h; nengel@3: decode_slice_entropy_task_args.ec = ec[k%bufs]; nengel@3: decode_slice_entropy_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * decode_slice_entropy_taskType.numDeps); nengel@9: /*sizeof(EntropyContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = ec[k%bufs]; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 2; nengel@5: taskID[2] = k; nengel@9: VSs__submit_task_with_ID(&decode_slice_entropy_taskType, &decode_slice_entropy_task_args, depsAddrs, taskID); nengel@3: //#pragma omp taskwait on(*pc) nengel@7: VSs__taskwait_on(pc); nengel@2: k++; nengel@2: } nengel@2: nengel@2: while(!pc->final_frame && frames++ < h->num_frames && !h->quit){ nengel@3: parse_taskArgs parse_task_args; nengel@3: parse_task_args.h = h; nengel@3: parse_task_args.pc = pc; nengel@3: parse_task_args.nc = nc; nengel@3: parse_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * parse_taskType.numDeps); nengel@9: /*sizeof(ParserContext), sizeof(NalContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = pc; nengel@9: depsAddrs[1] = nc; nengel@9: depsAddrs[2] = &sbe[k%bufs]; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 3; nengel@5: taskID[2] = k; nengel@9: VSs__submit_task_with_ID(&parse_taskType, &parse_task_args, depsAddrs, taskID); nengel@3: nengel@3: decode_slice_entropy_taskArgs decode_slice_entropy_task_args; nengel@3: decode_slice_entropy_task_args.h = h; nengel@3: decode_slice_entropy_task_args.ec = ec[k%bufs]; nengel@3: decode_slice_entropy_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * decode_slice_entropy_taskType.numDeps); nengel@9: /*sizeof(EntropyContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = ec[k%bufs]; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 4; nengel@5: taskID[2] = k; nengel@9: VSs__submit_task_with_ID(&decode_slice_entropy_taskType, &decode_slice_entropy_task_args, depsAddrs, taskID); nengel@2: nengel@2: k++; nengel@3: nengel@3: init_ref_list_and_get_dpb_taskArgs init_ref_list_and_get_dpb_task_args; nengel@3: init_ref_list_and_get_dpb_task_args.h = h; nengel@3: init_ref_list_and_get_dpb_task_args.d = rc[k%2]; nengel@3: init_ref_list_and_get_dpb_task_args.sbe = &sbe[k%bufs]; nengel@3: init_ref_list_and_get_dpb_task_args.init = &init; nengel@9: depsAddrs = malloc(sizeof(void*) * init_ref_list_and_get_dpb_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(int)*/ nengel@9: depsAddrs[0] = rc[k%2]; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@9: depsAddrs[2] = &init; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 5; nengel@5: taskID[2] = k; nengel@9: VSs__submit_task_with_ID(&init_ref_list_and_get_dpb_taskType, &init_ref_list_and_get_dpb_task_args, depsAddrs, taskID); nengel@2: nengel@2: smbc = acquire_smbc(h); nengel@7: SuperMBTask *lastsmb= add_decode_slice_3dwave_tasks(rc[k%2], &sbe[k%bufs], smbc, k); nengel@3: release_ref_list_taskArgs release_ref_list_task_args; nengel@3: release_ref_list_task_args.h = h; nengel@3: release_ref_list_task_args.smbc = smbc; nengel@3: release_ref_list_task_args.d = rc[k%2]; nengel@3: release_ref_list_task_args.sbe = &sbe[k%bufs]; nengel@3: release_ref_list_task_args.lastsmb = lastsmb; nengel@3: release_ref_list_task_args.release = &release; nengel@9: depsAddrs = malloc(sizeof(void*) * release_ref_list_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask), sizeof(int)*/ nengel@9: depsAddrs[0] = rc[k%2]; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@9: depsAddrs[2] = smbc; nengel@9: depsAddrs[3] = &release; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 6; nengel@5: taskID[2] = k; nengel@9: VSs__submit_task_with_ID(&release_ref_list_taskType, &release_ref_list_task_args, depsAddrs, taskID); nengel@2: nengel@3: output_taskArgs output_task_args; nengel@3: output_task_args.h = h; nengel@3: output_task_args.oc = oc; nengel@3: output_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * output_taskType.numDeps); nengel@9: /*sizeof(OutputContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = oc; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 7; nengel@5: taskID[2] = k; nengel@9: VSs__submit_task_with_ID(&output_taskType, &output_task_args, depsAddrs, taskID); nengel@3: //#pragma omp taskwait on(*pc) nengel@7: VSs__taskwait_on(pc); nengel@2: } nengel@2: nengel@2: for (int i=0; i< num_pre_ed; i++){ nengel@2: k++; nengel@3: init_ref_list_and_get_dpb_taskArgs init_ref_list_and_get_dpb_task_args; nengel@3: init_ref_list_and_get_dpb_task_args.h = h; nengel@3: init_ref_list_and_get_dpb_task_args.d = rc[k%2]; nengel@3: init_ref_list_and_get_dpb_task_args.sbe = &sbe[k%bufs]; nengel@3: init_ref_list_and_get_dpb_task_args.init = &init; nengel@9: depsAddrs = malloc(sizeof(void*) * init_ref_list_and_get_dpb_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(int)*/ nengel@9: depsAddrs[0] = rc[k%2]; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@9: depsAddrs[2] = &init; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 8; nengel@4: taskID[2] = i; nengel@9: VSs__submit_task_with_ID(&init_ref_list_and_get_dpb_taskType, &init_ref_list_and_get_dpb_task_args, depsAddrs, taskID); nengel@2: smbc = acquire_smbc(h); nengel@7: SuperMBTask *lastsmb= add_decode_slice_3dwave_tasks(rc[k%2], &sbe[k%bufs], smbc, k); nengel@3: release_ref_list_taskArgs release_ref_list_task_args; nengel@3: release_ref_list_task_args.h = h; nengel@3: release_ref_list_task_args.smbc = smbc; nengel@3: release_ref_list_task_args.d = rc[k%2]; nengel@3: release_ref_list_task_args.sbe = &sbe[k%bufs]; nengel@3: release_ref_list_task_args.lastsmb = lastsmb; nengel@3: release_ref_list_task_args.release = &release; nengel@9: depsAddrs = malloc(sizeof(void*) * release_ref_list_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry), sizeof(SuperMBTask), sizeof(int)*/ nengel@9: depsAddrs[0] = rc[k%2]; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@9: depsAddrs[2] = smbc; nengel@9: depsAddrs[3] = &release; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 9; nengel@5: taskID[2] = k; nengel@9: VSs__submit_task_with_ID(&release_ref_list_taskType, &release_ref_list_task_args, depsAddrs, taskID); nengel@2: nengel@3: output_taskArgs output_task_args; nengel@3: output_task_args.h = h; nengel@3: output_task_args.oc = oc; nengel@3: output_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * output_taskType.numDeps); nengel@9: /*sizeof(OutputContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = oc; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@7: taskID = VSs__create_taskID_of_size(2); nengel@4: taskID[1] = 10; nengel@5: taskID[2] = k; nengel@9: VSs__submit_task_with_ID(&output_taskType, &output_task_args, depsAddrs, taskID); nengel@2: } nengel@2: nengel@2: } else { nengel@2: while(!pc->final_frame && frames++ < h->num_frames && !h->quit){ nengel@4: nengel@7: taskID = VSs__create_taskID_of_size(1); nengel@3: taskID[1] = frames*10+1; nengel@3: parse_taskArgs parse_task_args; nengel@3: parse_task_args.h = h; nengel@3: parse_task_args.pc = pc; nengel@3: parse_task_args.nc = nc; nengel@3: parse_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * parse_taskType.numDeps); nengel@9: /*sizeof(ParserContext), sizeof(NalContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = pc; nengel@9: depsAddrs[1] = nc; nengel@9: depsAddrs[2] = &sbe[k%bufs]; nengel@9: VSs__submit_task_with_ID(&parse_taskType, &parse_task_args, depsAddrs, taskID); nengel@2: nengel@7: taskID = VSs__create_taskID_of_size(1); nengel@3: taskID[1] = frames*10+2; nengel@3: decode_slice_entropy_taskArgs decode_slice_entropy_task_args; nengel@3: decode_slice_entropy_task_args.h = h; nengel@3: decode_slice_entropy_task_args.ec = ec[k%bufs]; nengel@3: decode_slice_entropy_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * decode_slice_entropy_taskType.numDeps); nengel@9: /*sizeof(EntropyContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = ec[k%bufs]; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@9: VSs__submit_task_with_ID(&decode_slice_entropy_taskType, &decode_slice_entropy_task_args, depsAddrs, taskID); nengel@2: nengel@7: taskID = VSs__create_taskID_of_size(1); nengel@3: taskID[1] = frames*10+3; nengel@3: decode_slice_mb_taskArgs decode_slice_mb_task_args; nengel@3: decode_slice_mb_task_args.h = h; nengel@3: decode_slice_mb_task_args.d = rc[0]; nengel@3: decode_slice_mb_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * decode_slice_mb_taskType.numDeps); nengel@9: /*sizeof(MBRecContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = rc[0]; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@9: VSs__submit_task_with_ID(&decode_slice_mb_taskType, &decode_slice_mb_task_args, depsAddrs, taskID); nengel@2: nengel@7: taskID = VSs__create_taskID_of_size(1); nengel@3: taskID[1] = frames*10+4; nengel@3: output_taskArgs output_task_args; nengel@3: output_task_args.h = h; nengel@3: output_task_args.oc = oc; nengel@3: output_task_args.sbe = &sbe[k%bufs]; nengel@9: depsAddrs = malloc(sizeof(void*) * output_taskType.numDeps); nengel@9: /*sizeof(OutputContext), sizeof(SliceBufferEntry)*/ nengel@9: depsAddrs[0] = oc; nengel@9: depsAddrs[1] = &sbe[k%bufs]; nengel@9: VSs__submit_task_with_ID(&output_taskType, &output_task_args, depsAddrs, taskID); nengel@3: //#pragma omp taskwait on(*pc) nengel@7: VSs__taskwait_on(pc); nengel@2: k++; nengel@2: } nengel@2: } nengel@3: //#pragma omp taskwait nengel@7: VSs__taskwait(); nengel@3: nengel@2: while ((out=output_frame(h, oc, NULL, h->ofile, h->frame_width, h->frame_height))) ; nengel@2: nengel@6: //print_report(oc->frame_number, oc->video_size, 1, h->verbose); nengel@2: h->num_frames = oc->frame_number; nengel@2: /* finished ! */ nengel@2: nengel@2: free_parse_context(pc); nengel@2: free_nal_context (nc); nengel@2: free_output_context(oc); nengel@2: for (int i=0; idisplay){ nengel@2: signal_sdl_exit(h); nengel@2: pthread_join(sdl_thr, NULL); nengel@2: } nengel@2: #endif nengel@2: nengel@7: return 0; nengel@2: }