2013-03-07 8 views
15

मैं एमपी 4 फ़ाइल में mux H.264 डेटा करने की कोशिश कर रहा हूं। MP4 फ़ाइल में इस H.264 अनुलग्नक बी डेटा को सहेजने में कोई त्रुटि नहीं है, लेकिन फ़ाइल प्लेबैक में विफल हो जाती है।H.264 libavformat का उपयोग कर एमपी 4 में muxed

मैंने फ़ाइलों पर एक बाइनरी तुलना की है और यह समस्या एमपी 4 फ़ाइल के पाद लेख (ट्रेलर) में लिखे जाने वाले चीज़ों में कहीं कहीं है।

मुझे संदेह है कि इसे स्ट्रीम बनाने या कुछ तरीके से कुछ होना चाहिए।

Init:

AVOutputFormat* fmt = av_guess_format(0, "out.mp4", 0); 
oc = avformat_alloc_context(); 
oc->oformat = fmt; 
strcpy(oc->filename, filename); 

मैं प्रत्येक आइफ्रेम के लिए एक PNG फ़ाइल पैदा कर रही है इस प्रोटोटाइप एप्लिकेशन का एक हिस्सा। इसलिए जब पहली IFrame का सामना करना पड़ा है, मैं वीडियो स्ट्रीम बना सकते हैं और av हैडर आदि लिखें:

void addVideoStream(AVCodecContext* decoder) 
{ 
    videoStream = av_new_stream(oc, 0); 
    if (!videoStream) 
    { 
     cout << "ERROR creating video stream" << endl; 
     return;   
    } 
    vi = videoStream->index;  
    videoContext = videoStream->codec;  
    videoContext->codec_type = AVMEDIA_TYPE_VIDEO; 
    videoContext->codec_id = decoder->codec_id; 
    videoContext->bit_rate = 512000; 
    videoContext->width = decoder->width; 
    videoContext->height = decoder->height; 
    videoContext->time_base.den = 25; 
    videoContext->time_base.num = 1;  
    videoContext->gop_size = decoder->gop_size; 
    videoContext->pix_fmt = decoder->pix_fmt;  

    if (oc->oformat->flags & AVFMT_GLOBALHEADER) 
     videoContext->flags |= CODEC_FLAG_GLOBAL_HEADER; 

    av_dump_format(oc, 0, filename, 1); 

    if (!(oc->oformat->flags & AVFMT_NOFILE)) 
    { 
     if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) { 
     cout << "Error opening file" << endl; 
    } 
    avformat_write_header(oc, NULL); 
} 

मैं पैकेट लिखने आउट:

unsigned char* data = block->getData(); 
unsigned char videoFrameType = data[4]; 
int dataLen = block->getDataLen(); 

// store pps 
if (videoFrameType == 0x68) 
{ 
    if (ppsFrame != NULL) 
    { 
     delete ppsFrame; ppsFrameLength = 0; ppsFrame = NULL; 
    } 
    ppsFrameLength = block->getDataLen(); 
    ppsFrame = new unsigned char[ppsFrameLength]; 
    memcpy(ppsFrame, block->getData(), ppsFrameLength); 
} 
else if (videoFrameType == 0x67) 
{ 
    // sps 
    if (spsFrame != NULL) 
    { 
     delete spsFrame; spsFrameLength = 0; spsFrame = NULL; 
} 
    spsFrameLength = block->getDataLen(); 
    spsFrame = new unsigned char[spsFrameLength]; 
    memcpy(spsFrame, block->getData(), spsFrameLength);     
}           

if (videoFrameType == 0x65 || videoFrameType == 0x41) 
{ 
    videoFrameNumber++; 
} 
if (videoFrameType == 0x65) 
{ 
    decodeIFrame(videoFrameNumber, spsFrame, spsFrameLength, ppsFrame, ppsFrameLength, data, dataLen); 
} 

