static GF_Err OSVC_ProcessData(GF_MediaDecoder *ifcg, char *inBuffer, u32 inBufferLength, u16 ES_ID, u32 *CTS, char *outBuffer, u32 *outBufferLength, u8 PaddingBits, u32 mmlevel) { s32 got_pic; OPENSVCFRAME pic; int Layer[4]; u32 i, nalu_size, sc_size; u8 *ptr; OSVCDec *ctx = (OSVCDec*) ifcg->privateStack; u32 curMaxDqId = ctx->MaxDqId; if (!ES_ID || !ctx->codec) { *outBufferLength = 0; return GF_OK; } if (*outBufferLength < ctx->out_size) { *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } ctx->MaxDqId = GetDqIdMax((unsigned char *) inBuffer, inBufferLength, ctx->nalu_size_length, ctx->DqIdTable, ctx->nalu_size_length ? 1 : 0); if (!ctx->init_layer_set) { //AVC stream in a h264 file if (ctx->MaxDqId == -1) ctx->MaxDqId = 0; ctx->CurrentDqId = ctx->MaxDqId; ctx->init_layer_set = 1; } if (curMaxDqId != ctx->MaxDqId) ctx->CurrentDqId = ctx->MaxDqId; /*decode only current layer*/ SetCommandLayer(Layer, ctx->MaxDqId, ctx->CurrentDqId, &ctx->TemporalCom, ctx->TemporalId); got_pic = 0; nalu_size = 0; ptr = (u8 *) inBuffer; if (!ctx->nalu_size_length) { u32 size; sc_size = 0; size = gf_media_nalu_next_start_code((u8 *) inBuffer, inBufferLength, &sc_size); if (sc_size) { ptr += size+sc_size; assert(inBufferLength >= size+sc_size); inBufferLength -= size+sc_size; } else { /*no annex-B start-code found, discard */ *outBufferLength = 0; return GF_OK; } } while (inBufferLength) { if (ctx->nalu_size_length) { for (i=0; i<ctx->nalu_size_length; i++) { nalu_size = (nalu_size<<8) + ptr[i]; } ptr += ctx->nalu_size_length; } else { u32 sc_size; nalu_size = gf_media_nalu_next_start_code(ptr, inBufferLength, &sc_size); } #ifndef GPAC_DISABLE_LOG switch (ptr[0] & 0x1F) { case GF_AVC_NALU_SEQ_PARAM: case GF_AVC_NALU_SVC_SUBSEQ_PARAM: { u32 sps_id; gf_avc_get_sps_info((char *)ptr, nalu_size, &sps_id, NULL, NULL, NULL, NULL); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] ES%d: SPS id=\"%d\" code=\"%d\" size=\"%d\"\n", ES_ID, sps_id, ptr[0] & 0x1F, nalu_size)); } break; case GF_AVC_NALU_PIC_PARAM: { u32 sps_id, pps_id; gf_avc_get_pps_info((char *)ptr, nalu_size, &pps_id, &sps_id); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] ES%d: PPS id=\"%d\" code=\"%d\" size=\"%d\" sps_id=\"%d\"\n", ES_ID, pps_id, ptr[0] & 0x1F, nalu_size, sps_id)); } break; default: GF_LOG(GF_LOG_DEBUG, GF_LOG_CODEC, ("[SVC Decoder] ES%d: NALU code=\"%d\" size=\"%d\"\n", ES_ID, ptr[0] & 0x1F, nalu_size)); } #endif if (!ctx->state_found) { u8 nal_type = (ptr[0] & 0x1F) ; switch (nal_type) { case GF_AVC_NALU_SEQ_PARAM: case GF_AVC_NALU_PIC_PARAM: if (ctx->baseES_ID == ES_ID) ctx->state_found = 1; break; } } if (ctx->state_found) { if (!got_pic) got_pic = decodeNAL(ctx->codec, ptr, nalu_size, &pic, Layer); else decodeNAL(ctx->codec, ptr, nalu_size, &pic, Layer); } ptr += nalu_size; if (ctx->nalu_size_length) { if (inBufferLength < nalu_size + ctx->nalu_size_length) break; inBufferLength -= nalu_size + ctx->nalu_size_length; } else { if (!sc_size || (inBufferLength < nalu_size + sc_size)) break; inBufferLength -= nalu_size + sc_size; ptr += sc_size; } } if (got_pic!=1) { *outBufferLength = 0; return GF_OK; } if ((curMaxDqId != ctx->MaxDqId) || (pic.Width != ctx->width) || (pic.Height!=ctx->height)) { GF_LOG(GF_LOG_INFO, GF_LOG_CODEC, ("[SVC Decoder] Resizing from %dx%d to %dx%d\n", ctx->width, ctx->height, pic.Width, pic.Height )); ctx->width = pic.Width; ctx->stride = pic.Width + 32; ctx->height = pic.Height; ctx->out_size = ctx->stride * ctx->height * 3 / 2; /*always force layer resize*/ *outBufferLength = ctx->out_size; return GF_BUFFER_TOO_SMALL; } *outBufferLength = ctx->out_size; memcpy(outBuffer, pic.pY[0], ctx->stride*ctx->height); memcpy(outBuffer + ctx->stride * ctx->height, pic.pU[0], ctx->stride*ctx->height/4); memcpy(outBuffer + 5*ctx->stride * ctx->height/4, pic.pV[0], ctx->stride*ctx->height/4); return GF_OK; }
static GF_Err VTB_RewriteNALs(VTBDec *ctx, char *inBuffer, u32 inBufferLength, char **out_buffer, u32 *out_size) { u32 i, sc_size; char *ptr = inBuffer; u32 nal_size; GF_Err e = GF_OK; GF_BitStream *bs = NULL; *out_buffer = NULL; *out_size = 0; if (!ctx->nalu_size_length) { nal_size = gf_media_nalu_next_start_code((u8 *) inBuffer, inBufferLength, &sc_size); if (!sc_size) return GF_NON_COMPLIANT_BITSTREAM; ptr += nal_size + sc_size; assert(inBufferLength >= nal_size + sc_size); inBufferLength -= nal_size + sc_size; } while (inBufferLength) { Bool add_nal = GF_TRUE; u8 nal_type; if (ctx->nalu_size_length) { for (i=0; i<ctx->nalu_size_length; i++) { nal_size = (nal_size<<8) + ptr[i]; } ptr += ctx->nalu_size_length; } else { nal_size = gf_media_nalu_next_start_code(ptr, inBufferLength, &sc_size); } nal_type = ptr[0] & 0x1F; switch (nal_type) { case GF_AVC_NALU_SEQ_PARAM: if (!ctx->vtb_session) { ctx->sps = gf_malloc(sizeof(char)*nal_size); memcpy(ctx->sps, ptr, sizeof(char)*nal_size); ctx->sps_size=nal_size; add_nal = GF_FALSE; } break; case GF_AVC_NALU_PIC_PARAM: if (!ctx->vtb_session) { ctx->pps = gf_malloc(sizeof(char)*nal_size); memcpy(ctx->pps, ptr, sizeof(char)*nal_size); ctx->pps_size=nal_size; add_nal = GF_FALSE; } break; case GF_AVC_NALU_ACCESS_UNIT: case GF_AVC_NALU_END_OF_SEQ: case GF_AVC_NALU_END_OF_STREAM: case GF_AVC_NALU_FILLER_DATA: add_nal = GF_FALSE; break; default: break; } //if sps and pps are ready, init decoder if (!ctx->vtb_session && ctx->sps && ctx->pps) { e = VTBDec_InitDecoder(ctx, GF_TRUE); if (e) return e; } if (add_nal && !ctx->vtb_session) add_nal = GF_FALSE; if (add_nal) { if (!bs) bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_u32(bs, nal_size); gf_bs_write_data(bs, ptr, nal_size); } ptr += nal_size; if (ctx->nalu_size_length) { if (inBufferLength < nal_size + ctx->nalu_size_length) break; inBufferLength -= nal_size + ctx->nalu_size_length; } else { if (!sc_size || (inBufferLength < nal_size + sc_size)) break; inBufferLength -= nal_size + sc_size; ptr += sc_size; } } if (bs) { gf_bs_get_content(bs, out_buffer, out_size); gf_bs_del(bs); } return e; }
static GF_Err MCDec_ParseNALs(MCDec *ctx, char *inBuffer, u32 inBufferLength, char **out_buffer, u32 *out_size) { u32 i, sc_size; char *ptr = inBuffer; u32 nal_size; GF_Err e = GF_OK; GF_BitStream *bs = NULL; if (out_buffer) { *out_buffer = NULL; *out_size = 0; } if (!ctx->nalu_size_length) { sc_size = 0; nal_size = gf_media_nalu_next_start_code((u8 *)inBuffer, inBufferLength, &sc_size); if (!sc_size) return GF_NON_COMPLIANT_BITSTREAM; ptr += nal_size + sc_size; assert(inBufferLength >= nal_size + sc_size); inBufferLength -= nal_size + sc_size; } while (inBufferLength) { Bool add_nal = GF_TRUE; u8 nal_type, nal_hdr; GF_BitStream *nal_bs = NULL; if (ctx->nalu_size_length) { nal_size = 0; for (i = 0; i<ctx->nalu_size_length; i++) { nal_size = (nal_size << 8) + ((u8)ptr[i]); } ptr += ctx->nalu_size_length; } else { nal_size = gf_media_nalu_next_start_code(ptr, inBufferLength, &sc_size); } nal_bs = gf_bs_new(ptr, nal_size, GF_BITSTREAM_READ); nal_hdr = gf_bs_read_u8(nal_bs); nal_type = nal_hdr & 0x1F; switch (nal_type) { case GF_AVC_NALU_SEQ_PARAM: MCDec_RegisterParameterSet(ctx, ptr, nal_size, GF_TRUE); add_nal = GF_FALSE; break; case GF_AVC_NALU_PIC_PARAM: MCDec_RegisterParameterSet(ctx, ptr, nal_size, GF_FALSE); add_nal = GF_FALSE; break; case GF_AVC_NALU_ACCESS_UNIT: case GF_AVC_NALU_END_OF_SEQ: case GF_AVC_NALU_END_OF_STREAM: case GF_AVC_NALU_FILLER_DATA: add_nal = GF_FALSE; break; default: break; } gf_media_avc_parse_nalu(nal_bs, nal_hdr, &ctx->avc); gf_bs_del(nal_bs); if ((nal_type <= GF_AVC_NALU_IDR_SLICE) && ctx->avc.s_info.sps) { if (ctx->avc.sps_active_idx != ctx->active_sps) { ctx->reconfig_needed = 1; ctx->active_sps = ctx->avc.sps_active_idx; ctx->active_pps = ctx->avc.s_info.pps->id; return GF_OK; } } //if sps and pps are ready, init decoder if (!ctx->codec && gf_list_count(ctx->SPSs) && gf_list_count(ctx->PPSs)) { e = MCDec_InitDecoder(ctx); if (e) return e; } if (!out_buffer) add_nal = GF_FALSE; else if (add_nal && !ctx->codec) add_nal = GF_FALSE; if (add_nal) { if (!bs) bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_u32(bs, nal_size); gf_bs_write_data(bs, ptr, nal_size); } ptr += nal_size; if (ctx->nalu_size_length) { if (inBufferLength < nal_size + ctx->nalu_size_length) break; inBufferLength -= nal_size + ctx->nalu_size_length; } else { if (!sc_size || (inBufferLength < nal_size + sc_size)) break; inBufferLength -= nal_size + sc_size; ptr += sc_size; } } if (bs) { gf_bs_get_content(bs, out_buffer, out_size); gf_bs_del(bs); } return e; }
int dc_gpac_video_isom_write(VideoOutputFile *video_output_file) { GF_Err ret; AVCodecContext *video_codec_ctx = video_output_file->codec_ctx; u32 sc_size = 0; u32 nalu_size = 0; u32 buf_len = video_output_file->encoded_frame_size; u8 *buf_ptr = video_output_file->vbuf; GF_BitStream *out_bs = gf_bs_new(NULL, 2 * buf_len, GF_BITSTREAM_WRITE); nalu_size = gf_media_nalu_next_start_code(buf_ptr, buf_len, &sc_size); if (nalu_size != 0) { gf_bs_write_u32(out_bs, nalu_size); gf_bs_write_data(out_bs, (const char*) buf_ptr, nalu_size); } if (sc_size) { buf_ptr += (nalu_size + sc_size); buf_len -= (nalu_size + sc_size); } while (buf_len) { nalu_size = gf_media_nalu_next_start_code(buf_ptr, buf_len, &sc_size); if (nalu_size != 0) { gf_bs_write_u32(out_bs, nalu_size); gf_bs_write_data(out_bs, (const char*) buf_ptr, nalu_size); } buf_ptr += nalu_size; if (!sc_size || (buf_len < nalu_size + sc_size)) break; buf_len -= nalu_size + sc_size; buf_ptr += sc_size; } gf_bs_get_content(out_bs, &video_output_file->sample->data, &video_output_file->sample->dataLength); //video_output_file->sample->data = //(char *) (video_output_file->vbuf + nalu_size + sc_size); //video_output_file->sample->dataLength = //video_output_file->encoded_frame_size - (sc_size + nalu_size); video_output_file->sample->DTS = video_codec_ctx->coded_frame->pkt_dts; video_output_file->sample->CTS_Offset = (s32) (video_codec_ctx->coded_frame->pts - video_output_file->sample->DTS); video_output_file->sample->IsRAP = video_codec_ctx->coded_frame->key_frame; GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("Isom Write: RAP %d , DTS "LLD" CTS offset %d \n", video_output_file->sample->IsRAP, video_output_file->sample->DTS, video_output_file->sample->CTS_Offset)); ret = gf_isom_fragment_add_sample(video_output_file->isof, video_output_file->trackID, video_output_file->sample, 1, video_output_file->use_source_timing ? (u32) video_output_file->frame_dur : 1, 0, 0, 0); if (ret != GF_OK) { gf_bs_del(out_bs); GF_LOG(GF_LOG_ERROR, GF_LOG_DASH, ("%s: gf_isom_fragment_add_sample\n", gf_error_to_string(ret))); return -1; } //free data but keep sample structure alive gf_free(video_output_file->sample->data); video_output_file->sample->data = NULL; video_output_file->sample->dataLength = 0; gf_bs_del(out_bs); return 0; }