2013-03-07 22 views
15

Próbuję MUX H.264 danych w pliku MP4. Wygląda na to, że nie ma błędów w zapisywaniu tych danych Aneksu B H.264 na plik MP4, ale plik nie odtwarza się.H.264 Muxed do MP4 przy użyciu libavformat nie odtwarza

Zrobiłem binarne porównanie na plikach i problem wydaje się być gdzieś w tym, co jest zapisywane w stopce (zwiastunie) pliku MP4.

Podejrzewam, że musi to być coś w sposobie tworzenia strumienia lub czegoś.

Init:

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

Część tego prototypu aplikacji mam jest stworzenie pliku png dla każdego iframe. Więc kiedy pierwszy IFrame napotkano, tworzę strumienia wideo i pisać itp nagłówka 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); 
} 

piszę pakiety out:

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); 
    } 

Wreszcie, aby zamknąć plik off:

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); 

Jeśli wezmę dane H.264 alone i przekształcić go:

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

Wszystkie oprócz "stopki" plików są takie same.

Wyjście z mojego programu: readrec recording.tcp out.mp4 **** **** START 03.01.2013 14:26:01 180000 Wyjście # 0, mp4, aby „out.mp4 ": Strumień nr 0: 0: wideo: h264, yuv420p, 352 x 288, q = 2-31, 512 kb/s, 90 tys. Tbn, 25 tbc **** KONIEC **** 01-03-2013 14: 27:01 102000 Napisano 1499 klatek wideo.

Gdy próbuję przekonwertować za pomocą ffmpeg plik MP4 stworzone przy użyciu kodu:

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 

ja naprawdę nie wiem, gdzie problem jest, oprócz tego, że musi być coś wspólnego ze sposobem, strumienie są Ustawiać. Spojrzałem na fragmenty kodu, z których inni robią coś podobnego, i próbowali użyć tej rady przy konfigurowaniu strumieni, ale bezskutecznie!


Ostateczny kod, który dał mi plik zmultipleksowany (H.264/AAC) jest następujący. Najpierw trochę informacji podstawowych. Dane pochodzą z kamery IP. Dane są przedstawiane za pośrednictwem zewnętrznego interfejsu API jako pakiety wideo/audio. Pakiety wideo są przedstawiane jako dane ładunku RTP (bez nagłówka) i składają się z NALU, które są rekonstruowane i konwertowane na wideo H.264 w formacie Annex B. Dźwięk AAC jest przedstawiany jako surowy AAC i jest konwertowany na format ATT, aby umożliwić odtwarzanie. Pakiety te zostały umieszczone w formacie bitstream, który umożliwia transmisję znacznika czasu (64 bitów milisekund od 1 stycznia 1970) wraz z kilkoma innymi rzeczami.

To jest mniej więcej prototyp i nie jest czysty pod żadnym względem. Prawdopodobnie wycieki są złe. Mam jednak nadzieję, że pomoże to każdemu, kto spróbuje osiągnąć coś podobnego do tego, czym jestem.

Globals:

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; 

Główne:

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; 
} 

Strumień Strumień/kodeki są dodawane i nagłówek jest tworzony w funkcji o nazwie addVideoAndAudioStream(). Ta funkcja jest wywoływana z decodeIFrame(), więc istnieje kilka założeń (które niekoniecznie są dobre) 1. pakiet wideo pochodzi pierwszy 2. AAC występuje

decodeIFrame był rodzaj odrębnej prototypu przez gdzie Stworzyłem miniaturę dla każdej ramki. Kod do generowania miniaturek było od: https://gnunet.org/svn/Extractor/src/plugins/thumbnailffmpeg_extractor.c

Funkcja decodeIFrame przejdą AVCodecContext do addVideoAudioStream:

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); 
} 

O ile mogę powiedzieć, szereg założeń nie miało to znaczenia, na przykład: 1. Szybkość transmisji. Rzeczywista szybkość transmisji wideo wynosiła ~ 262 tys., Podczas gdy ja określiłem 512kbitów. Podałem mono, chociaż faktycznym wyjściem było Stereo z pamięci