if (videoStream != NULL) 
{ 
    AVPacket pkt = { 0 }; 
    av_init_packet(&pkt); 
    pkt.stream_index = vi; 
    pkt.flags = 0;      
    pkt.pts = pkt.dts = 0;         

    if (videoFrameType == 0x65) 
    { 
     // combine the SPS PPS & I frames together 
     pkt.flags |= AV_PKT_FLAG_KEY;             
     unsigned char* videoFrame = new unsigned char[spsFrameLength+ppsFrameLength+dataLen]; 
     memcpy(videoFrame, spsFrame, spsFrameLength); 
     memcpy(&videoFrame[spsFrameLength], ppsFrame, ppsFrameLength); 
     memcpy(&videoFrame[spsFrameLength+ppsFrameLength], data, dataLen); 

     // overwrite the start code (00 00 00 01 with a 32-bit length) 
     setLength(videoFrame, spsFrameLength-4); 
     setLength(&videoFrame[spsFrameLength], ppsFrameLength-4); 
     setLength(&videoFrame[spsFrameLength+ppsFrameLength], dataLen-4); 
     pkt.size = dataLen + spsFrameLength + ppsFrameLength; 
     pkt.data = videoFrame; 
     av_interleaved_write_frame(oc, &pkt); 
     delete videoFrame; videoFrame = NULL; 
    } 
    else if (videoFrameType != 0x67 && videoFrameType != 0x68) 
    { 
     // Send other frames except pps & sps which are caught and stored     
     pkt.size = dataLen; 
     pkt.data = data; 
     setLength(data, dataLen-4);      
     av_interleaved_write_frame(oc, &pkt); 
    } 

अंत में फ़ाइल बंद बंद करने के लिए:

av_write_trailer(oc); 
int i = 0; 
for (i = 0; i < oc->nb_streams; i++) 
{ 
    av_freep(&oc->streams[i]->codec); 
    av_freep(&oc->streams[i]);  
} 

if (!(oc->oformat->flags & AVFMT_NOFILE)) 
{ 
    avio_close(oc->pb); 
} 
av_free(oc); 

मैं अकेला 264 डेटा लेते हैं और इसे परिवर्तित हैं:

ffmpeg -i recording.h264 -vcodec copy recording.mp4 

सभी लेकिन फाइलों के "पाद लेख" समान हैं। मेरे कार्यक्रम से

आउटपुट: readrec recording.tcp out.mp4 **** शुरू **** 2013/01/03 14:26:01 180000 आउटपुट # 0, mp4, 'out.mp4 को ': स्ट्रीम # 0: 0: वीडियो: एच 264, yuv420p, 352x288, q = 2-31, 512 केबी/एस, 90 के टीबीएन, 25 टीबीसी **** अंत **** 01-03-2013 14: 27:01 102000 1499 वीडियो फ्रेम लिखा।

ffmpeg -i out.mp4 -vcodec copy out2.mp4 
ffmpeg version 0.11.1 Copyright (c) 2000-2012 the FFmpeg developers 
     built on Mar 7 2013 12:49:22 with suncc 0x5110 
     configuration: --extra-cflags=-KPIC -g --disable-mmx 
     --disable-protocol=udp --disable-encoder=nellymoser --cc=cc --cxx=CC 
libavutil  51. 54.100/51. 54.100 
libavcodec  54. 23.100/54. 23.100 
libavformat 54. 6.100/54. 6.100 
libavdevice 54. 0.100/54. 0.100 
libavfilter  2. 77.100/2. 77.100 
libswscale  2. 1.100/2. 1.100 
libswresample 0. 15.100/0. 15.100 
h264 @ 12eaac0] no frame! 
    Last message repeated 1 times 
[h264 @ 12eaac0] slice type too large (0) at 0 0 
[h264 @ 12eaac0] decode_slice_header error 
[h264 @ 12eaac0] no frame! 
    Last message repeated 23 times 
[h264 @ 12eaac0] slice type too large (0) at 0 0 
[h264 @ 12eaac0] decode_slice_header error 
[h264 @ 12eaac0] no frame! 
    Last message repeated 74 times 
[h264 @ 12eaac0] slice type too large (0) at 0 0 
[h264 @ 12eaac0] decode_slice_header error 
[h264 @ 12eaac0] no frame! 
    Last message repeated 64 times 
[h264 @ 12eaac0] slice type too large (0) at 0 0 
[h264 @ 12eaac0] decode_slice_header error 
[h264 @ 12eaac0] no frame! 
    Last message repeated 34 times 
[h264 @ 12eaac0] slice type too large (0) at 0 0 
[h264 @ 12eaac0] decode_slice_header error 
[h264 @ 12eaac0] no frame! 
    Last message repeated 49 times 
[h264 @ 12eaac0] slice type too large (0) at 0 0 
[h264 @ 12eaac0] decode_slice_header error 
[h264 @ 12eaac0] no frame! 
    Last message repeated 24 times 
