FAQ | Points | Add... | Recent posts | Search | Register | Log in


Mały odtwarzacz MP3,AAC,MP4 na AT91SAM7S256


[ + ] [ - ]
Post new topic  Reply to topic      Main Page -> Forum Index -> DIY Structures -> DIY Acoustics -> Mały odtwarzacz MP3,AAC,MP4 na AT91SAM7S256
Author
Message
Tytus Kosiarski
Poziom 11
Poziom 11


Joined: 29 Jul 2007
Posts: 74

Post#31 Post from the author of the topic 26 Nov 2011 20:14   

Re: Mały odtwarzacz MP3,AAC,MP4 na AT91SAM7S256


Acha, poprawność działania programu odtwarzania MP-czwórek sprawdziłem na kilkunastu plikach MP4 i M4A, które pościągałem z Sieci. Niemniej jednak, może się trafić jakiś taki plik, który nie będzie odtwarzany i może powodować np. zawieszenie się odtwarzacza. Proszę wtedy o przesłanie na priv tego pliku lub podanie linka do niego, abym mógł usunąć błędy w programie, uniemożliwiające odtworzenie tego pliku.
Pozdrawiam, KT
Back to top
   
Safrane70
Poziom 2
Poziom 2


Joined: 15 Mar 2009
Posts: 4
Location: Lublin

Post#32 27 Dec 2011 14:18   

Re: Mały odtwarzacz MP3,AAC,MP4 na AT91SAM7S256


Świetny projekt, ja od jakiegoś czasu własnie myślę żeby zrobić taki odtwarzacz MP3 do samochodu (i nie tylko) - Jaka byłaby orientacyjna cena złożenia tego projektu (procesor (najlepiej już zaprogramowany), płytka, gniazda, części?? Po "piętach" depcze YAMPP 7 - KIT kosztuje 230 zł. (pod warunkiem że jest jeszcze dostępny).
Dla mnie w obecnej chwili (praca, dzieci) odpada zbyt długie "chodzenie" przy projekcie i zmuszony jestem do pójścia na łatwiznę - niestety - chroniczny brak czasu... Czy Kolega Tytus ze swojego projektu myśli zrobić KIT do samodzielnego montażu?? Umiejętność operowania lutownicą jeszcze mi pozostała... ;)
Back to top
   
Google

Google Adsense


Post# 27 Dec 2011 14:18   





Back to top
   
Tytus Kosiarski
Poziom 11
Poziom 11


Joined: 29 Jul 2007
Posts: 74

Post#33 Post from the author of the topic 27 Dec 2011 16:30   

Re: Mały odtwarzacz MP3,AAC,MP4 na AT91SAM7S256


Witam:) Dzięki:) Dokumentacja odtwarzacza i dokładniejszy kosztorys jest w moim poście otwierającym ten wątek, całość wynosi tak ok 340zł. Nie przewiduję robienia z tego kitu w celach zarobkowych z dwóch powodów: 1. nie wiem,jak by było z prawami autorskimi, ale wydaje mi się, że kodu dekodera MP3 i AAC nie można wykorzystywać w celach komercyjnych;
2. nie mam możliwości zaprogramowania procesora poza układem. Jedynie w zmontowanym układzie odtwarzacza. Mogę doradzić jedynie poskładanie we własnym zakresie tego odtwarzacza (z wykorzystaniem dokumentacji) i dogadanie się ze mną na priv w celu zaprogramowania i uruchomienia całości.
Obecnie testuję poprawność odtwarzania plików MP4 (walka ze zwisami w wyjątkach Data Abort podczas odtwarzania tych plików). Wydaję mi się, że już odtwarzanie przebiega poprawnie, jak już będę pewien poprawności działania, wystawię, oczywiście, kod. Mogę również napomknąć, że pomału przygotowuję się do implementacji kodu tego odtwarzacza na procesorze ATSAM3S4B (pinowo zgodny z SAM7S, ale rdzeń procesora to Cortex M3). Ale to jeszcze zajmie mi czasu... (również chroniczny brak, niestety)
Pozdrawiam, KT
Back to top
   
Safrane70
Poziom 2
Poziom 2


Joined: 15 Mar 2009
Posts: 4
Location: Lublin

Post#34 30 Dec 2011 14:49   

Re: Mały odtwarzacz MP3,AAC,MP4 na AT91SAM7S256


Ech te "prawa autorskie" :( Napisałem maila do tej firmy która oferuje YAMPPa (softcom.gda.pl) ale nie dostałem odpowiedzi - pewnie już zarzucili ten projekt. No to nie pozostaje mi nic innego jak po szaleństwach "nocy sylwestrowej" ;) zabrać się za Kolegi projekt :) Poczekam tylko na efekty działań na nowym procesorze :)

