I want to decode a MP3 file. I manage to find the 32 bits in the header (sync word, ID, Layer, Bitrate, etc). The problem is I have no idea on how to find the starting (the position) of main_data_begin (side information). I am using MATLAB in this case.
I know it may be a simple question, but I really need your help. Please.
Thank you.
MPEG1/2 Layer III uses main_data_begin as a kind of pseudo-VBR over the granule headers & data. The simplest way to do it is to implement a circular buffer that receives all the physical frame data after the side info and throws-away the unused bytes at the beginning of the buffer (as indicated by main_data_begin) before starting frame decode.
Your best bet is to read an existing decoder's source. The spec is also really good for this, but main_data_begin is mis-documented in publicly-available versions (as best as I can find).
Related
Does Exoplayer download a chunk completely before processing (decrypting, decoding) it. Is there a way to override this and start decoding / playback before the chunk is completely downloaded.The content is an MPEG-DASH content with a 6 second chunk size.
I am on the latest version of Exoplayer. I am trying to improve the Video Start Time and hence this query. Also, will smaller chunk sizes impact the Video start time ?
I think you mean a dash segment when you say chunk - the terminology is important because DASH segments can contain subsegments, and each of these may be decodable, but it is also confusing as the term chunks and segments are both used in the ExoPlayer code.
Its useful when discussing this area to remember that the video download is actually a series of requests and responses, rather than a constant stream of media.
To start decoding earlier you typically have to request smaller 'pieces' (trying to avoid tripping over terminology...) of the video.
To be decodable, and video piece usually needs to start with a frame which does not reference any previous frames - an IDR frame or Stream Access Point (SAP).
Looking at ExoPlayer itself, you can set the number of segments you can download per chunk (Exoplayer terminology for the bit of the video you download) - take a look at the 'maxSegmentsPerLoad' attribute in the 'DefaultDashChunkSource': https://github.com/google/ExoPlayer/blob/bd54394391b0527893f382c9d641b8a55ffca765/library/dash/src/main/java/com/google/android/exoplayer2/source/dash/DashChunkSource.java
However, I think this is the opposite of what you are looking for - you would like to request a smaller piece of video - e.g. subsegments rather than the whole segments.
For that you most likely want to look at the new low latency mechanisms introduced for DASH and for HLS - ExoPlayer has added support for these and there is a public design document which provides a very good explanation of the background and the approach here (link correct at the time of writing - original ExoPlauer git issue also for reference - https://github.com/google/ExoPlayer/issues/4904):
https://docs.google.com/document/d/1z9qwuP7ff9sf3DZboXnhEF9hzW3Ng5rfJVqlGn8N38k/edit#
The diagrams in this document explain it well, but the short answer to your question is that yes, this approach does allow smaller 'pieces' of video be downloaded and played back and it does indeed help with video start time.
I have 2 questions
1)How do I write raw data to a file sinker. I am trying to mux.
2)How do I make sure the sinked data is not written to a file but to a memory buffer
So in Detail:
I am trying to use windows MPEG-4 File Sink to write some Intel SDK Encoded avc or hevc to memory and send it to websocket.
what is the right approach?
Can I just feed raw hevc or avc as (byte*, length) to MPEG-4 File Sink?
Or Do I need to wrap the Intel Encoder into a Custom Windows Media Foundation Encoder(well I can just use GUID to get the Intel Encoder anyway) from Windows Media Frame work. Correct me If I am wrong please.
So I have 2 problems, How do I write my raw data(avc||hevc) to MP4 Sinker(Encoded by a 3rd Party Encoder)
Do I need to implement a custom Sinker , And how custom is it. Can I inherit part of the MPEG4 Sinker(After all I do not want to re implement a full container for Mp4)
Or Modify MPEG4 Sinker behavior so that it does not write it to a file but writes to a Memory
I know I feel like I re iterated myself A few times. Sorry about that.
1) If you wrap the encoded bitstream in an IMFSample you can just call IMFStreamSink::ProcessSample. To wrap it in the IMFSample, create a memory buffer IMFMediaBuffer with MFCreateMemoryBuffer , then create an IMFSample with MFCreateSample and add the buffer to it with IMFSample::AddBuffer. And then pass it to the stream sink. Also, if you can constrain the output bitstream length you can actually use the underlying memofy from IMFMediaBuffer by using IMFMediaBuffer::Lock to obtain the pointer to the underlying memory and passing that to the Intel SDK.
2) When creating the MPEG-4 sink via MFCreateMPEG4MediaSink you pass in an IMFByteStream instance. You can make your own class which implements this interface and writes the data directly to memory or wherever you need. If you do not want to do a full implementation there are also MFCreateMFByteStreamOnStream and MFCreateMFByteStreamOnStreamEx which can wrap an IStream instance into a IMFByteStream but I have never used those and I am not aware of the underlying memory semantics. You can create a memory backed IStream with SHCreateMemStream and CreateStreamOnHGlobal.
I have used Intel SDK quite long ago but if I remember it had a MFT compatible encoder, but I always used the plain C++ one, and thus I am not sure how they differ in terms of configuration etc. But if the MFT one works, then you can setup a proper pipeline without processing the bitstream samples yourself as stated in (1) and just handle (2).
Also, performance wise, since as far as I remember Intel SDK did work on Direct3D surfaces as well, you could look into MFCreateDXSurfaceBuffer to used Direct3D surfaces instead of memory buffers for wrapping the data.
I'm implementing a small PCI driver for academic purposes, and one thing I'm not clear about if we actually have to provide driver.conf? Different materials which I read (including http://blog.csdn.net/hotsolaris/article/details/1763716), say that for PCI the driver config file is optional, however in my case it seems that pci_config_setup() is successful only with driver.conf provided:
name="mydrv" parent="/pci#0,0/pci8086,2e11"
Then I do:
% add_drv -i 'pciXXXX,YY' mydrv
and it adds in the system with no warning or error messages.
So I assume that some properties of a PCI device can't be derived automatically by the system, e.g. parent bus?
I would appreciate if anybody could shed some light on this. Thanks.
If you look at a random selection of very small files under /kernel/drv for actual physical hardware, you'll see that they almost always only contain the line
ddi_forceattach=1;
Pseudo drivers will have a driver.conf(4) file which reflects their parentage in the system. I really recommend reading that manpage, it goes into good detail about what's required here.
The following function calls are deprecated in OpenAL 1.1, what is a proper replacement?? THe only answer i found in google was "write your own function!!" ;-)
alutLoadWAVFile
alutUnloadWAV
There are 8 file loading functions in ALUT (not including the three deprecated functions alutLoadWAVFile, alutLoadWAVMemory, and alutUnloadWAV).
The prefix of the function determines where the data is going; four of them start alutCreateBuffer (create a new buffer and put the sound data into it), and the other four start alutLoadMemory (allocate a new memory region and put the sound data into it).
The suffix of the function determines where the data comes from. Your options are FromFile (from a file!), FromFileImage (from a memory region), HelloWorld (fixed internal data of someone saying "Hello, world!"), and Waveform (generate a waveform).
I believe the correct replacement for alutLoadWAVFile would therefore be alutCreateBufferFromFile.
However, I would not use this blindly - it's suitable for short sound clips, but for e.g. a music track you probably want to load it in chunks and queue up multiple buffers, to ease the memory load.
These functions are all covered in the alut documentation, by the way.
"write your own" is pretty much the correct answer.
You can usually get away with using the deprecated functions since most implementations still include the WAV file handling functions, with one notable exception being iOS, for which you'd need to use audio file services.
I'd suggest making a standard prototype for "load wav file" and then depending on the OS, use a different loading routine. You can just stub it with a call to alutLoadWAVFile for systems known to still support it.
It seems that since boost 1.40.0 there has been a change to the way that the the async_read_some() call works.
Previously, you could pass in a null_buffer and you would get a callback when there was data to read, but without the framework reading the data into any buffer (because there wasn't one!). This basically allowed you to write code that acted like a select() call, where you would be told when your socket had some data on it.
In the new code the behaviour has been changed to work in the following way:
If the total size of all buffers in the sequence mb is 0, the asynchronous read operation shall complete immediately and pass 0 as the argument to the handler that specifies the number of bytes read.
This means that my old (and incidentally, the method shown in this official example) way of detecting data on the socket no longer works. The problem for me is that I need a way detecting this because I've layered my own streaming classes on-top of the asio socket streams and as such, I cannot just read data off the sockets that my streams will expect to be there. The only workaround I can think of right now is to read a single byte, store it and when my stream classes then request some bytes, return that byte if one is set: not pretty.
Does anyone know of a better way to implement this kind of behaviour under the latest boost.asio code?
My quick test with an official example with boost-1.41 works... So I think it still should work (if you use null_buffers)