[h264 @ 12eaac0] Partitioned H.264 support is incomplete 
[h264 @ 12eaac0] no frame! 
    Last message repeated 23 times 
[h264 @ 12eaac0] sps_id out of range 
[h264 @ 12eaac0] no frame! 
    Last message repeated 148 times 
[h264 @ 12eaac0] sps_id (32) out of range 
    Last message repeated 1 times 
[h264 @ 12eaac0] no frame! 
    Last message repeated 33 times 
[h264 @ 12eaac0] slice type too large (0) at 0 0 
[h264 @ 12eaac0] decode_slice_header error 
[h264 @ 12eaac0] no frame! 
    Last message repeated 128 times 
[h264 @ 12eaac0] sps_id (32) out of range 
    Last message repeated 1 times 
[h264 @ 12eaac0] no frame! 
    Last message repeated 3 times 
[h264 @ 12eaac0] slice type too large (0) at 0 0 
[h264 @ 12eaac0] decode_slice_header error 
[h264 @ 12eaac0] no frame! 
    Last message repeated 3 times 
[h264 @ 12eaac0] slice type too large (0) at 0 0 
[h264 @ 12eaac0] decode_slice_header error 
[h264 @ 12eaac0] no frame! 
    Last message repeated 309 times 
[h264 @ 12eaac0] sps_id (32) out of range 
    Last message repeated 1 times 
[h264 @ 12eaac0] no frame! 
    Last message repeated 192 times 
[h264 @ 12eaac0] Partitioned H.264 support is incomplete 
[h264 @ 12eaac0] no frame! 
    Last message repeated 73 times 
[h264 @ 12eaac0] sps_id (32) out of range 
    Last message repeated 1 times 
[h264 @ 12eaac0] no frame! 
    Last message repeated 99 times 
[h264 @ 12eaac0] sps_id (32) out of range 
    Last message repeated 1 times 
[h264 @ 12eaac0] no frame! 
    Last message repeated 197 times 
[mov,mp4,m4a,3gp,3g2,mj2 @ 12e3100] decoding for stream 0 failed 
[mov,mp4,m4a,3gp,3g2,mj2 @ 12e3100] Could not find codec parameters 
(Video: h264 (avc1/0x31637661), 393539 kb/s) 
out.mp4: could not find codec parameters 

मैं वास्तव में, जहां मुद्दा है पता नहीं है सिवाय यह है जिस तरह से नदियों किया जा रहा है के साथ कुछ होने के लिए:

अगर मैं MP4 फ़ाइल ffmpeg का उपयोग कर बदलने की कोशिश कोड का उपयोग कर बनाई सेट अप। मैंने कोड के बिट्स को देखा है जहां से अन्य लोग एक समान काम कर रहे हैं, और धाराओं की स्थापना में इस सलाह का उपयोग करने की कोशिश की, लेकिन इसका कोई फायदा नहीं हुआ!


अंतिम कोड जिसने मुझे H.264/AAC muxed (synced) फ़ाइल दी है, निम्नानुसार है। पृष्ठभूमि की कुछ जानकारी पहले। डेटा एक आईपी कैमरा से आ रहा है। डेटा को तीसरे पक्ष एपीआई के माध्यम से वीडियो/ऑडियो पैकेट के रूप में प्रस्तुत किया जाता है। वीडियो पैकेट को आरटीपी पेलोड डेटा (कोई हेडर) के रूप में प्रस्तुत नहीं किया जाता है और इसमें एनयूएल शामिल होते हैं जिन्हें पुनर्निर्मित किया जाता है और अनुलग्नक बी प्रारूप में एच .264 वीडियो में परिवर्तित किया जाता है। एएसी ऑडियो कच्चे एएसी के रूप में प्रस्तुत किया जाता है और प्लेबैक को सक्षम करने के लिए विज्ञापन प्रारूप में परिवर्तित किया जाता है। इन पैकेट को बिटस्ट्रीम प्रारूप में रखा गया है जो कुछ अन्य चीजों के साथ टाइमस्टैम्प (64 बिट मिलीसेकंड के बाद से 64 बिट मिलीसेकंड) के संचरण की अनुमति देता है।

यह प्रोटोटाइप कम या कम है और किसी भी मामले में साफ नहीं है। यह शायद खराब हो जाता है। हालांकि, मुझे उम्मीद है कि यह किसी और चीज को प्राप्त करने की कोशिश करने में मेरी मदद करेगा।