Życzę Wszystkiego Dobrego na Nowy Rok oraz wszelkiej pomyślności :)

Pozdrawiam również :)
Back to top
   
Tytus Kosiarski
Poziom 11
Poziom 11


Joined: 29 Jul 2007
Posts: 74

Post#35 Post from the author of the topic 26 Feb 2012 01:39   

Re: Mały odtwarzacz MP3,AAC,MP4 na AT91SAM7S256


Witam
OK, po ponad dwumiesięcznej, intensywnej eksploatacji mp-czwórki wyszły na jaw błędy w programie, które kończyły się wyjątkiem Data Abort i "zwisem". Jedną z przyczyn udało się dość łatwo namierzyć, mianowicie wyjątek ten powodowany był tylko podczas odtwarzania jednego, specyficznego pliku MP4. Okazało się, że w tym pliku atom "stsc" składał się tylko z jednego 12-bajtowego wpisu, w którym to wpisie były: 4 bajty indeksu kawałka audio, 4 bajty ilości próbek audio w tym kawałku (ta próbka audio to jest pojedyncza, "surowa" ramka AAC, bez nagłówka ADTS) oraz 4 bajty Sample Duration Index (czas trwania pojedynczej próbki(?); zawsze równy 1). Te ostatnie 4 bajty SDI nie są mi potrzebne i nie wykorzystuję ich. W tym konkretnym pliku we wpisie atomu "stsc" indeks kawałka audio miał wartość 1, natomiast ilość próbek audio w tym kawałku danych była różna od 1 (a nie równa 1, jak w innych plikach z podobnie zbudowanym atomem "stsc"). Po "obczajeniu" tej różnicy w budowie atomu "stsc" wystarczyło wstawić po dwukropku:

Code C - [expand]
 
max_nSamples_for_chunk = k + (number_of_chunk_entries > 1 ? n_audio_samples_in_chunk : /*zwiększenie liczby przetworzonych próbek audio o liczbę próbek w nowym kawałku audio*/ stsc_atom_table[(n_elements_of_stsc_atom_table - (n_processed_entries_of_stsc_atom - i)) + 1]); /*lub o liczbę próbek pamiętaną w drugim elemencie stsc_atom_table, gdy number_of_chunk_entries == 1*/
 


zamiast wartości 1 w pętli odtwarzającej plik MP4 w funkcji play_mp4_file w pliku play_files.c. Ta zmiana spowodowała poprawne już odtwarzanie tego konkretnego pliku MP4.

Z inną przyczyną wyjątku Data Abort nie było już tak prosto - zawieszanie się w przypadkowych momentach, przy odtwarzaniu różnych plików. Było czasami tak, że cały katalog z plikami MP4 był poprawnie odtworzony do końca, po czym podczas próby ponownego odtworzenia zawartości tego katalogu zwis następował już na pierwszym pliku. Próby manewrowania rozmiarami heap'u i stack'a nie dawały jakiejś widocznej zmiany, nie mówiąc o poprawie. Wielogodzinne odtwarzanie tych plików w trybie debug-u ujawniło w końcu, że problem występuje podczas wykonywania się jednej funkcji RefillBitstreamCache w pliku aac_bitstream.c oraz drugiej funkcji DecodeSectionData w pliku noiseless.c. Wiele czasu zajęło mi ustalenie, co mogło być przyczyną takich problemów. Na właściwy trop naprowadziła mnie obserwacja wartości zmiennej
bsi->cachedBits w funkcji GetBits w pliku aac_bitstream.c podczas debug-u. Normalnie wartość ta powinna być >=0, gdy jest mniejsza, to w tej funkcji wywoływana jest kolejna funkcja RefillBitstreamCache. Podczas normalnego, prawidłowego dekodowania wartość zmiennej bsi->cachedBits nie była mniejsza niż (-16). Natomiast przed momentem zwisu wartość ta była, owszem, ujemna, ale przyjmowała "kosmiczne" wielkości!!! Wtedy kapnąłem się, że przyczyną takiego zachowania mogą być błędy w odczycie danych odtwarzanego pliku z karty SD (przekłamywanie bajtów). Błędy odczytu niekiedy zdarzały się na tyle rzadko, że możliwe było odtworzenie całego, kilkugodzinnego podkatalogu z plikami MP4 bez zwisów. Zastanawiając się, co by z tym zrobić, pomyślałem, że warto by było wykorzystać sumę kontrolną CRC generowaną przez kartę SD do wyeliminowania błędów odczytu. Dwubajtowa suma kontrolna CRC jest doklejana na końcu każdego 512-bajtowego sektora danych podczas odczytywania karty SD. Wartości CRC wpisuję do tablicy wskazywanej przez wskaźnik SD_CRC_table jak w poniższym kodzie (funkcja sd_get_response_and_read_write_data w pliku SD_Card_functions.c):