. Nadal trzeba wiedzieć, jaka jest częstotliwość klatek (podstawa czasu) dla dźwięku wideo &.

W przeciwieństwie do wielu innych przykładów, po ustawieniu pts & dts na pakietach wideo, nie można go było odtworzyć. Musiałem znać podstawę czasu (25fps), a następnie ustawić pts & dts zgodnie z tą podstawą czasu, tj. Pierwsza klatka = 0 (PPS, SPS, I), druga ramka = 1 (ramka pośrednia, jakkolwiek się ona nazywa;)) .

AAC Musiałem również przyjąć założenie, że jest to 16000 Hz. 1024 próbki na pakiet AAC (możesz też mieć próbki AAC @ 960, jak sądzę), aby określić "przesunięcie" dźwięku. Dodałem to do pkt & dts. Tak więc pts/dts to numer próbki, na który ma zostać odtworzony. Musisz również upewnić się, że czas trwania 1024 jest ustawiony w pakiecie przed napisaniem również.

-

Znalazłem dodatkowo dzisiaj, że załącznik B nie jest to zgodne z dowolnym innym odtwarzaczem Format AVCC tak naprawdę powinny być używane.

Adresy te pomogły: Problem to Decode H264 video over RTP with ffmpeg (libavcodec) http://aviadr1.blogspot.com.au/2010/05/h264-extradata-partially-explained-for.html

Przy konstruowaniu strumienia wideo, ja wypełniłem dodatkowymi danymi & extradata_size:

// 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]; 

Pisząc z klatki, nie dokleja SPS & PPS ramki, po prostu wypisz ramki I Frame & P. Ponadto zamień kod startowy Annex B zawarty w pierwszych 4 bajtach (0x00 0x00 0x00 0x01) z rozmiarem ramki I/P.

+0

Dlaczego łączysz SPS + PPS + I-frame razem do pisania? Również funkcja 'setLength()' może być odpowiedzialna, ale jest to mało prawdopodobne, jeśli twój plik binarny porównuje się z wynikiem polecenia reminking w linii poleceń ffmpeg, który nie wykazuje różnic w strumieniu. –

+0

Łączenie SPS i PPS i I Frame razem było po namyśle. Początkowo miałem je rozdzielone i wtedy też nie działało. Połączyłem je, ponieważ kiedy robiłem dekodowanie na elemencie iframe, potrzebowałem sps i pps, aby je odkodować i nie brałem ich osobno. setLength() po prostu zastępuje kod startowy 32-bitową długością i jak już powiedziałeś, nic nie zmienia się aż do stopki. –

+0

Łączenie SPS i PPS dla dekodera jest w porządku, ale może być niebezpieczne dla muxera (format mp4). Wierzę również, że kiedy wysyłasz plasterki do muxera, powinieneś usunąć nagłówek NALU. –

Odpowiedz

3

Podajcie proszę: problem z waszym (oryginalnym) kodem polegał na tym, że wejście do av_interleaved_write_frame() nie powinno rozpoczynać się od długości pakietu. Plik nadal może być odtwarzany, jeśli nie usuniesz kodów startowych 00 00 00 01, ale to IMHO jest zachowaniem elastyczności odtwarzacza i nie liczę na to.

+0

Rodzaj. Użycie ffmpeg do konwersji, np. Ffmpeg -i file.h264 -vcodec copy out.mp4 wydaje się zastępować kod startowy (00 00 00 01) długością ramki. Przynajmniej to było zgodne z hexdump pliku. Próbując zrobić to samo z kodu, nie działa z jakiegoś powodu. To musi być coś związanego ze sposobem, w jaki jest ustawiony strumień, a nawet wartościami pts/dts, nie jestem pewien. Jednak nie rozbiórki definately naprawione. Powinienem wkleić kod tego, co mam, aby pokazać ostateczny wynik, ponieważ dostałem wideo i audio zsynchronizowane w pliku MP4. Załaduję to za kilka godzin. –

+0

Dzięki za pomoc Alex. Twoje komentarze na temat kodu startowego skłoniły mnie do spojrzenia na to z innej perspektywy, więc biorę to jako odpowiedź. –

Powiązane problemy