वैश्विक:

AVFormatContext* oc = NULL; 
AVCodecContext* videoContext = NULL; 
AVStream* videoStream = NULL; 
AVCodecContext* audioContext = NULL; 
AVStream* audioStream = NULL; 
AVCodec* videoCodec = NULL; 
AVCodec* audioCodec = NULL; 
int vi = 0; // Video stream 
int ai = 1; // Audio stream 

uint64_t firstVideoTimeStamp = 0; 
uint64_t firstAudioTimeStamp = 0; 
int audioStartOffset = 0; 

char* filename = NULL; 

Boolean first = TRUE; 

int videoFrameNumber = 0; 
int audioFrameNumber = 0; 

मुख्य:

int main(int argc, char* argv[]) 
{ 
    if (argc != 3) 
    { 
     cout << argv[0] << " <stream playback file> <output mp4 file>" << endl; 
     return 0; 
    } 
    char* input_stream_file = argv[1]; 
    filename = argv[2]; 

    av_register_all();  

    fstream inFile; 
    inFile.open(input_stream_file, ios::in); 

    // Used to store the latest pps & sps frames 
    unsigned char* ppsFrame = NULL; 
    int ppsFrameLength = 0; 
    unsigned char* spsFrame = NULL; 
    int spsFrameLength = 0; 

    // Setup MP4 output file 
    AVOutputFormat* fmt = av_guess_format(0, filename, 0); 
    oc = avformat_alloc_context(); 
    oc->oformat = fmt; 
    strcpy(oc->filename, filename); 

    // Setup the bitstream filter for AAC in adts format. Could probably also achieve 
    // this by stripping the first 7 bytes! 
    AVBitStreamFilterContext* bsfc = av_bitstream_filter_init("aac_adtstoasc"); 
    if (!bsfc) 
    {  
     cout << "Error creating adtstoasc filter" << endl; 
     return -1; 
    } 

    while (inFile.good()) 
    { 
     TcpAVDataBlock* block = new TcpAVDataBlock(); 
     block->readStruct(inFile); 
     DateTime dt = block->getTimestampAsDateTime(); 
     switch (block->getPacketType()) 
     { 
      case TCP_PACKET_H264: 
      {  
       if (firstVideoTimeStamp == 0) 
        firstVideoTimeStamp = block->getTimeStamp(); 
       unsigned char* data = block->getData(); 
       unsigned char videoFrameType = data[4]; 
       int dataLen = block->getDataLen(); 

       // pps 
       if (videoFrameType == 0x68) 
       { 
        if (ppsFrame != NULL) 
        { 
         delete ppsFrame; ppsFrameLength = 0; 
         ppsFrame = NULL; 
        } 
        ppsFrameLength = block->getDataLen(); 
        ppsFrame = new unsigned char[ppsFrameLength]; 
        memcpy(ppsFrame, block->getData(), ppsFrameLength); 
       } 
       else if (videoFrameType == 0x67) 
       { 
        // sps 
        if (spsFrame != NULL) 
        { 
         delete spsFrame; spsFrameLength = 0; 
         spsFrame = NULL; 
        } 
        spsFrameLength = block->getDataLen(); 
        spsFrame = new unsigned char[spsFrameLength]; 
        memcpy(spsFrame, block->getData(), spsFrameLength);     
       }           

       if (videoFrameType == 0x65 || videoFrameType == 0x41) 
       { 
        videoFrameNumber++; 
       } 
       // Extract a thumbnail for each I-Frame 
       if (videoFrameType == 0x65) 
       { 
        decodeIFrame(h264, spsFrame, spsFrameLength, ppsFrame, ppsFrameLength, data, dataLen); 
       } 
       if (videoStream != NULL) 
       { 
        AVPacket pkt = { 0 }; 
        av_init_packet(&pkt); 
        pkt.stream_index = vi; 
        pkt.flags = 0;   
        pkt.pts = videoFrameNumber; 
        pkt.dts = videoFrameNumber;   
        if (videoFrameType == 0x65) 
        { 
         pkt.flags = 1;       

         unsigned char* videoFrame = new unsigned char[spsFrameLength+ppsFrameLength+dataLen]; 
         memcpy(videoFrame, spsFrame, spsFrameLength); 
         memcpy(&videoFrame[spsFrameLength], ppsFrame, ppsFrameLength); 

         memcpy(&videoFrame[spsFrameLength+ppsFrameLength], data, dataLen); 
         pkt.data = videoFrame; 
         av_interleaved_write_frame(oc, &pkt); 
         delete videoFrame; videoFrame = NULL; 
        } 
        else if (videoFrameType != 0x67 && videoFrameType != 0x68) 
        {      
         pkt.size = dataLen; 
         pkt.data = data; 
         av_interleaved_write_frame(oc, &pkt); 
        }      
       } 
       break; 
      } 

     case TCP_PACKET_AAC: 

      if (firstAudioTimeStamp == 0) 
      { 
       firstAudioTimeStamp = block->getTimeStamp(); 
       uint64_t millseconds_difference = firstAudioTimeStamp - firstVideoTimeStamp; 
       audioStartOffset = millseconds_difference * 16000/1000; 
       cout << "audio offset: " << audioStartOffset << endl; 
      } 

      if (audioStream != NULL) 
      { 
       AVPacket pkt = { 0 }; 
       av_init_packet(&pkt); 
       pkt.stream_index = ai; 
       pkt.flags = 1;   
       pkt.pts = audioFrameNumber*1024; 
       pkt.dts = audioFrameNumber*1024; 
       pkt.data = block->getData(); 
       pkt.size = block->getDataLen(); 
       pkt.duration = 1024; 

       AVPacket newpacket = pkt;      
       int rc = av_bitstream_filter_filter(bsfc, audioContext, 
        NULL, 
        &newpacket.data, &newpacket.size, 
        pkt.data, pkt.size, 
        pkt.flags & AV_PKT_FLAG_KEY); 

       if (rc >= 0) 
       { 
        //cout << "Write audio frame" << endl; 
        newpacket.pts = audioFrameNumber*1024; 
        newpacket.dts = audioFrameNumber*1024; 
        audioFrameNumber++; 
        newpacket.duration = 1024;     

        av_interleaved_write_frame(oc, &newpacket); 
        av_free_packet(&newpacket); 
       } 
       else 
       { 
        cout << "Error filtering aac packet" << endl; 

       } 
      } 
      break; 

     case TCP_PACKET_START: 
      break; 

     case TCP_PACKET_END: 
      break; 
     } 
     delete block; 
    } 
    inFile.close(); 

    av_write_trailer(oc); 
    int i = 0; 
    for (i = 0; i < oc->nb_streams; i++) 
    { 
     av_freep(&oc->streams[i]->codec); 
     av_freep(&oc->streams[i]);  
    } 

    if (!(oc->oformat->flags & AVFMT_NOFILE)) 
    { 
     avio_close(oc->pb); 
    } 

    av_free(oc); 

    delete spsFrame; spsFrame = NULL; 
    delete ppsFrame; ppsFrame = NULL; 

    cout << "Wrote " << videoFrameNumber << " video frames." << endl; 

    return 0; 
} 