Code C - [expand]
 
case CMD17: //gdy wysłana była do karty SD komenda odczytu pojedynczego bloku danych z karty
memset(SD_CRC_table, 0, 2); //wyczyszczenie tablicy przechowującej kody CRC odczytywane z karty SD
...
...
AT91F_SPI_PutChar(AT91C_BASE_SPI, 0xFF, SD_Card_Access); //wystawianie 0xFF na MOSI, by utrzymać aktywność CLK
odebrany_bajt = AT91F_SPI_GetChar( AT91C_BASE_SPI); //i teraz odczytywanie starszego bajtu CRC
SD_CRC_table[0] = (odebrany_bajt) << 8; //oraz wpisanie go do elementu [0] tablicy przechowującej sumy CRC i przesunięcie go na starszy bajt tego elementu
AT91F_SPI_PutChar(AT91C_BASE_SPI, 0xFF, SD_Card_Access); //wystawianie 0xFF na MOSI, by utrzymać aktywność CLK
odebrany_bajt = AT91F_SPI_GetChar( AT91C_BASE_SPI); //i teraz odczytywanie młodszego bajtu CRC
SD_CRC_table[0] = SD_CRC_table[0] | odebrany_bajt; //i wpisanie go na młodszy bajt elementu [0] tablicy przechowującej sumy CRC
break;
case CMD18: //gdy wysłana była do karty SD komenda odczytu kilku bloków danych z karty, to poniżej
memset(SD_CRC_table, 0, (liczba_blokow * 2)); //wyczyszczenie tablicy przechowującej kody CRC odczytywane z karty SD
while (liczba_blokow)
{
attempt = 0;
...
...
AT91F_SPI_PutChar(AT91C_BASE_SPI, 0xFF, SD_Card_Access); //wystawianie 0xFF na MOSI, by utrzymać aktywność CLK
odebrany_bajt = AT91F_SPI_GetChar( AT91C_BASE_SPI); //i teraz odczytywanie starszego bajtu CRC
SD_CRC_table[liczba_blokow - 1] = (odebrany_bajt) << 8; /*oraz wpisanie go do elementu [liczba_blokow - 1] tablicy przechowującej sumy CRC i
przesunięcie go na starszy bajt tego elementu*/

AT91F_SPI_PutChar(AT91C_BASE_SPI, 0xFF, SD_Card_Access); //wystawianie 0xFF na MOSI, by utrzymać aktywność CLK
odebrany_bajt = AT91F_SPI_GetChar( AT91C_BASE_SPI); //i teraz odczytywanie młodszego bajtu CRC
SD_CRC_table[liczba_blokow - 1] = (SD_CRC_table[liczba_blokow - 1]) | odebrany_bajt; /*i wpisanie go na młodszy bajt elementu [liczba_blokow - 1] tablicy przechowującej sumy CRC*/
liczba_blokow--; //i zmniejszenie o 1 liczby bloków do odczytu, bo jeden sektor karty został już odczytany
}
...
...
 


Następnie zapamiętane kody CRC wykorzystuję do porównania z obliczonymi kodami CRC i stosownie do wyniku porównania, ponownego odczytania uprzednio błędnie odczytanych danych, jak w poniższym kodzie (funkcje read_sector i read_multiple_sectors w pliku SD_Card_functions.c):

Code C - [expand]
 
