Decode_Status VaapiDecoderH264::decodeNalu(H264NalUnit * nalu)
{
    Decode_Status status;

    switch (nalu->type) {
    case H264_NAL_SLICE_IDR:
        /* fall-through. IDR specifics are handled in initPicture() */
    case H264_NAL_SLICE:
        if (!m_gotSPS || !m_gotPPS)
            return DECODE_SUCCESS;
        status = decodeSlice(nalu);
        break;
    case H264_NAL_SPS:
        status = decodeSPS(nalu);
        break;
    case H264_NAL_PPS:
        status = decodePPS(nalu);
        break;
    case H264_NAL_SEI:
        status = decodeSEI(nalu);
        break;
    case H264_NAL_SEQ_END:
        status = decodeSequenceEnd();
        break;
    case H264_NAL_AU_DELIMITER:
        /* skip all Access Unit NALs */
        status = DECODE_SUCCESS;
        break;
    case H264_NAL_FILLER_DATA:
        /* skip all Filler Data NALs */
        status = DECODE_SUCCESS;
        break;
    default:
        WARNING("unsupported NAL unit type %d", nalu->type);
        status = DECODE_PARSER_FAIL;
        break;
    }

    return status;
}
예제 #2
0
파일: h264.cpp 프로젝트: emericg/MiniVideo
int h264_decode_nalu(DecodingContext_t *dc, const int64_t nalu_offset, const int64_t nalu_size)
{
    TRACE_1(H264, BLD_GREEN "h264_decode_nalu()" CLR_RESET);
    int retcode = FAILURE;

    // Goto correct data offset
    //bitstream_goto_offset(dc->bitstr, nalu_offset);
    buffer_feed_manual(dc->bitstr, nalu_offset, nalu_size);

    // Check header validity
    if (nalu_parse_header(dc->bitstr, dc->active_nalu))
    {
        TRACE_1(H264, "decode: " BLD_GREEN "NALU_TYPE %i (at %lli) " CLR_RESET,
                dc->active_nalu->nal_unit_type,
                bitstream_get_absolute_byte_offset(dc->bitstr));

        // Decode NAL Unit content
        switch (dc->active_nalu->nal_unit_type)
        {
            case NALU_TYPE_SLICE: //////////////////////////////////////
            {
                TRACE_1(H264, "This decoder only support IDR slice decoding!");
            }
            break;

            case NALU_TYPE_IDR: ////////////////////////////////////////
            {
                TRACE_INFO(H264, "> " BLD_GREEN "decodeIDR(%i at %lli)" CLR_RESET,
                           dc->idrCounter, bitstream_get_absolute_byte_offset(dc->bitstr));

                nalu_clean_sample(dc->bitstr);
                dc->IdrPicFlag = true;

                if (decode_slice(dc))
                {
                    retcode = SUCCESS;
                    dc->errorCounter = 0;
                    dc->idrCounter++;
                    dc->frameCounter++;
                }
                else
                    dc->errorCounter++;
            }
            break;

            case NALU_TYPE_AUD: ////////////////////////////////////////
            {
                nalu_clean_sample(dc->bitstr);

                aud_t aud;
                if (decodeAUD(dc->bitstr, &aud))
                {
                    retcode = SUCCESS;
                }
                else
                    dc->errorCounter++;
            }
            break;

            case NALU_TYPE_SEI: ////////////////////////////////////////
            {
                nalu_clean_sample(dc->bitstr);

                if (dc->active_sei != NULL)
                    free(dc->active_sei);

                dc->active_sei = (sei_t*)calloc(1, sizeof(sei_t));
                if (dc->active_sei)
                {
                    if (decodeSEI(dc->bitstr, dc->active_sei))
                    {
                        retcode = SUCCESS;
                        printSEI(NULL);
                    }
                    else
                        dc->errorCounter++;
                }
            }
            break;

            case NALU_TYPE_SPS: ////////////////////////////////////////
            {
                nalu_clean_sample(dc->bitstr);

                retcode = decodeSPS_legacy(dc);
/*
                sps_t *sps = (sps_t*)calloc(1, sizeof(sps_t));
                if (sps)
                {
                    if (decodeSPS(dc->bitstr, sps))
                    {
                        dc->sps_array[sps->seq_parameter_set_id] = sps;

                        dc->active_sps = sps->seq_parameter_set_id;
                        dc->profile_idc = sps->profile_idc;
                        dc->ChromaArrayType = sps->ChromaArrayType;

                        // Init some quantization tables
                        computeLevelScale4x4(dc, sps);
                        computeLevelScale8x8(dc, sps);

                        // Macroblocks "table" allocation (on macroblock **mbs_data):
                        dc->PicSizeInMbs = sps->FrameHeightInMbs * sps->PicWidthInMbs;
                        dc->mb_array = (Macroblock_t**)calloc(dc->PicSizeInMbs, sizeof(Macroblock_t*));

                        //printSPS(sps);
                        retcode = SUCCESS;
                    }
                    else
                        dc->errorCounter++;
                }
*/
            }
            break;

            case NALU_TYPE_PPS: ////////////////////////////////////////
            {
                nalu_clean_sample(dc->bitstr);

                pps_t *pps = (pps_t*)calloc(1, sizeof(pps_t));
                if (pps)
                {
                    if (decodePPS(dc->bitstr, pps, dc->sps_array))
                    {
                        dc->pps_array[pps->pic_parameter_set_id] = pps;
                        dc->active_pps = pps->pic_parameter_set_id;
                        dc->entropy_coding_mode_flag = pps->entropy_coding_mode_flag,

                        //printPPS(pps, dc->sps_array);
                        retcode = SUCCESS;
                    }
                    else
                        dc->errorCounter++;
                }
            }
            break;

            default:
            {
                TRACE_ERROR(NALU, "Unsupported NAL Unit! (nal_unit_type %i)", dc->active_nalu->nal_unit_type);
                dc->errorCounter++;
            }
            break;
        }

        // Reset NAL Unit structure
        nalu_reset(dc->active_nalu);
    }
    else
    {
        retcode = FAILURE;
        dc->errorCounter++;
        TRACE_WARNING(NALU, "No valid NAL Unit to decode! (errorCounter = %i)", dc->errorCounter);
    }

    return retcode;
}
예제 #3
0
파일: h264.c 프로젝트: seanvk/MiniVideo
/*!
 * \brief Decode H.264 bitsream.
 * \param *input_video A pointer to a VideoFile_t structure, containing every informations available about the current video file.
 * \param *output_directory The directory where to save exported pictures.
 * \param picture_format The picture file format.
 * \param picture_quality The quality we want for exported picture [1;100].
 * \param picture_number The number of thumbnail(s) we want to extract.
 * \param picture_extractionmode The method of distribution for thumbnails extraction.
 * \return 1 if succeed, 0 otherwise.
 *
 * This decoder is based on the 'ITU-T H.264' recommendation:
 * 'Advanced Video Coding for generic audiovisual services'
 * It also correspond to 'ISO/IEC 14496-10' international standard, part 10:
 * 'Advanced Video Coding'.
 *
 * You can download the H.264 specification for free on the ITU website:
 * http://www.itu.int/rec/T-REC-H.264
 *
 * The very first step to H.264 bitstream decoding. Initialize DecodingContext,
 * then start the decoding process, which loop on NAL Units found in the bitstream.
 * Each NAL Unit is processed following it's content type.
 */