धारा धारा/codecs जोड़ रहे हैं और हैडर एक समारोह addVideoAndAudioStream कहा जाता है में बन जाता है()। इस समारोह decodeIFrame (से कहा जाता है) तो वहाँ कुछ मान्यताओं (जो जरूरी अच्छा नहीं है) कर रहे हैं 1. एक वीडियो पैकेट आता है पहले 2. एएसी मौजूद है

decodeIFrame जहां से एक अलग प्रोटोटाइप की तरह था मैं प्रत्येक फ्रेम के लिए एक थंबनेल बना रहा था। https://gnunet.org/svn/Extractor/src/plugins/thumbnailffmpeg_extractor.c

decodeIFrame समारोह addVideoAudioStream में एक AVCodecContext गुजरता है: कोड थंबनेल उत्पन्न करने के लिए से था

void addVideoAndAudioStream(AVCodecContext* decoder = NULL) 
{ 
    videoStream = av_new_stream(oc, 0); 
    if (!videoStream) 
    { 
     cout << "ERROR creating video stream" << endl; 
     return;  
    } 
    vi = videoStream->index; 
    videoContext = videoStream->codec;  
    videoContext->codec_type = AVMEDIA_TYPE_VIDEO; 
    videoContext->codec_id = decoder->codec_id; 
    videoContext->bit_rate = 512000; 
    videoContext->width = decoder->width; 
    videoContext->height = decoder->height; 
    videoContext->time_base.den = 25; 
    videoContext->time_base.num = 1; 
    videoContext->gop_size = decoder->gop_size; 
    videoContext->pix_fmt = decoder->pix_fmt;  

    audioStream = av_new_stream(oc, 1); 
    if (!audioStream) 
    { 
     cout << "ERROR creating audio stream" << endl; 
     return; 
    } 
    ai = audioStream->index; 
    audioContext = audioStream->codec; 
    audioContext->codec_type = AVMEDIA_TYPE_AUDIO; 
    audioContext->codec_id = CODEC_ID_AAC; 
    audioContext->bit_rate = 64000; 
    audioContext->sample_rate = 16000; 
    audioContext->channels = 1; 

    if (oc->oformat->flags & AVFMT_GLOBALHEADER) 
    { 
     videoContext->flags |= CODEC_FLAG_GLOBAL_HEADER; 
     audioContext->flags |= CODEC_FLAG_GLOBAL_HEADER; 
    } 

    av_dump_format(oc, 0, filename, 1); 

    if (!(oc->oformat->flags & AVFMT_NOFILE)) 
    { 
     if (avio_open(&oc->pb, filename, AVIO_FLAG_WRITE) < 0) { 
      cout << "Error opening file" << endl; 
     } 
    } 

    avformat_write_header(oc, NULL); 
} 