char read_sector(...)
{
...
...
do /*ta pętla do...while wykonuje się tak długo, jak długo kod CRC odczytany z SD razem z 512-bajtowym sektorem <> obliczonego CRC z danych 512-bajtowego sektora przechowywanego w tablicy adres_tablicy*/
{ //i poprawny odczyt z karty (read_OK == true)
komenda = send_command(CMD17,(adres * mnoznik)); /*wysłanie do karty komendy READ_SINGLE_BLOCK - odczytanie pojedynczego bloku danych poczynając od bajtu o adresie w zmiennej adres*/
read_OK = sd_get_response_and_read_write_data(adres_tablicy, komenda, 1, CRC16); /*w odpowiedzi karta zwraca odpowiedź R1, oraz, gdy nie ma błędu, 512 bajtów sektora o podanym adresie w zmiennej adres + 2 bajty CRC przechowywane w tablicy CRC16*/
calculated_CRC16 = 0;
for (i = 0; i < 512; i++) /*w tej pętli obliczenie CRC na podstawie danych w adres_tablicy, odczytanych wcześniej z SD*/
{
calculated_CRC16 = (calculated_CRC16 << 8) ^ CCITT_table[((calculated_CRC16 >> 8) ^ adres_tablicy[i])];
}
}
while ( (CRC16[0] != calculated_CRC16) && read_OK);
...
...
}
 
 
char read_multiple_sectors(...)
{
...
...
komenda = send_command(CMD18,(adres * mnoznik)); /*wysłanie do karty komendy READ_MULTIPLE_BLOCK - odczytanie kilku bloków danych poczynając od bajtu o adresie w zmiennej adres*/
read_OK = sd_get_response_and_read_write_data(adres_tablicy, komenda, liczba_sektorow, CRC16); /*w odpowiedzi karta zwraca odpowiedź R1, oraz, gdy nie ma błędu, (512 * liczba_sektorow) bajtów poczynając od sektora o podanym adresie w zmiennej adres*/
for (k = 0; k < liczba_sektorow; k++) /*w tej pętli obliczanie kodu CRC każdego 512-bajtowego kawałka z tablicy adres_tablicy i następnie porównywanie go z każdym kodem CRC odczytanym z SD i pamiętanym w tablicy CRC16*/
{
calculated_CRC16 = 0;
for (i = (k * 512); i < ((k * 512) + 512); i++) /*w tej pętli obliczenie CRC na podstawie każdego 512-bajtowego kawałka danych w adres_tablicy, odczytanych wcześniej z SD*/
{
calculated_CRC16 = (calculated_CRC16 << 8) ^ CCITT_table[((calculated_CRC16 >> 8) ^ adres_tablicy[i])];
}
if (calculated_CRC16 != CRC16[(liczba_sektorow - 1) - k]) //i gdy obliczony CRC <> odczytanego CRC z karty, to
read_OK = read_sector((adres_tablicy + (k * 512)), (adres + k), rodzaj_karty); /*ponowny odczyt tylko tego sektora z karty SD, w którym wystąpiły błędy, pozostałe, będące OK, nie są ruszane*/
}
...
...
}
 


Na razie działa:) Wykorzystałem sposób obliczania CRC CCITT z tej strony: http://groups.google.com/group/pl.comp.lang.delphi/browse_thread/thread/ef7c8fcf5605b9eb?fwc=1
oraz tablicę wielomianu CCITT stąd: http://www.elektroda.pl/rtvforum/topic1350530.html
Ponadto zmniejszyłem wykorzystanie RAMU do 48kB poprzez usunięcie trzech wielkich tablic ze zmiennych globalnych i dynamiczne tworzenie tych tablic jedynie przed rozpoczęciem odtwarzania pliku MP3, AAC i MP4 oraz usuwaniem tych tablic po zakończeniu odtwarzania tych plików, gdyż przymierzam się powoli do implementacji tego odtwarzacza na procesorze SAM3S4B.
Pozdrawiam, KT



odtwarzacz_MP3_AAC_MP4.zip
 Filename:  odtwarzacz_MP3_AAC_MP4.zip
Download
 Contents:  
 Filesize:  756.33 KB
 Punkty:  0

Back to top
   
Post new topic  Reply to topic   [ + ] [ - ]    Main Page -> Forum Index -> DIY Structures -> DIY Acoustics -> Mały odtwarzacz MP3,AAC,MP4 na AT91SAM7S256
Statement for Wykop Statement for Facebook Statement for Delicious Statement for Digg Statement for Google Statement for Twitter Statement for Blip
Page 2 of 2 Go to page Previous  1, 2
Similar topics
META odtwarzacz mp3 z pulsometrem (1)
Najmniejszy na świecie odtwarzacz mp3 (3)
Sieciowy odtwarzacz mp3 WLAN (26)
Bardzo prosty odtwarzacz mp3 (13)
Odtwarzacz MP3 zbudoany na Atmedze128 (9)
Samochodowy odtwarzacz MP3 (6)
Przenośny głośnik mono do Odtwarzacza MP3/MP4 (49)
Odtwarzacz MP3 na płytce startowej AVR (7)
Yampp-7, odtwarzacz mp3 na karty pamięci (6)
Odtwarzacz mp3 na PIC - zdjęcie, schemat, źródło (13)

Page generation time: 0.142 seconds


FAQ || Administrator || Moderators || Widgets and banners || Contact
elektroda.pl topic RSS feed