int h264_decode(VideoFile_t *input_video,
                const char *output_directory,
                const int picture_format,
                const int picture_quality,
                const int picture_number,
                const int picture_extractionmode)
{
    TRACE_INFO(H264, BLD_GREEN "h264_decode()\n" CLR_RESET);
    int retcode = FAILURE;

    // Init decoding context
    DecodingContext_t *dc = initDecodingContext(input_video);

    if (dc == NULL)
    {
        TRACE_ERROR(H264, "Unable to allocate DecodingContext_t, exiting decoder\n");
        return retcode;
    }
    else
    {
        // Init some quantization parameters
        computeNormAdjust(dc);

        // Init some export parameters
        //strncpy(dc->output_directory, output_directory, sizeof(output_directory));
        dc->output_format = picture_format;
        dc->picture_quality = picture_quality;
        dc->picture_number = picture_number;
        dc->picture_extractionmode = picture_extractionmode;

        // Start the decoding process
        dc->decoderRunning = true;
    }

    // Loop until end of file
    while (dc->decoderRunning)
    {
        // Load next NAL Unit
        retcode = buffer_feed_next_sample(dc->bitstr);

        // Check header validity
        if (nalu_parse_header(dc->bitstr, dc->active_nalu))
        {
            // Decode NAL Unit content
            switch (dc->active_nalu->nal_unit_type)
            {
            case NALU_TYPE_SLICE: // 1
            {
                TRACE_1(NALU, "This decoder only support IDR slice decoding!\n");
            }
            break;

            case NALU_TYPE_IDR: // 5
            {
                dc->IdrPicFlag = true;
                nalu_clean_sample(dc->bitstr);

                TRACE_INFO(MAIN, "> " BLD_GREEN "decodeIDR(%i)\n" CLR_RESET, dc->idrCounter);

                if (decode_slice(dc))
                {
                    retcode = SUCCESS;
                    dc->errorCounter = 0;
                    dc->idrCounter++;
                    dc->frameCounter++;
                }
                else
                    dc->errorCounter++;

                dc->IdrPicFlag = false;
            }
            break;

            case NALU_TYPE_SEI: // 6
            {
                nalu_clean_sample(dc->bitstr);

                if (decodeSEI(dc))
                {
                    retcode = SUCCESS;
                    printSEI(dc);
                }
                else
                    dc->errorCounter++;
            }
            break;

            case NALU_TYPE_SPS: // 7
            {
                nalu_clean_sample(dc->bitstr);

                if (decodeSPS(dc))
                {
                    retcode = SUCCESS;
                    printSPS(dc);
                }
                else
                    dc->errorCounter++;
            }
            break;

            case NALU_TYPE_PPS: // 8
            {
                nalu_clean_sample(dc->bitstr);

                if (decodePPS(dc))
                {
                    retcode = SUCCESS;
                    printPPS(dc);
                }
                else
                    dc->errorCounter++;
            }
            break;

            default:
            {
                dc->errorCounter++;
                TRACE_ERROR(NALU, "Unsupported NAL Unit! (nal_unit_type %i)\n", dc->active_nalu->nal_unit_type);
            }
            break;
            }

            // Reset NAL Unit structure
            nalu_reset(dc->active_nalu);
        }
        else
        {
            dc->errorCounter++;
            TRACE_WARNING(NALU, "No valid NAL Unit to decode! (errorCounter = %i)\n", dc->errorCounter);
        }

        if (dc->idrCounter == picture_number)
        {
            TRACE_INFO(H264, ">> " BLD_YELLOW "Decoding of %i IDR successfull!\n" CLR_RESET, dc->idrCounter);
            TRACE_INFO(H264, "H.264 decoding ended\n");
            retcode = SUCCESS;
            dc->decoderRunning = false;
        }

        if (dc->errorCounter > 64 || retcode == FAILURE)
        {
            TRACE_ERROR(H264, "Error inside NAL Unit decoding loop! (errorCounter = %i) (current nal_unit_type = %i)\n", dc->errorCounter, dc->active_nalu->nal_unit_type);
            TRACE_ERROR(H264, "H.264 decoding aborted\n");
            retcode = FAILURE;
            dc->decoderRunning = false;
        }
    }

    // Destroy decoding context
    freeDecodingContext(&dc);

    // Exit decoder
    return retcode;
}
예제 #4
0
/**
    \fn runH264
    \brief Index H264 stream
*/  
bool TsIndexer::runH264(const char *file,ADM_TS_TRACK *videoTrac)
{

bool    seq_found=false;
bool    firstSps=true;

TSVideo video;
indexerData  data;    
dmxPacketInfo tmpInfo;
TS_PESpacket SEI_nal(0);
bool result=false;
bool bAppend=false;

    beginConsuming=0;
    listOfUnits.clear();

    printf("Starting H264 indexer\n");
    if(!videoTrac) return false;
    if(videoTrac[0].trackType!=ADM_TS_H264)
    {
        printf("[Ts Indexer] Only H264 video supported\n");
        return false;
    }
    video.pid=videoTrac[0].trackPid;

    memset(&data,0,sizeof(data));
    data.picStructure=pictureFrame;
    string indexName=string(file);
    indexName=indexName+string(".idx2");
    index=qfopen(indexName,(const char*)"wt");

    if(!index)
    {
        printf("[PsIndex] Cannot create %s\n",indexName.c_str());
        return false;
    }

    
    pkt=new tsPacketLinearTracker(videoTrac->trackPid, audioTracks);
    
    FP_TYPE append=FP_DONT_APPEND;
    if(true==ADM_probeSequencedFile(file))
    {
        if(true==GUI_Question("There are several files with sequential file names. Should they be all loaded ?"))
                bAppend=true;
    }
    if(bAppend==true)
        append=FP_APPEND;
    writeSystem(file,bAppend);
    pkt->open(file,append);
    data.pkt=pkt;
    fullSize=pkt->getSize();
    gui=createProcessing("Indexing",pkt->getSize());
    int lastRefIdc=0;
    bool keepRunning=true;
    //******************
    // 1 search SPS
    //******************
      while(keepRunning)
      {
        int startCode=pkt->findStartCode();

        if(startCode&0x80) continue; // Marker missing
        startCode&=0x1f;
        if(startCode!=NAL_SPS) continue;

          // Got SPS!
          
          uint32_t xA,xR;
          // Get info
          pkt->getInfo(&tmpInfo);
          // Read just enough...
          {
            SEI_nal.empty();
            uint32_t code=0xffff+0xffff0000;
            while(((code&0xffffff)!=1) && pkt->stillOk())
            {
                    uint8_t r=pkt->readi8();
                    code=(code<<8)+r;
                    SEI_nal.pushByte(r);
            }
            if(!pkt->stillOk()) break;;
            pkt->seek(tmpInfo.startAt,tmpInfo.offset-5);
            if (extractSPSInfo(SEI_nal.payload, SEI_nal.payloadSize-4,&spsInfo))
            {
              ADM_info("[TsIndexer] Found video %"PRIu32"x%"PRIu32", fps=%"PRIu32"\n",video.w,video.h,video.fps);
              ADM_info("[TsIndexer] SPS says %"PRIu32"x%"PRIu32"\n",spsInfo.width,spsInfo.height);
              seq_found=1;
              video.w=spsInfo.width;
              video.h=spsInfo.height;
              video.fps=spsInfo.fps1000;
              xA=spsInfo.darNum;
              xR=spsInfo.darDen;
              writeVideo(&video,ADM_TS_H264);
              writeAudio();
              qfprintf(index,"[Data]");
              // Rewind
              
              break;              
          };
        }
      }
      
        if(!seq_found) goto the_end;
        
        decodingImage=false;
    //******************
    // 2 Index
    //******************
        bool fourBytes;
      while(keepRunning)
      {
          fourBytes=false;
        int startCode=pkt->findStartCode2(fourBytes);
resume:
        if(!pkt->stillOk()) break;

        int startCodeLength=4;
        if(fourBytes==true) startCodeLength++;

//  1:0 2:Nal ref idc 5:Nal Type
        if(startCode&0x80) 
        {
            printf("[Ts] Nal Marker missing:%x\n",startCode);
            continue; // Marker missing
        }
        int fullStartCode=startCode;
        int ref=(startCode>>5)&3;

        startCode&=0x1f; // Ignore nal ref IDR
        
        aprintf("[%02x] Nal :0x%x,ref=%d,lastRef=%d at : %d \n",fullStartCode,startCode,ref,lastRefIdc,pkt->getConsumed()-beginConsuming);
        
          // Ignore multiple chunk of the same pic
          if((startCode==NAL_NON_IDR || startCode==NAL_IDR)&&decodingImage )
          {
            aprintf("Still capturing, ignore\n");
            continue;
          }
                
          switch(startCode)
                  {
                  case NAL_AU_DELIMITER:
                        {
                          aprintf("AU DELIMITER\n");
                          decodingImage = false;
                        }
                          break;
                  case NAL_SEI:
                        {
                        // Load the whole NAL
                            SEI_nal.empty();
                            uint32_t code=0xffff+0xffff0000;
                            while(((0xffffff&code)!=1) && pkt->stillOk())
                            {
                                uint8_t r=pkt->readi8();
                                code=(code<<8)+r;
                                SEI_nal.pushByte(r);
                            }
                            if(!pkt->stillOk()) goto resume;
                            aprintf("[SEI] Nal size :%d\n",SEI_nal.payloadSize);
                            if(SEI_nal.payloadSize>=7)
                                decodeSEI(SEI_nal.payloadSize-4,
                                    SEI_nal.payload,&(thisUnit.recoveryCount),&(thisUnit.imageStructure));
                            else 
                                    printf("[SEI] Too short size+4=%d\n",*(SEI_nal.payload));
                            startCode=pkt->readi8();
                            
                            decodingImage=false;
                            pkt->getInfo(&thisUnit.packetInfo);
                            thisUnit.consumedSoFar=pkt->getConsumed();
                            if(!addUnit(data,unitTypeSei,thisUnit,startCodeLength+SEI_nal.payloadSize+1))
                                keepRunning=false;
                            fourBytes=true;
                            goto resume;
                            }
                            break;
                  
                  case NAL_SPS:
                                decodingImage=false;
                                pkt->getInfo(&thisUnit.packetInfo);
                                if(firstSps)
                                {
                                    pkt->setConsumed(startCodeLength); // reset consume counter
                                    firstSps=false;
                                }
                                thisUnit.consumedSoFar=pkt->getConsumed();
                                if(!addUnit(data,unitTypeSps,thisUnit,startCodeLength))
                                    keepRunning=false;
                          break;

                  case NAL_IDR:
                  case NAL_NON_IDR:
                    {
#define NON_IDR_PRE_READ 8
                      aprintf("Pic start last ref:%d cur ref:%d nb=%d\n",lastRefIdc,ref,data.nbPics);
                      lastRefIdc=ref;
                        
                      uint8_t bufr[NON_IDR_PRE_READ+4];
                      uint8_t header[NON_IDR_PRE_READ+4];
                      
                   
                        pkt->read(NON_IDR_PRE_READ,bufr);
                        // unescape...
                        ADM_unescapeH264(NON_IDR_PRE_READ,bufr,header);
                        //
                        getBits bits(NON_IDR_PRE_READ,header);
                        int first_mb_in_slice,slice_type;

                        first_mb_in_slice= bits.getUEG();
                        slice_type= bits.getUEG31();
                        if(slice_type>9) 
                        {
                            printf("[TsIndexer] Bad slice type\n");
                        }
                        if(slice_type>4) slice_type-=5;
                        switch(slice_type)
                        {

                            case 0 : thisUnit.imageType=2;break; // P
                            case 1 : thisUnit.imageType=3;break; // B
                            case 2 : thisUnit.imageType=1;break; // I
                            default : thisUnit.imageType=2;break; // SP/SI
                        }
                      if(startCode==NAL_IDR) thisUnit.imageType=4; // IDR
                      aprintf("[>>>>>>>>] Pic Type %"PRIu32" Recovery %"PRIu32"\n",thisUnit.imageType,recoveryCount);
                      if(thisUnit.imageType==1 && !thisUnit.recoveryCount) 
                                thisUnit.imageType=4; //I  + Recovery=0 = IDR!

                      data.nbPics++;

                      

                      decodingImage=true;
                      pkt->getInfo(&thisUnit.packetInfo);
                      thisUnit.consumedSoFar=pkt->getConsumed();

                      if(!addUnit(data,unitTypePic,thisUnit,startCodeLength+NON_IDR_PRE_READ))
                          keepRunning=false;
                        // reset to default
                      thisUnit.imageStructure=pictureFrame;
                      thisUnit.recoveryCount=0xff;
                      pkt->invalidatePtsDts();
                    }
                  
                    break;
                  default:
                      break;
          }
      } // End while
      result=true;
the_end:
        printf("\n");
        qfprintf(index,"\n[End]\n");
        qfclose(index);
        index=NULL;
        audioTracks=NULL;
        delete pkt;
        pkt=NULL;
        return result; 
}