जहां तक ​​मेरा बता सकते हैं, मान्यताओं के एक नंबर बात करने, उदाहरण के लिए नहीं मालूम था: 1. बिट दर। वास्तविक वीडियो बिट दर ~ 262k थी जबकि मैंने 512kbit 2. एएसी चैनल निर्दिष्ट किए थे। मैंने मोनो निर्दिष्ट किया, हालांकि वास्तविक आउटपुट स्मृति से स्टीरियो

आपको अभी भी यह जानने की आवश्यकता होगी कि वीडियो & ऑडियो के लिए फ्रेम दर (समय आधार) क्या है।

कई अन्य उदाहरणों के विपरीत, वीडियो पैकेट पर & डीटीएस सेट करते समय, यह बजाने योग्य नहीं था। मुझे टाइम बेस (25fps) जानने की आवश्यकता थी और फिर उस समय आधार के अनुसार & डीटीएस सेट करें, यानी पहले फ्रेम = 0 (पीपीएस, एसपीएस, आई), दूसरा फ्रेम = 1 (इंटरमीडिएट फ्रेम, जिसे भी कहा जाता है;)) ।

एएसी मुझे यह भी मानना ​​था कि यह 16000 हर्ट्ज था। ऑडियो "ऑफ़सेट" निर्धारित करने के लिए प्रति एएसी पैकेट के 1024 नमूने (आप एएसी @ 960 नमूने भी सोच सकते हैं)। मैंने इसे & डीटीएस में जोड़ा। तो पीटीएस/डीटीएस नमूना संख्या है जिसे इसे वापस खेला जाता है। आपको यह सुनिश्चित करने की भी आवश्यकता है कि 1024 की अवधि भी लिखने से पहले पैकेट में सेट की गई हो।

-

मैं अतिरिक्त आज जो अनुलग्नक बी वास्तव में किसी भी अन्य खिलाड़ी तो AVCC प्रारूप वास्तव में इस्तेमाल किया जाना चाहिए साथ संगत नहीं है मिल गया है।

अगर ये URL में मदद मिली:

// Extradata contains PPS & SPS for AVCC format 
int extradata_len = 8 + spsFrameLen-4 + 1 + 2 + ppsFrameLen-4; 
videoContext->extradata = (uint8_t*)av_mallocz(extradata_len); 
videoContext->extradata_size = extradata_len; 
videoContext->extradata[0] = 0x01; 
videoContext->extradata[1] = spsFrame[4+1]; 
videoContext->extradata[2] = spsFrame[4+2]; 
videoContext->extradata[3] = spsFrame[4+3]; 
videoContext->extradata[4] = 0xFC | 3; 
videoContext->extradata[5] = 0xE0 | 1; 
int tmp = spsFrameLen - 4; 
videoContext->extradata[6] = (tmp >> 8) & 0x00ff; 
videoContext->extradata[7] = tmp & 0x00ff; 
int i = 0; 
for (i=0;i<tmp;i++) 
    videoContext->extradata[8+i] = spsFrame[4+i]; 
videoContext->extradata[8+tmp] = 0x01; 
int tmp2 = ppsFrameLen-4; 
videoContext->extradata[8+tmp+1] = (tmp2 >> 8) & 0x00ff; 
videoContext->extradata[8+tmp+2] = tmp2 & 0x00ff; 
for (i=0;i<tmp2;i++) 
    videoContext->extradata[8+tmp+3+i] = ppsFrame[4+i]; 

जब फ्रेम बाहर लेखन, पहले जोड़ें नहीं है एसपीएस &: Problem to Decode H264 video over RTP with ffmpeg (libavcodec) http://aviadr1.blogspot.com.au/2010/05/h264-extradata-partially-explained-for.html

जब वीडियो स्ट्रीम का निर्माण, मैं extradata & extradata_size बाहर भरा पीपीएस फ्रेम, बस I फ्रेम & पी फ्रेम लिखें। इसके अलावा, I/P फ्रेम के आकार के साथ पहले 4 बाइट्स (0x00 0x00 0x00 0x01) में निहित अनुलग्नक बी प्रारंभ कोड को प्रतिस्थापित करें।

+0

आप एसपीएस + पीपीएस + आई-फ्रेम को एक साथ लिखने के लिए क्यों जोड़ते हैं? साथ ही, 'setLength() 'फ़ंक्शन ज़िम्मेदार हो सकता है, लेकिन यह संभव नहीं है कि ffmpeg कमांड लाइन रीमूक्सिंग के आउटपुट के साथ आपकी बाइनरी तुलना स्ट्रीम में कोई अंतर नहीं दिखाती है। –

+0

एक साथ एसपीएस और पीपीएस और आई फ्रेम संयोजन एक बाद विचार था। मैंने उन्हें शुरुआत में अलग कर दिया था और यह तब भी काम नहीं करता था। मैंने उन्हें संयुक्त किया क्योंकि जब मैं आईफ्रेम पर एक डिकोड करता हूं तो इसे डीकोड करने के लिए एसपी और पीपीएस की आवश्यकता होती है और यह उन्हें अलग से नहीं लेती। setLength() बस 32 बिट लंबाई के साथ प्रारंभ कोड को प्रतिस्थापित करता है और जैसा कि आपने कहा था, पाद लेख तक कुछ भी अलग नहीं है। –

+0

डीकोडर के लिए एसपीएस और पीपीएस को गठबंधन करना ठीक है, लेकिन मक्सर (एमपी 4 प्रारूप) के लिए खतरनाक हो सकता है। मुझे यह भी विश्वास है कि जब आप स्लाइस को मक्सर में भेजते हैं, तो आपको NALU शीर्षलेख को हटा देना चाहिए। –

उत्तर

3

कृपया मुझे इसे समेटने दें: आपके (मूल) कोड के साथ समस्या यह थी कि av_interleaved_write_frame() पर इनपुट पैकेट लंबाई से शुरू नहीं होना चाहिए। अगर आप 00 00 00 01 कोड शुरू नहीं करते हैं, तो फ़ाइल अभी भी बजाने योग्य हो सकती है, लेकिन आईएमएचओ प्लेयर का लचीला व्यवहार है, और मैं इस पर भरोसा नहीं करता।

+0

की तरह। रूपांतरण करने के लिए ffmpeg का उपयोग करना, यानी ffmpeg -i file.h264 -vcodec copy out.mp4 फ्रेम की लंबाई के साथ प्रारंभ कोड (00 00 00 01) को प्रतिस्थापित करता है। कम से कम यह फ़ाइल के हेक्सडम्प के साथ संगत था। कोड से एक ही चीज़ करने की कोशिश करके, किसी कारण से काम नहीं किया। इसे स्ट्रीम के तरीके या यहां तक ​​कि पीटीएस/डीटीएस मूल्यों के साथ कुछ करना है, मुझे यकीन नहीं है। हालांकि, निश्चित रूप से इसे अलग नहीं करना। मुझे अंतिम परिणाम दिखाने के लिए जो कुछ है, उसके कोड को पेस्ट करना चाहिए क्योंकि मुझे एमपी 4 फ़ाइल में वीडियो और ऑडियो सिंक किया गया था। मैं इसे कुछ घंटों में अपलोड करूंगा। –

+0

आपकी मदद के लिए धन्यवाद एलेक्स। स्टार्ट कोड के बारे में आपकी टिप्पणियां मुझे एक अलग कोण से देखने के लिए सोच रही हैं, इसलिए मैं इसे एक उत्तर के रूप में ले रहा हूं। –

संबंधित मुद्दे